Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75808 - trunk/tools/build/v2/engine
From: steven_at_[hidden]
Date: 2011-12-04 21:12:57


Author: steven_watanabe
Date: 2011-12-04 21:12:55 EST (Sun, 04 Dec 2011)
New Revision: 75808
URL: http://svn.boost.org/trac/boost/changeset/75808

Log:
Convert short paths to long paths on NT.
Text files modified:
   trunk/tools/build/v2/engine/filent.c | 1
   trunk/tools/build/v2/engine/pathsys.h | 1
   trunk/tools/build/v2/engine/pathunix.c | 270 +++++++++++++++++++++++----------------
   3 files changed, 160 insertions(+), 112 deletions(-)

Modified: trunk/tools/build/v2/engine/filent.c
==============================================================================
--- trunk/tools/build/v2/engine/filent.c (original)
+++ trunk/tools/build/v2/engine/filent.c 2011-12-04 21:12:55 EST (Sun, 04 Dec 2011)
@@ -169,6 +169,7 @@
             path_build( &f, filename, 0 );
 
             filename_obj = object_new( filename->value );
+ path_add_key( filename_obj );
             files = list_new( files, filename_obj );
             ff = file_info( filename_obj );
             ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;

Modified: trunk/tools/build/v2/engine/pathsys.h
==============================================================================
--- trunk/tools/build/v2/engine/pathsys.h (original)
+++ trunk/tools/build/v2/engine/pathsys.h 2011-12-04 21:12:55 EST (Sun, 04 Dec 2011)
@@ -65,6 +65,7 @@
     same key.
  */
 OBJECT * path_as_key( OBJECT * path );
+void path_add_key( OBJECT * path );
 
 #ifdef USE_PATHUNIX
 /** Returns a static pointer to the system dependent path to the temporary

Modified: trunk/tools/build/v2/engine/pathunix.c
==============================================================================
--- trunk/tools/build/v2/engine/pathunix.c (original)
+++ trunk/tools/build/v2/engine/pathunix.c 2011-12-04 21:12:55 EST (Sun, 04 Dec 2011)
@@ -18,6 +18,7 @@
 # include "filesys.h"
 # include <time.h>
 # include <stdlib.h>
+# include <assert.h>
 # ifndef OS_NT
 # include <unistd.h>
 # endif
@@ -273,131 +274,90 @@
 
 #ifdef NT
 #include <windows.h>
-#include <tchar.h>
 
 /* The definition of this in winnt.h is not ANSI-C compatible. */
 #undef INVALID_FILE_ATTRIBUTES
 #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
 
+OBJECT * path_as_key( OBJECT * path );
+static void path_write_key( char * path_, string * out );
 
-DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
- cchBuffer)
+void ShortPathToLongPath( char * short_path, string * out )
 {
- LONG i=0;
- TCHAR path[_MAX_PATH]={0};
- TCHAR ret[_MAX_PATH]={0};
- LONG pos=0, prev_pos=0;
- LONG len=_tcslen(lpszShortPath);
-
- /* Is the string valid? */
- if (!lpszShortPath) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- /* Is the path valid? */
- if (GetFileAttributes(lpszShortPath)==INVALID_FILE_ATTRIBUTES)
- return 0;
-
- /* Convert "/" to "\" */
- for (i=0;i<len;++i) {
- if (lpszShortPath[i]==_T('/'))
- path[i]=_T('\\');
- else
- path[i]=lpszShortPath[i];
+ const char * new_element;
+ unsigned long saved_size;
+ char * p;
+
+ if ( short_path[0] == '\0' )
+ {
+ return;
     }
 
- /* UNC path? */
- if (path[0]==_T('\\') && path[1]==_T('\\')) {
- pos=2;
- for (i=0;i<2;++i) {
- while (path[pos]!=_T('\\') && path[pos]!=_T('\0'))
- ++pos;
- ++pos;
- }
- _tcsncpy(ret,path,pos-1);
- } /* Drive letter? */
- else if (path[1]==_T(':')) {
- if (path[2]==_T('\\'))
- pos=3;
- if (len==3) {
- if (cchBuffer>3)
- _tcscpy(lpszLongPath,lpszShortPath);
- return len;
- }
- _tcsncpy(ret,path,2);
- ret[0] = toupper(ret[0]);
+ if ( short_path[1] == ':' &&
+ ( short_path[2] == '\0' ||
+ ( short_path[2] == '\\' && short_path[3] == '\0' ) ) )
+ {
+ string_push_back( out, toupper( short_path[0] ) );
+ string_push_back( out, ':' );
+ string_push_back( out, '\\' );
+ return;
     }
+
+ /* '/' already handled. */
+ if ( ( p = strrchr( short_path, '\\' ) ) )
+ {
+ char saved;
+ new_element = p + 1;
 
- /* Expand the path for each subpath, and strip trailing backslashes */
- for (prev_pos = pos-1;pos<=len;++pos) {
- if (path[pos]==_T('\\') || (path[pos]==_T('\0') &&
- path[pos-1]!=_T('\\'))) {
- WIN32_FIND_DATA fd;
- HANDLE hf=0;
- TCHAR c=path[pos];
- char* new_element;
- path[pos]=_T('\0');
-
- /* the path[prev_pos+1]... path[pos] range is the part of
- path we're handling right now. We need to find long
- name for that element and add it. */
- new_element = path + prev_pos + 1;
-
- /* First add separator, but only if there's something in result already. */
- if (ret[0] != _T('\0'))
- {
- _tcscat(ret,_T("\\"));
- }
-
- /* If it's ".." element, we need to append it, not
- the name in parent that FindFirstFile will return.
- Same goes for "." */
-
- if (new_element[0] == _T('.') && new_element[1] == _T('\0') ||
- new_element[0] == _T('.') && new_element[1] == _T('.')
- && new_element[2] == _T('\0'))
- {
- _tcscat(ret, new_element);
- }
- else
- {
- hf=FindFirstFile(path, &fd);
- if (hf==INVALID_HANDLE_VALUE)
- return 0;
-
- _tcscat(ret,fd.cFileName);
- FindClose(hf);
- }
+ /* special case \ */
+ if ( p == short_path )
+ ++p;
+
+ /* special case D:\ */
+ if ( p == short_path + 2 && short_path[1] == ':' )
+ ++p;
 
- path[pos]=c;
+ saved = *p;
+ *p = '\0';
+ path_write_key( short_path, out );
+ *p = saved;
+ }
+ else
+ {
+ new_element = short_path;
+ }
 
- prev_pos = pos;
- }
+ if ( out->size && out->value[ out->size - 1 ] != '\\' )
+ {
+ string_push_back( out, '\\' );
     }
+
+ saved_size = out->size;
+ string_append( out, new_element );
 
- len=_tcslen(ret)+1;
- if (cchBuffer>=len)
- _tcscpy(lpszLongPath,ret);
+ if ( ! ( new_element[0] == '.' && new_element[1] == '\0' ||
+ new_element[0] == '.' && new_element[1] == '.'
+ && new_element[2] == '\0' ) )
+ {
+ WIN32_FIND_DATA fd;
+ HANDLE hf = 0;
+ hf = FindFirstFile( out->value, &fd );
 
- return len;
+ /* If the file exists, replace the name. */
+ if ( hf != INVALID_HANDLE_VALUE )
+ {
+ string_truncate( out, saved_size );
+ string_append( out, fd.cFileName );
+ FindClose( hf );
+ }
+ }
 }
 
 OBJECT * short_path_to_long_path( OBJECT * short_path )
 {
- char buffer2[_MAX_PATH];
- int ret = ShortPathToLongPath( object_str( short_path ), buffer2, _MAX_PATH );
-
- if (ret)
- return object_new( buffer2 );
- else
- return object_copy( short_path );
+ return path_as_key( short_path );
 }
 
-#endif
-
-#ifdef NT
-
 struct path_key_entry
 {
     OBJECT * path;
@@ -406,6 +366,78 @@
 
 static struct hash * path_key_cache;
 
+static void path_write_key( char * path_, string * out )
+{
+ struct path_key_entry e, *result = &e;
+ OBJECT * path = object_new( path_ );
+
+ /* This is only called by path_as_key, which initializes the cache. */
+ assert( path_key_cache );
+
+ result->path = path;
+ if ( hashenter( path_key_cache, (HASHDATA * *)&result ) )
+ {
+ /* path_ is already normalized. */
+ 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;
+ for ( s = path->value; s < path->value + path->size; ++s )
+ {
+ if ( *s == '/' )
+ *s = '\\';
+ else
+ *s = tolower( *s );
+ }
+ /* Strip trailing "/" */
+ if ( path->size != 0 && path->size != 3 && path->value[ path->size - 1 ] == '\\' )
+ {
+ string_pop_back( path );
+ }
+}
+
+void path_add_key( OBJECT * path )
+{
+ struct path_key_entry e, *result = &e;
+
+ if ( ! path_key_cache )
+ path_key_cache = hashinit( sizeof( struct path_key_entry ), "path to key" );
+
+ result->path = path;
+ if ( hashenter( path_key_cache, (HASHDATA * *)&result ) )
+ {
+ string buf[1];
+ OBJECT * normalized;
+ struct path_key_entry ne, *nresult = &ne;
+ string_copy( buf, object_str( path ) );
+ normalize_path( buf );
+ normalized = object_new( buf->value );
+ string_free( buf );
+ nresult->path = normalized;
+ if ( hashenter( path_key_cache, (HASHDATA * *)&nresult ) || nresult == result )
+ {
+ nresult->path = object_copy( normalized );
+ nresult->key = object_copy( path );
+ }
+ object_free( normalized );
+ if ( nresult != result )
+ {
+ result->path = object_copy( path );
+ result->key = object_copy( nresult->key );
+ }
+ }
+}
+
 OBJECT * path_as_key( OBJECT * path )
 {
     struct path_key_entry e, *result = &e;
@@ -417,21 +449,31 @@
     if ( hashenter( path_key_cache, (HASHDATA * *)&result ) )
     {
         string buf[1];
- char * s;
+ OBJECT * normalized;
+ struct path_key_entry ne, *nresult = &ne;
         string_copy( buf, object_str( path ) );
- for ( s = buf->value; s < buf->value + buf->size; ++s )
+ normalize_path( buf );
+ normalized = object_new( buf->value );
+ nresult->path = normalized;
+ if ( hashenter( path_key_cache, (HASHDATA * *)&nresult ) || nresult == result )
         {
- if ( *s == '/' )
- *s = '\\';
- else
- *s = tolower( *s );
+ string long_path[1];
+ string_new( long_path );
+ ShortPathToLongPath( buf->value, long_path );
+ nresult->path = object_copy( normalized );
+ nresult->key = object_new( long_path->value );
+ string_free( long_path );
         }
- result->path = object_copy( path );
- result->key = object_new( buf->value );
         string_free( buf );
+ object_free( normalized );
+ if ( nresult != result )
+ {
+ result->path = object_copy( path );
+ result->key = object_copy( nresult->key );
+ }
     }
 
- return result->key;
+ return object_copy( result->key );
 }
 
 static void free_path_key_entry( void * xentry, void * data )
@@ -452,6 +494,10 @@
 
 #else
 
+void path_add_key( OBJECT * path )
+{
+}
+
 OBJECT * path_as_key( OBJECT * path )
 {
     return object_copy( path );


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk