diff --git a/src/engine/builtins.c b/src/engine/builtins.c index 22485ceb1..f96a32de8 100644 --- a/src/engine/builtins.c +++ b/src/engine/builtins.c @@ -627,7 +627,6 @@ static void builtin_glob_back( void * closure, OBJECT * file, int status, PROFILE_ENTER( BUILTIN_GLOB_BACK ); struct globbing * const globbing = (struct globbing *)closure; - LIST * l; PATHNAME f; string buf[ 1 ]; LISTITER iter; diff --git a/src/engine/execunix.c b/src/engine/execunix.c index 04fdb3300..6fdc2f12e 100644 --- a/src/engine/execunix.c +++ b/src/engine/execunix.c @@ -339,9 +339,8 @@ static int read_descriptor( int i, int s ) * contains the command status at beginning of it own line instead of * appended to end of the previous output. */ - if ( globs.max_buf && globs.max_buf <= cmdtab[i].buf_size[s] ) { + if ( globs.max_buf && globs.max_buf <= cmdtab[i].buf_size[s] ) cmdtab[ i ].buffer[ s ][ cmdtab[ i ].buf_size[ s ] - 2 ] = '\n'; - } return feof( cmdtab[ i ].stream[ s ] ); } diff --git a/src/engine/filent.c b/src/engine/filent.c index d73e33dee..804c27791 100644 --- a/src/engine/filent.c +++ b/src/engine/filent.c @@ -15,7 +15,6 @@ * filent.c - scan directories and archives on NT * * External routines: - * * file_dirscan() - scan a directory for files * file_time() - get timestamp of file, if not done by file_dirscan() * file_archscan() - scan an archive for files @@ -67,7 +66,6 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure ) file_info_t * const d = file_query( dir ); if ( !d || !d->is_dir ) { - object_free( dir ); PROFILE_EXIT( FILE_DIRSCAN ); return; } @@ -77,25 +75,19 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure ) PATHNAME f; string filespec[ 1 ]; string filename[ 1 ]; - long handle; - int ret; struct _finddata_t finfo[ 1 ]; LIST * files = L0; - int d_length; - - dir = short_path_to_long_path( dir ); - - d_length = strlen( object_str( dir ) ); + OBJECT * const long_dir = short_path_to_long_path( dir ); + int const d_length = strlen( object_str( long_dir ) ); memset( (char *)&f, '\0', sizeof( f ) ); - - f.f_dir.ptr = object_str( dir ); + f.f_dir.ptr = object_str( long_dir ); f.f_dir.len = d_length; /* Now enter contents of directory */ /* Prepare file search specification for the findfirst() API. */ - if ( d_length == 0 ) + if ( !d_length ) string_copy( filespec, ".\\*" ); else { @@ -103,85 +95,83 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure ) * its trailing path separator or otherwise we would not support the * Windows root folder specified without its drive letter, i.e. '\'. */ - char const trailingChar = object_str( dir )[ d_length - 1 ] ; - string_copy( filespec, object_str( dir ) ); + char const trailingChar = object_str( long_dir )[ d_length - 1 ] ; + string_copy( filespec, object_str( long_dir ) ); if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) ) string_append( filespec, "\\" ); string_append( filespec, "*" ); } if ( DEBUG_BINDSCAN ) - printf( "scan directory %s\n", dir ); + printf( "scan directory %s\n", long_dir ); #if defined(__BORLANDC__) && __BORLANDC__ < 0x550 - if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) ) + if ( findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) ) { string_free( filespec ); - object_free( dir ); + object_free( long_dir ); PROFILE_EXIT( FILE_DIRSCAN ); return; } string_new( filename ); - while ( !ret ) + do { - file_info_t * ff; - f.f_base.ptr = finfo->ff_name; f.f_base.len = strlen( finfo->ff_name ); - string_truncate( filename, 0 ); path_build( &f, filename ); files = list_push_back( files, object_new( filename->value ) ); - ff = file_info( filename->value ); - ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1; - ff->is_dir = !ff->is_file; - ff->size = finfo->ff_fsize; - ff->time = ( finfo->ff_ftime << 16 ) | finfo->ff_ftime; - - ret = findnext( finfo ); + { + file_info_t * const ff = file_info( filename->value ); + ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1; + ff->is_dir = !ff->is_file; + ff->size = finfo->ff_fsize; + ff->time = ( finfo->ff_ftime << 16 ) | finfo->ff_ftime; + } } + while ( !findnext( finfo ) ); #else - handle = _findfirst( filespec->value, finfo ); - - if ( ret = ( handle < 0L ) ) { - string_free( filespec ); - object_free( dir ); - PROFILE_EXIT( FILE_DIRSCAN ); - return; + long const handle = _findfirst( filespec->value, finfo ); + if ( handle < 0L ) + { + string_free( filespec ); + object_free( long_dir ); + PROFILE_EXIT( FILE_DIRSCAN ); + return; + } + + string_new( filename ); + do + { + OBJECT * filename_obj; + + f.f_base.ptr = finfo->name; + f.f_base.len = strlen( finfo->name ); + string_truncate( filename, 0 ); + path_build( &f, filename, 0 ); + + filename_obj = object_new( filename->value ); + path_key__register_long_path( filename_obj ); + files = list_push_back( files, filename_obj ); + { + file_info_t * const ff = file_info( filename_obj ); + ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1; + ff->is_dir = !ff->is_file; + ff->size = finfo->size; + ff->time = finfo->time_write; + } + } + while ( !_findnext( handle, finfo ) ); + + _findclose( handle ); } - - string_new( filename ); - while ( !ret ) - { - OBJECT * filename_obj; - file_info_t * ff; - - f.f_base.ptr = finfo->name; - f.f_base.len = strlen( finfo->name ); - - string_truncate( filename, 0 ); - path_build( &f, filename, 0 ); - - filename_obj = object_new( filename->value ); - path_add_key( filename_obj ); - files = list_push_back( files, filename_obj ); - ff = file_info( filename_obj ); - ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1; - ff->is_dir = !ff->is_file; - ff->size = finfo->size; - ff->time = finfo->time_write; - - ret = _findnext( handle, finfo ); - } - - _findclose( handle ); #endif string_free( filename ); string_free( filespec ); - object_free( dir ); + object_free( long_dir ); d->files = files; } @@ -191,16 +181,12 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure ) unsigned long len = strlen( object_str( d->name ) ); if ( len == 1 && object_str( d->name )[ 0 ] == '\\' ) { - OBJECT * const dir = short_path_to_long_path( d->name ); - (*func)( closure, dir, 1 /* stat()'ed */, d->time ); - object_free( dir ); + OBJECT * const long_dir = short_path_to_long_path( d->name ); + (*func)( closure, long_dir, 1 /* stat()'ed */, d->time ); + object_free( long_dir ); } else if ( len == 3 && object_str( d->name )[ 1 ] == ':' ) { - char buf[ 4 ]; - OBJECT * const dir1 = short_path_to_long_path( d->name ); - OBJECT * dir2; - (*func)( closure, dir1, 1 /* stat()'ed */, d->time ); /* We have just entered a 3-letter drive name spelling (with a * trailing slash), into the hash table. Now enter its two-letter * variant, without the trailing slash, so that if we try to check @@ -213,9 +199,11 @@ void file_dirscan( OBJECT * dir, scanback func, void * closure ) * There will be no trailing slash in $(p), but there will be one in * $(p2). But, that seems rather fragile. */ - strcpy( buf, object_str( dir1 ) ); - buf[ 2 ] = 0; - dir2 = object_new( buf ); + OBJECT * const dir1 = short_path_to_long_path( d->name ); + char const * const dir1_raw = object_str( dir1 ); + char const dir2_raw[ 3 ] = { dir1_raw[ 0 ], dir1_raw[ 1 ], 0 }; + OBJECT * const dir2 = object_new( dir2_raw ); + (*func)( closure, dir1, 1 /* stat()'ed */, d->time ); (*func)( closure, dir2, 1 /* stat()'ed */, d->time ); object_free( dir2 ); object_free( dir1 ); diff --git a/src/engine/filesys.c b/src/engine/filesys.c index f9dde2828..15807208e 100644 --- a/src/engine/filesys.c +++ b/src/engine/filesys.c @@ -37,30 +37,28 @@ void file_build1( PATHNAME * f, string * file ) static struct hash * filecache_hash = 0; -static file_info_t filecache_finfo; file_info_t * file_info( OBJECT * filename ) { - file_info_t * finfo = &filecache_finfo; + OBJECT * const path_key = path_as_key( filename ); + file_info_t * finfo; int found; if ( !filecache_hash ) filecache_hash = hashinit( sizeof( file_info_t ), "file_info" ); - filename = path_as_key( filename ); - - finfo = (file_info_t *)hash_insert( filecache_hash, filename, &found ); + finfo = (file_info_t *)hash_insert( filecache_hash, path_key, &found ); if ( !found ) { - finfo->name = object_copy( filename ); + finfo->name = path_key; finfo->is_file = 0; finfo->is_dir = 0; finfo->size = 0; finfo->time = 0; finfo->files = L0; } - - object_free( filename ); + else + object_free( path_key ); return finfo; } diff --git a/src/engine/filesys.h b/src/engine/filesys.h index 2eb76ccc1..4182f09f4 100644 --- a/src/engine/filesys.h +++ b/src/engine/filesys.h @@ -34,8 +34,7 @@ void file_build1( PATHNAME * f, string * file ) ; int file_is_file( OBJECT * filename ); int file_mkdir( char const * pathname ); -typedef struct file_info_t file_info_t ; -struct file_info_t +typedef struct file_info_t { OBJECT * name; short is_file; @@ -43,15 +42,17 @@ struct file_info_t unsigned long size; time_t time; LIST * files; -}; +} file_info_t; -/* Creates a pointer to information about file 'filename', creating it as +/* Returns a pointer to information about file 'filename', creating it as * necessary. If created, the structure will be default initialized. */ file_info_t * file_info( OBJECT * filename ); -/* Returns information about a file, queries the OS if needed. */ +/* Returns information about a file, queries the OS if needed. Will return 0 if + * the file does not exist. + */ file_info_t * file_query( OBJECT * filename ); void file_done(); diff --git a/src/engine/make1.c b/src/engine/make1.c index c30b3b8fe..c59febbef 100644 --- a/src/engine/make1.c +++ b/src/engine/make1.c @@ -99,7 +99,7 @@ static void make1atail ( state * ); static void make1b ( state * ); static void make1c ( state * ); static void make1d ( state * ); -static void make_closure( void * const closure, int const status, +static void make_closure( void * const closure, int status, timing_info const * const, char const * const cmd_stdout, char const * const cmd_stderr, int const cmd_exit_reason ); @@ -830,7 +830,7 @@ static void make_closure ) { TARGET * const t = (TARGET *)closure; - CMD * cmd = (CMD *)t->cmds; + CMD const * const cmd = (CMD *)t->cmds; char const * rule_name = 0; char const * target_name = 0; @@ -882,7 +882,7 @@ static void make_closure printf( "%s\n", cmd->buf->value ); printf( "...failed %s ", object_str( cmd->rule->name ) ); - list_print( lol_get( &cmd->args, 0 ) ); + list_print( lol_get( (LOL *)&cmd->args, 0 ) ); printf( "...\n" ); } diff --git a/src/engine/object.c b/src/engine/object.c index 07298ad01..ef46e4ae4 100644 --- a/src/engine/object.c +++ b/src/engine/object.c @@ -9,11 +9,12 @@ * object.c - object manipulation routines * * External functions: - * object_new() - create an object from a string - * object_copy() - return a copy of an object - * object_free() - free an object - * object_str() - get the string value of an object - * object_done() - free string tables + * object_new() - create an object from a string + * object_new_range() - create an object from a string of given length + * object_copy() - return a copy of an object + * object_free() - free an object + * object_str() - get the string value of an object + * object_done() - free string tables * * This implementation builds a hash table of all strings, so that multiple * calls of object_new() on the same string allocate memory for the string once. @@ -128,28 +129,27 @@ static char * allocate( size_t n ) } -static unsigned int hash_keyval( char const * key ) +static unsigned int hash_keyval( char const * key, int const size ) { + unsigned int const magic = 2147059363; unsigned int hash = 0; - unsigned i; - unsigned int len = strlen( key ); - for ( i = 0; i < len / sizeof( unsigned int ); ++i ) + unsigned int i; + for ( i = 0; i < size / sizeof( unsigned int ); ++i ) { unsigned int val; memcpy( &val, key, sizeof( unsigned int ) ); - hash = hash * 2147059363 + val; + hash = hash * magic + val; key += sizeof( unsigned int ); } { unsigned int val = 0; - memcpy( &val, key, len % sizeof( unsigned int ) ); - hash = hash * 2147059363 + val; + memcpy( &val, key, size % sizeof( unsigned int ) ); + hash = hash * magic + val; } - hash += (hash >> 17); - return hash; + return hash + ( hash >> 17 ); } @@ -193,16 +193,16 @@ static void string_set_resize( string_set * set ) } -static char const * string_set_insert( string_set * set, char const * string ) +static char const * string_set_insert( string_set * set, char const * string, + int const size ) { - unsigned hash = hash_keyval( string ); + unsigned hash = hash_keyval( string, size ); unsigned pos = hash % set->num; - unsigned len; struct hash_item * result; for ( result = set->data[ pos ]; result; result = result->header.next ) - if ( !strcmp( result->data, string ) ) + if ( !strncmp( result->data, string, size ) && !result->data[ size ] ) return result->data; if ( set->size >= set->num ) @@ -211,17 +211,18 @@ static char const * string_set_insert( string_set * set, char const * string ) pos = hash % set->num; } - len = strlen( string ) + 1; - result = (struct hash_item *)allocate( sizeof( struct hash_header ) + len ); + result = (struct hash_item *)allocate( sizeof( struct hash_header ) + size + + 1 ); result->header.hash = hash; result->header.next = set->data[ pos ]; #ifndef NDEBUG result->header.magic = OBJECT_MAGIC; #endif - memcpy( result->data, string, len ); - assert( hash_keyval( result->data ) == result->header.hash ); + memcpy( result->data, string, size ); + result->data[ size ] = '\0'; + assert( hash_keyval( result->data, size ) == result->header.hash ); set->data[ pos ] = result; - strtotal += len; + strtotal += size + 1; ++set->size; return result->data; @@ -243,32 +244,41 @@ static void object_validate( OBJECT * obj ) /* - * object_new() - create an object from a string. + * object_new_range() - create an object from a string of given length */ -OBJECT * object_new( char const * string ) +OBJECT * object_new_range( char const * const string, int const size ) { ++strcount_in; #ifdef BJAM_NO_MEM_CACHE { - int const len = strlen( string ) + 1; struct hash_item * const m = (struct hash_item *)BJAM_MALLOC( sizeof( - struct hash_header ) + len ); - - strtotal += len; - memcpy( m->data, string, len ); + struct hash_header ) + size + 1 ); + strtotal += size + 1; + memcpy( m->data, string, size ); + m->data[ size ] = '\0'; m->header.magic = OBJECT_MAGIC; return (OBJECT *)m->data; } #else if ( !strhash.data ) string_set_init( &strhash ); - return (OBJECT *)string_set_insert( &strhash, string ); + return (OBJECT *)string_set_insert( &strhash, string, size ); #endif } +/* + * object_new() - create an object from a string + */ + +OBJECT * object_new( char const * const string ) +{ + return object_new_range( string, strlen( string ) ); +} + + #ifndef object_copy /* @@ -337,7 +347,7 @@ unsigned int object_hash( OBJECT * obj ) { object_validate( obj ); #ifdef BJAM_NO_MEM_CACHE - return hash_keyval( object_str( obj ) ); + return hash_keyval( object_str( obj ), strlen( object_str( obj ) ) ); #else return object_get_item( obj )->header.hash; #endif diff --git a/src/engine/object.h b/src/engine/object.h index 19f7b16c5..cabb9f6f2 100644 --- a/src/engine/object.h +++ b/src/engine/object.h @@ -13,8 +13,9 @@ typedef struct _object OBJECT; -OBJECT * object_new ( char const * ); -void object_done( void ); +OBJECT * object_new( char const * const ); +OBJECT * object_new_range( char const * const, int const size ); +void object_done( void ); #if defined(NDEBUG) && !defined(BJAM_NO_MEM_CACHE) diff --git a/src/engine/pathsys.h b/src/engine/pathsys.h index d46b17099..c76dfed00 100644 --- a/src/engine/pathsys.h +++ b/src/engine/pathsys.h @@ -72,7 +72,7 @@ OBJECT * path_as_key( OBJECT * path ); * long form. Avoids the need for some subsequent path_as_key() call to do a * potentially expensive short-->long path conversion. */ -void path_add_key( OBJECT * long_path ); +void path_key__register_long_path( OBJECT * long_path ); #ifdef USE_PATHUNIX /* Returns a static pointer to the system dependent path to the temporary diff --git a/src/engine/pathunix.c b/src/engine/pathunix.c index f1357e3f2..0d54e4487 100644 --- a/src/engine/pathunix.c +++ b/src/engine/pathunix.c @@ -247,68 +247,151 @@ void path_parent( PATHNAME * f ) #undef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) -static void path_write_key( char const * const path_, string * const out ); + +typedef struct path_key_entry +{ + OBJECT * path; + OBJECT * key; +} path_key_entry; + +static struct hash * path_key_cache; -static void ShortPathToLongPath( char const * const short_path, +/* + * may_be_a_valid_short_name() - returns whether the given file name may be a + * valid Windows short name, i.e. whether it might have a different long name. + */ + +static int may_be_a_valid_short_name( char const * const n, int const n_length ) +{ + char const * p; + char const * const n_end = n + n_length; + char const * dot = 0; + + /* Short names have at most 12 characters (8 + dot + 3). */ + if ( n_length > 12 ) + return 0; + + for ( p = n; p != n_end; ++p ) + switch ( *p ) + { + case ' ': + /* Short names may not contain spaces. */ + return 0; + + case '.': + /* Short name may contain at most one dot. */ + if ( dot ) + return 0; + dot = p; + /* Short name base must have at least one character. */ + if ( dot == n ) + return 0; + /* Short name base may not be longer than 8 characters. */ + if ( dot - n > 8 ) + return 0; + /* Short name extension may not be longer than 3 characters. */ + if ( n_end - dot - 1 > 3 ) + return 0; + } + + return 1; +} + + +/* + * ShortPathToLongPath() - convert a given path into its long format + * + * In the process, automatically registers long paths for all of the parent + * folders on the path, if they have not already been registered. + * + * Prerequisites: + * - Path to given in normalized form, i.e. all of its folder separators have + * already been converted into '\\'. + * - path_key_cache path/key mapping cache object has already been initialized. + */ + +static void ShortPathToLongPath( char const * const path, int const path_length, string * const out ) { - char const * new_element; + char const * last_element; unsigned long saved_size; - char * p; + char const * p; - if ( short_path[ 0 ] == '\0' ) + /* This is only called via path_key(), which initializes the cache. */ + assert( path_key_cache ); + + if ( !path_length ) return; - if ( short_path[ 0 ] == '\\' && short_path[ 1 ] == '\0' ) + if ( path_length == 1 && path[ 0 ] == '\\' ) { string_push_back( out, '\\' ); return; } - if ( short_path[ 1 ] == ':' && - ( short_path[ 2 ] == '\0' || - ( short_path[ 2 ] == '\\' && short_path[ 3 ] == '\0' ) ) ) + if ( path[ 1 ] == ':' && + ( path_length == 2 || + ( path_length == 3 && path[ 2 ] == '\\' ) ) ) { - string_push_back( out, toupper( short_path[ 0 ] ) ); + string_push_back( out, toupper( path[ 0 ] ) ); string_push_back( out, ':' ); string_push_back( out, '\\' ); return; } - /* '/' already handled. */ - if ( ( p = strrchr( short_path, '\\' ) ) ) + /* Find last '\\'. */ + for ( p = path + path_length - 1; p >= path && *p != '\\'; --p ); + last_element = p + 1; + + /* Special case '\' && 'D:\' - include trailing '\'. */ + if ( p == path || + p == path + 2 && path[ 1 ] == ':' ) + ++p; + + if ( p >= path ) { - char saved; - new_element = p + 1; - - /* special case '\' */ - if ( p == short_path ) - ++p; - - /* special case 'D:\' */ - if ( p == short_path + 2 && short_path[ 1 ] == ':' ) - ++p; - - saved = *p; - *p = '\0'; - path_write_key( short_path, out ); - *p = saved; + char const * const dir = path; + int const dir_length = p - path; + OBJECT * const dir_obj = object_new_range( dir, dir_length ); + int found; + path_key_entry * const result = (path_key_entry *)hash_insert( + path_key_cache, dir_obj, &found ); + if ( !found ) + { + /* dir is already normalized. */ + result->path = dir_obj; + ShortPathToLongPath( dir, dir_length, out ); + result->key = object_new( out->value ); + } + else + { + object_free( dir_obj ); + string_append( out, object_str( result->key ) ); + } } - else - new_element = short_path; if ( out->size && out->value[ out->size - 1 ] != '\\' ) string_push_back( out, '\\' ); saved_size = out->size; - string_append( out, new_element ); + string_append_range( out, last_element, path + path_length ); - /* If the file exists, replace its name with its long name variant. */ + /* If we have a name that can not be a valid short name then it must be a + * valid long name and we are done. If there is a chance this is not the + * file's long name, ask the OS for the file's actual long name. We try to + * avoid this file system access as it could be unnecessarily expensive. + * Note that there is no way to detect the file's 'long name' in case it + * does not already exist, in which case in theory a file could later be + * created that has a different long name and the name given here as its + * short name. + */ { - char const * const n = new_element; - if ( !( n[ 0 ] == '.' && n[ 1 ] == '\0' || - n[ 0 ] == '.' && n[ 1 ] == '.' && n[ 2 ] == '\0' ) ) + char const * const n = last_element; + int const n_length = path + path_length - n; + if ( !( n_length == 1 && n[ 0 ] == '.' ) + && !( n_length == 2 && n[ 0 ] == '.' && n[ 1 ] == '.' ) + && may_be_a_valid_short_name( n, n_length ) ) { WIN32_FIND_DATA fd; HANDLE const hf = FindFirstFile( out->value, &fd ); @@ -329,40 +412,6 @@ OBJECT * short_path_to_long_path( OBJECT * short_path ) } -typedef struct path_key_entry -{ - OBJECT * path; - OBJECT * key; -} path_key_entry; - -static struct hash * path_key_cache; - - -static void path_write_key( char const * const path_, string * const out ) -{ - path_key_entry * result; - OBJECT * const path = object_new( path_ ); - int found; - - /* This is only called via path_as_key(), which initializes the cache. */ - assert( path_key_cache ); - - result = (path_key_entry *)hash_insert( path_key_cache, path, &found ); - if ( !found ) - { - /* path_ is already normalized. */ - result->path = path; - ShortPathToLongPath( path_, out ); - result->key = object_new( out->value ); - } - else - { - object_free( path ); - string_append( out, object_str( result->key ) ); - } -} - - static void normalize_path( string * path ) { char * s; @@ -387,13 +436,18 @@ static path_key_entry * path_key( OBJECT * const path, result = (path_key_entry *)hash_insert( path_key_cache, path, &found ); if ( !found ) { - string buf[ 1 ]; OBJECT * normalized; + int normalized_size; path_key_entry * nresult; result->path = path; - string_copy( buf, object_str( path ) ); - normalize_path( buf ); - normalized = object_new( buf->value ); + { + string buf[ 1 ]; + string_copy( buf, object_str( path ) ); + normalize_path( buf ); + normalized = object_new( buf->value ); + normalized_size = buf->size; + string_free( buf ); + } nresult = (path_key_entry *)hash_insert( path_key_cache, normalized, &found ); if ( !found || nresult == result ) @@ -405,14 +459,14 @@ static path_key_entry * path_key( OBJECT * const path, { string long_path[ 1 ]; string_new( long_path ); - ShortPathToLongPath( buf->value, long_path ); + ShortPathToLongPath( object_str( normalized ), normalized_size, + long_path ); nresult->key = object_new( long_path->value ); string_free( long_path ); } } else object_free( normalized ); - string_free( buf ); if ( nresult != result ) { result->path = object_copy( path ); @@ -424,7 +478,7 @@ static path_key_entry * path_key( OBJECT * const path, } -void path_add_key( OBJECT * long_path ) +void path_key__register_long_path( OBJECT * long_path ) { path_key( long_path, 1 ); } @@ -456,7 +510,7 @@ void path_done( void ) #else /* NT */ -void path_add_key( OBJECT * path ) +void path_key__register_long_path( OBJECT * path ) { }