00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "kmp_str.h"
00048
00049 #include <stdarg.h>
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052
00053 #include "kmp.h"
00054 #include "kmp_i18n.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #define KMP_STR_BUF_INVARIANT( b ) \
00102 { \
00103 KMP_DEBUG_ASSERT( (b)->str != NULL ); \
00104 KMP_DEBUG_ASSERT( (b)->size >= sizeof( (b)->bulk ) ); \
00105 KMP_DEBUG_ASSERT( (b)->size % sizeof( (b)->bulk ) == 0 ); \
00106 KMP_DEBUG_ASSERT( (b)->used < (b)->size ); \
00107 KMP_DEBUG_ASSERT( (b)->size == sizeof( (b)->bulk ) ? (b)->str == & (b)->bulk[ 0 ] : 1 ); \
00108 KMP_DEBUG_ASSERT( (b)->size > sizeof( (b)->bulk ) ? (b)->str != & (b)->bulk[ 0 ] : 1 ); \
00109 }
00110
00111 void
00112 __kmp_str_buf_clear(
00113 kmp_str_buf_t * buffer
00114 ) {
00115 KMP_STR_BUF_INVARIANT( buffer );
00116 if ( buffer->used > 0 ) {
00117 buffer->used = 0;
00118 buffer->str[ 0 ] = 0;
00119 };
00120 KMP_STR_BUF_INVARIANT( buffer );
00121 }
00122
00123
00124 void
00125 __kmp_str_buf_reserve(
00126 kmp_str_buf_t * buffer,
00127 int size
00128 ) {
00129
00130 KMP_STR_BUF_INVARIANT( buffer );
00131 KMP_DEBUG_ASSERT( size >= 0 );
00132
00133 if ( buffer->size < size ) {
00134
00135
00136 do {
00137 buffer->size *= 2;
00138 } while ( buffer->size < size );
00139
00140
00141 if ( buffer->str == & buffer->bulk[ 0 ] ) {
00142 buffer->str = (char *) KMP_INTERNAL_MALLOC( buffer->size );
00143 if ( buffer->str == NULL ) {
00144 KMP_FATAL( MemoryAllocFailed );
00145 };
00146 memcpy( buffer->str, buffer->bulk, buffer->used + 1 );
00147 } else {
00148 buffer->str = (char *) KMP_INTERNAL_REALLOC( buffer->str, buffer->size );
00149 if ( buffer->str == NULL ) {
00150 KMP_FATAL( MemoryAllocFailed );
00151 };
00152 };
00153
00154 };
00155
00156 KMP_DEBUG_ASSERT( buffer->size > 0 );
00157 KMP_DEBUG_ASSERT( buffer->size >= size );
00158 KMP_STR_BUF_INVARIANT( buffer );
00159
00160 }
00161
00162
00163 void
00164 __kmp_str_buf_detach(
00165 kmp_str_buf_t * buffer
00166 ) {
00167
00168 KMP_STR_BUF_INVARIANT( buffer );
00169
00170
00171 if ( buffer->size <= sizeof( buffer->bulk ) ) {
00172 buffer->str = (char *) KMP_INTERNAL_MALLOC( buffer->size );
00173 if ( buffer->str == NULL ) {
00174 KMP_FATAL( MemoryAllocFailed );
00175 };
00176 memcpy( buffer->str, buffer->bulk, buffer->used + 1 );
00177 };
00178
00179 }
00180
00181
00182 void
00183 __kmp_str_buf_free(
00184 kmp_str_buf_t * buffer
00185 ) {
00186 KMP_STR_BUF_INVARIANT( buffer );
00187 if ( buffer->size > sizeof( buffer->bulk ) ) {
00188 KMP_INTERNAL_FREE( buffer->str );
00189 };
00190 buffer->str = buffer->bulk;
00191 buffer->size = sizeof( buffer->bulk );
00192 buffer->used = 0;
00193 KMP_STR_BUF_INVARIANT( buffer );
00194 }
00195
00196
00197 void
00198 __kmp_str_buf_cat(
00199 kmp_str_buf_t * buffer,
00200 char const * str,
00201 int len
00202 ) {
00203 KMP_STR_BUF_INVARIANT( buffer );
00204 KMP_DEBUG_ASSERT( str != NULL );
00205 KMP_DEBUG_ASSERT( len >= 0 );
00206 __kmp_str_buf_reserve( buffer, buffer->used + len + 1 );
00207 memcpy( buffer->str + buffer->used, str, len );
00208 buffer->str[ buffer->used + len ] = 0;
00209 buffer->used += len;
00210 KMP_STR_BUF_INVARIANT( buffer );
00211 }
00212
00213
00214 void
00215 __kmp_str_buf_vprint(
00216 kmp_str_buf_t * buffer,
00217 char const * format,
00218 va_list args
00219 ) {
00220
00221 KMP_STR_BUF_INVARIANT( buffer );
00222
00223 for ( ; ; ) {
00224
00225 int const free = buffer->size - buffer->used;
00226 int rc;
00227 int size;
00228
00229
00230 {
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 #if ! KMP_OS_WINDOWS
00241 va_list _args;
00242 __va_copy( _args, args );
00243 #define args _args // Substitute args with its copy, _args.
00244 #endif // KMP_OS_WINDOWS
00245 rc = vsnprintf( buffer->str + buffer->used, free, format, args );
00246 #if ! KMP_OS_WINDOWS
00247 #undef args // Remove substitution.
00248 va_end( _args );
00249 #endif // KMP_OS_WINDOWS
00250 }
00251
00252
00253 if ( rc >= 0 && rc < free ) {
00254 buffer->used += rc;
00255 break;
00256 };
00257
00258
00259 if ( rc >= 0 ) {
00260
00261 size = buffer->used + rc + 1;
00262 } else {
00263
00264 size = buffer->size * 2;
00265 };
00266
00267
00268 __kmp_str_buf_reserve( buffer, size );
00269
00270
00271
00272 };
00273
00274 KMP_DEBUG_ASSERT( buffer->size > 0 );
00275 KMP_STR_BUF_INVARIANT( buffer );
00276
00277 }
00278
00279
00280 void
00281 __kmp_str_buf_print(
00282 kmp_str_buf_t * buffer,
00283 char const * format,
00284 ...
00285 ) {
00286
00287 va_list args;
00288 va_start( args, format );
00289 __kmp_str_buf_vprint( buffer, format, args );
00290 va_end( args );
00291
00292 }
00293
00294
00295
00296
00297
00298
00299
00300 void
00301 __kmp_str_buf_print_size(
00302 kmp_str_buf_t * buf,
00303 size_t size
00304 ) {
00305
00306 char const * names[] = { "", "k", "M", "G", "T", "P", "E", "Z", "Y" };
00307 int const units = sizeof( names ) / sizeof( char const * );
00308 int u = 0;
00309 int rc;
00310 if ( size > 0 ) {
00311 while ( ( size % 1024 == 0 ) && ( u + 1 < units ) ) {
00312 size = size / 1024;
00313 ++ u;
00314 };
00315 };
00316
00317 __kmp_str_buf_print( buf, "%" KMP_SIZE_T_SPEC "%s", size, names[ u ] );
00318
00319 }
00320
00321
00322 void
00323 __kmp_str_fname_init(
00324 kmp_str_fname_t * fname,
00325 char const * path
00326 ) {
00327
00328 fname->path = NULL;
00329 fname->dir = NULL;
00330 fname->base = NULL;
00331
00332 if ( path != NULL ) {
00333 char * slash = NULL;
00334 char * base = NULL;
00335 fname->path = __kmp_str_format( "%s", path );
00336
00337
00338 if ( KMP_OS_WINDOWS ) {
00339 __kmp_str_replace( fname->path, '\\', '/' );
00340 };
00341 fname->dir = __kmp_str_format( "%s", fname->path );
00342 slash = strrchr( fname->dir, '/' );
00343 if ( KMP_OS_WINDOWS && slash == NULL ) {
00344 char first = TOLOWER( fname->dir[ 0 ] );
00345 if ( 'a' <= first && first <= 'z' && fname->dir[ 1 ] == ':' ) {
00346 slash = & fname->dir[ 1 ];
00347 };
00348 };
00349 base = ( slash == NULL ? fname->dir : slash + 1 );
00350 fname->base = __kmp_str_format( "%s", base );
00351 * base = 0;
00352 };
00353
00354 }
00355
00356
00357 void
00358 __kmp_str_fname_free(
00359 kmp_str_fname_t * fname
00360 ) {
00361 __kmp_str_free( const_cast< char const ** >( & fname->path ) );
00362 __kmp_str_free( const_cast< char const ** >( & fname->dir ) );
00363 __kmp_str_free( const_cast< char const ** >( & fname->base ) );
00364 }
00365
00366
00367 int
00368 __kmp_str_fname_match(
00369 kmp_str_fname_t const * fname,
00370 char const * pattern
00371 ) {
00372
00373 int dir_match = 1;
00374 int base_match = 1;
00375
00376 if ( pattern != NULL ) {
00377 kmp_str_fname_t ptrn;
00378 __kmp_str_fname_init( & ptrn, pattern );
00379 dir_match =
00380 strcmp( ptrn.dir, "*/" ) == 0
00381 ||
00382 ( fname->dir != NULL && __kmp_str_eqf( fname->dir, ptrn.dir ) );
00383 base_match =
00384 strcmp( ptrn.base, "*" ) == 0
00385 ||
00386 ( fname->base != NULL && __kmp_str_eqf( fname->base, ptrn.base ) );
00387 __kmp_str_fname_free( & ptrn );
00388 };
00389
00390 return dir_match && base_match;
00391
00392 }
00393
00394
00395 kmp_str_loc_t
00396 __kmp_str_loc_init(
00397 char const * psource,
00398 int init_fname
00399 ) {
00400
00401 kmp_str_loc_t loc;
00402
00403 loc._bulk = NULL;
00404 loc.file = NULL;
00405 loc.func = NULL;
00406 loc.line = 0;
00407 loc.col = 0;
00408
00409 if ( psource != NULL ) {
00410
00411 char * str = NULL;
00412 char * dummy = NULL;
00413 char * line = NULL;
00414 char * col = NULL;
00415
00416
00417 loc._bulk = __kmp_str_format( "%s", psource );
00418
00419
00420 str = loc._bulk;
00421 __kmp_str_split( str, ';', & dummy, & str );
00422 __kmp_str_split( str, ';', & loc.file, & str );
00423 __kmp_str_split( str, ';', & loc.func, & str );
00424 __kmp_str_split( str, ';', & line, & str );
00425 __kmp_str_split( str, ';', & col, & str );
00426
00427
00428 if ( line != NULL ) {
00429 loc.line = atoi( line );
00430 if ( loc.line < 0 ) {
00431 loc.line = 0;
00432 };
00433 };
00434 if ( col != NULL ) {
00435 loc.col = atoi( col );
00436 if ( loc.col < 0 ) {
00437 loc.col = 0;
00438 };
00439 };
00440
00441 };
00442
00443 __kmp_str_fname_init( & loc.fname, init_fname ? loc.file : NULL );
00444
00445 return loc;
00446
00447 }
00448
00449
00450 void
00451 __kmp_str_loc_free(
00452 kmp_str_loc_t * loc
00453 ) {
00454 __kmp_str_fname_free( & loc->fname );
00455 KMP_INTERNAL_FREE( loc->_bulk );
00456 loc->_bulk = NULL;
00457 loc->file = NULL;
00458 loc->func = NULL;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 int
00471 __kmp_str_eqf(
00472 char const * lhs,
00473 char const * rhs
00474 ) {
00475 int result;
00476 #if KMP_OS_WINDOWS
00477 result = ( _stricmp( lhs, rhs ) == 0 );
00478 #else
00479 result = ( strcmp( lhs, rhs ) == 0 );
00480 #endif
00481 return result;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 char *
00516 __kmp_str_format(
00517 char const * format,
00518 ...
00519 ) {
00520
00521 va_list args;
00522 int size = 512;
00523 char * buffer = NULL;
00524 int rc;
00525
00526
00527 buffer = (char *) KMP_INTERNAL_MALLOC( size );
00528 if ( buffer == NULL ) {
00529 KMP_FATAL( MemoryAllocFailed );
00530 };
00531
00532 for ( ; ; ) {
00533
00534
00535 va_start( args, format );
00536 rc = vsnprintf( buffer, size, format, args );
00537 va_end( args );
00538
00539
00540 if ( rc >= 0 && rc < size ) {
00541 break;
00542 };
00543
00544
00545 if ( rc >= 0 ) {
00546
00547 size = rc + 1;
00548 } else {
00549
00550 size = size * 2;
00551 };
00552
00553
00554 buffer = (char *) KMP_INTERNAL_REALLOC( buffer, size );
00555 if ( buffer == NULL ) {
00556 KMP_FATAL( MemoryAllocFailed );
00557 };
00558
00559 };
00560
00561 return buffer;
00562
00563 }
00564
00565
00566 void
00567 __kmp_str_free(
00568 char const * * str
00569 ) {
00570 KMP_DEBUG_ASSERT( str != NULL );
00571 KMP_INTERNAL_FREE( (void *) * str );
00572 * str = NULL;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581 int
00582 __kmp_str_match(
00583 char const * target,
00584 int len,
00585 char const * data
00586 ) {
00587 int i;
00588 if ( target == NULL || data == NULL ) {
00589 return FALSE;
00590 };
00591 for ( i = 0; target[i] && data[i]; ++ i ) {
00592 if ( TOLOWER( target[i] ) != TOLOWER( data[i] ) ) {
00593 return FALSE;
00594 };
00595 };
00596 return ( ( len > 0 ) ? i >= len : ( ! target[i] && ( len || ! data[i] ) ) );
00597 }
00598
00599
00600 int
00601 __kmp_str_match_false( char const * data ) {
00602 int result =
00603 __kmp_str_match( "false", 1, data ) ||
00604 __kmp_str_match( "off", 2, data ) ||
00605 __kmp_str_match( "0", 1, data ) ||
00606 __kmp_str_match( ".false.", 2, data ) ||
00607 __kmp_str_match( ".f.", 2, data ) ||
00608 __kmp_str_match( "no", 1, data );
00609 return result;
00610 }
00611
00612
00613 int
00614 __kmp_str_match_true( char const * data ) {
00615 int result =
00616 __kmp_str_match( "true", 1, data ) ||
00617 __kmp_str_match( "on", 2, data ) ||
00618 __kmp_str_match( "1", 1, data ) ||
00619 __kmp_str_match( ".true.", 2, data ) ||
00620 __kmp_str_match( ".t.", 2, data ) ||
00621 __kmp_str_match( "yes", 1, data );
00622 return result;
00623 }
00624
00625 void
00626 __kmp_str_replace(
00627 char * str,
00628 char search_for,
00629 char replace_with
00630 ) {
00631
00632 char * found = NULL;
00633
00634 found = strchr( str, search_for );
00635 while ( found ) {
00636 * found = replace_with;
00637 found = strchr( found + 1, search_for );
00638 };
00639
00640 }
00641
00642
00643 void
00644 __kmp_str_split(
00645 char * str,
00646 char delim,
00647 char ** head,
00648 char ** tail
00649 ) {
00650 char * h = str;
00651 char * t = NULL;
00652 if ( str != NULL ) {
00653 char * ptr = strchr( str, delim );
00654 if ( ptr != NULL ) {
00655 * ptr = 0;
00656 t = ptr + 1;
00657 };
00658 };
00659 if ( head != NULL ) {
00660 * head = h;
00661 };
00662 if ( tail != NULL ) {
00663 * tail = t;
00664 };
00665 }
00666
00667
00668
00669
00670 char *
00671 __kmp_str_token(
00672 char * str,
00673 char const * delim,
00674 char ** buf
00675 ) {
00676 char * token = NULL;
00677 #if KMP_OS_WINDOWS
00678
00679 if ( str != NULL ) {
00680 * buf = str;
00681 };
00682 * buf += strspn( * buf, delim );
00683 if ( ** buf != 0 ) {
00684 token = * buf;
00685 * buf += strcspn( * buf, delim );
00686 if ( ** buf != 0 ) {
00687 ** buf = 0;
00688 * buf += 1;
00689 };
00690 };
00691 #else
00692
00693 token = strtok_r( str, delim, buf );
00694 #endif
00695 return token;
00696 };
00697
00698
00699 int
00700 __kmp_str_to_int(
00701 char const * str,
00702 char sentinel
00703 ) {
00704 int result, factor;
00705 char const * t;
00706
00707 result = 0;
00708
00709 for (t = str; *t != '\0'; ++t) {
00710 if (*t < '0' || *t > '9')
00711 break;
00712 result = (result * 10) + (*t - '0');
00713 }
00714
00715 switch (*t) {
00716 case '\0':
00717 factor = 1;
00718 break;
00719 case 'b': case 'B':
00720 ++t;
00721 factor = 1;
00722 break;
00723 case 'k': case 'K':
00724 ++t;
00725 factor = 1024;
00726 break;
00727 case 'm': case 'M':
00728 ++t;
00729 factor = (1024 * 1024);
00730 break;
00731 default:
00732 if(*t != sentinel)
00733 return (-1);
00734 t = "";
00735 factor = 1;
00736 }
00737
00738 if (result > (INT_MAX / factor))
00739 result = INT_MAX;
00740 else
00741 result *= factor;
00742
00743 return (*t != 0 ? 0 : result);
00744
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 void
00757 __kmp_str_to_size(
00758 char const * str,
00759 size_t * out,
00760 size_t dfactor,
00761 char const * * error
00762 ) {
00763
00764 size_t value = 0;
00765 size_t factor = 0;
00766 int overflow = 0;
00767 int bad_unit = 0;
00768 int i = 0;
00769 int digit;
00770
00771
00772 KMP_DEBUG_ASSERT( str != NULL );
00773
00774
00775 while ( str[ i ] == ' ' || str[ i ] == '\t') {
00776 ++ i;
00777 };
00778
00779
00780 if ( str[ i ] < '0' || str[ i ] > '9' ) {
00781 * error = KMP_I18N_STR( NotANumber );
00782 return;
00783 };
00784 do {
00785 digit = str[ i ] - '0';
00786 overflow = overflow || ( value > ( KMP_SIZE_T_MAX - digit ) / 10 );
00787 value = ( value * 10 ) + digit;
00788 ++ i;
00789 } while ( str[ i ] >= '0' && str[ i ] <= '9' );
00790
00791
00792 while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
00793 ++ i;
00794 };
00795
00796
00797 #define _case( ch, exp ) \
00798 case ch : \
00799 case ch - ( 'a' - 'A' ) : { \
00800 size_t shift = (exp) * 10; \
00801 ++ i; \
00802 if ( shift < sizeof( size_t ) * 8 ) { \
00803 factor = (size_t)( 1 ) << shift; \
00804 } else { \
00805 overflow = 1; \
00806 }; \
00807 } break;
00808 switch ( str[ i ] ) {
00809 _case( 'k', 1 );
00810 _case( 'm', 2 );
00811 _case( 'g', 3 );
00812 _case( 't', 4 );
00813 _case( 'p', 5 );
00814 _case( 'e', 6 );
00815 _case( 'z', 7 );
00816 _case( 'y', 8 );
00817
00818 };
00819 #undef _case
00820 if ( str[ i ] == 'b' || str[ i ] == 'B' ) {
00821 if ( factor == 0 ) {
00822 factor = 1;
00823 }
00824 ++ i;
00825 };
00826 if ( ! ( str[ i ] == ' ' || str[ i ] == '\t' || str[ i ] == 0 ) ) {
00827 * error = KMP_I18N_STR( BadUnit );
00828 return;
00829 };
00830
00831 if ( factor == 0 ) {
00832 factor = dfactor;
00833 }
00834
00835
00836 overflow = overflow || ( value > ( KMP_SIZE_T_MAX / factor ) );
00837 value *= factor;
00838
00839
00840 while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
00841 ++ i;
00842 };
00843
00844 if ( str[ i ] != 0 ) {
00845 * error = KMP_I18N_STR( IllegalCharacters );
00846 return;
00847 };
00848
00849 if ( overflow ) {
00850 * error = KMP_I18N_STR( ValueTooLarge );
00851 * out = KMP_SIZE_T_MAX;
00852 return;
00853 };
00854
00855 * error = NULL;
00856 * out = value;
00857
00858 }
00859
00860
00861 void
00862 __kmp_str_to_uint(
00863 char const * str,
00864 kmp_uint64 * out,
00865 char const * * error
00866 ) {
00867
00868 size_t value = 0;
00869 int overflow = 0;
00870 int i = 0;
00871 int digit;
00872
00873
00874 KMP_DEBUG_ASSERT( str != NULL );
00875
00876
00877 while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
00878 ++ i;
00879 };
00880
00881
00882 if ( str[ i ] < '0' || str[ i ] > '9' ) {
00883 * error = KMP_I18N_STR( NotANumber );
00884 return;
00885 };
00886 do {
00887 digit = str[ i ] - '0';
00888 overflow = overflow || ( value > ( KMP_SIZE_T_MAX - digit ) / 10 );
00889 value = ( value * 10 ) + digit;
00890 ++ i;
00891 } while ( str[ i ] >= '0' && str[ i ] <= '9' );
00892
00893
00894 while ( str[ i ] == ' ' || str[ i ] == '\t' ) {
00895 ++ i;
00896 };
00897
00898 if ( str[ i ] != 0 ) {
00899 * error = KMP_I18N_STR( IllegalCharacters );
00900 return;
00901 };
00902
00903 if ( overflow ) {
00904 * error = KMP_I18N_STR( ValueTooLarge );
00905 * out = (kmp_uint64) -1;
00906 return;
00907 };
00908
00909 * error = NULL;
00910 * out = value;
00911
00912 }
00913
00914
00915
00916