Renamed env_vars to env_vars_snapshot_t

Cleanup of non-wcstring version of path_get_path
This commit is contained in:
ridiculousfish 2012-07-20 20:39:31 -07:00
parent b290fd33b9
commit b08fb86637
19 changed files with 95 additions and 194 deletions

View file

@ -114,7 +114,7 @@ int autoload_t::load( const wcstring &cmd, bool reload )
return res;
}
bool autoload_t::can_load( const wcstring &cmd, const env_vars &vars )
bool autoload_t::can_load( const wcstring &cmd, const env_vars_snapshot_t &vars )
{
const wchar_t *path_var_ptr = vars.get(env_var_name.c_str());
if (! path_var_ptr || ! path_var_ptr[0])

View file

@ -35,7 +35,7 @@ struct autoload_function_t : public lru_node_t
struct builtin_script_t;
class env_vars;
class env_vars_snapshot_t;
/**
A class that represents a path from which we can autoload, and the autoloaded contents.
@ -122,7 +122,7 @@ private:
void unload_all( );
/** Check whether the given command could be loaded, but do not load it. */
bool can_load( const wcstring &cmd, const env_vars &vars );
bool can_load( const wcstring &cmd, const env_vars_snapshot_t &vars );
};

View file

@ -609,7 +609,7 @@ static wcstring format_error(const wchar_t *prefix, const wcstring &str) {
Find the full path and commandname from a command string 'str'.
*/
static void parse_cmd_string(const wcstring &str, wcstring &path, wcstring &cmd) {
if (! path_get_path_string(str, path)) {
if (! path_get_path(str, &path)) {
/** Use the empty string as the 'path' for commands that can not be found. */
path = L"";
}

14
env.cpp
View file

@ -1535,7 +1535,7 @@ void env_export_arr(bool recalc, null_terminated_array_t<char> &output)
output = export_array;
}
env_vars::env_vars(const wchar_t * const *keys)
env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t * const *keys)
{
ASSERT_IS_MAIN_THREAD();
for (size_t i=0; keys[i]; i++) {
@ -1546,13 +1546,19 @@ env_vars::env_vars(const wchar_t * const *keys)
}
}
env_vars::env_vars() { }
env_vars_snapshot_t::env_vars_snapshot_t() { }
const wchar_t *env_vars::get(const wchar_t *key) const
const wchar_t *env_vars_snapshot_t::get(const wchar_t *key) const
{
std::map<wcstring, wcstring>::const_iterator iter = vars.find(key);
return (iter == vars.end() ? NULL : iter->second.c_str());
}
const wchar_t * const env_vars::highlighting_keys[] = {L"PATH", L"CDPATH", L"HIGHLIGHT_DELAY", L"fish_function_path", NULL};
env_var_t env_vars_snapshot_t::get(const wcstring &key) const
{
std::map<wcstring, wcstring>::const_iterator iter = vars.find(key);
return (iter == vars.end() ? env_var_t::missing_var() : env_var_t(iter->second));
}
const wchar_t * const env_vars_snapshot_t::highlighting_keys[] = {L"PATH", L"CDPATH", L"HIGHLIGHT_DELAY", L"fish_function_path", NULL};

7
env.h
View file

@ -181,14 +181,15 @@ wcstring_list_t env_get_names( int flags );
*/
int env_set_pwd();
class env_vars {
class env_vars_snapshot_t {
std::map<wcstring, wcstring> vars;
public:
env_vars(const wchar_t * const * keys);
env_vars(void);
env_vars_snapshot_t(const wchar_t * const * keys);
env_vars_snapshot_t(void);
const wchar_t *get(const wchar_t *key) const;
env_var_t get(const wcstring &key) const;
// vars necessary for highlighting
static const wchar_t * const highlighting_keys[];

View file

@ -237,7 +237,7 @@ static void safe_launch_process( process_t *p, const char *actual_cmd, char **ar
// debug( 1, L"exec '%ls'", p->argv[0] );
execve ( wcs2str(p->actual_cmd),
execve ( wcs2str(p->actual_cmd.c_str()),
argv,
envv );
@ -367,7 +367,7 @@ static void launch_process_nofork( process_t *p )
char **argv = wcsv2strv(p->get_argv());
char **envv = env_export_arr( 0 );
char *actual_cmd = wcs2str(p->actual_cmd);
char *actual_cmd = wcs2str(p->actual_cmd.c_str());
/* Bounce to launch_process. This never returns. */
safe_launch_process(p, actual_cmd, argv, envv);

View file

@ -263,13 +263,13 @@ static int iswnumeric( const wchar_t *n )
See if the process described by \c proc matches the commandline \c
cmd
*/
static bool match_pid( const wchar_t *cmd,
static bool match_pid( const wcstring &cmd,
const wchar_t *proc,
int flags,
int *offset)
{
/* Test for a direct match. If the proc string is empty (e.g. the user tries to complete against %), then return an offset pointing at the base command. That ensures that you don't see a bunch of dumb paths when completing against all processes. */
if( proc[0] != L'\0' && wcsncmp( cmd, proc, wcslen( proc ) ) == 0 )
if( proc[0] != L'\0' && wcsncmp( cmd.c_str(), proc, wcslen( proc ) ) == 0 )
{
if( offset )
*offset = 0;
@ -284,7 +284,7 @@ static bool match_pid( const wchar_t *cmd,
{
/* It's a match. Return the offset within the full command. */
if (offset)
*offset = wcslen(cmd) - base_cmd.size();
*offset = cmd.size() - base_cmd.size();
}
return result;
}
@ -629,7 +629,7 @@ static int find_process( const wchar_t *proc,
if( j->command_is_empty() )
continue;
if( match_pid( j->command_wcstr(), proc, flags, &offset ) )
if( match_pid( j->command(), proc, flags, &offset ) )
{
if( flags & ACCEPT_INCOMPLETE )
{
@ -661,7 +661,7 @@ static int find_process( const wchar_t *proc,
{
int offset;
if( p->actual_cmd == 0 )
if( p->actual_cmd.empty() )
continue;
if( match_pid( p->actual_cmd, proc, flags, &offset ) )
@ -669,7 +669,7 @@ static int find_process( const wchar_t *proc,
if( flags & ACCEPT_INCOMPLETE )
{
append_completion( out,
p->actual_cmd + offset + wcslen(proc),
wcstring(p->actual_cmd, offset + wcslen(proc)),
COMPLETE_CHILD_PROCESS_DESC,
0 );
}
@ -698,7 +698,7 @@ static int find_process( const wchar_t *proc,
{
int offset;
if( match_pid( process_name.c_str(), proc, flags, &offset ) )
if( match_pid( process_name, proc, flags, &offset ) )
{
if( flags & ACCEPT_INCOMPLETE )
{

View file

@ -212,7 +212,7 @@ int function_exists( const wcstring &cmd )
return loaded_functions.find(cmd) != loaded_functions.end();
}
int function_exists_no_autoload( const wcstring &cmd, const env_vars &vars )
int function_exists_no_autoload( const wcstring &cmd, const env_vars_snapshot_t &vars )
{
if( parser_keywords_is_reserved(cmd) )
return 0;

View file

@ -17,7 +17,7 @@
#include "event.h"
class parser_t;
class env_vars;
class env_vars_snapshot_t;
/**
Structure describing a function. This is used by the parser to
@ -124,7 +124,7 @@ int function_exists( const wcstring &name );
/**
Returns true if the function with the name name exists, without triggering autoload.
*/
int function_exists_no_autoload( const wcstring &name, const env_vars &vars );
int function_exists_no_autoload( const wcstring &name, const env_vars_snapshot_t &vars );
/**
Returns all function names.

View file

@ -828,7 +828,7 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
return result;
}
bool autosuggest_validate_from_history(const history_item_t &item, file_detection_context_t &detector, const wcstring &working_directory, const env_vars &vars) {
bool autosuggest_validate_from_history(const history_item_t &item, file_detection_context_t &detector, const wcstring &working_directory, const env_vars_snapshot_t &vars) {
ASSERT_IS_BACKGROUND_THREAD();
bool handled = false, suggestionOK = false;
@ -868,12 +868,12 @@ bool autosuggest_validate_from_history(const history_item_t &item, file_detectio
if (! handled) {
bool cmd_ok = false;
wchar_t *full_path = path_get_path(parsed_command.c_str());
if (full_path) {
if (path_get_path(parsed_command, NULL))
{
cmd_ok = true;
free(full_path);
}
else if (builtin_exists(parsed_command) || function_exists_no_autoload(parsed_command, vars)) {
else if (builtin_exists(parsed_command) || function_exists_no_autoload(parsed_command, vars))
{
cmd_ok = true;
}
@ -893,7 +893,7 @@ bool autosuggest_validate_from_history(const history_item_t &item, file_detectio
}
// This function does I/O
static void tokenize( const wchar_t * const buff, std::vector<int> &color, const int pos, wcstring_list_t *error, const wcstring &working_directory, const env_vars &vars) {
static void tokenize( const wchar_t * const buff, std::vector<int> &color, const int pos, wcstring_list_t *error, const wcstring &working_directory, const env_vars_snapshot_t &vars) {
ASSERT_IS_BACKGROUND_THREAD();
wcstring cmd;
@ -1077,8 +1077,7 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
*/
if (! is_cmd && use_command )
{
wcstring tmp;
is_cmd = path_get_path_string( cmd, tmp, vars );
is_cmd = path_get_path( cmd, NULL, vars );
}
/* Maybe it is a path for a implicit cd command. */
@ -1267,7 +1266,7 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
// PCA This function does I/O, (calls is_potential_path, path_get_path, maybe others) and so ought to only run on a background thread
void highlight_shell( const wcstring &buff, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars &vars )
void highlight_shell( const wcstring &buff, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars_snapshot_t &vars )
{
ASSERT_IS_BACKGROUND_THREAD();
@ -1500,7 +1499,7 @@ static void highlight_universal_internal( const wcstring &buffstr,
}
}
void highlight_universal( const wcstring &buff, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars &vars )
void highlight_universal( const wcstring &buff, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars_snapshot_t &vars )
{
assert(buff.size() == color.size());
std::fill(color.begin(), color.end(), 0);

View file

@ -83,7 +83,7 @@ struct file_detection_context_t;
\param pos the cursor position. Used for quote matching, etc.
\param error a list in which a description of each error will be inserted. May be 0, in whcich case no error descriptions will be generated.
*/
void highlight_shell( const wcstring &buffstr, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars &vars );
void highlight_shell( const wcstring &buffstr, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars_snapshot_t &vars );
/**
Perform syntax highlighting for the text in buff. Matching quotes and paranthesis are highlighted. The result is
@ -95,7 +95,7 @@ void highlight_shell( const wcstring &buffstr, std::vector<int> &color, int pos,
\param pos the cursor position. Used for quote matching, etc.
\param error a list in which a description of each error will be inserted. May be 0, in whcich case no error descriptions will be generated.
*/
void highlight_universal( const wcstring &buffstr, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars &vars );
void highlight_universal( const wcstring &buffstr, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars_snapshot_t &vars );
/**
Translate from HIGHLIGHT_* to FISH_COLOR_* according to environment
@ -112,7 +112,7 @@ rgb_color_t highlight_get_color( int highlight, bool is_background );
/** Given a command 'str' from the history, try to determine whether we ought to suggest it by specially recognizing the command.
Returns true if we validated the command. If so, returns by reference whether the suggestion is valid or not.
*/
bool autosuggest_validate_from_history(const history_item_t &item, file_detection_context_t &detector, const wcstring &working_directory, const env_vars &vars);
bool autosuggest_validate_from_history(const history_item_t &item, file_detection_context_t &detector, const wcstring &working_directory, const env_vars_snapshot_t &vars);
/** Given the command line contents 'str', return via reference a suggestion by specially recognizing the command. The suggestion is escaped. Returns true if we recognized the command (even if we couldn't think of a suggestion for it).
*/

View file

@ -57,14 +57,9 @@ static wchar_t *cut_buffer=0;
*/
static int has_xsel()
{
static int called=0;
static int res = 0;
if (!called) {
wchar_t *path = path_get_path( L"xsel" );
res = !!path;
free(path);
called = 1;
static int res=-1;
if (res < 0) {
res = !! path_get_path(L"xsel", NULL);
}
return res;

View file

@ -1979,16 +1979,16 @@ int parser_t::parse_job( process_t *p,
*/
if( current_block->skip )
{
p->actual_cmd = wcsdup(L"");
p->actual_cmd.clear();
}
else
{
int err;
p->actual_cmd = path_get_path( args.at(0).completion.c_str() );
bool has_command = path_get_path(args.at(0).completion, &p->actual_cmd);
err = errno;
bool use_implicit_cd = false;
if (p->actual_cmd == NULL)
if (! has_command)
{
/* If the specified command does not exist, try using an implicit cd. */
wcstring implicit_cd_path;
@ -2008,7 +2008,7 @@ int parser_t::parse_job( process_t *p,
}
/* Check if the specified command exists */
if( p->actual_cmd == NULL && ! use_implicit_cd )
if( ! has_command && ! use_implicit_cd )
{
int tmp;

145
path.cpp
View file

@ -23,110 +23,7 @@
*/
#define MISSING_COMMAND_ERR_MSG _( L"Error while searching for command '%ls'" )
bool path_get_path_string(const wcstring &cmd_str, wcstring &output, const env_vars &vars)
{
const wchar_t * const cmd = cmd_str.c_str();
int err = ENOENT;
debug( 3, L"path_get_path_string( '%ls' )", cmd );
if(wcschr( cmd, L'/' ) != 0 )
{
if( waccess( cmd, X_OK )==0 )
{
struct stat buff;
if(wstat( cmd, &buff ))
{
return false;
}
if (S_ISREG(buff.st_mode))
{
output = cmd_str;
return true;
}
else
{
errno = EACCES;
return false;
}
}
else
{
//struct stat buff;
//wstat( cmd, &buff );
return false;
}
}
else
{
const wchar_t *path = vars.get(L"PATH");
if( path == 0 )
{
if( contains( PREFIX L"/bin", L"/bin", L"/usr/bin" ) )
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
}
else
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
}
}
wcstokenizer tokenizer(path, ARRAY_SEP_STR);
wcstring new_cmd;
while (tokenizer.next(new_cmd))
{
size_t path_len = new_cmd.size();
if (path_len == 0) continue;
append_path_component(new_cmd, cmd_str);
if( waccess( new_cmd, X_OK )==0 )
{
struct stat buff;
if( wstat( new_cmd, &buff )==-1 )
{
if( errno != EACCES )
{
wperror( L"stat" );
}
continue;
}
if( S_ISREG(buff.st_mode) )
{
output = new_cmd;
return true;
}
err = EACCES;
}
else
{
switch( errno )
{
case ENOENT:
case ENAMETOOLONG:
case EACCES:
case ENOTDIR:
break;
default:
{
debug( 1,
MISSING_COMMAND_ERR_MSG,
new_cmd.c_str() );
wperror( L"access" );
}
}
}
}
}
errno = err;
return false;
}
bool path_get_path_string(const wcstring &cmd, wcstring &out_path)
static bool path_get_path_core(const wcstring &cmd, wcstring *out_path, const env_var_t &bin_path_var)
{
int err = ENOENT;
@ -145,7 +42,8 @@ bool path_get_path_string(const wcstring &cmd, wcstring &out_path)
if( S_ISREG(buff.st_mode) )
{
out_path = cmd;
if (out_path)
out_path->assign(cmd);
return true;
}
else
@ -164,21 +62,25 @@ bool path_get_path_string(const wcstring &cmd, wcstring &out_path)
}
else
{
env_var_t path = env_get_string(L"PATH");
if( path.missing() )
wcstring bin_path;
if (! bin_path_var.missing())
{
if( contains( PREFIX L"/bin", L"/bin", L"/usr/bin" ) )
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
bin_path = bin_path_var;
}
else
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
if (contains( PREFIX L"/bin", L"/bin", L"/usr/bin" ))
{
bin_path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
}
else
{
bin_path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
}
}
wcstring nxt_path;
wcstokenizer tokenizer(path, ARRAY_SEP_STR);
wcstokenizer tokenizer(bin_path, ARRAY_SEP_STR);
while (tokenizer.next(nxt_path))
{
if (nxt_path.empty())
@ -197,7 +99,8 @@ bool path_get_path_string(const wcstring &cmd, wcstring &out_path)
}
if( S_ISREG(buff.st_mode) )
{
out_path.swap(nxt_path);
if (out_path)
out_path->swap(nxt_path);
return true;
}
err = EACCES;
@ -228,23 +131,17 @@ bool path_get_path_string(const wcstring &cmd, wcstring &out_path)
return false;
}
wchar_t *path_get_path(const wchar_t *cmd)
bool path_get_path(const wcstring &cmd, wcstring *out_path, const env_vars_snapshot_t &vars)
{
wcstring tmp;
wchar_t *result = NULL;
if (cmd != NULL && path_get_path_string(cmd, tmp))
{
result = wcsdup(tmp.c_str());
}
return result;
return path_get_path_core(cmd, out_path, vars.get(wcstring(L"PATH")));
}
bool path_get_path( const wcstring &cmd, wcstring &output )
bool path_get_path(const wcstring &cmd, wcstring *out_path)
{
return path_get_path_string(cmd, output);
return path_get_path_core(cmd, out_path, env_get_string(L"PATH"));
}
bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env_vars &vars)
bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env_vars_snapshot_t &vars)
{
wchar_t *res = 0;
int err = ENOENT;

16
path.h
View file

@ -29,16 +29,18 @@ bool path_get_config(wcstring &path);
\param cmd The name of the executable.
\return 0 if the command can not be found, the path of the command otherwise. The result should be freed with free().
*/
wchar_t *path_get_path( const wchar_t *cmd );
bool path_get_path( const wcstring &cmd, wcstring &output );
bool path_get_path( const wcstring &cmd, wcstring *output_or_NULL );
/**
A version of path_get_path() that takes the user's PATH variable from the given environment variable snapshot
*/
class env_vars_snapshot_t;
bool path_get_path(const wcstring &cmd, wcstring *output_or_NULL, const env_vars_snapshot_t &vars);
/** Returns whether the path can be used for an implicit cd command; if so, also returns the path by reference (if desired). This requires it to start with one of the allowed prefixes (., .., ~) and resolve to a directory. */
bool path_can_be_implicit_cd(const wcstring &path, wcstring *out_path = NULL, const wchar_t *wd = NULL);
class env_vars;
bool path_get_path_string(const wcstring &cmd, wcstring &output);
bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars &vars);
/**
Returns the full path of the specified directory, using the CDPATH
variable as a list of base directories for relative paths. The
@ -59,7 +61,7 @@ bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars
wchar_t *path_allocate_cdpath( const wcstring &in, const wchar_t *wd = NULL);
bool path_can_get_cdpath(const wcstring &in, const wchar_t *wd = NULL);
bool path_get_cdpath_string(const wcstring &in, wcstring &out, const env_vars &vars);
bool path_get_cdpath_string(const wcstring &in, wcstring &out, const env_vars_snapshot_t &vars);
/**
Remove double slashes and trailing slashes from a path,

View file

@ -1212,7 +1212,6 @@ void proc_sanity_check()
validate_pointer( p->get_argv(), _( L"Process argument list" ), 0 );
validate_pointer( p->argv0(), _( L"Process name" ), 0 );
validate_pointer( p->next, _( L"Process list pointer" ), 1 );
validate_pointer( p->actual_cmd, _( L"Process command" ), 1 );
if ( (p->stopped & (~0x00000001)) != 0 )
{

20
proc.h
View file

@ -144,7 +144,7 @@ class process_t
process_t() :
argv_array(),
type(0),
actual_cmd(NULL),
actual_cmd(),
pid(0),
pipe_write_fd(0),
pipe_read_fd(0),
@ -164,7 +164,6 @@ class process_t
{
if (this->next != NULL)
delete this->next;
free((void *)actual_cmd); //may be NULL
}
/**
@ -203,8 +202,8 @@ class process_t
return argv0_narrow.get();
}
/** actual command to pass to exec in case of EXTERNAL or INTERNAL_EXEC. malloc'd! */
const wchar_t *actual_cmd;
/** actual command to pass to exec in case of EXTERNAL or INTERNAL_EXEC. */
wcstring actual_cmd;
/** process ID */
pid_t pid;
@ -311,7 +310,7 @@ class job_t
job. It is used for displaying messages about job status
on the terminal.
*/
wcstring command;
wcstring command_str;
/* narrow copy so we don't have to convert after fork */
narrow_string_rep_t command_narrow;
@ -323,7 +322,7 @@ class job_t
public:
job_t(job_id_t jobid) :
command(),
command_str(),
first_process(NULL),
pgid(0),
tmodes(),
@ -346,17 +345,20 @@ class job_t
}
/** Returns whether the command is empty. */
bool command_is_empty() const { return command.empty(); }
bool command_is_empty() const { return command_str.empty(); }
/** Returns the command as a wchar_t *. */
const wchar_t *command_wcstr() const { return command.c_str(); }
const wchar_t *command_wcstr() const { return command_str.c_str(); }
/** Returns the command */
const wcstring &command() const { return command_str; }
/** Returns the command as a char *. */
const char *command_cstr() const { return command_narrow.get(); }
/** Sets the command */
void set_command(const wcstring &cmd) {
command = cmd;
command_str = cmd;
command_narrow.set(cmd);
}

View file

@ -1078,7 +1078,7 @@ struct autosuggestion_context_t {
history_search_t searcher;
file_detection_context_t detector;
const wcstring working_directory;
const env_vars vars;
const env_vars_snapshot_t vars;
wcstring_list_t commands_to_load;
const unsigned int generation_count;
@ -1091,7 +1091,7 @@ struct autosuggestion_context_t {
searcher(*history, term, HISTORY_SEARCH_TYPE_PREFIX),
detector(history, term),
working_directory(get_working_directory()),
vars(env_vars::highlighting_keys),
vars(env_vars_snapshot_t::highlighting_keys),
generation_count(s_generation_count),
has_tried_reloading(false)
{
@ -2223,7 +2223,7 @@ public:
const highlight_function_t highlight_function;
/** Environment variables */
const env_vars vars;
const env_vars_snapshot_t vars;
/** When the request was made */
const double when;
@ -2235,7 +2235,7 @@ public:
string_to_highlight(pbuff),
match_highlight_pos(phighlight_pos),
highlight_function(phighlight_func),
vars(env_vars::highlighting_keys),
vars(env_vars_snapshot_t::highlighting_keys),
when(timef()),
generation_count(s_generation_count)
{

View file

@ -145,8 +145,8 @@ void reader_set_complete_function( complete_function_t );
/**
The type of a highlight function.
*/
class env_vars;
typedef void (*highlight_function_t)( const wcstring &, std::vector<int> &, int, wcstring_list_t *, const env_vars &vars );
class env_vars_snapshot_t;
typedef void (*highlight_function_t)( const wcstring &, std::vector<int> &, int, wcstring_list_t *, const env_vars_snapshot_t &vars );
/**
Specify function for syntax highlighting. The function must take these arguments: