17cc577a4SJonathan Peyton /*
2de4749b7SJonathan Peyton  * kmp_str.cpp -- String manipulation routines.
37cc577a4SJonathan Peyton  */
47cc577a4SJonathan Peyton 
57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
67cc577a4SJonathan Peyton //
757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
107cc577a4SJonathan Peyton //
117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
127cc577a4SJonathan Peyton 
137cc577a4SJonathan Peyton #include "kmp_str.h"
147cc577a4SJonathan Peyton 
157cc577a4SJonathan Peyton #include <stdarg.h> // va_*
167cc577a4SJonathan Peyton #include <stdio.h> // vsnprintf()
177cc577a4SJonathan Peyton #include <stdlib.h> // malloc(), realloc()
187cc577a4SJonathan Peyton 
197cc577a4SJonathan Peyton #include "kmp.h"
207cc577a4SJonathan Peyton #include "kmp_i18n.h"
217cc577a4SJonathan Peyton 
223041982dSJonathan Peyton /* String buffer.
237cc577a4SJonathan Peyton 
247cc577a4SJonathan Peyton    Usage:
257cc577a4SJonathan Peyton 
267cc577a4SJonathan Peyton    // Declare buffer and initialize it.
277cc577a4SJonathan Peyton    kmp_str_buf_t  buffer;
287cc577a4SJonathan Peyton    __kmp_str_buf_init( & buffer );
297cc577a4SJonathan Peyton 
307cc577a4SJonathan Peyton    // Print to buffer.
317cc577a4SJonathan Peyton    __kmp_str_buf_print(& buffer, "Error in file \"%s\" line %d\n", "foo.c", 12);
327cc577a4SJonathan Peyton    __kmp_str_buf_print(& buffer, "    <%s>\n", line);
337cc577a4SJonathan Peyton 
343041982dSJonathan Peyton    // Use buffer contents. buffer.str is a pointer to data, buffer.used is a
353041982dSJonathan Peyton    // number of printed characters (not including terminating zero).
367cc577a4SJonathan Peyton    write( fd, buffer.str, buffer.used );
377cc577a4SJonathan Peyton 
387cc577a4SJonathan Peyton    // Free buffer.
397cc577a4SJonathan Peyton    __kmp_str_buf_free( & buffer );
407cc577a4SJonathan Peyton 
417cc577a4SJonathan Peyton    // Alternatively, you can detach allocated memory from buffer:
427cc577a4SJonathan Peyton    __kmp_str_buf_detach( & buffer );
437cc577a4SJonathan Peyton    return buffer.str;    // That memory should be freed eventually.
447cc577a4SJonathan Peyton 
457cc577a4SJonathan Peyton    Notes:
467cc577a4SJonathan Peyton 
473041982dSJonathan Peyton    * Buffer users may use buffer.str and buffer.used. Users should not change
483041982dSJonathan Peyton      any fields of buffer directly.
493041982dSJonathan Peyton    * buffer.str is never NULL. If buffer is empty, buffer.str points to empty
503041982dSJonathan Peyton      string ("").
513041982dSJonathan Peyton    * For performance reasons, buffer uses stack memory (buffer.bulk) first. If
523041982dSJonathan Peyton      stack memory is exhausted, buffer allocates memory on heap by malloc(), and
533041982dSJonathan Peyton      reallocates it by realloc() as amount of used memory grows.
547cc577a4SJonathan Peyton    * Buffer doubles amount of allocated memory each time it is exhausted.
557cc577a4SJonathan Peyton */
567cc577a4SJonathan Peyton 
577cc577a4SJonathan Peyton // TODO: __kmp_str_buf_print() can use thread local memory allocator.
587cc577a4SJonathan Peyton 
597cc577a4SJonathan Peyton #define KMP_STR_BUF_INVARIANT(b)                                               \
607cc577a4SJonathan Peyton   {                                                                            \
617cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT((b)->str != NULL);                                        \
627cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT((b)->size >= sizeof((b)->bulk));                          \
637cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT((b)->size % sizeof((b)->bulk) == 0);                      \
647cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT((unsigned)(b)->used < (b)->size);                         \
653041982dSJonathan Peyton     KMP_DEBUG_ASSERT(                                                          \
663041982dSJonathan Peyton         (b)->size == sizeof((b)->bulk) ? (b)->str == &(b)->bulk[0] : 1);       \
673041982dSJonathan Peyton     KMP_DEBUG_ASSERT((b)->size > sizeof((b)->bulk) ? (b)->str != &(b)->bulk[0] \
683041982dSJonathan Peyton                                                    : 1);                       \
697cc577a4SJonathan Peyton   }
707cc577a4SJonathan Peyton 
__kmp_str_buf_clear(kmp_str_buf_t * buffer)713041982dSJonathan Peyton void __kmp_str_buf_clear(kmp_str_buf_t *buffer) {
727cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
737cc577a4SJonathan Peyton   if (buffer->used > 0) {
747cc577a4SJonathan Peyton     buffer->used = 0;
757cc577a4SJonathan Peyton     buffer->str[0] = 0;
76bd3a7633SJonathan Peyton   }
777cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
787cc577a4SJonathan Peyton } // __kmp_str_buf_clear
797cc577a4SJonathan Peyton 
__kmp_str_buf_reserve(kmp_str_buf_t * buffer,size_t size)806b316febSTerry Wilmarth void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, size_t size) {
817cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
827cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(size >= 0);
837cc577a4SJonathan Peyton 
847cc577a4SJonathan Peyton   if (buffer->size < (unsigned int)size) {
857cc577a4SJonathan Peyton     // Calculate buffer size.
867cc577a4SJonathan Peyton     do {
877cc577a4SJonathan Peyton       buffer->size *= 2;
887cc577a4SJonathan Peyton     } while (buffer->size < (unsigned int)size);
897cc577a4SJonathan Peyton 
907cc577a4SJonathan Peyton     // Enlarge buffer.
917cc577a4SJonathan Peyton     if (buffer->str == &buffer->bulk[0]) {
927cc577a4SJonathan Peyton       buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
937cc577a4SJonathan Peyton       if (buffer->str == NULL) {
947cc577a4SJonathan Peyton         KMP_FATAL(MemoryAllocFailed);
95bd3a7633SJonathan Peyton       }
967cc577a4SJonathan Peyton       KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
977cc577a4SJonathan Peyton     } else {
987cc577a4SJonathan Peyton       buffer->str = (char *)KMP_INTERNAL_REALLOC(buffer->str, buffer->size);
997cc577a4SJonathan Peyton       if (buffer->str == NULL) {
1007cc577a4SJonathan Peyton         KMP_FATAL(MemoryAllocFailed);
101bd3a7633SJonathan Peyton       }
102bd3a7633SJonathan Peyton     }
103bd3a7633SJonathan Peyton   }
1047cc577a4SJonathan Peyton 
1057cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(buffer->size > 0);
1067cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(buffer->size >= (unsigned)size);
1077cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1087cc577a4SJonathan Peyton } // __kmp_str_buf_reserve
1097cc577a4SJonathan Peyton 
__kmp_str_buf_detach(kmp_str_buf_t * buffer)1103041982dSJonathan Peyton void __kmp_str_buf_detach(kmp_str_buf_t *buffer) {
1117cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1127cc577a4SJonathan Peyton 
1137cc577a4SJonathan Peyton   // If internal bulk is used, allocate memory and copy it.
1147cc577a4SJonathan Peyton   if (buffer->size <= sizeof(buffer->bulk)) {
1157cc577a4SJonathan Peyton     buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
1167cc577a4SJonathan Peyton     if (buffer->str == NULL) {
1177cc577a4SJonathan Peyton       KMP_FATAL(MemoryAllocFailed);
118bd3a7633SJonathan Peyton     }
1197cc577a4SJonathan Peyton     KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
120bd3a7633SJonathan Peyton   }
1217cc577a4SJonathan Peyton } // __kmp_str_buf_detach
1227cc577a4SJonathan Peyton 
__kmp_str_buf_free(kmp_str_buf_t * buffer)1233041982dSJonathan Peyton void __kmp_str_buf_free(kmp_str_buf_t *buffer) {
1247cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1257cc577a4SJonathan Peyton   if (buffer->size > sizeof(buffer->bulk)) {
1267cc577a4SJonathan Peyton     KMP_INTERNAL_FREE(buffer->str);
127bd3a7633SJonathan Peyton   }
1287cc577a4SJonathan Peyton   buffer->str = buffer->bulk;
1297cc577a4SJonathan Peyton   buffer->size = sizeof(buffer->bulk);
1307cc577a4SJonathan Peyton   buffer->used = 0;
1317cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1327cc577a4SJonathan Peyton } // __kmp_str_buf_free
1337cc577a4SJonathan Peyton 
__kmp_str_buf_cat(kmp_str_buf_t * buffer,char const * str,size_t len)1346b316febSTerry Wilmarth void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len) {
1357cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1367cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(str != NULL);
1377cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(len >= 0);
1386b316febSTerry Wilmarth 
1397cc577a4SJonathan Peyton   __kmp_str_buf_reserve(buffer, buffer->used + len + 1);
1407cc577a4SJonathan Peyton   KMP_MEMCPY(buffer->str + buffer->used, str, len);
1417cc577a4SJonathan Peyton   buffer->str[buffer->used + len] = 0;
1426b316febSTerry Wilmarth   __kmp_type_convert(buffer->used + len, &(buffer->used));
1437cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1447cc577a4SJonathan Peyton } // __kmp_str_buf_cat
1457cc577a4SJonathan Peyton 
__kmp_str_buf_catbuf(kmp_str_buf_t * dest,const kmp_str_buf_t * src)1466d88e049SJonathan Peyton void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src) {
1476d88e049SJonathan Peyton   KMP_DEBUG_ASSERT(dest);
1486d88e049SJonathan Peyton   KMP_DEBUG_ASSERT(src);
1496d88e049SJonathan Peyton   KMP_STR_BUF_INVARIANT(dest);
1506d88e049SJonathan Peyton   KMP_STR_BUF_INVARIANT(src);
1516d88e049SJonathan Peyton   if (!src->str || !src->used)
1526d88e049SJonathan Peyton     return;
1536d88e049SJonathan Peyton   __kmp_str_buf_reserve(dest, dest->used + src->used + 1);
1546d88e049SJonathan Peyton   KMP_MEMCPY(dest->str + dest->used, src->str, src->used);
1556d88e049SJonathan Peyton   dest->str[dest->used + src->used] = 0;
1566d88e049SJonathan Peyton   dest->used += src->used;
1576d88e049SJonathan Peyton   KMP_STR_BUF_INVARIANT(dest);
1586d88e049SJonathan Peyton } // __kmp_str_buf_catbuf
1596d88e049SJonathan Peyton 
1606d88e049SJonathan Peyton // Return the number of characters written
__kmp_str_buf_vprint(kmp_str_buf_t * buffer,char const * format,va_list args)1616d88e049SJonathan Peyton int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
1623041982dSJonathan Peyton                          va_list args) {
1636d88e049SJonathan Peyton   int rc;
1647cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
1657cc577a4SJonathan Peyton 
1667cc577a4SJonathan Peyton   for (;;) {
1677cc577a4SJonathan Peyton     int const free = buffer->size - buffer->used;
1687cc577a4SJonathan Peyton     int size;
1697cc577a4SJonathan Peyton 
1707cc577a4SJonathan Peyton     // Try to format string.
1717cc577a4SJonathan Peyton     {
172309b00a4SShilei Tian       /* On Linux* OS Intel(R) 64, vsnprintf() modifies args argument, so
173309b00a4SShilei Tian          vsnprintf() crashes if it is called for the second time with the same
174309b00a4SShilei Tian          args. To prevent the crash, we have to pass a fresh intact copy of args
175309b00a4SShilei Tian          to vsnprintf() on each iteration.
1767cc577a4SJonathan Peyton 
177309b00a4SShilei Tian          Unfortunately, standard va_copy() macro is not available on Windows*
178309b00a4SShilei Tian          OS. However, it seems vsnprintf() does not modify args argument on
179309b00a4SShilei Tian          Windows* OS.
1807cc577a4SJonathan Peyton       */
1817cc577a4SJonathan Peyton 
1827cc577a4SJonathan Peyton #if !KMP_OS_WINDOWS
1837cc577a4SJonathan Peyton       va_list _args;
1840447708fSJonathan Peyton       va_copy(_args, args); // Make copy of args.
1857cc577a4SJonathan Peyton #define args _args // Substitute args with its copy, _args.
1867cc577a4SJonathan Peyton #endif // KMP_OS_WINDOWS
1877cc577a4SJonathan Peyton       rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
1887cc577a4SJonathan Peyton #if !KMP_OS_WINDOWS
1897cc577a4SJonathan Peyton #undef args // Remove substitution.
1907cc577a4SJonathan Peyton       va_end(_args);
1917cc577a4SJonathan Peyton #endif // KMP_OS_WINDOWS
1927cc577a4SJonathan Peyton     }
1937cc577a4SJonathan Peyton 
1947cc577a4SJonathan Peyton     // No errors, string has been formatted.
1957cc577a4SJonathan Peyton     if (rc >= 0 && rc < free) {
1967cc577a4SJonathan Peyton       buffer->used += rc;
1977cc577a4SJonathan Peyton       break;
198bd3a7633SJonathan Peyton     }
1997cc577a4SJonathan Peyton 
2007cc577a4SJonathan Peyton     // Error occurred, buffer is too small.
2017cc577a4SJonathan Peyton     if (rc >= 0) {
2023041982dSJonathan Peyton       // C99-conforming implementation of vsnprintf returns required buffer size
2037cc577a4SJonathan Peyton       size = buffer->used + rc + 1;
2047cc577a4SJonathan Peyton     } else {
2057cc577a4SJonathan Peyton       // Older implementations just return -1. Double buffer size.
2067cc577a4SJonathan Peyton       size = buffer->size * 2;
207bd3a7633SJonathan Peyton     }
2087cc577a4SJonathan Peyton 
2097cc577a4SJonathan Peyton     // Enlarge buffer.
2107cc577a4SJonathan Peyton     __kmp_str_buf_reserve(buffer, size);
2117cc577a4SJonathan Peyton 
2127cc577a4SJonathan Peyton     // And try again.
213bd3a7633SJonathan Peyton   }
2147cc577a4SJonathan Peyton 
2157cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(buffer->size > 0);
2167cc577a4SJonathan Peyton   KMP_STR_BUF_INVARIANT(buffer);
2176d88e049SJonathan Peyton   return rc;
2187cc577a4SJonathan Peyton } // __kmp_str_buf_vprint
2197cc577a4SJonathan Peyton 
2206d88e049SJonathan Peyton // Return the number of characters written
__kmp_str_buf_print(kmp_str_buf_t * buffer,char const * format,...)2216d88e049SJonathan Peyton int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
2226d88e049SJonathan Peyton   int rc;
2237cc577a4SJonathan Peyton   va_list args;
2247cc577a4SJonathan Peyton   va_start(args, format);
2256d88e049SJonathan Peyton   rc = __kmp_str_buf_vprint(buffer, format, args);
2267cc577a4SJonathan Peyton   va_end(args);
2276d88e049SJonathan Peyton   return rc;
2287cc577a4SJonathan Peyton } // __kmp_str_buf_print
2297cc577a4SJonathan Peyton 
2303041982dSJonathan Peyton /* The function prints specified size to buffer. Size is expressed using biggest
2313041982dSJonathan Peyton    possible unit, for example 1024 is printed as "1k". */
__kmp_str_buf_print_size(kmp_str_buf_t * buf,size_t size)2323041982dSJonathan Peyton void __kmp_str_buf_print_size(kmp_str_buf_t *buf, size_t size) {
2337cc577a4SJonathan Peyton   char const *names[] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y"};
2347cc577a4SJonathan Peyton   int const units = sizeof(names) / sizeof(char const *);
2357cc577a4SJonathan Peyton   int u = 0;
2367cc577a4SJonathan Peyton   if (size > 0) {
2377cc577a4SJonathan Peyton     while ((size % 1024 == 0) && (u + 1 < units)) {
2387cc577a4SJonathan Peyton       size = size / 1024;
2397cc577a4SJonathan Peyton       ++u;
240bd3a7633SJonathan Peyton     }
241bd3a7633SJonathan Peyton   }
2427cc577a4SJonathan Peyton 
2437cc577a4SJonathan Peyton   __kmp_str_buf_print(buf, "%" KMP_SIZE_T_SPEC "%s", size, names[u]);
2447cc577a4SJonathan Peyton } // __kmp_str_buf_print_size
2457cc577a4SJonathan Peyton 
__kmp_str_fname_init(kmp_str_fname_t * fname,char const * path)2463041982dSJonathan Peyton void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path) {
2477cc577a4SJonathan Peyton   fname->path = NULL;
2487cc577a4SJonathan Peyton   fname->dir = NULL;
2497cc577a4SJonathan Peyton   fname->base = NULL;
2507cc577a4SJonathan Peyton 
2517cc577a4SJonathan Peyton   if (path != NULL) {
2527cc577a4SJonathan Peyton     char *slash = NULL; // Pointer to the last character of dir.
2537cc577a4SJonathan Peyton     char *base = NULL; // Pointer to the beginning of basename.
2547cc577a4SJonathan Peyton     fname->path = __kmp_str_format("%s", path);
2553041982dSJonathan Peyton     // Original code used strdup() function to copy a string, but on Windows* OS
256ed5fe645SKelvin Li     // Intel(R) 64 it causes assertion id debug heap, so I had to replace
2573041982dSJonathan Peyton     // strdup with __kmp_str_format().
2587cc577a4SJonathan Peyton     if (KMP_OS_WINDOWS) {
2597cc577a4SJonathan Peyton       __kmp_str_replace(fname->path, '\\', '/');
260bd3a7633SJonathan Peyton     }
2617cc577a4SJonathan Peyton     fname->dir = __kmp_str_format("%s", fname->path);
2627cc577a4SJonathan Peyton     slash = strrchr(fname->dir, '/');
2633041982dSJonathan Peyton     if (KMP_OS_WINDOWS &&
2643041982dSJonathan Peyton         slash == NULL) { // On Windows* OS, if slash not found,
2656b316febSTerry Wilmarth       char first = (char)TOLOWER(fname->dir[0]); // look for drive.
2667cc577a4SJonathan Peyton       if ('a' <= first && first <= 'z' && fname->dir[1] == ':') {
2677cc577a4SJonathan Peyton         slash = &fname->dir[1];
268bd3a7633SJonathan Peyton       }
269bd3a7633SJonathan Peyton     }
2707cc577a4SJonathan Peyton     base = (slash == NULL ? fname->dir : slash + 1);
2717cc577a4SJonathan Peyton     fname->base = __kmp_str_format("%s", base); // Copy basename
2727cc577a4SJonathan Peyton     *base = 0; // and truncate dir.
273bd3a7633SJonathan Peyton   }
2747cc577a4SJonathan Peyton 
2757cc577a4SJonathan Peyton } // kmp_str_fname_init
2767cc577a4SJonathan Peyton 
__kmp_str_fname_free(kmp_str_fname_t * fname)2773041982dSJonathan Peyton void __kmp_str_fname_free(kmp_str_fname_t *fname) {
278aeb40adaSJonas Hahnfeld   __kmp_str_free(&fname->path);
279aeb40adaSJonas Hahnfeld   __kmp_str_free(&fname->dir);
280aeb40adaSJonas Hahnfeld   __kmp_str_free(&fname->base);
2817cc577a4SJonathan Peyton } // kmp_str_fname_free
2827cc577a4SJonathan Peyton 
__kmp_str_fname_match(kmp_str_fname_t const * fname,char const * pattern)2833041982dSJonathan Peyton int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern) {
2847cc577a4SJonathan Peyton   int dir_match = 1;
2857cc577a4SJonathan Peyton   int base_match = 1;
2867cc577a4SJonathan Peyton 
2877cc577a4SJonathan Peyton   if (pattern != NULL) {
2887cc577a4SJonathan Peyton     kmp_str_fname_t ptrn;
2897cc577a4SJonathan Peyton     __kmp_str_fname_init(&ptrn, pattern);
2903041982dSJonathan Peyton     dir_match = strcmp(ptrn.dir, "*/") == 0 ||
2917cc577a4SJonathan Peyton                 (fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
2923041982dSJonathan Peyton     base_match = strcmp(ptrn.base, "*") == 0 ||
2937cc577a4SJonathan Peyton                  (fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
2947cc577a4SJonathan Peyton     __kmp_str_fname_free(&ptrn);
295bd3a7633SJonathan Peyton   }
2967cc577a4SJonathan Peyton 
2977cc577a4SJonathan Peyton   return dir_match && base_match;
2987cc577a4SJonathan Peyton } // __kmp_str_fname_match
2997cc577a4SJonathan Peyton 
30022558c85SAndreyChurbanov // Get the numeric fields from source location string.
30122558c85SAndreyChurbanov // For clang these fields are Line/Col of the start of the construct.
30222558c85SAndreyChurbanov // For icc these are LineBegin/LineEnd of the construct.
30322558c85SAndreyChurbanov // Function is fast as it does not duplicate string (which involves memory
30422558c85SAndreyChurbanov // allocation), and parses the string in place.
__kmp_str_loc_numbers(char const * Psource,int * LineBeg,int * LineEndOrCol)30522558c85SAndreyChurbanov void __kmp_str_loc_numbers(char const *Psource, int *LineBeg,
30622558c85SAndreyChurbanov                            int *LineEndOrCol) {
30722558c85SAndreyChurbanov   char *Str;
30822558c85SAndreyChurbanov   KMP_DEBUG_ASSERT(LineBeg);
30922558c85SAndreyChurbanov   KMP_DEBUG_ASSERT(LineEndOrCol);
31022558c85SAndreyChurbanov   // Parse Psource string ";file;func;line;line_end_or_column;;" to get
31122558c85SAndreyChurbanov   // numbers only, skipping string fields "file" and "func".
31222558c85SAndreyChurbanov 
31322558c85SAndreyChurbanov   // Find 1-st semicolon.
31422558c85SAndreyChurbanov   KMP_DEBUG_ASSERT(Psource);
31522558c85SAndreyChurbanov #ifdef __cplusplus
31622558c85SAndreyChurbanov   Str = strchr(CCAST(char *, Psource), ';');
31722558c85SAndreyChurbanov #else
31822558c85SAndreyChurbanov   Str = strchr(Psource, ';');
31922558c85SAndreyChurbanov #endif
32022558c85SAndreyChurbanov   // Check returned pointer to see if the format of Psource is broken.
32122558c85SAndreyChurbanov   if (Str) {
32222558c85SAndreyChurbanov     // Find 2-nd semicolon.
32322558c85SAndreyChurbanov     Str = strchr(Str + 1, ';');
32422558c85SAndreyChurbanov   }
32522558c85SAndreyChurbanov   if (Str) {
32622558c85SAndreyChurbanov     // Find 3-rd semicolon.
32722558c85SAndreyChurbanov     Str = strchr(Str + 1, ';');
32822558c85SAndreyChurbanov   }
32922558c85SAndreyChurbanov   if (Str) {
33022558c85SAndreyChurbanov     // Read begin line number.
33122558c85SAndreyChurbanov     *LineBeg = atoi(Str + 1);
33222558c85SAndreyChurbanov     // Find 4-th semicolon.
33322558c85SAndreyChurbanov     Str = strchr(Str + 1, ';');
33422558c85SAndreyChurbanov   } else {
33522558c85SAndreyChurbanov     // Broken format of input string, cannot read the number.
33622558c85SAndreyChurbanov     *LineBeg = 0;
33722558c85SAndreyChurbanov   }
33822558c85SAndreyChurbanov   if (Str) {
339fff1abc4SAndreyChurbanov     // Read end line or column number.
34022558c85SAndreyChurbanov     *LineEndOrCol = atoi(Str + 1);
34122558c85SAndreyChurbanov   } else {
34222558c85SAndreyChurbanov     // Broken format of input string, cannot read the number.
34322558c85SAndreyChurbanov     *LineEndOrCol = 0;
34422558c85SAndreyChurbanov   }
34522558c85SAndreyChurbanov }
34622558c85SAndreyChurbanov 
__kmp_str_loc_init(char const * psource,bool init_fname)34722558c85SAndreyChurbanov kmp_str_loc_t __kmp_str_loc_init(char const *psource, bool init_fname) {
3487cc577a4SJonathan Peyton   kmp_str_loc_t loc;
3497cc577a4SJonathan Peyton 
3507cc577a4SJonathan Peyton   loc._bulk = NULL;
3517cc577a4SJonathan Peyton   loc.file = NULL;
3527cc577a4SJonathan Peyton   loc.func = NULL;
3537cc577a4SJonathan Peyton   loc.line = 0;
3547cc577a4SJonathan Peyton   loc.col = 0;
3557cc577a4SJonathan Peyton 
3567cc577a4SJonathan Peyton   if (psource != NULL) {
3577cc577a4SJonathan Peyton     char *str = NULL;
3587cc577a4SJonathan Peyton     char *dummy = NULL;
3597cc577a4SJonathan Peyton     char *line = NULL;
3607cc577a4SJonathan Peyton     char *col = NULL;
3617cc577a4SJonathan Peyton 
3627cc577a4SJonathan Peyton     // Copy psource to keep it intact.
3637cc577a4SJonathan Peyton     loc._bulk = __kmp_str_format("%s", psource);
3647cc577a4SJonathan Peyton 
3657cc577a4SJonathan Peyton     // Parse psource string: ";file;func;line;col;;"
3667cc577a4SJonathan Peyton     str = loc._bulk;
3677cc577a4SJonathan Peyton     __kmp_str_split(str, ';', &dummy, &str);
3687cc577a4SJonathan Peyton     __kmp_str_split(str, ';', &loc.file, &str);
3697cc577a4SJonathan Peyton     __kmp_str_split(str, ';', &loc.func, &str);
3707cc577a4SJonathan Peyton     __kmp_str_split(str, ';', &line, &str);
3717cc577a4SJonathan Peyton     __kmp_str_split(str, ';', &col, &str);
3727cc577a4SJonathan Peyton 
3737cc577a4SJonathan Peyton     // Convert line and col into numberic values.
3747cc577a4SJonathan Peyton     if (line != NULL) {
3757cc577a4SJonathan Peyton       loc.line = atoi(line);
3767cc577a4SJonathan Peyton       if (loc.line < 0) {
3777cc577a4SJonathan Peyton         loc.line = 0;
378bd3a7633SJonathan Peyton       }
379bd3a7633SJonathan Peyton     }
3807cc577a4SJonathan Peyton     if (col != NULL) {
3817cc577a4SJonathan Peyton       loc.col = atoi(col);
3827cc577a4SJonathan Peyton       if (loc.col < 0) {
3837cc577a4SJonathan Peyton         loc.col = 0;
384bd3a7633SJonathan Peyton       }
385bd3a7633SJonathan Peyton     }
386bd3a7633SJonathan Peyton   }
3877cc577a4SJonathan Peyton 
3887cc577a4SJonathan Peyton   __kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
3897cc577a4SJonathan Peyton 
3907cc577a4SJonathan Peyton   return loc;
3917cc577a4SJonathan Peyton } // kmp_str_loc_init
3927cc577a4SJonathan Peyton 
__kmp_str_loc_free(kmp_str_loc_t * loc)3933041982dSJonathan Peyton void __kmp_str_loc_free(kmp_str_loc_t *loc) {
3947cc577a4SJonathan Peyton   __kmp_str_fname_free(&loc->fname);
395aeb40adaSJonas Hahnfeld   __kmp_str_free(&(loc->_bulk));
3967cc577a4SJonathan Peyton   loc->file = NULL;
3977cc577a4SJonathan Peyton   loc->func = NULL;
3987cc577a4SJonathan Peyton } // kmp_str_loc_free
3997cc577a4SJonathan Peyton 
4003041982dSJonathan Peyton /* This function is intended to compare file names. On Windows* OS file names
4013041982dSJonathan Peyton    are case-insensitive, so functions performs case-insensitive comparison. On
4023041982dSJonathan Peyton    Linux* OS it performs case-sensitive comparison. Note: The function returns
4033041982dSJonathan Peyton    *true* if strings are *equal*. */
__kmp_str_eqf(char const * lhs,char const * rhs)4043041982dSJonathan Peyton int __kmp_str_eqf( // True, if strings are equal, false otherwise.
4057cc577a4SJonathan Peyton     char const *lhs, // First string.
4067cc577a4SJonathan Peyton     char const *rhs // Second string.
4077cc577a4SJonathan Peyton ) {
4087cc577a4SJonathan Peyton   int result;
4097cc577a4SJonathan Peyton #if KMP_OS_WINDOWS
4107cc577a4SJonathan Peyton   result = (_stricmp(lhs, rhs) == 0);
4117cc577a4SJonathan Peyton #else
4127cc577a4SJonathan Peyton   result = (strcmp(lhs, rhs) == 0);
4137cc577a4SJonathan Peyton #endif
4147cc577a4SJonathan Peyton   return result;
4157cc577a4SJonathan Peyton } // __kmp_str_eqf
4167cc577a4SJonathan Peyton 
4173041982dSJonathan Peyton /* This function is like sprintf, but it *allocates* new buffer, which must be
4183041982dSJonathan Peyton    freed eventually by __kmp_str_free(). The function is very convenient for
4193041982dSJonathan Peyton    constructing strings, it successfully replaces strdup(), strcat(), it frees
4203041982dSJonathan Peyton    programmer from buffer allocations and helps to avoid buffer overflows.
4213041982dSJonathan Peyton    Examples:
4227cc577a4SJonathan Peyton 
4233041982dSJonathan Peyton    str = __kmp_str_format("%s", orig); //strdup() doesn't care about buffer size
4247cc577a4SJonathan Peyton    __kmp_str_free( & str );
4253041982dSJonathan Peyton    str = __kmp_str_format( "%s%s", orig1, orig2 ); // strcat(), doesn't care
4263041982dSJonathan Peyton                                                    // about buffer size.
4277cc577a4SJonathan Peyton    __kmp_str_free( & str );
4287cc577a4SJonathan Peyton    str = __kmp_str_format( "%s/%s.txt", path, file ); // constructing string.
4297cc577a4SJonathan Peyton    __kmp_str_free( & str );
4307cc577a4SJonathan Peyton 
4317cc577a4SJonathan Peyton    Performance note:
4327cc577a4SJonathan Peyton    This function allocates memory with malloc() calls, so do not call it from
4333041982dSJonathan Peyton    performance-critical code. In performance-critical code consider using
4343041982dSJonathan Peyton    kmp_str_buf_t instead, since it uses stack-allocated buffer for short
4353041982dSJonathan Peyton    strings.
4367cc577a4SJonathan Peyton 
4377cc577a4SJonathan Peyton    Why does this function use malloc()?
4383041982dSJonathan Peyton    1. __kmp_allocate() returns cache-aligned memory allocated with malloc().
4393041982dSJonathan Peyton       There are no reasons in using __kmp_allocate() for strings due to extra
4403041982dSJonathan Peyton       overhead while cache-aligned memory is not necessary.
4413041982dSJonathan Peyton    2. __kmp_thread_malloc() cannot be used because it requires pointer to thread
4423041982dSJonathan Peyton       structure. We need to perform string operations during library startup
4433041982dSJonathan Peyton       (for example, in __kmp_register_library_startup()) when no thread
4443041982dSJonathan Peyton       structures are allocated yet.
4457cc577a4SJonathan Peyton    So standard malloc() is the only available option.
4467cc577a4SJonathan Peyton */
4477cc577a4SJonathan Peyton 
__kmp_str_format(char const * format,...)4483041982dSJonathan Peyton char *__kmp_str_format( // Allocated string.
4497cc577a4SJonathan Peyton     char const *format, // Format string.
4507cc577a4SJonathan Peyton     ... // Other parameters.
4517cc577a4SJonathan Peyton ) {
4527cc577a4SJonathan Peyton   va_list args;
4537cc577a4SJonathan Peyton   int size = 512;
4547cc577a4SJonathan Peyton   char *buffer = NULL;
4557cc577a4SJonathan Peyton   int rc;
4567cc577a4SJonathan Peyton 
4577cc577a4SJonathan Peyton   // Allocate buffer.
4587cc577a4SJonathan Peyton   buffer = (char *)KMP_INTERNAL_MALLOC(size);
4597cc577a4SJonathan Peyton   if (buffer == NULL) {
4607cc577a4SJonathan Peyton     KMP_FATAL(MemoryAllocFailed);
461bd3a7633SJonathan Peyton   }
4627cc577a4SJonathan Peyton 
4637cc577a4SJonathan Peyton   for (;;) {
4647cc577a4SJonathan Peyton     // Try to format string.
4657cc577a4SJonathan Peyton     va_start(args, format);
4667cc577a4SJonathan Peyton     rc = KMP_VSNPRINTF(buffer, size, format, args);
4677cc577a4SJonathan Peyton     va_end(args);
4687cc577a4SJonathan Peyton 
4697cc577a4SJonathan Peyton     // No errors, string has been formatted.
4707cc577a4SJonathan Peyton     if (rc >= 0 && rc < size) {
4717cc577a4SJonathan Peyton       break;
472bd3a7633SJonathan Peyton     }
4737cc577a4SJonathan Peyton 
4747cc577a4SJonathan Peyton     // Error occurred, buffer is too small.
4757cc577a4SJonathan Peyton     if (rc >= 0) {
4763041982dSJonathan Peyton       // C99-conforming implementation of vsnprintf returns required buffer
4773041982dSJonathan Peyton       // size.
4787cc577a4SJonathan Peyton       size = rc + 1;
4797cc577a4SJonathan Peyton     } else {
4807cc577a4SJonathan Peyton       // Older implementations just return -1.
4817cc577a4SJonathan Peyton       size = size * 2;
482bd3a7633SJonathan Peyton     }
4837cc577a4SJonathan Peyton 
4847cc577a4SJonathan Peyton     // Enlarge buffer and try again.
4857cc577a4SJonathan Peyton     buffer = (char *)KMP_INTERNAL_REALLOC(buffer, size);
4867cc577a4SJonathan Peyton     if (buffer == NULL) {
4877cc577a4SJonathan Peyton       KMP_FATAL(MemoryAllocFailed);
488bd3a7633SJonathan Peyton     }
489bd3a7633SJonathan Peyton   }
4907cc577a4SJonathan Peyton 
4917cc577a4SJonathan Peyton   return buffer;
4927cc577a4SJonathan Peyton } // func __kmp_str_format
4937cc577a4SJonathan Peyton 
__kmp_str_free(char ** str)494aeb40adaSJonas Hahnfeld void __kmp_str_free(char **str) {
4957cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(str != NULL);
496aeb40adaSJonas Hahnfeld   KMP_INTERNAL_FREE(*str);
4977cc577a4SJonathan Peyton   *str = NULL;
4987cc577a4SJonathan Peyton } // func __kmp_str_free
4997cc577a4SJonathan Peyton 
5003041982dSJonathan Peyton /* If len is zero, returns true iff target and data have exact case-insensitive
5013041982dSJonathan Peyton    match. If len is negative, returns true iff target is a case-insensitive
5023041982dSJonathan Peyton    substring of data. If len is positive, returns true iff target is a
5033041982dSJonathan Peyton    case-insensitive substring of data or vice versa, and neither is shorter than
5043041982dSJonathan Peyton    len. */
__kmp_str_match(char const * target,int len,char const * data)5053041982dSJonathan Peyton int __kmp_str_match(char const *target, int len, char const *data) {
5067cc577a4SJonathan Peyton   int i;
5077cc577a4SJonathan Peyton   if (target == NULL || data == NULL) {
5087cc577a4SJonathan Peyton     return FALSE;
509bd3a7633SJonathan Peyton   }
5107cc577a4SJonathan Peyton   for (i = 0; target[i] && data[i]; ++i) {
5117cc577a4SJonathan Peyton     if (TOLOWER(target[i]) != TOLOWER(data[i])) {
5127cc577a4SJonathan Peyton       return FALSE;
513bd3a7633SJonathan Peyton     }
514bd3a7633SJonathan Peyton   }
5157cc577a4SJonathan Peyton   return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
5167cc577a4SJonathan Peyton } // __kmp_str_match
5177cc577a4SJonathan Peyton 
518*d8e4cb91STerry Wilmarth // If data contains all of target, returns true, otherwise returns false.
519*d8e4cb91STerry Wilmarth // len should be the length of target
__kmp_str_contains(char const * target,int len,char const * data)520*d8e4cb91STerry Wilmarth bool __kmp_str_contains(char const *target, int len, char const *data) {
521*d8e4cb91STerry Wilmarth   int i = 0, j = 0, start = 0;
522*d8e4cb91STerry Wilmarth   if (target == NULL || data == NULL) {
523*d8e4cb91STerry Wilmarth     return FALSE;
524*d8e4cb91STerry Wilmarth   }
525*d8e4cb91STerry Wilmarth   while (target[i]) {
526*d8e4cb91STerry Wilmarth     if (!data[j])
527*d8e4cb91STerry Wilmarth       return FALSE;
528*d8e4cb91STerry Wilmarth     if (TOLOWER(target[i]) != TOLOWER(data[j])) {
529*d8e4cb91STerry Wilmarth       j = start + 1;
530*d8e4cb91STerry Wilmarth       start = j;
531*d8e4cb91STerry Wilmarth       i = 0;
532*d8e4cb91STerry Wilmarth     } else {
533*d8e4cb91STerry Wilmarth       if (i == 0)
534*d8e4cb91STerry Wilmarth         start = j;
535*d8e4cb91STerry Wilmarth       j++;
536*d8e4cb91STerry Wilmarth       i++;
537*d8e4cb91STerry Wilmarth     }
538*d8e4cb91STerry Wilmarth   }
539*d8e4cb91STerry Wilmarth 
540*d8e4cb91STerry Wilmarth   return i == len;
541*d8e4cb91STerry Wilmarth } // __kmp_str_contains
542*d8e4cb91STerry Wilmarth 
__kmp_str_match_false(char const * data)5433041982dSJonathan Peyton int __kmp_str_match_false(char const *data) {
5447cc577a4SJonathan Peyton   int result =
5453041982dSJonathan Peyton       __kmp_str_match("false", 1, data) || __kmp_str_match("off", 2, data) ||
5463041982dSJonathan Peyton       __kmp_str_match("0", 1, data) || __kmp_str_match(".false.", 2, data) ||
54760eec6feSJonathan Peyton       __kmp_str_match(".f.", 2, data) || __kmp_str_match("no", 1, data) ||
54860eec6feSJonathan Peyton       __kmp_str_match("disabled", 0, data);
5497cc577a4SJonathan Peyton   return result;
5507cc577a4SJonathan Peyton } // __kmp_str_match_false
5517cc577a4SJonathan Peyton 
__kmp_str_match_true(char const * data)5523041982dSJonathan Peyton int __kmp_str_match_true(char const *data) {
5537cc577a4SJonathan Peyton   int result =
5543041982dSJonathan Peyton       __kmp_str_match("true", 1, data) || __kmp_str_match("on", 2, data) ||
5553041982dSJonathan Peyton       __kmp_str_match("1", 1, data) || __kmp_str_match(".true.", 2, data) ||
55660eec6feSJonathan Peyton       __kmp_str_match(".t.", 2, data) || __kmp_str_match("yes", 1, data) ||
55760eec6feSJonathan Peyton       __kmp_str_match("enabled", 0, data);
5587cc577a4SJonathan Peyton   return result;
5597cc577a4SJonathan Peyton } // __kmp_str_match_true
5607cc577a4SJonathan Peyton 
__kmp_str_replace(char * str,char search_for,char replace_with)5613041982dSJonathan Peyton void __kmp_str_replace(char *str, char search_for, char replace_with) {
5627cc577a4SJonathan Peyton   char *found = NULL;
5637cc577a4SJonathan Peyton 
5647cc577a4SJonathan Peyton   found = strchr(str, search_for);
5657cc577a4SJonathan Peyton   while (found) {
5667cc577a4SJonathan Peyton     *found = replace_with;
5677cc577a4SJonathan Peyton     found = strchr(found + 1, search_for);
568bd3a7633SJonathan Peyton   }
5697cc577a4SJonathan Peyton } // __kmp_str_replace
5707cc577a4SJonathan Peyton 
__kmp_str_split(char * str,char delim,char ** head,char ** tail)5713041982dSJonathan Peyton void __kmp_str_split(char *str, // I: String to split.
5727cc577a4SJonathan Peyton                      char delim, // I: Character to split on.
5737cc577a4SJonathan Peyton                      char **head, // O: Pointer to head (may be NULL).
5747cc577a4SJonathan Peyton                      char **tail // O: Pointer to tail (may be NULL).
5757cc577a4SJonathan Peyton ) {
5767cc577a4SJonathan Peyton   char *h = str;
5777cc577a4SJonathan Peyton   char *t = NULL;
5787cc577a4SJonathan Peyton   if (str != NULL) {
5797cc577a4SJonathan Peyton     char *ptr = strchr(str, delim);
5807cc577a4SJonathan Peyton     if (ptr != NULL) {
5817cc577a4SJonathan Peyton       *ptr = 0;
5827cc577a4SJonathan Peyton       t = ptr + 1;
583bd3a7633SJonathan Peyton     }
584bd3a7633SJonathan Peyton   }
5857cc577a4SJonathan Peyton   if (head != NULL) {
5867cc577a4SJonathan Peyton     *head = h;
587bd3a7633SJonathan Peyton   }
5887cc577a4SJonathan Peyton   if (tail != NULL) {
5897cc577a4SJonathan Peyton     *tail = t;
590bd3a7633SJonathan Peyton   }
5917cc577a4SJonathan Peyton } // __kmp_str_split
5927cc577a4SJonathan Peyton 
5933041982dSJonathan Peyton /* strtok_r() is not available on Windows* OS. This function reimplements
5943041982dSJonathan Peyton    strtok_r(). */
__kmp_str_token(char * str,char const * delim,char ** buf)5953041982dSJonathan Peyton char *__kmp_str_token(
5967cc577a4SJonathan Peyton     char *str, // String to split into tokens. Note: String *is* modified!
5977cc577a4SJonathan Peyton     char const *delim, // Delimiters.
5987cc577a4SJonathan Peyton     char **buf // Internal buffer.
5997cc577a4SJonathan Peyton ) {
6007cc577a4SJonathan Peyton   char *token = NULL;
6017cc577a4SJonathan Peyton #if KMP_OS_WINDOWS
6027cc577a4SJonathan Peyton   // On Windows* OS there is no strtok_r() function. Let us implement it.
6037cc577a4SJonathan Peyton   if (str != NULL) {
6047cc577a4SJonathan Peyton     *buf = str; // First call, initialize buf.
605bd3a7633SJonathan Peyton   }
6067cc577a4SJonathan Peyton   *buf += strspn(*buf, delim); // Skip leading delimiters.
6077cc577a4SJonathan Peyton   if (**buf != 0) { // Rest of the string is not yet empty.
6087cc577a4SJonathan Peyton     token = *buf; // Use it as result.
6097cc577a4SJonathan Peyton     *buf += strcspn(*buf, delim); // Skip non-delimiters.
6107cc577a4SJonathan Peyton     if (**buf != 0) { // Rest of the string is not yet empty.
6117cc577a4SJonathan Peyton       **buf = 0; // Terminate token here.
6127cc577a4SJonathan Peyton       *buf += 1; // Advance buf to start with the next token next time.
613bd3a7633SJonathan Peyton     }
614bd3a7633SJonathan Peyton   }
6157cc577a4SJonathan Peyton #else
6167cc577a4SJonathan Peyton   // On Linux* OS and OS X*, strtok_r() is available. Let us use it.
6177cc577a4SJonathan Peyton   token = strtok_r(str, delim, buf);
6187cc577a4SJonathan Peyton #endif
6197cc577a4SJonathan Peyton   return token;
620bd3a7633SJonathan Peyton } // __kmp_str_token
6217cc577a4SJonathan Peyton 
__kmp_str_to_int(char const * str,char sentinel)6223041982dSJonathan Peyton int __kmp_str_to_int(char const *str, char sentinel) {
6237cc577a4SJonathan Peyton   int result, factor;
6247cc577a4SJonathan Peyton   char const *t;
6257cc577a4SJonathan Peyton 
6267cc577a4SJonathan Peyton   result = 0;
6277cc577a4SJonathan Peyton 
6287cc577a4SJonathan Peyton   for (t = str; *t != '\0'; ++t) {
6297cc577a4SJonathan Peyton     if (*t < '0' || *t > '9')
6307cc577a4SJonathan Peyton       break;
6317cc577a4SJonathan Peyton     result = (result * 10) + (*t - '0');
6327cc577a4SJonathan Peyton   }
6337cc577a4SJonathan Peyton 
6347cc577a4SJonathan Peyton   switch (*t) {
6357cc577a4SJonathan Peyton   case '\0': /* the current default for no suffix is bytes */
6367cc577a4SJonathan Peyton     factor = 1;
6377cc577a4SJonathan Peyton     break;
6383041982dSJonathan Peyton   case 'b':
6393041982dSJonathan Peyton   case 'B': /* bytes */
6407cc577a4SJonathan Peyton     ++t;
6417cc577a4SJonathan Peyton     factor = 1;
6427cc577a4SJonathan Peyton     break;
6433041982dSJonathan Peyton   case 'k':
6443041982dSJonathan Peyton   case 'K': /* kilo-bytes */
6457cc577a4SJonathan Peyton     ++t;
6467cc577a4SJonathan Peyton     factor = 1024;
6477cc577a4SJonathan Peyton     break;
6483041982dSJonathan Peyton   case 'm':
6493041982dSJonathan Peyton   case 'M': /* mega-bytes */
6507cc577a4SJonathan Peyton     ++t;
6517cc577a4SJonathan Peyton     factor = (1024 * 1024);
6527cc577a4SJonathan Peyton     break;
6537cc577a4SJonathan Peyton   default:
6547cc577a4SJonathan Peyton     if (*t != sentinel)
6557cc577a4SJonathan Peyton       return (-1);
6567cc577a4SJonathan Peyton     t = "";
6577cc577a4SJonathan Peyton     factor = 1;
6587cc577a4SJonathan Peyton   }
6597cc577a4SJonathan Peyton 
6607cc577a4SJonathan Peyton   if (result > (INT_MAX / factor))
6617cc577a4SJonathan Peyton     result = INT_MAX;
6627cc577a4SJonathan Peyton   else
6637cc577a4SJonathan Peyton     result *= factor;
6647cc577a4SJonathan Peyton 
6657cc577a4SJonathan Peyton   return (*t != 0 ? 0 : result);
6667cc577a4SJonathan Peyton } // __kmp_str_to_int
6677cc577a4SJonathan Peyton 
6683041982dSJonathan Peyton /* The routine parses input string. It is expected it is a unsigned integer with
6693041982dSJonathan Peyton    optional unit. Units are: "b" for bytes, "kb" or just "k" for kilobytes, "mb"
6703041982dSJonathan Peyton    or "m" for megabytes, ..., "yb" or "y" for yottabytes. :-) Unit name is
6713041982dSJonathan Peyton    case-insensitive. The routine returns 0 if everything is ok, or error code:
6723041982dSJonathan Peyton    -1 in case of overflow, -2 in case of unknown unit. *size is set to parsed
6733041982dSJonathan Peyton    value. In case of overflow *size is set to KMP_SIZE_T_MAX, in case of unknown
6743041982dSJonathan Peyton    unit *size is set to zero. */
__kmp_str_to_size(char const * str,size_t * out,size_t dfactor,char const ** error)6753041982dSJonathan Peyton void __kmp_str_to_size( // R: Error code.
6763041982dSJonathan Peyton     char const *str, // I: String of characters, unsigned number and unit ("b",
6773041982dSJonathan Peyton     // "kb", etc).
6787cc577a4SJonathan Peyton     size_t *out, // O: Parsed number.
6797cc577a4SJonathan Peyton     size_t dfactor, // I: The factor if none of the letters specified.
6807cc577a4SJonathan Peyton     char const **error // O: Null if everything is ok, error message otherwise.
6817cc577a4SJonathan Peyton ) {
6827cc577a4SJonathan Peyton 
6837cc577a4SJonathan Peyton   size_t value = 0;
6847cc577a4SJonathan Peyton   size_t factor = 0;
6857cc577a4SJonathan Peyton   int overflow = 0;
6867cc577a4SJonathan Peyton   int i = 0;
6877cc577a4SJonathan Peyton   int digit;
6887cc577a4SJonathan Peyton 
6897cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(str != NULL);
6907cc577a4SJonathan Peyton 
6917cc577a4SJonathan Peyton   // Skip spaces.
6927cc577a4SJonathan Peyton   while (str[i] == ' ' || str[i] == '\t') {
6937cc577a4SJonathan Peyton     ++i;
694bd3a7633SJonathan Peyton   }
6957cc577a4SJonathan Peyton 
6967cc577a4SJonathan Peyton   // Parse number.
6977cc577a4SJonathan Peyton   if (str[i] < '0' || str[i] > '9') {
6987cc577a4SJonathan Peyton     *error = KMP_I18N_STR(NotANumber);
6997cc577a4SJonathan Peyton     return;
700bd3a7633SJonathan Peyton   }
7017cc577a4SJonathan Peyton   do {
7027cc577a4SJonathan Peyton     digit = str[i] - '0';
7037cc577a4SJonathan Peyton     overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
7047cc577a4SJonathan Peyton     value = (value * 10) + digit;
7057cc577a4SJonathan Peyton     ++i;
7067cc577a4SJonathan Peyton   } while (str[i] >= '0' && str[i] <= '9');
7077cc577a4SJonathan Peyton 
7087cc577a4SJonathan Peyton   // Skip spaces.
7097cc577a4SJonathan Peyton   while (str[i] == ' ' || str[i] == '\t') {
7107cc577a4SJonathan Peyton     ++i;
711bd3a7633SJonathan Peyton   }
7127cc577a4SJonathan Peyton 
7137cc577a4SJonathan Peyton // Parse unit.
7147cc577a4SJonathan Peyton #define _case(ch, exp)                                                         \
7157cc577a4SJonathan Peyton   case ch:                                                                     \
7167cc577a4SJonathan Peyton   case ch - ('a' - 'A'): {                                                     \
7177cc577a4SJonathan Peyton     size_t shift = (exp)*10;                                                   \
7187cc577a4SJonathan Peyton     ++i;                                                                       \
7197cc577a4SJonathan Peyton     if (shift < sizeof(size_t) * 8) {                                          \
7207cc577a4SJonathan Peyton       factor = (size_t)(1) << shift;                                           \
7217cc577a4SJonathan Peyton     } else {                                                                   \
7227cc577a4SJonathan Peyton       overflow = 1;                                                            \
723bd3a7633SJonathan Peyton     }                                                                          \
7247cc577a4SJonathan Peyton   } break;
7257cc577a4SJonathan Peyton   switch (str[i]) {
7267cc577a4SJonathan Peyton     _case('k', 1); // Kilo
7277cc577a4SJonathan Peyton     _case('m', 2); // Mega
7287cc577a4SJonathan Peyton     _case('g', 3); // Giga
7297cc577a4SJonathan Peyton     _case('t', 4); // Tera
7307cc577a4SJonathan Peyton     _case('p', 5); // Peta
7317cc577a4SJonathan Peyton     _case('e', 6); // Exa
7327cc577a4SJonathan Peyton     _case('z', 7); // Zetta
7337cc577a4SJonathan Peyton     _case('y', 8); // Yotta
7347cc577a4SJonathan Peyton     // Oops. No more units...
735bd3a7633SJonathan Peyton   }
7367cc577a4SJonathan Peyton #undef _case
7377cc577a4SJonathan Peyton   if (str[i] == 'b' || str[i] == 'B') { // Skip optional "b".
7387cc577a4SJonathan Peyton     if (factor == 0) {
7397cc577a4SJonathan Peyton       factor = 1;
7407cc577a4SJonathan Peyton     }
7417cc577a4SJonathan Peyton     ++i;
742bd3a7633SJonathan Peyton   }
7437cc577a4SJonathan Peyton   if (!(str[i] == ' ' || str[i] == '\t' || str[i] == 0)) { // Bad unit
7447cc577a4SJonathan Peyton     *error = KMP_I18N_STR(BadUnit);
7457cc577a4SJonathan Peyton     return;
746bd3a7633SJonathan Peyton   }
7477cc577a4SJonathan Peyton 
7487cc577a4SJonathan Peyton   if (factor == 0) {
7497cc577a4SJonathan Peyton     factor = dfactor;
7507cc577a4SJonathan Peyton   }
7517cc577a4SJonathan Peyton 
7527cc577a4SJonathan Peyton   // Apply factor.
7537cc577a4SJonathan Peyton   overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
7547cc577a4SJonathan Peyton   value *= factor;
7557cc577a4SJonathan Peyton 
7567cc577a4SJonathan Peyton   // Skip spaces.
7577cc577a4SJonathan Peyton   while (str[i] == ' ' || str[i] == '\t') {
7587cc577a4SJonathan Peyton     ++i;
759bd3a7633SJonathan Peyton   }
7607cc577a4SJonathan Peyton 
7617cc577a4SJonathan Peyton   if (str[i] != 0) {
7627cc577a4SJonathan Peyton     *error = KMP_I18N_STR(IllegalCharacters);
7637cc577a4SJonathan Peyton     return;
764bd3a7633SJonathan Peyton   }
7657cc577a4SJonathan Peyton 
7667cc577a4SJonathan Peyton   if (overflow) {
7677cc577a4SJonathan Peyton     *error = KMP_I18N_STR(ValueTooLarge);
7687cc577a4SJonathan Peyton     *out = KMP_SIZE_T_MAX;
7697cc577a4SJonathan Peyton     return;
770bd3a7633SJonathan Peyton   }
7717cc577a4SJonathan Peyton 
7727cc577a4SJonathan Peyton   *error = NULL;
7737cc577a4SJonathan Peyton   *out = value;
7747cc577a4SJonathan Peyton } // __kmp_str_to_size
7757cc577a4SJonathan Peyton 
__kmp_str_to_uint(char const * str,kmp_uint64 * out,char const ** error)7763041982dSJonathan Peyton void __kmp_str_to_uint( // R: Error code.
7777cc577a4SJonathan Peyton     char const *str, // I: String of characters, unsigned number.
7787cc577a4SJonathan Peyton     kmp_uint64 *out, // O: Parsed number.
7797cc577a4SJonathan Peyton     char const **error // O: Null if everything is ok, error message otherwise.
7807cc577a4SJonathan Peyton ) {
7817cc577a4SJonathan Peyton   size_t value = 0;
7827cc577a4SJonathan Peyton   int overflow = 0;
7837cc577a4SJonathan Peyton   int i = 0;
7847cc577a4SJonathan Peyton   int digit;
7857cc577a4SJonathan Peyton 
7867cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(str != NULL);
7877cc577a4SJonathan Peyton 
7887cc577a4SJonathan Peyton   // Skip spaces.
7897cc577a4SJonathan Peyton   while (str[i] == ' ' || str[i] == '\t') {
7907cc577a4SJonathan Peyton     ++i;
791bd3a7633SJonathan Peyton   }
7927cc577a4SJonathan Peyton 
7937cc577a4SJonathan Peyton   // Parse number.
7947cc577a4SJonathan Peyton   if (str[i] < '0' || str[i] > '9') {
7957cc577a4SJonathan Peyton     *error = KMP_I18N_STR(NotANumber);
7967cc577a4SJonathan Peyton     return;
797bd3a7633SJonathan Peyton   }
7987cc577a4SJonathan Peyton   do {
7997cc577a4SJonathan Peyton     digit = str[i] - '0';
8007cc577a4SJonathan Peyton     overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
8017cc577a4SJonathan Peyton     value = (value * 10) + digit;
8027cc577a4SJonathan Peyton     ++i;
8037cc577a4SJonathan Peyton   } while (str[i] >= '0' && str[i] <= '9');
8047cc577a4SJonathan Peyton 
8057cc577a4SJonathan Peyton   // Skip spaces.
8067cc577a4SJonathan Peyton   while (str[i] == ' ' || str[i] == '\t') {
8077cc577a4SJonathan Peyton     ++i;
808bd3a7633SJonathan Peyton   }
8097cc577a4SJonathan Peyton 
8107cc577a4SJonathan Peyton   if (str[i] != 0) {
8117cc577a4SJonathan Peyton     *error = KMP_I18N_STR(IllegalCharacters);
8127cc577a4SJonathan Peyton     return;
813bd3a7633SJonathan Peyton   }
8147cc577a4SJonathan Peyton 
8157cc577a4SJonathan Peyton   if (overflow) {
8167cc577a4SJonathan Peyton     *error = KMP_I18N_STR(ValueTooLarge);
8177cc577a4SJonathan Peyton     *out = (kmp_uint64)-1;
8187cc577a4SJonathan Peyton     return;
819bd3a7633SJonathan Peyton   }
8207cc577a4SJonathan Peyton 
8217cc577a4SJonathan Peyton   *error = NULL;
8227cc577a4SJonathan Peyton   *out = value;
8237cc577a4SJonathan Peyton } // __kmp_str_to_unit
8247cc577a4SJonathan Peyton 
8257cc577a4SJonathan Peyton // end of file //
826