Some changes to migrate towards C++ and a multithreaded model

This commit is contained in:
ridiculousfish
2011-12-26 19:18:46 -08:00
parent 3f16ace678
commit 8d2f107d61
90 changed files with 7368 additions and 5981 deletions

View File

@@ -43,7 +43,7 @@ wildcards using **.
/**
The maximum length of a filename token. This is a fallback value,
an attempt to find the true value using patchconf is always made.
an attempt to find the true value using patchconf is always made.
*/
#define MAX_FILE_LENGTH 1024
@@ -111,20 +111,20 @@ static hash_table_t *suffix_hash=0;
which is quite slow if the list is large. It might make sense to
use a hashtable for this.
*/
static void al_push_check( array_list_t *l, const wchar_t *new )
static void al_push_check( array_list_t *l, const wchar_t *newv )
{
int i;
for( i = 0; i < al_get_count(l); i++ )
for( i = 0; i < al_get_count(l); i++ )
{
if( !wcscmp( al_get(l, i), new ) )
if( !wcscmp( (const wchar_t *)al_get(l, i), newv ) )
{
free( (void *)new );
free( (void *)newv );
return;
}
}
al_push( l, new );
al_push( l, newv );
}
@@ -143,7 +143,7 @@ int wildcard_has( const wchar_t *str, int internal )
if( !str )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
return 0;
}
if( internal )
@@ -164,33 +164,33 @@ int wildcard_has( const wchar_t *str, int internal )
prev = *str;
}
}
return 0;
}
/**
Check whether the string str matches the wildcard string wc.
\param str String to be matched.
\param wc The wildcard.
\param is_first Whether files beginning with dots should not be matched against wildcards.
\param is_first Whether files beginning with dots should not be matched against wildcards.
*/
static int wildcard_match2( const wchar_t *str,
const wchar_t *wc,
static int wildcard_match2( const wchar_t *str,
const wchar_t *wc,
int is_first )
{
if( *str == 0 && *wc==0 )
return 1;
if( *wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE)
{
{
/* Ignore hidden file */
if( is_first && *str == L'.' )
{
return 0;
}
/* Try all submatches */
do
{
@@ -215,10 +215,10 @@ static int wildcard_match2( const wchar_t *str,
{
return 0;
}
return wildcard_match2( str+1, wc+1, 0 );
}
if( *wc == *str )
return wildcard_match2( str+1, wc+1, 0 );
@@ -230,9 +230,9 @@ static int wildcard_match2( const wchar_t *str,
possible completion of the string, the remainder of the string is
inserted into the array_list_t.
*/
static int wildcard_complete_internal( const wchar_t *orig,
const wchar_t *str,
const wchar_t *wc,
static int wildcard_complete_internal( const wchar_t *orig,
const wchar_t *str,
const wchar_t *wc,
int is_first,
const wchar_t *desc,
const wchar_t *(*desc_func)(const wchar_t *),
@@ -242,7 +242,7 @@ static int wildcard_complete_internal( const wchar_t *orig,
if( !wc || !str || !orig)
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
return 0;
}
if( *wc == 0 &&
@@ -250,12 +250,12 @@ static int wildcard_complete_internal( const wchar_t *orig,
{
wchar_t *out_completion = 0;
const wchar_t *out_desc = desc;
if( !out )
{
return 1;
}
if( flags & COMPLETE_NO_CASE )
{
out_completion = wcsdup( orig );
@@ -271,11 +271,11 @@ static int wildcard_complete_internal( const wchar_t *orig,
This completion has an embedded description, du not use the generic description
*/
wchar_t *sep;
sep = wcschr(out_completion, PROG_COMPLETE_SEP );
*sep = 0;
out_desc = sep + 1;
}
else
{
@@ -290,31 +290,31 @@ static int wildcard_complete_internal( const wchar_t *orig,
if( func_desc )
out_desc = func_desc;
}
}
if( out_completion )
{
completion_allocate( out,
completion_allocate( out,
out_completion,
out_desc,
flags );
}
free ( out_completion );
return 1;
}
if( *wc == ANY_STRING )
{
{
int res=0;
/* Ignore hidden file */
if( is_first && str[0] == L'.' )
return 0;
/* Try all submatches */
do
{
@@ -324,12 +324,12 @@ static int wildcard_complete_internal( const wchar_t *orig,
}
while( *str++ != 0 );
return res;
}
else if( *wc == ANY_CHAR )
{
return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags );
}
}
else if( *wc == *str )
{
return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags );
@@ -338,19 +338,19 @@ static int wildcard_complete_internal( const wchar_t *orig,
{
return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags | COMPLETE_NO_CASE );
}
return 0;
return 0;
}
int wildcard_complete( const wchar_t *str,
const wchar_t *wc,
const wchar_t *desc,
const wchar_t *desc,
const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *out,
int flags )
{
int res;
res = wildcard_complete_internal( str, str, wc, 1, desc, desc_func, out, flags );
res = wildcard_complete_internal( str, str, wc, 1, desc, desc_func, out, flags );
return res;
}
@@ -358,21 +358,21 @@ int wildcard_complete( const wchar_t *str,
int wildcard_match( const wchar_t *str, const wchar_t *wc )
{
return wildcard_match2( str, wc, 1 );
return wildcard_match2( str, wc, 1 );
}
/**
Creates a path from the specified directory and filename.
Creates a path from the specified directory and filename.
*/
static wchar_t *make_path( const wchar_t *base_dir, const wchar_t *name )
{
wchar_t *long_name;
int base_len = wcslen( base_dir );
if( !(long_name= malloc( sizeof(wchar_t)*(base_len+wcslen(name)+1) )))
if( !(long_name= (wchar_t *)malloc( sizeof(wchar_t)*(base_len+wcslen(name)+1) )))
{
DIE_MEM();
}
}
wcscpy( long_name, base_dir );
wcscpy(&long_name[base_len], name );
return long_name;
@@ -393,12 +393,12 @@ static wchar_t *complete_get_desc_suffix_internal( const wchar_t *suff_orig )
if( !suff || !cmd )
DIE_MEM();
al_init( &l );
if( exec_subshell( cmd, &l ) != -1 )
{
if( al_get_count( &l )>0 )
{
wchar_t *ln = (wchar_t *)al_get(&l, 0 );
@@ -414,16 +414,16 @@ static wchar_t *complete_get_desc_suffix_internal( const wchar_t *suff_orig )
}
}
}
free(cmd);
al_foreach( &l, &free );
al_destroy( &l );
if( !desc )
{
desc = wcsdup(COMPLETE_FILE_DESC);
}
hash_put( suffix_hash, suff, desc );
return desc;
@@ -458,13 +458,13 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
wchar_t *desc;
len = wcslen(suff_orig );
if( len == 0 )
return COMPLETE_FILE_DESC;
if( !suffix_hash )
{
suffix_hash = malloc( sizeof( hash_table_t) );
suffix_hash = (hash_table_t *)malloc( sizeof( hash_table_t) );
if( !suffix_hash )
DIE_MEM();
hash_init( suffix_hash, &hash_wcs_func, &hash_wcs_cmp );
@@ -494,7 +494,7 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
{
desc = complete_get_desc_suffix_internal( suff );
}
free( suff );
return desc;
@@ -511,20 +511,20 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
\param lbuf The struct buf output of calling lstat on the file
\param stat_res The result of calling stat on the file
\param buf The struct buf output of calling stat on the file
\param err The errno value after a failed stat call on the file.
\param err The errno value after a failed stat call on the file.
*/
static const wchar_t *file_get_desc( const wchar_t *filename,
static const wchar_t *file_get_desc( const wchar_t *filename,
int lstat_res,
struct stat lbuf,
int stat_res,
struct stat buf,
struct stat lbuf,
int stat_res,
struct stat buf,
int err )
{
wchar_t *suffix;
CHECK( filename, 0 );
if( !lstat_res )
{
if( S_ISLNK(lbuf.st_mode))
@@ -542,7 +542,7 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
( buf.st_mode & S_IXGRP ) ||
( buf.st_mode & S_IXOTH ) )
{
if( waccess( filename, X_OK ) == 0 )
{
/*
@@ -557,7 +557,7 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
}
}
}
return COMPLETE_SYMLINK_DESC;
}
@@ -569,7 +569,7 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
{
return COMPLETE_ROTTEN_SYMLINK_DESC;
}
case ELOOP:
{
return COMPLETE_LOOP_SYMLINK_DESC;
@@ -602,13 +602,13 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
{
return COMPLETE_DIRECTORY_DESC;
}
else
else
{
if( ( buf.st_mode & S_IXUSR ) ||
( buf.st_mode & S_IXGRP ) ||
( buf.st_mode & S_IXOTH ) )
{
if( waccess( filename, X_OK ) == 0 )
{
/*
@@ -624,19 +624,19 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
}
}
}
suffix = wcsrchr( filename, L'.' );
if( suffix != 0 && !wcsrchr( suffix, L'/' ) )
{
return complete_get_desc_suffix( suffix );
}
return COMPLETE_FILE_DESC ;
}
/**
Add the specified filename if it matches the specified wildcard.
Add the specified filename if it matches the specified wildcard.
If the filename matches, first get the description of the specified
filename. If this is a regular file, append the filesize to the
@@ -648,8 +648,8 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
\param wc the wildcard to match against
\param is_cmd whether we are performing command completion
*/
static void wildcard_completion_allocate( array_list_t *list,
const wchar_t *fullname,
static void wildcard_completion_allocate( array_list_t *list,
const wchar_t *fullname,
const wchar_t *completion,
const wchar_t *wc,
int is_cmd )
@@ -657,14 +657,14 @@ static void wildcard_completion_allocate( array_list_t *list,
const wchar_t *desc;
struct stat buf, lbuf;
static string_buffer_t *sb = 0;
int free_completion = 0;
int flags = 0;
int stat_res, lstat_res;
int stat_errno=0;
long long sz;
long long sz;
if( !sb )
{
@@ -676,7 +676,7 @@ static void wildcard_completion_allocate( array_list_t *list,
}
CHECK( fullname, );
sb_clear( sb );
/*
@@ -694,7 +694,7 @@ static void wildcard_completion_allocate( array_list_t *list,
{
if( S_ISLNK(lbuf.st_mode))
{
if( ( stat_res = wstat( fullname, &buf ) ) )
{
sz=-1;
@@ -703,7 +703,7 @@ static void wildcard_completion_allocate( array_list_t *list,
{
sz = (long long)buf.st_size;
}
/*
In order to differentiate between e.g. rotten symlinks
and symlink loops, we also need to know the error status of wstat.
@@ -717,9 +717,9 @@ static void wildcard_completion_allocate( array_list_t *list,
sz = (long long)buf.st_size;
}
}
desc = file_get_desc( fullname, lstat_res, lbuf, stat_res, buf, stat_errno );
if( sz >= 0 && S_ISDIR(buf.st_mode) )
{
free_completion = 1;
@@ -728,8 +728,8 @@ static void wildcard_completion_allocate( array_list_t *list,
sb_append( sb, desc );
}
else
{
sb_append( sb, desc, L", ", (void *)0 );
{
sb_append( sb, desc, L", ", NULL );
sb_format_size( sb, sz );
}
@@ -743,7 +743,7 @@ static void wildcard_completion_allocate( array_list_t *list,
expansion flags specified. flags can be a combination of
EXECUTABLES_ONLY and DIRECTORIES_ONLY.
*/
static int test_flags( wchar_t *filename,
static int test_flags( const wchar_t *filename,
int flags )
{
if( flags & DIRECTORIES_ONLY )
@@ -759,14 +759,14 @@ static int test_flags( wchar_t *filename,
return 0;
}
}
if( flags & EXECUTABLES_ONLY )
{
if ( waccess( filename, X_OK ) != 0)
return 0;
}
return 1;
}
@@ -776,24 +776,23 @@ static int test_flags( wchar_t *filename,
This function traverses the relevant directory tree looking for
matches, and recurses when needed to handle wildcrards spanning
multiple components and recursive wildcards.
multiple components and recursive wildcards.
*/
static int wildcard_expand_internal( const wchar_t *wc,
static int wildcard_expand_internal( const wchar_t *wc,
const wchar_t *base_dir,
int flags,
array_list_t *out )
{
/* Points to the end of the current wildcard segment */
wchar_t *wc_end;
/* Variables for traversing a directory */
struct wdirent *next;
DIR *dir;
/* The result returned */
int res = 0;
/* Length of the directory to search in */
int base_len;
@@ -806,24 +805,24 @@ static int wildcard_expand_internal( const wchar_t *wc,
/* Description for completions */
string_buffer_t sb_desc;
// debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
if( reader_interrupted() )
{
return -1;
}
if( !wc || !base_dir || !out)
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
return 0;
}
if( flags & ACCEPT_INCOMPLETE )
{
/*
Avoid excessive number of returned matches for wc ending with a *
{
/*
Avoid excessive number of returned matches for wc ending with a *
*/
int len = wcslen(wc);
if( len && (wc[len-1]==ANY_STRING) )
@@ -832,7 +831,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
foo[len-1]=0;
int res = wildcard_expand_internal( foo, base_dir, flags, out );
free( foo );
return res;
return res;
}
}
@@ -841,7 +840,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
*/
dir_string = base_dir[0]==L'\0'?L".":base_dir;
if( !(dir = wopendir( dir_string )))
{
return 0;
@@ -852,7 +851,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
/*
Test for recursive match string in current segment
*/
*/
wc_recursive = wcschr( wc, ANY_STRING_RECURSIVE );
is_recursive = ( wc_recursive && (!wc_end || wc_recursive < wc_end));
@@ -877,13 +876,14 @@ static int wildcard_expand_internal( const wchar_t *wc,
*/
if( flags & ACCEPT_INCOMPLETE )
{
while( (next=wreaddir(dir))!=0 )
wcstring next;
while(wreaddir(dir, next))
{
if( next->d_name[0] != L'.' )
if( next[0] != L'.' )
{
wchar_t *name = next->d_name;
wchar_t *long_name = make_path( base_dir, name );
const wchar_t *name = next.c_str();
const wchar_t *long_name = make_path( base_dir, name );
if( test_flags( long_name, flags ) )
{
wildcard_completion_allocate( out,
@@ -892,33 +892,34 @@ static int wildcard_expand_internal( const wchar_t *wc,
L"",
flags & EXECUTABLES_ONLY );
}
free( long_name );
}
free( (void *)long_name );
}
}
}
else
{
{
res = 1;
al_push_check( out, wcsdup( base_dir ) );
}
}
}
else
{
/*
This is the last wildcard segment, and it is not empty. Match files/directories.
*/
while( (next=wreaddir(dir))!=0 )
wcstring next;
while(wreaddir(dir, next))
{
wchar_t *name = next->d_name;
const wchar_t *name = next.c_str();
if( flags & ACCEPT_INCOMPLETE )
{
wchar_t *long_name = make_path( base_dir, name );
/*
Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
*/
if( wildcard_complete( name,
wc,
@@ -934,12 +935,12 @@ static int wildcard_expand_internal( const wchar_t *wc,
name,
wc,
flags & EXECUTABLES_ONLY );
}
}
free( long_name );
}
else
{
@@ -947,7 +948,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
{
wchar_t *long_name = make_path( base_dir, name );
int skip = 0;
if( is_recursive )
{
/*
@@ -959,9 +960,9 @@ static int wildcard_expand_internal( const wchar_t *wc,
if( !wstat( long_name, &buf ) )
{
skip = S_ISDIR(buf.st_mode);
}
}
}
if( skip )
{
free( long_name );
@@ -983,7 +984,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
Wilcard segment is not the last segment. Recursively call
wildcard_expand for all matching subdirectories.
*/
/*
wc_str is the part of the wildcarded string from the
beginning to the first slash
@@ -1010,20 +1011,20 @@ static int wildcard_expand_internal( const wchar_t *wc,
if( narrow_dir_string )
{
/*
/*
Find out how long the filename can be in a worst case
scenario
*/
ln = pathconf( narrow_dir_string, _PC_NAME_MAX );
ln = pathconf( narrow_dir_string, _PC_NAME_MAX );
/*
If not specified, use som large number as fallback
*/
if( ln < 0 )
ln = MAX_FILE_LENGTH;
ln = MAX_FILE_LENGTH;
free( narrow_dir_string );
}
new_dir= malloc( sizeof(wchar_t)*(base_len+ln+2) );
new_dir= (wchar_t *)malloc( sizeof(wchar_t)*(base_len+ln+2) );
wc_str = wc_end?wcsndup(wc, wc_end-wc):wcsdup(wc);
@@ -1033,19 +1034,20 @@ static int wildcard_expand_internal( const wchar_t *wc,
}
wcscpy( new_dir, base_dir );
while( (next=wreaddir(dir))!=0 )
wcstring next;
while (wreaddir(dir, next))
{
wchar_t *name = next->d_name;
const wchar_t *name = next.c_str();
/*
Test if the file/directory name matches the whole
wildcard element, i.e. regular matching.
*/
int whole_match = wildcard_match2( name, wc_str, 1 );
int partial_match = 0;
/*
/*
If we are doing recursive matching, also check if this
directory matches the part up to the recusrive
wildcard, if so, then we can search all subdirectories
@@ -1057,24 +1059,24 @@ static int wildcard_expand_internal( const wchar_t *wc,
wchar_t *wc_sub = wcsndup( wc, end-wc+1);
partial_match = wildcard_match2( name, wc_sub, 1 );
free( wc_sub );
}
}
if( whole_match || partial_match )
{
int new_len;
struct stat buf;
struct stat buf;
char *dir_str;
int stat_res;
int new_res;
wcscpy(&new_dir[base_len], name );
dir_str = wcs2str( new_dir );
if( dir_str )
{
stat_res = stat( dir_str, &buf );
free( dir_str );
if( !stat_res )
{
if( S_ISDIR(buf.st_mode) )
@@ -1082,7 +1084,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
new_len = wcslen( new_dir );
new_dir[new_len] = L'/';
new_dir[new_len+1] = L'\0';
/*
Regular matching
*/
@@ -1100,51 +1102,51 @@ static int wildcard_expand_internal( const wchar_t *wc,
new_wc++;
}
}
new_res = wildcard_expand_internal( new_wc,
new_dir,
flags,
new_dir,
flags,
out );
if( new_res == -1 )
{
res = -1;
break;
}
}
res |= new_res;
}
/*
Recursive matching
*/
if( partial_match )
{
new_res = wildcard_expand_internal( wcschr( wc, ANY_STRING_RECURSIVE ),
new_res = wildcard_expand_internal( wcschr( wc, ANY_STRING_RECURSIVE ),
new_dir,
flags | WILDCARD_RECURSIVE,
flags | WILDCARD_RECURSIVE,
out );
if( new_res == -1 )
{
res = -1;
break;
}
}
res |= new_res;
}
}
}
}
}
}
}
free( wc_str );
free( new_dir );
}
closedir( dir );
if( flags & ACCEPT_INCOMPLETE )
{
sb_destroy( &sb_desc );
@@ -1154,7 +1156,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
}
int wildcard_expand( const wchar_t *wc,
int wildcard_expand( const wchar_t *wc,
const wchar_t *base_dir,
int flags,
array_list_t *out )
@@ -1162,41 +1164,58 @@ int wildcard_expand( const wchar_t *wc,
int c = al_get_count( out );
int res = wildcard_expand_internal( wc, base_dir, flags, out );
int i;
if( flags & ACCEPT_INCOMPLETE )
{
wchar_t *wc_base=L"";
wchar_t *wc_base_ptr = wcsrchr( wc, L'/' );
string_buffer_t sb;
if( wc_base_ptr )
{
wc_base = wcsndup( wc, (wc_base_ptr-wc)+1 );
}
sb_init( &sb );
for( i=c; i<al_get_count( out ); i++ )
{
completion_t *c = al_get( out, i );
completion_t *c = (completion_t *)al_get( out, i );
if( c->flags & COMPLETE_NO_CASE )
{
sb_clear( &sb );
sb_printf( &sb, L"%ls%ls%ls", base_dir, wc_base, c->completion );
c->completion = halloc_wcsdup( out, (wchar_t *)sb.buff );
}
}
sb_destroy( &sb );
if( wc_base_ptr )
{
free( wc_base );
}
}
return res;
}
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, std::vector<wcstring> &outputs )
{
array_list_t lst;
al_init(&lst);
int res = wildcard_expand(wc.c_str(), base_dir.c_str(), flags, &lst);
int i, max = al_get_count(&lst);
for (i=0; i < max; i++) {
wchar_t *tmp = (wchar_t *)al_get(&lst, i);
outputs.push_back(tmp);
free(tmp);
}
al_destroy(&lst);
return res;
}