aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Łukasz Niemier <lukasz@niemier.pl>2012-11-18 11:23:22 +0100
committerGravatar Łukasz Niemier <lukasz@niemier.pl>2012-11-18 11:23:22 +0100
commit47df1ae40adecd0a02fc7dd06ab0745cb18c3fe0 (patch)
tree13bf3e8fdcae60fdfb5fa5e26c95818dc7a49790
parentb79854ad1aa814d9d35d76a1929b4726fa4bffa5 (diff)
Remove trailing whitespaces and change tabs to spaces
-rw-r--r--CHANGELOG4
-rw-r--r--autoload.cpp92
-rw-r--r--autoload.h40
-rw-r--r--build_tools/fish_shell.pmdoc/index.xml8
-rw-r--r--builtin.cpp5932
-rw-r--r--builtin.h20
-rw-r--r--builtin_commandline.cpp1048
-rw-r--r--builtin_complete.cpp1046
-rw-r--r--builtin_jobs.cpp500
-rw-r--r--builtin_set.cpp1250
-rw-r--r--builtin_test.cpp242
-rw-r--r--builtin_ulimit.cpp798
-rw-r--r--color.cpp50
-rw-r--r--color.h52
-rw-r--r--common.cpp2474
-rw-r--r--common.h164
-rw-r--r--complete.cpp2158
-rw-r--r--complete.h120
-rw-r--r--configure.ac826
-rw-r--r--env.cpp1776
-rw-r--r--env.h18
-rw-r--r--env_universal.cpp606
-rw-r--r--env_universal.h14
-rw-r--r--env_universal_common.cpp1278
-rw-r--r--env_universal_common.h114
-rw-r--r--event.cpp726
-rw-r--r--event.h80
-rw-r--r--exec.cpp1908
-rw-r--r--exec.h4
-rw-r--r--expand.cpp1560
-rw-r--r--expand.h76
-rw-r--r--fallback.cpp1524
-rw-r--r--fallback.h92
-rw-r--r--fish.cpp646
-rw-r--r--fish_indent.cpp562
-rw-r--r--fish_pager.cpp2116
-rw-r--r--fish_tests.cpp934
-rw-r--r--fishd.cpp1222
-rw-r--r--function.cpp140
-rw-r--r--function.h94
-rw-r--r--highlight.cpp1782
-rw-r--r--highlight.h12
-rw-r--r--history.cpp394
-rw-r--r--history.h142
-rw-r--r--input.cpp792
-rw-r--r--input.h70
-rw-r--r--input_common.cpp326
-rw-r--r--input_common.h18
-rw-r--r--intern.cpp16
-rw-r--r--io.cpp172
-rw-r--r--io.h82
-rw-r--r--iothread.cpp206
-rw-r--r--iothread.h6
-rw-r--r--key_reader.cpp140
-rw-r--r--kill.cpp172
-rw-r--r--kill.h4
-rw-r--r--lru.h72
-rw-r--r--mimedb.cpp2200
-rw-r--r--output.cpp658
-rw-r--r--output.h58
-rw-r--r--parse_util.cpp1236
-rw-r--r--parse_util.h40
-rw-r--r--parser.cpp5520
-rw-r--r--parser.h306
-rw-r--r--parser_keywords.cpp64
-rw-r--r--parser_keywords.h8
-rw-r--r--path.cpp392
-rw-r--r--path.h14
-rw-r--r--postfork.cpp640
-rw-r--r--postfork.h4
-rw-r--r--print_help.cpp26
-rw-r--r--print_help.h6
-rw-r--r--proc.cpp1654
-rw-r--r--proc.h358
-rw-r--r--reader.cpp3730
-rw-r--r--reader.h18
-rw-r--r--sanity.cpp60
-rw-r--r--sanity.h4
-rw-r--r--screen.cpp1166
-rw-r--r--screen.h94
-rw-r--r--set_color.cpp408
-rw-r--r--share/completions/abook.fish2
-rw-r--r--share/completions/adduser.fish2
-rw-r--r--share/completions/dvipdf.fish6
-rw-r--r--share/completions/dvipdfm.fish8
-rw-r--r--share/completions/find.fish6
-rw-r--r--share/completions/kill.fish2
-rw-r--r--share/completions/killall.fish2
-rw-r--r--share/completions/latexmk.fish2
-rw-r--r--share/completions/lpadmin.fish4
-rw-r--r--share/completions/mocp.fish2
-rw-r--r--share/completions/pactree.fish2
-rw-r--r--share/completions/pkgfile.fish2
-rw-r--r--share/completions/ps2pdf.fish6
-rw-r--r--share/completions/rfkill.fish2
-rw-r--r--share/completions/setxkbmap.fish2
-rw-r--r--share/completions/tree.fish14
-rw-r--r--share/completions/xdg-mime.fish2
-rw-r--r--share/completions/xrandr.fish10
-rw-r--r--share/completions/xrdb.fish4
-rw-r--r--share/functions/__fish_complete_atool.fish2
-rw-r--r--share/functions/__fish_complete_cd.fish2
-rw-r--r--share/functions/__fish_complete_list.fish2
-rw-r--r--share/functions/__fish_complete_lpr.fish14
-rw-r--r--share/functions/__fish_complete_pacman.fish2
-rw-r--r--share/functions/__fish_complete_python.fish6
-rw-r--r--share/functions/__fish_complete_subcommand.fish2
-rw-r--r--share/functions/__fish_complete_svn.fish34
-rw-r--r--share/functions/__fish_complete_svn_diff.fish2
-rw-r--r--share/functions/__fish_complete_tex.fish2
-rw-r--r--share/functions/__fish_make_completion_signals.fish2
-rw-r--r--share/functions/__fish_print_help.fish2
-rw-r--r--share/functions/dirh.fish2
-rw-r--r--share/functions/funced.fish4
-rw-r--r--share/functions/history.fish34
-rwxr-xr-xshare/tools/create_manpage_completions.py176
-rwxr-xr-xshare/tools/deroff.py158
-rw-r--r--signal.cpp912
-rw-r--r--tokenizer.cpp1040
-rw-r--r--tokenizer.h88
-rw-r--r--util.cpp144
-rw-r--r--util.h18
-rw-r--r--wgetopt.cpp748
-rw-r--r--wgetopt.h132
-rw-r--r--wildcard.cpp1588
-rw-r--r--wildcard.h62
-rw-r--r--wutil.cpp200
-rw-r--r--wutil.h12
-rw-r--r--xdgmime.cpp158
-rw-r--r--xdgmime.h24
-rw-r--r--xdgmimealias.cpp62
-rw-r--r--xdgmimealias.h6
-rw-r--r--xdgmimeglob.cpp126
-rw-r--r--xdgmimeglob.h12
-rw-r--r--xdgmimeint.cpp94
-rw-r--r--xdgmimeint.h18
-rw-r--r--xdgmimemagic.cpp364
-rw-r--r--xdgmimemagic.h8
-rw-r--r--xdgmimeparent.cpp112
-rw-r--r--xdgmimeparent.h6
140 files changed, 30922 insertions, 30922 deletions
diff --git a/CHANGELOG b/CHANGELOG
index da7b3594..1d877a48 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,3 @@
24-01-2012 Jan Kanis
- * Added a changelog file
- * removed unescaping if the 'commandline' builtin is called without the -o (tokenise) flag
+ * Added a changelog file
+ * removed unescaping if the 'commandline' builtin is called without the -o (tokenise) flag
diff --git a/autoload.cpp b/autoload.cpp
index 8f77f74f..d57e69d9 100644
--- a/autoload.cpp
+++ b/autoload.cpp
@@ -1,5 +1,5 @@
/** \file autoload.cpp
-
+
The classes responsible for autoloading functions and completions.
*/
@@ -31,7 +31,7 @@ file_access_attempt_t access_file(const wcstring &path, int mode) {
result.accessible = true;
}
}
-
+
// Note that we record the last checked time after the call, on the assumption that in a slow filesystem, the lag comes before the kernel check, not after.
result.stale = false;
result.last_checked = time(NULL);
@@ -56,7 +56,7 @@ autoload_t::~autoload_t() {
void autoload_t::node_was_evicted(autoload_function_t *node) {
// This should only ever happen on the main thread
ASSERT_IS_MAIN_THREAD();
-
+
// Tell ourselves that the command was removed if it was loaded
if (! node->is_loaded)
this->command_removed(node->key);
@@ -70,18 +70,18 @@ int autoload_t::unload( const wcstring &cmd )
int autoload_t::load( const wcstring &cmd, bool reload )
{
- int res;
- CHECK_BLOCK( 0 );
+ int res;
+ CHECK_BLOCK( 0 );
ASSERT_IS_MAIN_THREAD();
-
- env_var_t path_var = env_get_string( env_var_name );
-
+
+ env_var_t path_var = env_get_string( env_var_name );
+
/*
Do we know where to look?
*/
if( path_var.empty() )
return 0;
-
+
/* Check if the lookup path has changed. If so, drop all loaded files. path_var may only be inspected on the main thread. */
if( path_var != this->last_path )
{
@@ -89,32 +89,32 @@ int autoload_t::load( const wcstring &cmd, bool reload )
scoped_lock locker(lock);
this->evict_all_nodes();
}
-
+
/** Warn and fail on infinite recursion. It's OK to do this because this function is only called on the main thread. */
if (this->is_loading(cmd))
{
- debug( 0,
- _( L"Could not autoload item '%ls', it is already being autoloaded. "
- L"This is a circular dependency in the autoloading scripts, please remove it."),
+ debug( 0,
+ _( L"Could not autoload item '%ls', it is already being autoloaded. "
+ L"This is a circular dependency in the autoloading scripts, please remove it."),
cmd.c_str() );
return 1;
}
-
+
/* Mark that we're loading this */
is_loading_set.insert(cmd);
/* Get the list of paths from which we will try to load */
std::vector<wcstring> path_list;
- tokenize_variable_array( path_var, path_list );
+ tokenize_variable_array( path_var, path_list );
+
+ /* Try loading it */
+ res = this->locate_file_and_maybe_load_it( cmd, true, reload, path_list );
- /* Try loading it */
- res = this->locate_file_and_maybe_load_it( cmd, true, reload, path_list );
-
/* Clean up */
bool erased = !! is_loading_set.erase(cmd);
assert(erased);
-
- return res;
+
+ return res;
}
bool autoload_t::can_load( const wcstring &cmd, const env_vars_snapshot_t &vars )
@@ -124,7 +124,7 @@ bool autoload_t::can_load( const wcstring &cmd, const env_vars_snapshot_t &vars
return false;
std::vector<wcstring> path_list;
- tokenize_variable_array( path_var, path_list );
+ tokenize_variable_array( path_var, path_list );
return this->locate_file_and_maybe_load_it( cmd, false, false, path_list );
}
@@ -141,7 +141,7 @@ void autoload_t::unload_all(void) {
/** Check whether the given command is loaded. */
bool autoload_t::has_tried_loading( const wcstring &cmd )
{
- scoped_lock locker(lock);
+ scoped_lock locker(lock);
autoload_function_t * func = this->get_node(cmd);
return func != NULL;
}
@@ -170,30 +170,30 @@ autoload_function_t *autoload_t::get_autoloaded_function_with_creation(const wcs
This internal helper function does all the real work. By using two
functions, the internal function can return on various places in
the code, and the caller can take care of various cleanup work.
-
+
cmd: the command name ('grep')
really_load: whether to actually parse it as a function, or just check it it exists
reload: whether to reload it if it's already loaded
path_list: the set of paths to check
-
+
Result: if really_load is true, returns whether the function was loaded. Otherwise returns whether the function existed.
*/
bool autoload_t::locate_file_and_maybe_load_it( const wcstring &cmd, bool really_load, bool reload, const wcstring_list_t &path_list )
{
/* Note that we are NOT locked in this function! */
- size_t i;
- bool reloaded = 0;
+ size_t i;
+ bool reloaded = 0;
/* Try using a cached function. If we really want the function to be loaded, require that it be really loaded. If we're not reloading, allow stale functions. */
{
bool allow_stale_functions = ! reload;
-
+
/* Take a lock */
scoped_lock locker(lock);
-
+
/* Get the function */
autoload_function_t * func = this->get_node(cmd);
-
+
/* Determine if we can use this cached function */
bool use_cached;
if (! func) {
@@ -209,19 +209,19 @@ bool autoload_t::locate_file_and_maybe_load_it( const wcstring &cmd, bool really
/* I guess we can use it */
use_cached = true;
}
-
+
/* If we can use this function, return whether we were able to access it */
if (use_cached) {
return func->is_internalized || func->access.accessible;
}
- }
+ }
/* The source of the script will end up here */
wcstring script_source;
bool has_script_source = false;
-
+
/* Whether we found an accessible file */
bool found_file = false;
-
+
/* Look for built-in scripts via a binary search */
const builtin_script_t *matching_builtin_script = NULL;
if (builtin_script_count > 0)
@@ -238,18 +238,18 @@ bool autoload_t::locate_file_and_maybe_load_it( const wcstring &cmd, bool really
if (matching_builtin_script) {
has_script_source = true;
script_source = str2wcstring(matching_builtin_script->def);
-
+
/* Make a node representing this function */
scoped_lock locker(lock);
autoload_function_t *func = this->get_autoloaded_function_with_creation(cmd, really_load);
-
+
/* This function is internalized */
func->is_internalized = true;
-
+
/* It's a fiction to say the script is loaded at this point, but we're definitely going to load it down below. */
if (really_load) func->is_loaded = true;
}
-
+
if (! has_script_source)
{
/* Iterate over path searching for suitable completion files */
@@ -262,38 +262,38 @@ bool autoload_t::locate_file_and_maybe_load_it( const wcstring &cmd, bool really
if (access.accessible) {
/* Found it! */
found_file = true;
-
+
/* Now we're actually going to take the lock. */
scoped_lock locker(lock);
autoload_function_t *func = this->get_node(cmd);
-
+
/* Generate the source if we need to load it */
bool need_to_load_function = really_load && (func == NULL || func->access.mod_time != access.mod_time || ! func->is_loaded);
if (need_to_load_function) {
-
+
/* Generate the script source */
wcstring esc = escape_string(path, 1);
script_source = L". " + esc;
has_script_source = true;
-
+
/* Remove any loaded command because we are going to reload it. Note that this will deadlock if command_removed calls back into us. */
if (func && func->is_loaded) {
command_removed(cmd);
func->is_placeholder = false;
}
-
+
/* Mark that we're reloading it */
reloaded = true;
}
-
+
/* Create the function if we haven't yet. This does not load it. Do not trigger eviction unless we are actually loading, because we don't want to evict off of the main thread. */
if (! func) {
func = get_autoloaded_function_with_creation(cmd, really_load);
}
-
+
/* It's a fiction to say the script is loaded at this point, but we're definitely going to load it down below. */
if (need_to_load_function) func->is_loaded = true;
-
+
/* Unconditionally record our access time */
func->access = access;
@@ -323,7 +323,7 @@ bool autoload_t::locate_file_and_maybe_load_it( const wcstring &cmd, bool really
func->access.last_checked = time(NULL);
}
}
-
+
/* If we have a script, either built-in or a file source, then run it */
if (really_load && has_script_source)
{
diff --git a/autoload.h b/autoload.h
index 4b0b1139..3635d5f2 100644
--- a/autoload.h
+++ b/autoload.h
@@ -25,7 +25,7 @@ struct file_access_attempt_t {
file_access_attempt_t access_file(const wcstring &path, int mode);
struct autoload_function_t : public lru_node_t
-{
+{
autoload_function_t(const wcstring &key) : lru_node_t(key), access(), is_loaded(false), is_placeholder(false), is_internalized(false) { }
file_access_attempt_t access; /** The last access attempt */
bool is_loaded; /** Whether we have actually loaded this function */
@@ -48,61 +48,61 @@ private:
/** The environment variable name */
const wcstring env_var_name;
-
+
/** Builtin script array */
const struct builtin_script_t *const builtin_scripts;
-
+
/** Builtin script count */
const size_t builtin_script_count;
/** The path from which we most recently autoloaded */
wcstring last_path;
- /**
- A table containing all the files that are currently being
- loaded. This is here to help prevent recursion.
- */
+ /**
+ A table containing all the files that are currently being
+ loaded. This is here to help prevent recursion.
+ */
std::set<wcstring> is_loading_set;
bool is_loading(const wcstring &name) const {
return is_loading_set.find(name) != is_loading_set.end();
}
-
+
void remove_all_functions(void) {
this->evict_all_nodes();
}
-
+
bool locate_file_and_maybe_load_it( const wcstring &cmd, bool really_load, bool reload, const wcstring_list_t &path_list );
-
+
virtual void node_was_evicted(autoload_function_t *node);
autoload_function_t *get_autoloaded_function_with_creation(const wcstring &cmd, bool allow_eviction);
-
- protected:
+
+ protected:
/** Overridable callback for when a command is removed */
virtual void command_removed(const wcstring &cmd) { }
-
+
public:
-
+
/** Create an autoload_t for the given environment variable name */
autoload_t(const wcstring &env_var_name_var, const builtin_script_t *scripts, size_t script_count );
-
+
/** Destructor */
virtual ~autoload_t();
-
+
/**
Autoload the specified file, if it exists in the specified path. Do
not load it multiple times unless it's timestamp changes or
parse_util_unload is called.
- Autoloading one file may unload another.
+ Autoloading one file may unload another.
\param cmd the filename to search for. The suffix '.fish' is always added to this name
\param on_unload a callback function to run if a suitable file is found, which has not already been run. unload will also be called for old files which are unloaded.
\param reload wheter to recheck file timestamps on already loaded files
*/
int load( const wcstring &cmd, bool reload );
-
+
/** Check whether we have tried loading the given command. Does not do any I/O. */
bool has_tried_loading( const wcstring &cmd );
@@ -115,12 +115,12 @@ private:
\return non-zero if the file was removed, zero if the file had not yet been loaded
*/
int unload( const wcstring &cmd );
-
+
/**
Unloads all files.
*/
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_snapshot_t &vars );
diff --git a/build_tools/fish_shell.pmdoc/index.xml b/build_tools/fish_shell.pmdoc/index.xml
index 4dcfeacb..0da74990 100644
--- a/build_tools/fish_shell.pmdoc/index.xml
+++ b/build_tools/fish_shell.pmdoc/index.xml
@@ -13,25 +13,25 @@ This release is beta r2.\
{\colortbl;\red255\green255\blue255;}
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
-\f0\fs26 \cf0 Run
+\f0\fs26 \cf0 Run
\f1 fish
\f0 at the command line to start it up! Some useful commands:\
\
Interactively set your colors from a web page:\
\
-
+
\f1 fish_config
\f0 \
\
Update man-page completions:\
\
-
+
\f1 fish_update_completions
\f0 \
\
Make fish your default shell:\
\
-
+
\f1 chsh -s /usr/local/bin/fish\
\f0 \
diff --git a/builtin.cpp b/builtin.cpp
index 21d16402..707d0cd8 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -1,19 +1,19 @@
/** \file builtin.c
- Functions for executing builtin functions.
+ Functions for executing builtin functions.
- How to add a new builtin function:
+ How to add a new builtin function:
- 1). Create a function in builtin.c with the following signature:
+ 1). Create a function in builtin.c with the following signature:
- <tt>static int builtin_NAME( parser_t &parser, wchar_t ** args )</tt>
+ <tt>static int builtin_NAME( parser_t &parser, wchar_t ** args )</tt>
- where NAME is the name of the builtin, and args is a zero-terminated list of arguments.
+ where NAME is the name of the builtin, and args is a zero-terminated list of arguments.
- 2). Add a line like { L"NAME", &builtin_NAME, N_(L"Bla bla bla") }, to the builtin_data_t variable. The description is used by the completion system. Note that this array is sorted!
+ 2). Add a line like { L"NAME", &builtin_NAME, N_(L"Bla bla bla") }, to the builtin_data_t variable. The description is used by the completion system. Note that this array is sorted!
- 3). Create a file doc_src/NAME.txt, containing the manual for the builtin in Doxygen-format. Check the other builtin manuals for proper syntax.
+ 3). Create a file doc_src/NAME.txt, containing the manual for the builtin in Doxygen-format. Check the other builtin manuals for proper syntax.
- 4). Use 'darcs add doc_src/NAME.txt' to start tracking changes to the documentation file.
+ 4). Use 'darcs add doc_src/NAME.txt' to start tracking changes to the documentation file.
*/
@@ -82,23 +82,23 @@
#define FG_MSG _( L"Send job %d, '%ls' to foreground\n" )
/**
- Datastructure to describe a builtin.
+ Datastructure to describe a builtin.
*/
struct builtin_data_t
{
- /**
- Name of the builtin
- */
- const wchar_t *name;
- /**
- Function pointer tothe builtin implementation
- */
- int (*func)(parser_t &parser, wchar_t **argv);
- /**
- Description of what the builtin does
- */
- const wchar_t *desc;
-
+ /**
+ Name of the builtin
+ */
+ const wchar_t *name;
+ /**
+ Function pointer tothe builtin implementation
+ */
+ int (*func)(parser_t &parser, wchar_t **argv);
+ /**
+ Description of what the builtin does
+ */
+ const wchar_t *desc;
+
bool operator<(const wcstring &) const;
bool operator<(const builtin_data_t *) const;
};
@@ -162,35 +162,35 @@ static const io_chain_t *real_io;
*/
static int builtin_count_args( wchar_t **argv )
{
- int argc = 1;
- while( argv[argc] != 0 )
- {
- argc++;
- }
- return argc;
+ int argc = 1;
+ while( argv[argc] != 0 )
+ {
+ argc++;
+ }
+ return argc;
}
-/**
- This function works like wperror, but it prints its result into
- the sb_err string instead of to stderr. Used by the builtin
- commands.
+/**
+ This function works like wperror, but it prints its result into
+ the sb_err string instead of to stderr. Used by the builtin
+ commands.
*/
static void builtin_wperror( const wchar_t *s)
{
- if( s != 0 )
- {
+ if( s != 0 )
+ {
stderr_buffer.append(s);
stderr_buffer.append(L": ");
- }
- char *err = strerror( errno );
- wchar_t *werr = str2wcs( err );
- if( werr )
- {
+ }
+ char *err = strerror( errno );
+ wchar_t *werr = str2wcs( err );
+ if( werr )
+ {
stderr_buffer.append(werr);
stderr_buffer.push_back(L'\n');
- free( werr );
- }
+ free( werr );
+ }
}
/**
@@ -198,12 +198,12 @@ static void builtin_wperror( const wchar_t *s)
*/
static int count_char( const wchar_t *str, wchar_t c )
{
- int res = 0;
- for( ; *str; str++ )
- {
- res += (*str==c);
- }
- return res;
+ int res = 0;
+ for( ; *str; str++ )
+ {
+ res += (*str==c);
+ }
+ return res;
}
wcstring builtin_help_get( parser_t &parser, const wchar_t *name )
@@ -212,15 +212,15 @@ wcstring builtin_help_get( parser_t &parser, const wchar_t *name )
wcstring out;
const wcstring name_esc = escape_string(name, 1);
const wcstring cmd = format_string(L"__fish_print_help %ls", name_esc.c_str());
- if( exec_subshell( cmd, lst ) >= 0 )
- {
- for( size_t i=0; i<lst.size(); i++ )
- {
+ if( exec_subshell( cmd, lst ) >= 0 )
+ {
+ for( size_t i=0; i<lst.size(); i++ )
+ {
out.append(lst.at(i));
out.push_back(L'\n');
- }
- }
- return out;
+ }
+ }
+ return out;
}
/**
@@ -231,116 +231,116 @@ wcstring builtin_help_get( parser_t &parser, const wchar_t *name )
message is about to be printed to an interactive screen, it may be
shortened to fit the screen.
-
+
*/
static void builtin_print_help( parser_t &parser, const wchar_t *cmd, wcstring &b )
{
-
- int is_short = 0;
-
- if( &b == &stderr_buffer )
- {
+
+ int is_short = 0;
+
+ if( &b == &stderr_buffer )
+ {
stderr_buffer.append(parser.current_line());
- }
-
- const wcstring h = builtin_help_get( parser, cmd );
-
- if( !h.size())
- return;
-
- wchar_t *str = wcsdup( h.c_str() );
- if( str )
- {
-
- if( &b == &stderr_buffer )
- {
-
- /*
- Interactive mode help to screen - only print synopsis if
- the rest won't fit
- */
-
- int screen_height, lines;
-
- screen_height = common_get_height();
- lines = count_char( str, L'\n' );
- if( !get_is_interactive() || (lines > 2*screen_height/3) )
- {
- wchar_t *pos;
- int cut=0;
- int i;
-
- is_short = 1;
-
- /*
- First move down 4 lines
- */
-
- pos = str;
- for( i=0; (i<4) && pos && *pos; i++ )
- {
- pos = wcschr( pos+1, L'\n' );
- }
-
- if( pos && *pos )
- {
-
- /*
- Then find the next empty line
- */
- for( ; *pos; pos++ )
- {
- if( *pos == L'\n' )
- {
- wchar_t *pos2;
- int is_empty = 1;
-
- for( pos2 = pos+1; *pos2; pos2++ )
- {
- if( *pos2 == L'\n' )
- break;
-
- if( *pos2 != L'\t' && *pos2 !=L' ' )
- {
- is_empty = 0;
- break;
- }
- }
- if( is_empty )
- {
- /*
- And cut it
- */
- *(pos2+1)=L'\0';
- cut = 1;
- break;
- }
- }
- }
- }
-
- /*
- We did not find a good place to cut message to
- shorten it - so we make sure we don't print
- anything.
- */
- if( !cut )
- {
- *str = 0;
- }
-
- }
- }
-
+ }
+
+ const wcstring h = builtin_help_get( parser, cmd );
+
+ if( !h.size())
+ return;
+
+ wchar_t *str = wcsdup( h.c_str() );
+ if( str )
+ {
+
+ if( &b == &stderr_buffer )
+ {
+
+ /*
+ Interactive mode help to screen - only print synopsis if
+ the rest won't fit
+ */
+
+ int screen_height, lines;
+
+ screen_height = common_get_height();
+ lines = count_char( str, L'\n' );
+ if( !get_is_interactive() || (lines > 2*screen_height/3) )
+ {
+ wchar_t *pos;
+ int cut=0;
+ int i;
+
+ is_short = 1;
+
+ /*
+ First move down 4 lines
+ */
+
+ pos = str;
+ for( i=0; (i<4) && pos && *pos; i++ )
+ {
+ pos = wcschr( pos+1, L'\n' );
+ }
+
+ if( pos && *pos )
+ {
+
+ /*
+ Then find the next empty line
+ */
+ for( ; *pos; pos++ )
+ {
+ if( *pos == L'\n' )
+ {
+ wchar_t *pos2;
+ int is_empty = 1;
+
+ for( pos2 = pos+1; *pos2; pos2++ )
+ {
+ if( *pos2 == L'\n' )
+ break;
+
+ if( *pos2 != L'\t' && *pos2 !=L' ' )
+ {
+ is_empty = 0;
+ break;
+ }
+ }
+ if( is_empty )
+ {
+ /*
+ And cut it
+ */
+ *(pos2+1)=L'\0';
+ cut = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ We did not find a good place to cut message to
+ shorten it - so we make sure we don't print
+ anything.
+ */
+ if( !cut )
+ {
+ *str = 0;
+ }
+
+ }
+ }
+
b.append(str);
- if( is_short )
- {
+ if( is_short )
+ {
append_format(b, _(L"%ls: Type 'help %ls' for related documentation\n\n"), cmd, cmd);
- }
-
- free( str );
- }
+ }
+
+ free( str );
+ }
}
/**
@@ -349,7 +349,7 @@ static void builtin_print_help( parser_t &parser, const wchar_t *cmd, wcstring &
static void builtin_unknown_option( parser_t &parser, const wchar_t *cmd, const wchar_t *opt )
{
append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, cmd, opt);
- builtin_print_help( parser, cmd, stderr_buffer );
+ builtin_print_help( parser, cmd, stderr_buffer );
}
/**
@@ -358,7 +358,7 @@ static void builtin_unknown_option( parser_t &parser, const wchar_t *cmd, const
static void builtin_missing_argument( parser_t &parser, const wchar_t *cmd, const wchar_t *opt )
{
append_format(stderr_buffer, BUILTIN_ERR_MISSING, cmd, opt);
- builtin_print_help( parser, cmd, stderr_buffer );
+ builtin_print_help( parser, cmd, stderr_buffer );
}
/*
@@ -396,29 +396,29 @@ int builtin_test( parser_t &parser, wchar_t **argv );
*/
static void builtin_bind_list()
{
- size_t i;
+ size_t i;
wcstring_list_t lst;
- input_mapping_get_names( lst );
-
- for( i=0; i<lst.size(); i++ )
- {
- wcstring seq = lst.at(i);
-
+ input_mapping_get_names( lst );
+
+ for( i=0; i<lst.size(); i++ )
+ {
+ wcstring seq = lst.at(i);
+
wcstring ecmd;
input_mapping_get(seq, ecmd);
- ecmd = escape_string(ecmd, 1);
-
- wcstring tname;
- if( input_terminfo_get_name(seq, tname) )
- {
- append_format(stdout_buffer, L"bind -k %ls %ls\n", tname.c_str(), ecmd.c_str() );
- }
- else
- {
- const wcstring eseq = escape_string( seq, 1 );
- append_format(stdout_buffer, L"bind %ls %ls\n", eseq.c_str(), ecmd.c_str() );
- }
- }
+ ecmd = escape_string(ecmd, 1);
+
+ wcstring tname;
+ if( input_terminfo_get_name(seq, tname) )
+ {
+ append_format(stdout_buffer, L"bind -k %ls %ls\n", tname.c_str(), ecmd.c_str() );
+ }
+ else
+ {
+ const wcstring eseq = escape_string( seq, 1 );
+ append_format(stdout_buffer, L"bind %ls %ls\n", eseq.c_str(), ecmd.c_str() );
+ }
+ }
}
/**
@@ -430,13 +430,13 @@ static void builtin_bind_list()
*/
static void builtin_bind_key_names( int all )
{
- const wcstring_list_t names = input_terminfo_get_names(!all);
- for( size_t i=0; i<names.size(); i++ )
- {
+ const wcstring_list_t names = input_terminfo_get_names(!all);
+ for( size_t i=0; i<names.size(); i++ )
+ {
const wcstring &name = names.at(i);
-
- append_format(stdout_buffer, L"%ls\n", name.c_str() );
- }
+
+ append_format(stdout_buffer, L"%ls\n", name.c_str() );
+ }
}
/**
@@ -446,12 +446,12 @@ static void builtin_bind_key_names( int all )
static void builtin_bind_function_names()
{
wcstring_list_t names = input_function_get_names();
-
- for( size_t i=0; i<names.size(); i++ )
- {
- const wchar_t *seq = names.at(i).c_str();
- append_format(stdout_buffer, L"%ls\n", seq );
- }
+
+ for( size_t i=0; i<names.size(); i++ )
+ {
+ const wchar_t *seq = names.at(i).c_str();
+ append_format(stdout_buffer, L"%ls\n", seq );
+ }
}
/**
@@ -460,49 +460,49 @@ static void builtin_bind_function_names()
static int builtin_bind_add( wchar_t *seq, wchar_t *cmd, int terminfo )
{
- if( terminfo )
- {
- const wchar_t *seq2 = input_terminfo_get_sequence( seq );
- if( seq2 )
- {
- input_mapping_add( seq2, cmd );
- }
- else
- {
- switch( errno )
- {
-
- case ENOENT:
- {
- append_format(stderr_buffer, _(L"%ls: No key with name '%ls' found\n"), L"bind", seq );
- break;
- }
-
- case EILSEQ:
- {
- append_format(stderr_buffer, _(L"%ls: Key with name '%ls' does not have any mapping\n"), L"bind", seq );
- break;
- }
-
- default:
- {
- append_format(stderr_buffer, _(L"%ls: Unknown error trying to bind to key named '%ls'\n"), L"bind", seq );
- break;
- }
-
- }
-
- return 1;
- }
-
- }
- else
- {
- input_mapping_add( seq, cmd );
- }
-
- return 0;
-
+ if( terminfo )
+ {
+ const wchar_t *seq2 = input_terminfo_get_sequence( seq );
+ if( seq2 )
+ {
+ input_mapping_add( seq2, cmd );
+ }
+ else
+ {
+ switch( errno )
+ {
+
+ case ENOENT:
+ {
+ append_format(stderr_buffer, _(L"%ls: No key with name '%ls' found\n"), L"bind", seq );
+ break;
+ }
+
+ case EILSEQ:
+ {
+ append_format(stderr_buffer, _(L"%ls: Key with name '%ls' does not have any mapping\n"), L"bind", seq );
+ break;
+ }
+
+ default:
+ {
+ append_format(stderr_buffer, _(L"%ls: Unknown error trying to bind to key named '%ls'\n"), L"bind", seq );
+ break;
+ }
+
+ }
+
+ return 1;
+ }
+
+ }
+ else
+ {
+ input_mapping_add( seq, cmd );
+ }
+
+ return 0;
+
}
/**
@@ -513,27 +513,27 @@ static int builtin_bind_add( wchar_t *seq, wchar_t *cmd, int terminfo )
*/
static void builtin_bind_erase( wchar_t **seq, int all )
{
- if( all )
- {
- size_t i;
- wcstring_list_t lst;
- input_mapping_get_names( lst );
-
- for( i=0; i<lst.size(); i++ )
- {
- input_mapping_erase( lst.at(i).c_str() );
- }
-
- }
- else
- {
- while( *seq )
- {
- input_mapping_erase( *seq++ );
- }
-
- }
-
+ if( all )
+ {
+ size_t i;
+ wcstring_list_t lst;
+ input_mapping_get_names( lst );
+
+ for( i=0; i<lst.size(); i++ )
+ {
+ input_mapping_erase( lst.at(i).c_str() );
+ }
+
+ }
+ else
+ {
+ while( *seq )
+ {
+ input_mapping_erase( *seq++ );
+ }
+
+ }
+
}
@@ -543,173 +543,173 @@ static void builtin_bind_erase( wchar_t **seq, int all )
static int builtin_bind( parser_t &parser, wchar_t **argv )
{
- enum
- {
- BIND_INSERT,
- BIND_ERASE,
- BIND_KEY_NAMES,
- BIND_FUNCTION_NAMES
- }
- ;
-
- int argc=builtin_count_args( argv );
- int mode = BIND_INSERT;
- int res = STATUS_BUILTIN_OK;
- int all = 0;
-
- int use_terminfo = 0;
-
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"all", no_argument, 0, 'a'
- }
- ,
- {
- L"erase", no_argument, 0, 'e'
- }
- ,
- {
- L"function-names", no_argument, 0, 'f'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- L"key", no_argument, 0, 'k'
- }
- ,
- {
- L"key-names", no_argument, 0, 'K'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
- int opt = wgetopt_long( argc,
- argv,
- L"aehkKf",
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
- argv[0],
- long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
-
- case 'a':
- all = 1;
- break;
-
- case 'e':
- mode = BIND_ERASE;
- break;
-
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
- case 'k':
- use_terminfo = 1;
- break;
-
- case 'K':
- mode = BIND_KEY_NAMES;
- break;
-
- case 'f':
- mode = BIND_FUNCTION_NAMES;
- break;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- }
-
- }
-
- switch( mode )
- {
-
- case BIND_ERASE:
- {
- builtin_bind_erase( &argv[woptind], all);
- break;
- }
-
- case BIND_INSERT:
- {
- switch( argc-woptind )
- {
- case 0:
- {
- builtin_bind_list();
- break;
- }
-
- case 2:
- {
- builtin_bind_add(argv[woptind], argv[woptind+1], use_terminfo );
- break;
- }
-
- default:
- {
- res = STATUS_BUILTIN_ERROR;
- append_format(stderr_buffer, _(L"%ls: Expected zero or two parameters, got %d"), argv[0], argc-woptind );
- break;
- }
- }
- break;
- }
-
- case BIND_KEY_NAMES:
- {
- builtin_bind_key_names( all );
- break;
- }
-
-
- case BIND_FUNCTION_NAMES:
- {
- builtin_bind_function_names();
- break;
- }
-
-
- default:
- {
- res = STATUS_BUILTIN_ERROR;
- append_format(stderr_buffer, _(L"%ls: Invalid state\n"), argv[0] );
- break;
- }
- }
-
- return res;
+ enum
+ {
+ BIND_INSERT,
+ BIND_ERASE,
+ BIND_KEY_NAMES,
+ BIND_FUNCTION_NAMES
+ }
+ ;
+
+ int argc=builtin_count_args( argv );
+ int mode = BIND_INSERT;
+ int res = STATUS_BUILTIN_OK;
+ int all = 0;
+
+ int use_terminfo = 0;
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"all", no_argument, 0, 'a'
+ }
+ ,
+ {
+ L"erase", no_argument, 0, 'e'
+ }
+ ,
+ {
+ L"function-names", no_argument, 0, 'f'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ L"key", no_argument, 0, 'k'
+ }
+ ,
+ {
+ L"key-names", no_argument, 0, 'K'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+ int opt = wgetopt_long( argc,
+ argv,
+ L"aehkKf",
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
+ append_format(stderr_buffer,
+ BUILTIN_ERR_UNKNOWN,
+ argv[0],
+ long_options[opt_index].name );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+
+ case 'a':
+ all = 1;
+ break;
+
+ case 'e':
+ mode = BIND_ERASE;
+ break;
+
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case 'k':
+ use_terminfo = 1;
+ break;
+
+ case 'K':
+ mode = BIND_KEY_NAMES;
+ break;
+
+ case 'f':
+ mode = BIND_FUNCTION_NAMES;
+ break;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ }
+
+ }
+
+ switch( mode )
+ {
+
+ case BIND_ERASE:
+ {
+ builtin_bind_erase( &argv[woptind], all);
+ break;
+ }
+
+ case BIND_INSERT:
+ {
+ switch( argc-woptind )
+ {
+ case 0:
+ {
+ builtin_bind_list();
+ break;
+ }
+
+ case 2:
+ {
+ builtin_bind_add(argv[woptind], argv[woptind+1], use_terminfo );
+ break;
+ }
+
+ default:
+ {
+ res = STATUS_BUILTIN_ERROR;
+ append_format(stderr_buffer, _(L"%ls: Expected zero or two parameters, got %d"), argv[0], argc-woptind );
+ break;
+ }
+ }
+ break;
+ }
+
+ case BIND_KEY_NAMES:
+ {
+ builtin_bind_key_names( all );
+ break;
+ }
+
+
+ case BIND_FUNCTION_NAMES:
+ {
+ builtin_bind_function_names();
+ break;
+ }
+
+
+ default:
+ {
+ res = STATUS_BUILTIN_ERROR;
+ append_format(stderr_buffer, _(L"%ls: Invalid state\n"), argv[0] );
+ break;
+ }
+ }
+
+ return res;
}
/**
@@ -717,147 +717,147 @@ static int builtin_bind( parser_t &parser, wchar_t **argv )
*/
static int builtin_block( parser_t &parser, wchar_t **argv )
{
- enum
- {
- UNSET,
- GLOBAL,
- LOCAL,
- }
- ;
-
- int scope=UNSET;
- int erase = 0;
- int argc=builtin_count_args( argv );
- int type = (1<<EVENT_ANY);
-
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"erase", no_argument, 0, 'e'
- }
- ,
- {
- L"local", no_argument, 0, 'l'
- }
- ,
- {
- L"global", no_argument, 0, 'g'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"elgh",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
- argv[0],
- long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
- case 'g':
- scope = GLOBAL;
- break;
-
- case 'l':
- scope = LOCAL;
- break;
-
- case 'e':
- erase = 1;
- break;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- }
-
- }
-
- if( erase )
- {
- if( scope != UNSET )
- {
- append_format(stderr_buffer, _( L"%ls: Can not specify scope when removing block\n" ), argv[0] );
- return STATUS_BUILTIN_ERROR;
- }
-
+ enum
+ {
+ UNSET,
+ GLOBAL,
+ LOCAL,
+ }
+ ;
+
+ int scope=UNSET;
+ int erase = 0;
+ int argc=builtin_count_args( argv );
+ int type = (1<<EVENT_ANY);
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"erase", no_argument, 0, 'e'
+ }
+ ,
+ {
+ L"local", no_argument, 0, 'l'
+ }
+ ,
+ {
+ L"global", no_argument, 0, 'g'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"elgh",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
+ append_format(stderr_buffer,
+ BUILTIN_ERR_UNKNOWN,
+ argv[0],
+ long_options[opt_index].name );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case 'g':
+ scope = GLOBAL;
+ break;
+
+ case 'l':
+ scope = LOCAL;
+ break;
+
+ case 'e':
+ erase = 1;
+ break;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ }
+
+ }
+
+ if( erase )
+ {
+ if( scope != UNSET )
+ {
+ append_format(stderr_buffer, _( L"%ls: Can not specify scope when removing block\n" ), argv[0] );
+ return STATUS_BUILTIN_ERROR;
+ }
+
if (parser.global_event_blocks.empty())
- {
- append_format(stderr_buffer, _( L"%ls: No blocks defined\n" ), argv[0] );
- return STATUS_BUILTIN_ERROR;
- }
- parser.global_event_blocks.pop_front();
- }
- else
- {
- block_t *block=parser.current_block;
+ {
+ append_format(stderr_buffer, _( L"%ls: No blocks defined\n" ), argv[0] );
+ return STATUS_BUILTIN_ERROR;
+ }
+ parser.global_event_blocks.pop_front();
+ }
+ else
+ {
+ block_t *block=parser.current_block;
event_blockage_t eb = {};
- eb.typemask = type;
-
- switch( scope )
- {
- case LOCAL:
- {
- if( !block->outer )
- block=0;
- break;
- }
- case GLOBAL:
- {
- block=0;
- }
- case UNSET:
- {
- while( block &&
- block->type() != FUNCTION_CALL &&
- block->type() != FUNCTION_CALL_NO_SHADOW )
- block = block->outer;
- }
- }
- if( block )
- {
+ eb.typemask = type;
+
+ switch( scope )
+ {
+ case LOCAL:
+ {
+ if( !block->outer )
+ block=0;
+ break;
+ }
+ case GLOBAL:
+ {
+ block=0;
+ }
+ case UNSET:
+ {
+ while( block &&
+ block->type() != FUNCTION_CALL &&
+ block->type() != FUNCTION_CALL_NO_SHADOW )
+ block = block->outer;
+ }
+ }
+ if( block )
+ {
block->event_blocks.push_front(eb);
- }
- else
- {
+ }
+ else
+ {
parser.global_event_blocks.push_front(eb);
- }
- }
+ }
+ }
- return STATUS_BUILTIN_OK;
+ return STATUS_BUILTIN_OK;
}
@@ -869,83 +869,83 @@ static int builtin_block( parser_t &parser, wchar_t **argv )
*/
static int builtin_builtin( parser_t &parser, wchar_t **argv )
{
- int argc=builtin_count_args( argv );
- int list=0;
-
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"names", no_argument, 0, 'n'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"nh",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ int argc=builtin_count_args( argv );
+ int list=0;
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"names", no_argument, 0, 'n'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"nh",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
+ builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
+ return STATUS_BUILTIN_ERROR;
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
- case 'n':
- list=1;
- break;
+ case 'n':
+ list=1;
+ break;
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
- }
+ }
- }
+ }
- if( list )
- {
+ if( list )
+ {
wcstring_list_t names = builtin_get_names();
sort(names.begin(), names.end());
-
- for( size_t i=0; i<names.size(); i++ )
- {
- const wchar_t *el = names.at(i).c_str();
-
- stdout_buffer.append(el);
+
+ for( size_t i=0; i<names.size(); i++ )
+ {
+ const wchar_t *el = names.at(i).c_str();
+
+ stdout_buffer.append(el);
stdout_buffer.append(L"\n");
- }
- }
- return STATUS_BUILTIN_OK;
+ }
+ }
+ return STATUS_BUILTIN_OK;
}
/**
@@ -953,68 +953,68 @@ static int builtin_builtin( parser_t &parser, wchar_t **argv )
*/
static int builtin_emit( parser_t &parser, wchar_t **argv )
{
- int argc=builtin_count_args( argv );
-
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"h",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ int argc=builtin_count_args( argv );
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"h",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ }
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
+ }
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
+ for (; woptind < argc; woptind++ )
+ {
+ event_fire_generic( argv[woptind] );
+ }
- }
+ return STATUS_BUILTIN_OK;
- }
- for (; woptind < argc; woptind++ )
- {
- event_fire_generic( argv[woptind] );
- }
- return STATUS_BUILTIN_OK;
-
-
-
}
@@ -1025,58 +1025,58 @@ static int builtin_emit( parser_t &parser, wchar_t **argv )
*/
static int builtin_generic( parser_t &parser, wchar_t **argv )
{
- int argc=builtin_count_args( argv );
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"h",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ int argc=builtin_count_args( argv );
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"h",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
- }
+ }
- }
- return STATUS_BUILTIN_ERROR;
+ }
+ return STATUS_BUILTIN_ERROR;
}
/**
@@ -1086,20 +1086,20 @@ static int builtin_generic( parser_t &parser, wchar_t **argv )
static void functions_def( const wcstring &name, wcstring &out )
{
CHECK( ! name.empty(), );
-
+
wcstring desc, def;
function_get_desc(name, &desc);
function_get_definition(name, &def);
- event_t search(EVENT_ANY);
+ event_t search(EVENT_ANY);
- search.function_name = name;
+ search.function_name = name;
- std::vector<event_t *> ev;
- event_get( &search, &ev );
+ std::vector<event_t *> ev;
+ event_get( &search, &ev );
out.append(L"function ");
-
+
/* Typically we prefer to specify the function name first, e.g. "function foo --description bar"
But If the function name starts with a -, we'll need to output it after all the options. */
bool defer_function_name = (name.at(0) == L'-');
@@ -1107,82 +1107,82 @@ static void functions_def( const wcstring &name, wcstring &out )
out.append(name);
}
- if (! desc.empty())
- {
+ if (! desc.empty())
+ {
wcstring esc_desc = escape_string(desc, true);
- out.append(L" --description ");
+ out.append(L" --description ");
out.append(esc_desc);
- }
-
- if( !function_get_shadows( name ) )
- {
- out.append(L" --no-scope-shadowing" );
- }
-
- for( size_t i=0; i<ev.size(); i++ )
- {
- event_t *next = ev.at(i);
- switch( next->type )
- {
- case EVENT_SIGNAL:
- {
- append_format( out, L" --on-signal %ls", sig2wcs( next->param1.signal ) );
- break;
- }
-
- case EVENT_VARIABLE:
- {
- append_format( out, L" --on-variable %ls", next->str_param1.c_str() );
- break;
- }
-
- case EVENT_EXIT:
- {
- if( next->param1.pid > 0 )
- append_format( out, L" --on-process-exit %d", next->param1.pid );
- else
- append_format( out, L" --on-job-exit %d", -next->param1.pid );
- break;
- }
-
- case EVENT_JOB_ID:
- {
- const job_t *j = job_get( next->param1.job_id );
- if( j )
- append_format( out, L" --on-job-exit %d", j->pgid );
- break;
- }
-
- case EVENT_GENERIC:
- {
- append_format( out, L" --on-event %ls", next->str_param1.c_str() );
- break;
- }
-
- }
-
- }
-
-
+ }
+
+ if( !function_get_shadows( name ) )
+ {
+ out.append(L" --no-scope-shadowing" );
+ }
+
+ for( size_t i=0; i<ev.size(); i++ )
+ {
+ event_t *next = ev.at(i);
+ switch( next->type )
+ {
+ case EVENT_SIGNAL:
+ {
+ append_format( out, L" --on-signal %ls", sig2wcs( next->param1.signal ) );
+ break;
+ }
+
+ case EVENT_VARIABLE:
+ {
+ append_format( out, L" --on-variable %ls", next->str_param1.c_str() );
+ break;
+ }
+
+ case EVENT_EXIT:
+ {
+ if( next->param1.pid > 0 )
+ append_format( out, L" --on-process-exit %d", next->param1.pid );
+ else
+ append_format( out, L" --on-job-exit %d", -next->param1.pid );
+ break;
+ }
+
+ case EVENT_JOB_ID:
+ {
+ const job_t *j = job_get( next->param1.job_id );
+ if( j )
+ append_format( out, L" --on-job-exit %d", j->pgid );
+ break;
+ }
+
+ case EVENT_GENERIC:
+ {
+ append_format( out, L" --on-event %ls", next->str_param1.c_str() );
+ break;
+ }
+
+ }
+
+ }
+
+
wcstring_list_t named = function_get_named_arguments( name );
- if( named.size() > 0 )
- {
- append_format( out, L" --argument" );
- for( size_t i=0; i < named.size(); i++ )
- {
- append_format( out, L" %ls", named.at(i).c_str() );
- }
- }
+ if( named.size() > 0 )
+ {
+ append_format( out, L" --argument" );
+ for( size_t i=0; i < named.size(); i++ )
+ {
+ append_format( out, L" %ls", named.at(i).c_str() );
+ }
+ }
/* Output the function name if we deferred it */
if ( defer_function_name ){
out.append(L" -- ");
out.append(name);
}
-
+
/* This forced tab is sort of crummy - not all functions start with a tab */
append_format( out, L"\n\t%ls", def.c_str());
-
+
/* Append a newline before the 'end', unless there already is one there */
if (! string_suffixes_string(L"\n", def)) {
out.push_back(L'\n');
@@ -1196,271 +1196,271 @@ static void functions_def( const wcstring &name, wcstring &out )
*/
static int builtin_functions( parser_t &parser, wchar_t **argv )
{
- int i;
- int erase=0;
- wchar_t *desc=0;
-
- int argc=builtin_count_args( argv );
- int list=0;
- int show_hidden=0;
- int res = STATUS_BUILTIN_OK;
- int query = 0;
- int copy = 0;
-
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"erase", no_argument, 0, 'e'
- }
- ,
- {
- L"description", required_argument, 0, 'd'
- }
- ,
- {
- L"names", no_argument, 0, 'n'
- }
- ,
- {
- L"all", no_argument, 0, 'a'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- L"query", no_argument, 0, 'q'
- }
- ,
- {
- L"copy", no_argument, 0, 'c'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"ed:nahqc",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ int i;
+ int erase=0;
+ wchar_t *desc=0;
+
+ int argc=builtin_count_args( argv );
+ int list=0;
+ int show_hidden=0;
+ int res = STATUS_BUILTIN_OK;
+ int query = 0;
+ int copy = 0;
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"erase", no_argument, 0, 'e'
+ }
+ ,
+ {
+ L"description", required_argument, 0, 'd'
+ }
+ ,
+ {
+ L"names", no_argument, 0, 'n'
+ }
+ ,
+ {
+ L"all", no_argument, 0, 'a'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ L"query", no_argument, 0, 'q'
+ }
+ ,
+ {
+ L"copy", no_argument, 0, 'c'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"ed:nahqc",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
-
- return STATUS_BUILTIN_ERROR;
-
- case 'e':
- erase=1;
- break;
-
- case 'd':
- desc=woptarg;
- break;
-
- case 'n':
- list=1;
- break;
-
- case 'a':
- show_hidden=1;
- break;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
- case 'q':
- query = 1;
- break;
-
- case 'c':
- copy = 1;
- break;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- }
-
- }
-
- /*
- Erase, desc, query, copy and list are mutually exclusive
- */
- if( (erase + (!!desc) + list + query + copy) > 1 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Invalid combination of options\n" ),
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
-
- if( erase )
- {
- int i;
- for( i=woptind; i<argc; i++ )
- function_remove( argv[i] );
- return STATUS_BUILTIN_OK;
- }
- else if( desc )
- {
- wchar_t *func;
-
- if( argc-woptind != 1 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Expected exactly one function name\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
- func = argv[woptind];
- if( !function_exists( func ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Function '%ls' does not exist\n" ),
- argv[0],
- func );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
-
- function_set_desc( func, desc );
-
- return STATUS_BUILTIN_OK;
- }
- else if( list || (argc==woptind))
- {
- int is_screen = !builtin_out_redirect && isatty(1);
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+
+ return STATUS_BUILTIN_ERROR;
+
+ case 'e':
+ erase=1;
+ break;
+
+ case 'd':
+ desc=woptarg;
+ break;
+
+ case 'n':
+ list=1;
+ break;
+
+ case 'a':
+ show_hidden=1;
+ break;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case 'q':
+ query = 1;
+ break;
+
+ case 'c':
+ copy = 1;
+ break;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ }
+
+ }
+
+ /*
+ Erase, desc, query, copy and list are mutually exclusive
+ */
+ if( (erase + (!!desc) + list + query + copy) > 1 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Invalid combination of options\n" ),
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ if( erase )
+ {
+ int i;
+ for( i=woptind; i<argc; i++ )
+ function_remove( argv[i] );
+ return STATUS_BUILTIN_OK;
+ }
+ else if( desc )
+ {
+ wchar_t *func;
+
+ if( argc-woptind != 1 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Expected exactly one function name\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+ func = argv[woptind];
+ if( !function_exists( func ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Function '%ls' does not exist\n" ),
+ argv[0],
+ func );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ function_set_desc( func, desc );
+
+ return STATUS_BUILTIN_OK;
+ }
+ else if( list || (argc==woptind))
+ {
+ int is_screen = !builtin_out_redirect && isatty(1);
size_t i;
- wcstring_list_t names = function_get_names( show_hidden );
+ wcstring_list_t names = function_get_names( show_hidden );
std::sort(names.begin(), names.end());
- if( is_screen )
- {
+ if( is_screen )
+ {
wcstring buff;
- for( i=0; i<names.size(); i++ )
- {
+ for( i=0; i<names.size(); i++ )
+ {
buff.append(names.at(i));
buff.append(L", ");
- }
-
- write_screen( buff, stdout_buffer );
- }
- else
- {
- for( i=0; i<names.size(); i++ )
- {
- stdout_buffer.append(names.at(i).c_str());
+ }
+
+ write_screen( buff, stdout_buffer );
+ }
+ else
+ {
+ for( i=0; i<names.size(); i++ )
+ {
+ stdout_buffer.append(names.at(i).c_str());
stdout_buffer.append(L"\n");
- }
- }
-
- return STATUS_BUILTIN_OK;
- }
- else if( copy )
- {
- wcstring current_func;
- wcstring new_func;
-
- if( argc-woptind != 2 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Expected exactly two names (current function name, and new function name)\n" ),
- argv[0] );
- builtin_print_help ( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
- current_func = argv[woptind];
- new_func = argv[woptind+1];
-
- if( !function_exists( current_func ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Function '%ls' does not exist\n" ),
- argv[0],
- current_func.c_str() );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
-
- if( (wcsfuncname( new_func.c_str() ) != 0) || parser_keywords_is_reserved( new_func ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Illegal function name '%ls'\n"),
- argv[0],
- new_func.c_str());
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
- // keep things simple: don't allow existing names to be copy targets.
- if( function_exists( new_func ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n" ),
- argv[0],
- new_func.c_str(),
- current_func.c_str() );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
-
- if( function_copy( current_func, new_func ) )
- return STATUS_BUILTIN_OK;
- return STATUS_BUILTIN_ERROR;
- }
-
- for( i=woptind; i<argc; i++ )
- {
- if( !function_exists( argv[i] ) )
- res++;
- else
- {
- if( !query )
- {
- if( i != woptind)
- stdout_buffer.append( L"\n" );
-
- functions_def( argv[i], stdout_buffer );
- }
- }
- }
-
- return res;
+ }
+ }
+
+ return STATUS_BUILTIN_OK;
+ }
+ else if( copy )
+ {
+ wcstring current_func;
+ wcstring new_func;
+
+ if( argc-woptind != 2 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Expected exactly two names (current function name, and new function name)\n" ),
+ argv[0] );
+ builtin_print_help ( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+ current_func = argv[woptind];
+ new_func = argv[woptind+1];
+
+ if( !function_exists( current_func ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Function '%ls' does not exist\n" ),
+ argv[0],
+ current_func.c_str() );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ if( (wcsfuncname( new_func.c_str() ) != 0) || parser_keywords_is_reserved( new_func ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Illegal function name '%ls'\n"),
+ argv[0],
+ new_func.c_str());
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ // keep things simple: don't allow existing names to be copy targets.
+ if( function_exists( new_func ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n" ),
+ argv[0],
+ new_func.c_str(),
+ current_func.c_str() );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ if( function_copy( current_func, new_func ) )
+ return STATUS_BUILTIN_OK;
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ for( i=woptind; i<argc; i++ )
+ {
+ if( !function_exists( argv[i] ) )
+ res++;
+ else
+ {
+ if( !query )
+ {
+ if( i != woptind)
+ stdout_buffer.append( L"\n" );
+
+ functions_def( argv[i], stdout_buffer );
+ }
+ }
+ }
+
+ return res;
}
static unsigned int builtin_echo_digit(wchar_t wc, unsigned int base)
@@ -1496,7 +1496,7 @@ static unsigned int builtin_echo_digit(wchar_t wc, unsigned int base)
/* Parse a numeric escape sequence in str, returning whether we succeeded.
Also return the number of characters consumed and the resulting value.
Supported escape sequences:
-
+
\0nnn: octal value, zero to three digits
\nnn: octal value, one to three digits
\xhh: hex value, one to two digits
@@ -1506,7 +1506,7 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons
bool success = false;
unsigned char val = 0; //resulting character
unsigned int start = 0; //the first character of the numeric part of the sequence
-
+
unsigned int base = 0, max_digits = 0;
if (builtin_echo_digit(str[0], 8) != UINT_MAX)
{
@@ -1522,11 +1522,11 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons
// Hex escape
base = 16;
max_digits = 2;
-
+
// Skip the x
start = 1;
}
-
+
if (base != 0)
{
unsigned int idx;
@@ -1536,7 +1536,7 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons
if (digit == UINT_MAX) break;
val = val * base + digit;
}
-
+
// We succeeded if we consumed at least one digit
if (idx > start)
{
@@ -1558,7 +1558,7 @@ static int builtin_echo( parser_t &parser, wchar_t **argv )
/* Skip first arg */
if (! *argv++)
return STATUS_BUILTIN_ERROR;
-
+
/* Process options */
bool print_newline = true, print_spaces = true, interpret_special_chars = false;
while (*argv) {
@@ -1575,10 +1575,10 @@ static int builtin_echo( parser_t &parser, wchar_t **argv )
}
argv++;
}
-
+
/* The special character \c can be used to indicate no more output */
bool continue_output = true;
-
+
for (size_t idx = 0; continue_output && argv[idx] != NULL; idx++) {
if (print_spaces && idx > 0)
@@ -1608,9 +1608,9 @@ static int builtin_echo( parser_t &parser, wchar_t **argv )
case L't': wc = L'\t'; break;
case L'v': wc = L'\v'; break;
case L'\\': wc = L'\\'; break;
-
+
case L'c': wc = 0; continue_output = false; break;
-
+
default:
{
/* Octal and hex escape sequences */
@@ -1629,10 +1629,10 @@ static int builtin_echo( parser_t &parser, wchar_t **argv )
break;
}
}
-
+
/* Skip over characters that were part of this escape sequence (but not the backslash, which will be handled by the loop increment */
j += consumed;
-
+
if (continue_output)
stdout_buffer.push_back(wc);
}
@@ -1646,8 +1646,8 @@ static int builtin_echo( parser_t &parser, wchar_t **argv )
/** The pwd builtin. We don't respect -P to resolve symbolic links because we try to always resolve them. */
static int builtin_pwd( parser_t &parser, wchar_t **argv )
{
- wchar_t dir_path[4096];
- wchar_t *res = wgetcwd( dir_path, 4096 );
+ wchar_t dir_path[4096];
+ wchar_t *res = wgetcwd( dir_path, 4096 );
if (res == NULL) {
return STATUS_BUILTIN_ERROR;
} else {
@@ -1663,348 +1663,348 @@ static int builtin_pwd( parser_t &parser, wchar_t **argv )
*/
static int builtin_function( parser_t &parser, wchar_t **argv )
{
- int argc = builtin_count_args( argv );
- int res=STATUS_BUILTIN_OK;
- wchar_t *desc=0;
- std::vector<event_t> events;
-
+ int argc = builtin_count_args( argv );
+ int res=STATUS_BUILTIN_OK;
+ wchar_t *desc=0;
+ std::vector<event_t> events;
+
std::auto_ptr<wcstring_list_t> named_arguments(NULL);
- wchar_t *name = 0;
- bool shadows = true;
-
- woptind=0;
+ wchar_t *name = 0;
+ bool shadows = true;
+
+ woptind=0;
function_def_block_t * const fdb = new function_def_block_t();
- parser.push_block( fdb );
-
- static const struct woption
- long_options[] =
- {
- {
- L"description", required_argument, 0, 'd'
- }
- ,
- {
- L"on-signal", required_argument, 0, 's'
- }
- ,
- {
- L"on-job-exit", required_argument, 0, 'j'
- }
- ,
- {
- L"on-process-exit", required_argument, 0, 'p'
- }
- ,
- {
- L"on-variable", required_argument, 0, 'v'
- }
- ,
- {
- L"on-event", required_argument, 0, 'e'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- L"argument-names", no_argument, 0, 'a'
- }
- ,
- {
- L"no-scope-shadowing", no_argument, 0, 'S'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 && (!res ) )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"d:s:j:p:v:e:haS",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ parser.push_block( fdb );
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"description", required_argument, 0, 'd'
+ }
+ ,
+ {
+ L"on-signal", required_argument, 0, 's'
+ }
+ ,
+ {
+ L"on-job-exit", required_argument, 0, 'j'
+ }
+ ,
+ {
+ L"on-process-exit", required_argument, 0, 'p'
+ }
+ ,
+ {
+ L"on-variable", required_argument, 0, 'v'
+ }
+ ,
+ {
+ L"on-event", required_argument, 0, 'e'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ L"argument-names", no_argument, 0, 'a'
+ }
+ ,
+ {
+ L"no-scope-shadowing", no_argument, 0, 'S'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 && (!res ) )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"d:s:j:p:v:e:haS",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- res = 1;
- break;
-
- case 'd':
- desc=woptarg;
- break;
-
- case 's':
- {
- int sig = wcs2sig( woptarg );
-
- if( sig < 0 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Unknown signal '%ls'\n" ),
- argv[0],
- woptarg );
- res=1;
- break;
- }
+ res = 1;
+ break;
+
+ case 'd':
+ desc=woptarg;
+ break;
+
+ case 's':
+ {
+ int sig = wcs2sig( woptarg );
+
+ if( sig < 0 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Unknown signal '%ls'\n" ),
+ argv[0],
+ woptarg );
+ res=1;
+ break;
+ }
events.push_back(event_t::signal_event(sig));
- break;
- }
-
- case 'v':
- {
- if( wcsvarname( woptarg ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Invalid variable name '%ls'\n" ),
- argv[0],
- woptarg );
- res=STATUS_BUILTIN_ERROR;
- break;
- }
+ break;
+ }
+
+ case 'v':
+ {
+ if( wcsvarname( woptarg ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Invalid variable name '%ls'\n" ),
+ argv[0],
+ woptarg );
+ res=STATUS_BUILTIN_ERROR;
+ break;
+ }
events.push_back(event_t::variable_event(woptarg));
- break;
- }
+ break;
+ }
- case 'e':
- {
+ case 'e':
+ {
events.push_back(event_t::generic_event(woptarg));
- break;
- }
-
- case 'j':
- case 'p':
- {
- pid_t pid;
- wchar_t *end;
+ break;
+ }
+
+ case 'j':
+ case 'p':
+ {
+ pid_t pid;
+ wchar_t *end;
event_t e(EVENT_ANY);
-
- if( ( opt == 'j' ) &&
- ( wcscasecmp( woptarg, L"caller" ) == 0 ) )
- {
- int job_id = -1;
-
- if( is_subshell )
- {
- block_t *b = parser.current_block;
-
- while( b && (b->type() != SUBST) )
- b = b->outer;
-
- if( b )
- {
- b=b->outer;
- }
- if( b->job )
- {
- job_id = b->job->job_id;
- }
- }
-
- if( job_id == -1 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Cannot find calling job for event handler\n" ),
- argv[0] );
- res=1;
- }
- else
- {
- e.type = EVENT_JOB_ID;
- e.param1.job_id = job_id;
- }
-
- }
- else
- {
- errno = 0;
- pid = fish_wcstoi( woptarg, &end, 10 );
- if( errno || !end || *end )
- {
- append_format(stderr_buffer,
- _( L"%ls: Invalid process id %ls\n" ),
- argv[0],
- woptarg );
- res=1;
- break;
- }
-
-
- e.type = EVENT_EXIT;
- e.param1.pid = (opt=='j'?-1:1)*abs(pid);
- }
- if( res )
- {
+
+ if( ( opt == 'j' ) &&
+ ( wcscasecmp( woptarg, L"caller" ) == 0 ) )
+ {
+ int job_id = -1;
+
+ if( is_subshell )
+ {
+ block_t *b = parser.current_block;
+
+ while( b && (b->type() != SUBST) )
+ b = b->outer;
+
+ if( b )
+ {
+ b=b->outer;
+ }
+ if( b->job )
+ {
+ job_id = b->job->job_id;
+ }
+ }
+
+ if( job_id == -1 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Cannot find calling job for event handler\n" ),
+ argv[0] );
+ res=1;
+ }
+ else
+ {
+ e.type = EVENT_JOB_ID;
+ e.param1.job_id = job_id;
+ }
+
+ }
+ else
+ {
+ errno = 0;
+ pid = fish_wcstoi( woptarg, &end, 10 );
+ if( errno || !end || *end )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Invalid process id %ls\n" ),
+ argv[0],
+ woptarg );
+ res=1;
+ break;
+ }
+
+
+ e.type = EVENT_EXIT;
+ e.param1.pid = (opt=='j'?-1:1)*abs(pid);
+ }
+ if( res )
+ {
/* nothing */
- }
- else
- {
+ }
+ else
+ {
events.push_back(e);
- }
- break;
- }
-
- case 'a':
- if( named_arguments.get() == NULL )
- named_arguments.reset(new wcstring_list_t);
- break;
-
- case 'S':
- shadows = 0;
- break;
-
- case 'h':
- parser.pop_block();
- parser.push_block( new fake_block_t() );
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- res = 1;
- break;
-
- }
-
- }
-
- if( !res )
- {
-
- if( argc == woptind )
- {
- append_format(stderr_buffer,
- _( L"%ls: Expected function name\n" ),
- argv[0] );
- res=1;
- }
- else if( wcsfuncname( argv[woptind] ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Illegal function name '%ls'\n" ),
- argv[0],
- argv[woptind] );
-
- res=1;
- }
- else if( parser_keywords_is_reserved(argv[woptind] ) )
- {
-
- append_format(stderr_buffer,
- _( L"%ls: The name '%ls' is reserved,\nand can not be used as a function name\n" ),
- argv[0],
- argv[woptind] );
-
- res=1;
- }
- else
- {
-
- name = argv[woptind++];
-
- if( named_arguments.get() )
- {
- while( woptind < argc )
- {
- if( wcsvarname( argv[woptind] ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Invalid variable name '%ls'\n" ),
- argv[0],
- argv[woptind] );
- res = STATUS_BUILTIN_ERROR;
- break;
- }
-
+ }
+ break;
+ }
+
+ case 'a':
+ if( named_arguments.get() == NULL )
+ named_arguments.reset(new wcstring_list_t);
+ break;
+
+ case 'S':
+ shadows = 0;
+ break;
+
+ case 'h':
+ parser.pop_block();
+ parser.push_block( new fake_block_t() );
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ res = 1;
+ break;
+
+ }
+
+ }
+
+ if( !res )
+ {
+
+ if( argc == woptind )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Expected function name\n" ),
+ argv[0] );
+ res=1;
+ }
+ else if( wcsfuncname( argv[woptind] ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Illegal function name '%ls'\n" ),
+ argv[0],
+ argv[woptind] );
+
+ res=1;
+ }
+ else if( parser_keywords_is_reserved(argv[woptind] ) )
+ {
+
+ append_format(stderr_buffer,
+ _( L"%ls: The name '%ls' is reserved,\nand can not be used as a function name\n" ),
+ argv[0],
+ argv[woptind] );
+
+ res=1;
+ }
+ else
+ {
+
+ name = argv[woptind++];
+
+ if( named_arguments.get() )
+ {
+ while( woptind < argc )
+ {
+ if( wcsvarname( argv[woptind] ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Invalid variable name '%ls'\n" ),
+ argv[0],
+ argv[woptind] );
+ res = STATUS_BUILTIN_ERROR;
+ break;
+ }
+
named_arguments->push_back(argv[woptind++]);
- }
- }
- else if( woptind != argc )
- {
- append_format(stderr_buffer,
- _( L"%ls: Expected one argument, got %d\n" ),
- argv[0],
- argc );
- res=1;
-
- }
- }
- }
-
- if( res )
- {
- size_t i;
- size_t chars=0;
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- const wchar_t *cfa = _( L"Current functions are: " );
- stderr_buffer.append( cfa );
- chars += wcslen( cfa );
+ }
+ }
+ else if( woptind != argc )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Expected one argument, got %d\n" ),
+ argv[0],
+ argc );
+ res=1;
+
+ }
+ }
+ }
+
+ if( res )
+ {
+ size_t i;
+ size_t chars=0;
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ const wchar_t *cfa = _( L"Current functions are: " );
+ stderr_buffer.append( cfa );
+ chars += wcslen( cfa );
wcstring_list_t names = function_get_names(0);
sort(names.begin(), names.end());
- for( i=0; i<names.size(); i++ )
- {
- const wchar_t *nxt = names.at(i).c_str();
- size_t l = wcslen( nxt + 2 );
- if( chars+l > common_get_width() )
- {
- chars = 0;
+ for( i=0; i<names.size(); i++ )
+ {
+ const wchar_t *nxt = names.at(i).c_str();
+ size_t l = wcslen( nxt + 2 );
+ if( chars+l > common_get_width() )
+ {
+ chars = 0;
stderr_buffer.push_back(L'\n');
- }
+ }
stderr_buffer.append(nxt);
stderr_buffer.append(L" ");
- }
+ }
stderr_buffer.push_back(L'\n');
- parser.pop_block();
- parser.push_block( new fake_block_t() );
- }
- else
- {
- function_data_t &d = fdb->function_data;
-
+ parser.pop_block();
+ parser.push_block( new fake_block_t() );
+ }
+ else
+ {
+ function_data_t &d = fdb->function_data;
+
d.name = name;
if (desc)
d.description = desc;
- d.events.swap(events);
- d.shadows = shadows;
+ d.events.swap(events);
+ d.shadows = shadows;
if (named_arguments.get())
d.named_arguments.swap(*named_arguments);
-
- for( size_t i=0; i<d.events.size(); i++ )
- {
- event_t &e = d.events.at(i);
- e.function_name = d.name;
- }
- }
-
- parser.current_block->tok_pos = parser.get_pos();
- parser.current_block->skip = 1;
-
- return STATUS_BUILTIN_OK;
+
+ for( size_t i=0; i<d.events.size(); i++ )
+ {
+ event_t &e = d.events.at(i);
+ e.function_name = d.name;
+ }
+ }
+
+ parser.current_block->tok_pos = parser.get_pos();
+ parser.current_block->skip = 1;
+
+ return STATUS_BUILTIN_OK;
}
@@ -2013,113 +2013,113 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
*/
static int builtin_random( parser_t &parser, wchar_t **argv )
{
- static int seeded=0;
- static struct drand48_data seed_buffer;
-
- int argc = builtin_count_args( argv );
-
- woptind=0;
-
- static const struct woption
- long_options[] =
- {
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"h",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ static int seeded=0;
+ static struct drand48_data seed_buffer;
+
+ int argc = builtin_count_args( argv );
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"h",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- break;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- }
-
- }
-
- switch( argc-woptind )
- {
-
- case 0:
- {
- long res;
-
- if( !seeded )
- {
- seeded=1;
- srand48_r(time(0), &seed_buffer);
- }
- lrand48_r( &seed_buffer, &res );
-
- append_format(stdout_buffer, L"%ld\n", labs(res%32767) );
- break;
- }
-
- case 1:
- {
- long foo;
- wchar_t *end=0;
-
- errno=0;
- foo = wcstol( argv[woptind], &end, 10 );
- if( errno || *end )
- {
- append_format(stderr_buffer,
- _( L"%ls: Seed value '%ls' is not a valid number\n" ),
- argv[0],
- argv[woptind] );
-
- return STATUS_BUILTIN_ERROR;
- }
- seeded=1;
- srand48_r( foo, &seed_buffer);
- break;
- }
-
- default:
- {
- append_format(stderr_buffer,
- _( L"%ls: Expected zero or one argument, got %d\n" ),
- argv[0],
- argc-woptind );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- }
- return STATUS_BUILTIN_OK;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ break;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ }
+
+ }
+
+ switch( argc-woptind )
+ {
+
+ case 0:
+ {
+ long res;
+
+ if( !seeded )
+ {
+ seeded=1;
+ srand48_r(time(0), &seed_buffer);
+ }
+ lrand48_r( &seed_buffer, &res );
+
+ append_format(stdout_buffer, L"%ld\n", labs(res%32767) );
+ break;
+ }
+
+ case 1:
+ {
+ long foo;
+ wchar_t *end=0;
+
+ errno=0;
+ foo = wcstol( argv[woptind], &end, 10 );
+ if( errno || *end )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Seed value '%ls' is not a valid number\n" ),
+ argv[0],
+ argv[woptind] );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+ seeded=1;
+ srand48_r( foo, &seed_buffer);
+ break;
+ }
+
+ default:
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Expected zero or one argument, got %d\n" ),
+ argv[0],
+ argc-woptind );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ }
+ return STATUS_BUILTIN_OK;
}
@@ -2128,308 +2128,308 @@ static int builtin_random( parser_t &parser, wchar_t **argv )
*/
static int builtin_read( parser_t &parser, wchar_t **argv )
{
- wchar_t *buff=0;
- int i, argc = builtin_count_args( argv );
- int place = ENV_USER;
- wchar_t *nxt;
- const wchar_t *prompt = DEFAULT_READ_PROMPT;
- const wchar_t *commandline = L"";
- int exit_res=STATUS_BUILTIN_OK;
- const wchar_t *mode_name = READ_MODE_NAME;
- int shell = 0;
-
- woptind=0;
-
- while( 1 )
- {
- static const struct woption
- long_options[] =
- {
- {
- L"export", no_argument, 0, 'x'
- }
- ,
- {
- L"global", no_argument, 0, 'g'
- }
- ,
- {
- L"local", no_argument, 0, 'l'
- }
- ,
- {
- L"universal", no_argument, 0, 'U'
- }
- ,
- {
- L"unexport", no_argument, 0, 'u'
- }
- ,
- {
- L"prompt", required_argument, 0, 'p'
- }
- ,
- {
- L"command", required_argument, 0, 'c'
- }
- ,
- {
- L"mode-name", required_argument, 0, 'm'
- }
- ,
- {
- L"shell", no_argument, 0, 's'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"xglUup:c:hm:s",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ wchar_t *buff=0;
+ int i, argc = builtin_count_args( argv );
+ int place = ENV_USER;
+ wchar_t *nxt;
+ const wchar_t *prompt = DEFAULT_READ_PROMPT;
+ const wchar_t *commandline = L"";
+ int exit_res=STATUS_BUILTIN_OK;
+ const wchar_t *mode_name = READ_MODE_NAME;
+ int shell = 0;
+
+ woptind=0;
+
+ while( 1 )
+ {
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"export", no_argument, 0, 'x'
+ }
+ ,
+ {
+ L"global", no_argument, 0, 'g'
+ }
+ ,
+ {
+ L"local", no_argument, 0, 'l'
+ }
+ ,
+ {
+ L"universal", no_argument, 0, 'U'
+ }
+ ,
+ {
+ L"unexport", no_argument, 0, 'u'
+ }
+ ,
+ {
+ L"prompt", required_argument, 0, 'p'
+ }
+ ,
+ {
+ L"command", required_argument, 0, 'c'
+ }
+ ,
+ {
+ L"mode-name", required_argument, 0, 'm'
+ }
+ ,
+ {
+ L"shell", no_argument, 0, 's'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"xglUup:c:hm:s",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
-
- case L'x':
- place |= ENV_EXPORT;
- break;
-
- case L'g':
- place |= ENV_GLOBAL;
- break;
-
- case L'l':
- place |= ENV_LOCAL;
- break;
-
- case L'U':
- place |= ENV_UNIVERSAL;
- break;
-
- case L'u':
- place |= ENV_UNEXPORT;
- break;
-
- case L'p':
- prompt = woptarg;
- break;
-
- case L'c':
- commandline = woptarg;
- break;
-
- case L'm':
- mode_name = woptarg;
- break;
-
- case 's':
- shell = 1;
- break;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
- case L'?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
- }
-
- }
-
- if( ( place & ENV_UNEXPORT ) && ( place & ENV_EXPORT ) )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_EXPUNEXP,
- argv[0] );
-
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
- if( (place&ENV_LOCAL?1:0) + (place & ENV_GLOBAL?1:0) + (place & ENV_UNIVERSAL?1:0) > 1)
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_GLOCAL,
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return STATUS_BUILTIN_ERROR;
- }
-
- /*
- Verify all variable names
- */
- for( i=woptind; i<argc; i++ )
- {
- wchar_t *src;
-
- if( !wcslen( argv[i] ) )
- {
- append_format(stderr_buffer, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
- return STATUS_BUILTIN_ERROR;
- }
-
- for( src=argv[i]; *src; src++ )
- {
- if( (!iswalnum(*src)) && (*src != L'_' ) )
- {
- append_format(stderr_buffer, BUILTIN_ERR_VARCHAR, argv[0], *src );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- }
-
- }
-
- /*
- The call to reader_readline may change woptind, so we save it away here
- */
- i=woptind;
-
- /*
- Check if we should read interactively using \c reader_readline()
- */
- if( isatty(0) && builtin_stdin == 0 )
- {
- const wchar_t *line;
-
- reader_push( mode_name );
- reader_set_left_prompt( prompt );
- if( shell )
- {
- reader_set_complete_function( &complete );
- reader_set_highlight_function( &highlight_shell );
- reader_set_test_function( &reader_shell_test );
- }
-
- reader_set_buffer( commandline, wcslen( commandline ) );
- proc_push_interactive( 1 );
-
- event_fire_generic(L"fish_prompt");
- line = reader_readline( );
- proc_pop_interactive();
- if( line )
- {
- buff = wcsdup( line );
- }
- else
- {
- exit_res = STATUS_BUILTIN_ERROR;
- }
- reader_pop();
- }
- else
- {
- int eof=0;
-
- wcstring sb;
-
- while( 1 )
- {
- int finished=0;
-
- wchar_t res=0;
- static mbstate_t state;
- memset (&state, '\0', sizeof (state));
-
- while( !finished )
- {
- char b;
- if( read_blocked( builtin_stdin, &b, 1 ) <= 0 )
- {
- eof=1;
- break;
- }
-
- size_t sz = mbrtowc( &res, &b, 1, &state );
-
- switch( sz )
- {
- case (size_t)(-1):
- memset (&state, '\0', sizeof (state));
- break;
-
- case (size_t)(-2):
- break;
- case 0:
- eof=1;
- finished = 1;
- break;
-
- default:
- finished=1;
- break;
-
- }
- }
-
- if( eof )
- break;
-
- if( res == L'\n' )
- break;
-
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+
+ case L'x':
+ place |= ENV_EXPORT;
+ break;
+
+ case L'g':
+ place |= ENV_GLOBAL;
+ break;
+
+ case L'l':
+ place |= ENV_LOCAL;
+ break;
+
+ case L'U':
+ place |= ENV_UNIVERSAL;
+ break;
+
+ case L'u':
+ place |= ENV_UNEXPORT;
+ break;
+
+ case L'p':
+ prompt = woptarg;
+ break;
+
+ case L'c':
+ commandline = woptarg;
+ break;
+
+ case L'm':
+ mode_name = woptarg;
+ break;
+
+ case 's':
+ shell = 1;
+ break;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case L'?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ }
+
+ if( ( place & ENV_UNEXPORT ) && ( place & ENV_EXPORT ) )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_EXPUNEXP,
+ argv[0] );
+
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ if( (place&ENV_LOCAL?1:0) + (place & ENV_GLOBAL?1:0) + (place & ENV_UNIVERSAL?1:0) > 1)
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_GLOCAL,
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ /*
+ Verify all variable names
+ */
+ for( i=woptind; i<argc; i++ )
+ {
+ wchar_t *src;
+
+ if( !wcslen( argv[i] ) )
+ {
+ append_format(stderr_buffer, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ for( src=argv[i]; *src; src++ )
+ {
+ if( (!iswalnum(*src)) && (*src != L'_' ) )
+ {
+ append_format(stderr_buffer, BUILTIN_ERR_VARCHAR, argv[0], *src );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ }
+
+ }
+
+ /*
+ The call to reader_readline may change woptind, so we save it away here
+ */
+ i=woptind;
+
+ /*
+ Check if we should read interactively using \c reader_readline()
+ */
+ if( isatty(0) && builtin_stdin == 0 )
+ {
+ const wchar_t *line;
+
+ reader_push( mode_name );
+ reader_set_left_prompt( prompt );
+ if( shell )
+ {
+ reader_set_complete_function( &complete );
+ reader_set_highlight_function( &highlight_shell );
+ reader_set_test_function( &reader_shell_test );
+ }
+
+ reader_set_buffer( commandline, wcslen( commandline ) );
+ proc_push_interactive( 1 );
+
+ event_fire_generic(L"fish_prompt");
+ line = reader_readline( );
+ proc_pop_interactive();
+ if( line )
+ {
+ buff = wcsdup( line );
+ }
+ else
+ {
+ exit_res = STATUS_BUILTIN_ERROR;
+ }
+ reader_pop();
+ }
+ else
+ {
+ int eof=0;
+
+ wcstring sb;
+
+ while( 1 )
+ {
+ int finished=0;
+
+ wchar_t res=0;
+ static mbstate_t state;
+ memset (&state, '\0', sizeof (state));
+
+ while( !finished )
+ {
+ char b;
+ if( read_blocked( builtin_stdin, &b, 1 ) <= 0 )
+ {
+ eof=1;
+ break;
+ }
+
+ size_t sz = mbrtowc( &res, &b, 1, &state );
+
+ switch( sz )
+ {
+ case (size_t)(-1):
+ memset (&state, '\0', sizeof (state));
+ break;
+
+ case (size_t)(-2):
+ break;
+ case 0:
+ eof=1;
+ finished = 1;
+ break;
+
+ default:
+ finished=1;
+ break;
+
+ }
+ }
+
+ if( eof )
+ break;
+
+ if( res == L'\n' )
+ break;
+
sb.push_back(res);
- }
-
- if( sb.size() < 2 && eof )
- {
- exit_res = 1;
- }
-
- buff = wcsdup( sb.c_str() );
- }
-
- if( i != argc && !exit_res )
- {
-
- wchar_t *state;
-
- env_var_t ifs = env_get_string( L"IFS" );
- if( ifs.missing() )
- ifs = L"";
-
- nxt = wcstok( buff, (i<argc-1)?ifs.c_str():L"", &state );
-
- while( i<argc )
- {
- env_set( argv[i], nxt != 0 ? nxt: L"", place );
-
- i++;
- if( nxt != 0 )
- nxt = wcstok( 0, (i<argc-1)?ifs.c_str():L"", &state);
- }
- }
-
- free( buff );
-
- return exit_res;
+ }
+
+ if( sb.size() < 2 && eof )
+ {
+ exit_res = 1;
+ }
+
+ buff = wcsdup( sb.c_str() );
+ }
+
+ if( i != argc && !exit_res )
+ {
+
+ wchar_t *state;
+
+ env_var_t ifs = env_get_string( L"IFS" );
+ if( ifs.missing() )
+ ifs = L"";
+
+ nxt = wcstok( buff, (i<argc-1)?ifs.c_str():L"", &state );
+
+ while( i<argc )
+ {
+ env_set( argv[i], nxt != 0 ? nxt: L"", place );
+
+ i++;
+ if( nxt != 0 )
+ nxt = wcstok( 0, (i<argc-1)?ifs.c_str():L"", &state);
+ }
+ }
+
+ free( buff );
+
+ return exit_res;
}
/**
@@ -2437,243 +2437,243 @@ static int builtin_read( parser_t &parser, wchar_t **argv )
*/
static int builtin_status( parser_t &parser, wchar_t **argv )
{
-
- enum
- {
- NORMAL,
- IS_SUBST,
- IS_BLOCK,
- IS_INTERACTIVE,
- IS_LOGIN,
- IS_FULL_JOB_CONTROL,
- IS_INTERACTIVE_JOB_CONTROL,
- IS_NO_JOB_CONTROL,
- STACK_TRACE,
- DONE,
- CURRENT_FILENAME,
- CURRENT_LINE_NUMBER
- }
- ;
-
- int mode = NORMAL;
-
- int argc = builtin_count_args( argv );
- int res=STATUS_BUILTIN_OK;
-
- woptind=0;
-
-
- const struct woption
- long_options[] =
- {
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- L"is-command-substitution", no_argument, 0, 'c'
- }
- ,
- {
- L"is-block", no_argument, 0, 'b'
- }
- ,
- {
- L"is-interactive", no_argument, 0, 'i'
- }
- ,
- {
- L"is-login", no_argument, 0, 'l'
- }
- ,
- {
- L"is-full-job-control", no_argument, &mode, IS_FULL_JOB_CONTROL
- }
- ,
- {
- L"is-interactive-job-control", no_argument, &mode, IS_INTERACTIVE_JOB_CONTROL
- }
- ,
- {
- L"is-no-job-control", no_argument, &mode, IS_NO_JOB_CONTROL
- }
- ,
- {
- L"current-filename", no_argument, 0, 'f'
- }
- ,
- {
- L"current-line-number", no_argument, 0, 'n'
- }
- ,
- {
- L"job-control", required_argument, 0, 'j'
- }
- ,
- {
- L"print-stack-trace", no_argument, 0, 't'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L":cbilfnhj:t",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+
+ enum
+ {
+ NORMAL,
+ IS_SUBST,
+ IS_BLOCK,
+ IS_INTERACTIVE,
+ IS_LOGIN,
+ IS_FULL_JOB_CONTROL,
+ IS_INTERACTIVE_JOB_CONTROL,
+ IS_NO_JOB_CONTROL,
+ STACK_TRACE,
+ DONE,
+ CURRENT_FILENAME,
+ CURRENT_LINE_NUMBER
+ }
+ ;
+
+ int mode = NORMAL;
+
+ int argc = builtin_count_args( argv );
+ int res=STATUS_BUILTIN_OK;
+
+ woptind=0;
+
+
+ const struct woption
+ long_options[] =
+ {
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ L"is-command-substitution", no_argument, 0, 'c'
+ }
+ ,
+ {
+ L"is-block", no_argument, 0, 'b'
+ }
+ ,
+ {
+ L"is-interactive", no_argument, 0, 'i'
+ }
+ ,
+ {
+ L"is-login", no_argument, 0, 'l'
+ }
+ ,
+ {
+ L"is-full-job-control", no_argument, &mode, IS_FULL_JOB_CONTROL
+ }
+ ,
+ {
+ L"is-interactive-job-control", no_argument, &mode, IS_INTERACTIVE_JOB_CONTROL
+ }
+ ,
+ {
+ L"is-no-job-control", no_argument, &mode, IS_NO_JOB_CONTROL
+ }
+ ,
+ {
+ L"current-filename", no_argument, 0, 'f'
+ }
+ ,
+ {
+ L"current-line-number", no_argument, 0, 'n'
+ }
+ ,
+ {
+ L"job-control", required_argument, 0, 'j'
+ }
+ ,
+ {
+ L"print-stack-trace", no_argument, 0, 't'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L":cbilfnhj:t",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
-
- case 'c':
- mode = IS_SUBST;
- break;
-
- case 'b':
- mode = IS_BLOCK;
- break;
-
- case 'i':
- mode = IS_INTERACTIVE;
- break;
-
- case 'l':
- mode = IS_LOGIN;
- break;
-
- case 'f':
- mode = CURRENT_FILENAME;
- break;
-
- case 'n':
- mode = CURRENT_LINE_NUMBER;
- break;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
- case 'j':
- if( wcscmp( woptarg, L"full" ) == 0 )
- job_control_mode = JOB_CONTROL_ALL;
- else if( wcscmp( woptarg, L"interactive" ) == 0 )
- job_control_mode = JOB_CONTROL_INTERACTIVE;
- else if( wcscmp( woptarg, L"none" ) == 0 )
- job_control_mode = JOB_CONTROL_NONE;
- else
- {
- append_format(stderr_buffer,
- L"%ls: Invalid job control mode '%ls'\n",
- woptarg );
- res = 1;
- }
- mode = DONE;
- break;
-
- case 't':
- mode = STACK_TRACE;
- break;
-
-
- case ':':
- builtin_missing_argument( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- }
-
- }
-
- if( !res )
- {
-
- switch( mode )
- {
- case CURRENT_FILENAME:
- {
- const wchar_t *fn = parser.current_filename();
-
- if( !fn )
- fn = _(L"Standard input");
-
- append_format(stdout_buffer, L"%ls\n", fn );
-
- break;
- }
-
- case CURRENT_LINE_NUMBER:
- {
- append_format(stdout_buffer, L"%d\n", parser.get_lineno() );
- break;
- }
-
- case IS_INTERACTIVE:
- return !is_interactive_session;
-
- case IS_SUBST:
- return !is_subshell;
-
- case IS_BLOCK:
- return !is_block;
-
- case IS_LOGIN:
- return !is_login;
-
- case IS_FULL_JOB_CONTROL:
- return job_control_mode != JOB_CONTROL_ALL;
-
- case IS_INTERACTIVE_JOB_CONTROL:
- return job_control_mode != JOB_CONTROL_INTERACTIVE;
-
- case IS_NO_JOB_CONTROL:
- return job_control_mode != JOB_CONTROL_NONE;
-
- case STACK_TRACE:
- {
- parser.stack_trace( parser.current_block, stdout_buffer );
- break;
- }
-
- case NORMAL:
- {
- if( is_login )
- append_format(stdout_buffer, _( L"This is a login shell\n" ) );
- else
- append_format(stdout_buffer, _( L"This is not a login shell\n" ) );
-
- append_format(stdout_buffer, _( L"Job control: %ls\n" ),
- job_control_mode==JOB_CONTROL_INTERACTIVE?_( L"Only on interactive jobs" ):
- (job_control_mode==JOB_CONTROL_NONE ? _( L"Never" ) : _( L"Always" ) ) );
-
- parser.stack_trace( parser.current_block, stdout_buffer );
- break;
- }
- }
- }
-
- return res;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+
+ case 'c':
+ mode = IS_SUBST;
+ break;
+
+ case 'b':
+ mode = IS_BLOCK;
+ break;
+
+ case 'i':
+ mode = IS_INTERACTIVE;
+ break;
+
+ case 'l':
+ mode = IS_LOGIN;
+ break;
+
+ case 'f':
+ mode = CURRENT_FILENAME;
+ break;
+
+ case 'n':
+ mode = CURRENT_LINE_NUMBER;
+ break;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+ case 'j':
+ if( wcscmp( woptarg, L"full" ) == 0 )
+ job_control_mode = JOB_CONTROL_ALL;
+ else if( wcscmp( woptarg, L"interactive" ) == 0 )
+ job_control_mode = JOB_CONTROL_INTERACTIVE;
+ else if( wcscmp( woptarg, L"none" ) == 0 )
+ job_control_mode = JOB_CONTROL_NONE;
+ else
+ {
+ append_format(stderr_buffer,
+ L"%ls: Invalid job control mode '%ls'\n",
+ woptarg );
+ res = 1;
+ }
+ mode = DONE;
+ break;
+
+ case 't':
+ mode = STACK_TRACE;
+ break;
+
+
+ case ':':
+ builtin_missing_argument( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ }
+
+ }
+
+ if( !res )
+ {
+
+ switch( mode )
+ {
+ case CURRENT_FILENAME:
+ {
+ const wchar_t *fn = parser.current_filename();
+
+ if( !fn )
+ fn = _(L"Standard input");
+
+ append_format(stdout_buffer, L"%ls\n", fn );
+
+ break;
+ }
+
+ case CURRENT_LINE_NUMBER:
+ {
+ append_format(stdout_buffer, L"%d\n", parser.get_lineno() );
+ break;
+ }
+
+ case IS_INTERACTIVE:
+ return !is_interactive_session;
+
+ case IS_SUBST:
+ return !is_subshell;
+
+ case IS_BLOCK:
+ return !is_block;
+
+ case IS_LOGIN:
+ return !is_login;
+
+ case IS_FULL_JOB_CONTROL:
+ return job_control_mode != JOB_CONTROL_ALL;
+
+ case IS_INTERACTIVE_JOB_CONTROL:
+ return job_control_mode != JOB_CONTROL_INTERACTIVE;
+
+ case IS_NO_JOB_CONTROL:
+ return job_control_mode != JOB_CONTROL_NONE;
+
+ case STACK_TRACE:
+ {
+ parser.stack_trace( parser.current_block, stdout_buffer );
+ break;
+ }
+
+ case NORMAL:
+ {
+ if( is_login )
+ append_format(stdout_buffer, _( L"This is a login shell\n" ) );
+ else
+ append_format(stdout_buffer, _( L"This is not a login shell\n" ) );
+
+ append_format(stdout_buffer, _( L"Job control: %ls\n" ),
+ job_control_mode==JOB_CONTROL_INTERACTIVE?_( L"Only on interactive jobs" ):
+ (job_control_mode==JOB_CONTROL_NONE ? _( L"Never" ) : _( L"Always" ) ) );
+
+ parser.stack_trace( parser.current_block, stdout_buffer );
+ break;
+ }
+ }
+ }
+
+ return res;
}
@@ -2682,47 +2682,47 @@ static int builtin_status( parser_t &parser, wchar_t **argv )
*/
static int builtin_exit( parser_t &parser, wchar_t **argv )
{
- int argc = builtin_count_args( argv );
-
- long ec=0;
- switch( argc )
- {
- case 1:
- {
- ec = proc_get_last_status();
- break;
- }
-
- case 2:
- {
- wchar_t *end;
- errno = 0;
- ec = wcstol(argv[1],&end,10);
- if( errno || *end != 0)
- {
- append_format(stderr_buffer,
- _( L"%ls: Argument '%ls' must be an integer\n" ),
- argv[0],
- argv[1] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- break;
- }
-
- default:
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_TOO_MANY_ARGUMENTS,
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
- }
- reader_exit( 1, 0 );
- return (int)ec;
+ int argc = builtin_count_args( argv );
+
+ long ec=0;
+ switch( argc )
+ {
+ case 1:
+ {
+ ec = proc_get_last_status();
+ break;
+ }
+
+ case 2:
+ {
+ wchar_t *end;
+ errno = 0;
+ ec = wcstol(argv[1],&end,10);
+ if( errno || *end != 0)
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Argument '%ls' must be an integer\n" ),
+ argv[0],
+ argv[1] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ break;
+ }
+
+ default:
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_TOO_MANY_ARGUMENTS,
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ }
+ reader_exit( 1, 0 );
+ return (int)ec;
}
/**
@@ -2732,23 +2732,23 @@ static int builtin_exit( parser_t &parser, wchar_t **argv )
*/
static int builtin_cd( parser_t &parser, wchar_t **argv )
{
- env_var_t dir_in;
- wcstring dir;
- int res=STATUS_BUILTIN_OK;
-
-
- if (argv[1] == NULL)
- {
- dir_in = env_get_string( L"HOME" );
- if( dir_in.missing_or_empty() )
- {
- append_format(stderr_buffer,
- _( L"%ls: Could not find home directory\n" ),
- argv[0] );
- }
- }
- else {
- dir_in = argv[1];
+ env_var_t dir_in;
+ wcstring dir;
+ int res=STATUS_BUILTIN_OK;
+
+
+ if (argv[1] == NULL)
+ {
+ dir_in = env_get_string( L"HOME" );
+ if( dir_in.missing_or_empty() )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Could not find home directory\n" ),
+ argv[0] );
+ }
+ }
+ else {
+ dir_in = argv[1];
}
bool got_cd_path = false;
@@ -2757,84 +2757,84 @@ static int builtin_cd( parser_t &parser, wchar_t **argv )
got_cd_path = path_get_cdpath(dir_in, &dir);
}
- if( !got_cd_path )
- {
- if( errno == ENOTDIR )
- {
- append_format(stderr_buffer,
- _( L"%ls: '%ls' is not a directory\n" ),
- argv[0],
- dir_in.c_str() );
- }
- else if( errno == ENOENT )
- {
- append_format(stderr_buffer,
- _( L"%ls: The directory '%ls' does not exist\n" ),
- argv[0],
- dir_in.c_str() );
- }
- else if( errno == EROTTEN )
- {
- append_format(stderr_buffer,
- _( L"%ls: '%ls' is a rotten symlink\n" ),
- argv[0],
- dir_in.c_str() );
-
- }
- else
- {
- append_format(stderr_buffer,
- _( L"%ls: Unknown error trying to locate directory '%ls'\n" ),
- argv[0],
- dir_in.c_str() );
-
- }
-
-
- if( !get_is_interactive() )
- {
+ if( !got_cd_path )
+ {
+ if( errno == ENOTDIR )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: '%ls' is not a directory\n" ),
+ argv[0],
+ dir_in.c_str() );
+ }
+ else if( errno == ENOENT )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: The directory '%ls' does not exist\n" ),
+ argv[0],
+ dir_in.c_str() );
+ }
+ else if( errno == EROTTEN )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: '%ls' is a rotten symlink\n" ),
+ argv[0],
+ dir_in.c_str() );
+
+ }
+ else
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Unknown error trying to locate directory '%ls'\n" ),
+ argv[0],
+ dir_in.c_str() );
+
+ }
+
+
+ if( !get_is_interactive() )
+ {
stderr_buffer.append(parser.current_line());
- }
-
- res = 1;
- }
- else if( wchdir( dir ) != 0 )
- {
- struct stat buffer;
- int status;
-
- status = wstat( dir, &buffer );
- if( !status && S_ISDIR(buffer.st_mode))
- {
- append_format(stderr_buffer,
- _( L"%ls: Permission denied: '%ls'\n" ),
- argv[0],
- dir.c_str() );
-
- }
- else
- {
-
- append_format(stderr_buffer,
- _( L"%ls: '%ls' is not a directory\n" ),
- argv[0],
- dir.c_str() );
- }
-
- if( !get_is_interactive() )
- {
+ }
+
+ res = 1;
+ }
+ else if( wchdir( dir ) != 0 )
+ {
+ struct stat buffer;
+ int status;
+
+ status = wstat( dir, &buffer );
+ if( !status && S_ISDIR(buffer.st_mode))
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Permission denied: '%ls'\n" ),
+ argv[0],
+ dir.c_str() );
+
+ }
+ else
+ {
+
+ append_format(stderr_buffer,
+ _( L"%ls: '%ls' is not a directory\n" ),
+ argv[0],
+ dir.c_str() );
+ }
+
+ if( !get_is_interactive() )
+ {
stderr_buffer.append(parser.current_line());
- }
-
- res = 1;
- }
- else if( !env_set_pwd() )
- {
- res=1;
- append_format(stderr_buffer, _( L"%ls: Could not set PWD variable\n" ), argv[0] );
- }
-
- return res;
+ }
+
+ res = 1;
+ }
+ else if( !env_set_pwd() )
+ {
+ res=1;
+ append_format(stderr_buffer, _( L"%ls: Could not set PWD variable\n" ), argv[0] );
+ }
+
+ return res;
}
/**
@@ -2843,10 +2843,10 @@ static int builtin_cd( parser_t &parser, wchar_t **argv )
*/
static int builtin_count( parser_t &parser, wchar_t ** argv )
{
- int argc;
- argc = builtin_count_args( argv );
- append_format(stdout_buffer, L"%d\n", argc-1 );
- return !(argc-1);
+ int argc;
+ argc = builtin_count_args( argv );
+ append_format(stdout_buffer, L"%d\n", argc-1 );
+ return !(argc-1);
}
/**
@@ -2855,96 +2855,96 @@ static int builtin_count( parser_t &parser, wchar_t ** argv )
*/
static int builtin_contains( parser_t &parser, wchar_t ** argv )
{
- int argc;
- argc = builtin_count_args( argv );
- int i;
- wchar_t *needle;
- int index=0;
-
- woptind=0;
-
- const struct woption
- long_options[] =
- {
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- L"index", no_argument, 0, 'i'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- while( 1 )
- {
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"+hi",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
+ int argc;
+ argc = builtin_count_args( argv );
+ int i;
+ wchar_t *needle;
+ int index=0;
+
+ woptind=0;
+
+ const struct woption
+ long_options[] =
+ {
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ L"index", no_argument, 0, 'i'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ while( 1 )
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"+hi",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
assert(opt_index >= 0 && (size_t)opt_index < sizeof long_options / sizeof *long_options);
- if(long_options[opt_index].flag != 0)
- break;
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
- argv[0],
- long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
-
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
-
-
- case ':':
- builtin_missing_argument( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return STATUS_BUILTIN_ERROR;
-
- case 'i':
- index=1;
- break;
- }
-
- }
-
-
-
- needle = argv[woptind];
- if (!needle)
- {
- append_format(stderr_buffer, _( L"%ls: Key not specified\n" ), argv[0] );
- }
-
-
- for( i=woptind+1; i<argc; i++ )
- {
-
- if( !wcscmp( needle, argv[i]) )
- {
- if ( index ) append_format(stdout_buffer, L"%d\n", i-woptind );
- return 0;
- }
- }
- return 1;
+ if(long_options[opt_index].flag != 0)
+ break;
+ append_format(stderr_buffer,
+ BUILTIN_ERR_UNKNOWN,
+ argv[0],
+ long_options[opt_index].name );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+
+
+ case ':':
+ builtin_missing_argument( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return STATUS_BUILTIN_ERROR;
+
+ case 'i':
+ index=1;
+ break;
+ }
+
+ }
+
+
+
+ needle = argv[woptind];
+ if (!needle)
+ {
+ append_format(stderr_buffer, _( L"%ls: Key not specified\n" ), argv[0] );
+ }
+
+
+ for( i=woptind+1; i<argc; i++ )
+ {
+
+ if( !wcscmp( needle, argv[i]) )
+ {
+ if ( index ) append_format(stdout_buffer, L"%d\n", i-woptind );
+ return 0;
+ }
+ }
+ return 1;
}
@@ -2955,92 +2955,92 @@ static int builtin_contains( parser_t &parser, wchar_t ** argv )
static int builtin_source( parser_t &parser, wchar_t ** argv )
{
ASSERT_IS_MAIN_THREAD();
- int fd;
- int res = STATUS_BUILTIN_OK;
- struct stat buf;
- int argc;
-
- argc = builtin_count_args( argv );
-
- const wchar_t *fn;
- const wchar_t *fn_intern;
-
-
-
- if( argc < 2 || (wcscmp( argv[1], L"-" ) == 0) )
- {
- fn = L"-";
- fn_intern = fn;
- fd = dup(builtin_stdin);
- }
- else
- {
-
- if( ( fd = wopen_cloexec( argv[1], O_RDONLY ) ) == -1 )
- {
- append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
- builtin_wperror( L"." );
- return STATUS_BUILTIN_ERROR;
- }
-
- if( fstat(fd, &buf) == -1 )
- {
- close(fd);
- append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
- builtin_wperror( L"." );
- return STATUS_BUILTIN_ERROR;
- }
-
- if( !S_ISREG(buf.st_mode) )
- {
- close(fd);
- append_format(stderr_buffer, _( L"%ls: '%ls' is not a file\n" ), argv[0], argv[1] );
- return STATUS_BUILTIN_ERROR;
- }
-
- fn = wrealpath( argv[1], 0 );
-
- if( !fn )
- {
- fn_intern = intern( argv[1] );
- }
- else
- {
- fn_intern = intern(fn);
- free( (void *)fn );
- }
-
- }
-
- parser.push_block( new source_block_t(fn_intern) );
- reader_push_current_filename( fn_intern );
-
- parse_util_set_argv( (argc>2)?(argv+2):(argv+1), wcstring_list_t());
-
- res = reader_read( fd, real_io ? *real_io : io_chain_t() );
-
- parser.pop_block();
-
- if( res )
- {
- append_format(stderr_buffer,
- _( L"%ls: Error while reading file '%ls'\n" ),
- argv[0],
- fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern );
- }
- else
- {
- res = proc_get_last_status();
- }
-
- /*
- Do not close fd after calling reader_read. reader_read
- automatically closes it before calling eval.
- */
-
- reader_pop_current_filename();
-
- return res;
+ int fd;
+ int res = STATUS_BUILTIN_OK;
+ struct stat buf;
+ int argc;
+
+ argc = builtin_count_args( argv );
+
+ const wchar_t *fn;
+ const wchar_t *fn_intern;
+
+
+
+ if( argc < 2 || (wcscmp( argv[1], L"-" ) == 0) )
+ {
+ fn = L"-";
+ fn_intern = fn;
+ fd = dup(builtin_stdin);
+ }
+ else
+ {
+
+ if( ( fd = wopen_cloexec( argv[1], O_RDONLY ) ) == -1 )
+ {
+ append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
+ builtin_wperror( L"." );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ if( fstat(fd, &buf) == -1 )
+ {
+ close(fd);
+ append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
+ builtin_wperror( L"." );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ if( !S_ISREG(buf.st_mode) )
+ {
+ close(fd);
+ append_format(stderr_buffer, _( L"%ls: '%ls' is not a file\n" ), argv[0], argv[1] );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ fn = wrealpath( argv[1], 0 );
+
+ if( !fn )
+ {
+ fn_intern = intern( argv[1] );
+ }
+ else
+ {
+ fn_intern = intern(fn);
+ free( (void *)fn );
+ }
+
+ }
+
+ parser.push_block( new source_block_t(fn_intern) );
+ reader_push_current_filename( fn_intern );
+
+ parse_util_set_argv( (argc>2)?(argv+2):(argv+1), wcstring_list_t());
+
+ res = reader_read( fd, real_io ? *real_io : io_chain_t() );
+
+ parser.pop_block();
+
+ if( res )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Error while reading file '%ls'\n" ),
+ argv[0],
+ fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern );
+ }
+ else
+ {
+ res = proc_get_last_status();
+ }
+
+ /*
+ Do not close fd after calling reader_read. reader_read
+ automatically closes it before calling eval.
+ */
+
+ reader_pop_current_filename();
+
+ return res;
}
/**
@@ -3059,146 +3059,146 @@ static void make_first( job_t *j )
*/
static int builtin_fg( parser_t &parser, wchar_t **argv )
{
- job_t *j=NULL;
-
- if( argv[1] == 0 )
- {
- /*
- Select last constructed job (I.e. first job in the job que)
- that is possible to put in the foreground
- */
-
+ job_t *j=NULL;
+
+ if( argv[1] == 0 )
+ {
+ /*
+ Select last constructed job (I.e. first job in the job que)
+ that is possible to put in the foreground
+ */
+
job_iterator_t jobs;
while ((j = jobs.next()))
- {
- if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) &&
- ( (job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND)) ) && job_get_flag( j, JOB_CONTROL) ) )
- {
- break;
- }
- }
- if( !j )
- {
- append_format(stderr_buffer,
- _( L"%ls: There are no suitable jobs\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- }
- }
- else if( argv[2] != 0 )
- {
- /*
- Specifying what more than one job to put to the foreground
- is a syntax error, we still try to locate the job argv[1],
- since we want to know if this is an ambigous job
- specification or if this is an malformed job id
- */
- wchar_t *endptr;
- int pid;
- int found_job = 0;
-
- errno = 0;
- pid = fish_wcstoi( argv[1], &endptr, 10 );
- if( !( *endptr || errno ) )
- {
- j = job_get_from_pid( pid );
- if( j )
- found_job = 1;
- }
-
- if( found_job )
- {
- append_format(stderr_buffer,
- _( L"%ls: Ambiguous job\n" ),
- argv[0] );
- }
- else
- {
- append_format(stderr_buffer,
- _( L"%ls: '%ls' is not a job\n" ),
- argv[0],
- argv[1] );
- }
-
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- j=0;
-
- }
- else
- {
- wchar_t *end;
- int pid;
- errno = 0;
- pid = abs(fish_wcstoi( argv[1], &end, 10 ));
-
- if( *end || errno )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_NOT_NUMBER,
- argv[0],
- argv[1] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- }
- else
- {
- j = job_get_from_pid( pid );
- if( !j || !job_get_flag( j, JOB_CONSTRUCTED ) || job_is_completed( j ))
- {
- append_format(stderr_buffer,
- _( L"%ls: No suitable job: %d\n" ),
- argv[0],
- pid );
- builtin_print_help( parser, argv[0], stderr_buffer );
- j=0;
- }
- else if( !job_get_flag( j, JOB_CONTROL) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
- argv[0],
- pid,
- j->command_wcstr() );
- builtin_print_help( parser, argv[0], stderr_buffer );
- j=0;
- }
- }
- }
-
- if( j )
- {
- if( builtin_err_redirect )
- {
- append_format(stderr_buffer,
- FG_MSG,
- j->job_id,
- j->command_wcstr() );
- }
- else
- {
- /*
- If we aren't redirecting, send output to real stderr,
- since stuff in sb_err won't get printed until the
- command finishes.
- */
- fwprintf( stderr,
- FG_MSG,
- j->job_id,
- j->command_wcstr() );
- }
-
- wchar_t *ft = tok_first( j->command_wcstr() );
- if( ft != 0 )
- env_set( L"_", ft, ENV_EXPORT );
- free(ft);
- reader_write_title();
-
- make_first( j );
- job_set_flag( j, JOB_FOREGROUND, 1 );
-
- job_continue( j, job_is_stopped(j) );
- }
- return j != 0;
+ {
+ if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) &&
+ ( (job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND)) ) && job_get_flag( j, JOB_CONTROL) ) )
+ {
+ break;
+ }
+ }
+ if( !j )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: There are no suitable jobs\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ }
+ }
+ else if( argv[2] != 0 )
+ {
+ /*
+ Specifying what more than one job to put to the foreground
+ is a syntax error, we still try to locate the job argv[1],
+ since we want to know if this is an ambigous job
+ specification or if this is an malformed job id
+ */
+ wchar_t *endptr;
+ int pid;
+ int found_job = 0;
+
+ errno = 0;
+ pid = fish_wcstoi( argv[1], &endptr, 10 );
+ if( !( *endptr || errno ) )
+ {
+ j = job_get_from_pid( pid );
+ if( j )
+ found_job = 1;
+ }
+
+ if( found_job )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Ambiguous job\n" ),
+ argv[0] );
+ }
+ else
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: '%ls' is not a job\n" ),
+ argv[0],
+ argv[1] );
+ }
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ j=0;
+
+ }
+ else
+ {
+ wchar_t *end;
+ int pid;
+ errno = 0;
+ pid = abs(fish_wcstoi( argv[1], &end, 10 ));
+
+ if( *end || errno )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_NOT_NUMBER,
+ argv[0],
+ argv[1] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ }
+ else
+ {
+ j = job_get_from_pid( pid );
+ if( !j || !job_get_flag( j, JOB_CONSTRUCTED ) || job_is_completed( j ))
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: No suitable job: %d\n" ),
+ argv[0],
+ pid );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ j=0;
+ }
+ else if( !job_get_flag( j, JOB_CONTROL) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
+ argv[0],
+ pid,
+ j->command_wcstr() );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ j=0;
+ }
+ }
+ }
+
+ if( j )
+ {
+ if( builtin_err_redirect )
+ {
+ append_format(stderr_buffer,
+ FG_MSG,
+ j->job_id,
+ j->command_wcstr() );
+ }
+ else
+ {
+ /*
+ If we aren't redirecting, send output to real stderr,
+ since stuff in sb_err won't get printed until the
+ command finishes.
+ */
+ fwprintf( stderr,
+ FG_MSG,
+ j->job_id,
+ j->command_wcstr() );
+ }
+
+ wchar_t *ft = tok_first( j->command_wcstr() );
+ if( ft != 0 )
+ env_set( L"_", ft, ENV_EXPORT );
+ free(ft);
+ reader_write_title();
+
+ make_first( j );
+ job_set_flag( j, JOB_FOREGROUND, 1 );
+
+ job_continue( j, job_is_stopped(j) );
+ }
+ return j != 0;
}
/**
@@ -3206,36 +3206,36 @@ static int builtin_fg( parser_t &parser, wchar_t **argv )
*/
static int send_to_bg( parser_t &parser, job_t *j, const wchar_t *name )
{
- if( j == 0 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Unknown job '%ls'\n" ),
- L"bg",
- name );
- builtin_print_help( parser, L"bg", stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- else if( !job_get_flag( j, JOB_CONTROL ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n" ),
- L"bg",
- j->job_id,
- j->command_wcstr() );
- builtin_print_help( parser, L"bg", stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- else
- {
- append_format(stderr_buffer,
- _(L"Send job %d '%ls' to background\n"),
- j->job_id,
- j->command_wcstr() );
- }
- make_first( j );
- job_set_flag( j, JOB_FOREGROUND, 0 );
- job_continue( j, job_is_stopped(j) );
- return STATUS_BUILTIN_OK;
+ if( j == 0 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Unknown job '%ls'\n" ),
+ L"bg",
+ name );
+ builtin_print_help( parser, L"bg", stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ else if( !job_get_flag( j, JOB_CONTROL ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n" ),
+ L"bg",
+ j->job_id,
+ j->command_wcstr() );
+ builtin_print_help( parser, L"bg", stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ else
+ {
+ append_format(stderr_buffer,
+ _(L"Send job %d '%ls' to background\n"),
+ j->job_id,
+ j->command_wcstr() );
+ }
+ make_first( j );
+ job_set_flag( j, JOB_FOREGROUND, 0 );
+ job_continue( j, job_is_stopped(j) );
+ return STATUS_BUILTIN_OK;
}
@@ -3244,65 +3244,65 @@ static int send_to_bg( parser_t &parser, job_t *j, const wchar_t *name )
*/
static int builtin_bg( parser_t &parser, wchar_t **argv )
{
- int res = STATUS_BUILTIN_OK;
+ int res = STATUS_BUILTIN_OK;
- if( argv[1] == 0 )
- {
- job_t *j;
+ if( argv[1] == 0 )
+ {
+ job_t *j;
job_iterator_t jobs;
while ((j = jobs.next()))
{
- if( job_is_stopped(j) && job_get_flag( j, JOB_CONTROL ) && (!job_is_completed(j)) )
- {
- break;
- }
- }
-
- if( !j )
- {
- append_format(stderr_buffer,
- _( L"%ls: There are no suitable jobs\n" ),
- argv[0] );
- res = 1;
- }
- else
- {
- res = send_to_bg( parser, j, _(L"(default)" ) );
- }
- }
- else
- {
- wchar_t *end;
- int i;
- int pid;
- int err = 0;
-
- for( i=1; argv[i]; i++ )
- {
- errno=0;
- pid = fish_wcstoi( argv[i], &end, 10 );
- if( errno || pid < 0 || *end || !job_get_from_pid( pid ) )
- {
- append_format(stderr_buffer,
- _( L"%ls: '%ls' is not a job\n" ),
- argv[0],
- argv[i] );
- err = 1;
- break;
- }
- }
-
- if( !err )
- {
- for( i=1; !res && argv[i]; i++ )
- {
- pid = fish_wcstoi( argv[i], 0, 10 );
- res |= send_to_bg( parser, job_get_from_pid( pid ), *argv);
- }
- }
- }
-
- return res;
+ if( job_is_stopped(j) && job_get_flag( j, JOB_CONTROL ) && (!job_is_completed(j)) )
+ {
+ break;
+ }
+ }
+
+ if( !j )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: There are no suitable jobs\n" ),
+ argv[0] );
+ res = 1;
+ }
+ else
+ {
+ res = send_to_bg( parser, j, _(L"(default)" ) );
+ }
+ }
+ else
+ {
+ wchar_t *end;
+ int i;
+ int pid;
+ int err = 0;
+
+ for( i=1; argv[i]; i++ )
+ {
+ errno=0;
+ pid = fish_wcstoi( argv[i], &end, 10 );
+ if( errno || pid < 0 || *end || !job_get_from_pid( pid ) )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: '%ls' is not a job\n" ),
+ argv[0],
+ argv[i] );
+ err = 1;
+ break;
+ }
+ }
+
+ if( !err )
+ {
+ for( i=1; !res && argv[i]; i++ )
+ {
+ pid = fish_wcstoi( argv[i], 0, 10 );
+ res |= send_to_bg( parser, job_get_from_pid( pid ), *argv);
+ }
+ }
+ }
+
+ return res;
}
@@ -3311,65 +3311,65 @@ static int builtin_bg( parser_t &parser, wchar_t **argv )
*/
static int builtin_for( parser_t &parser, wchar_t **argv )
{
- int argc = builtin_count_args( argv );
- int res=STATUS_BUILTIN_ERROR;
-
-
- if( argc < 3)
- {
- append_format(stderr_buffer,
- BUILTIN_FOR_ERR_COUNT,
- argv[0] ,
- argc );
- builtin_print_help( parser, argv[0], stderr_buffer );
- }
- else if ( wcsvarname(argv[1]) )
- {
- append_format(stderr_buffer,
- BUILTIN_FOR_ERR_NAME,
- argv[0],
- argv[1] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- }
- else if (wcscmp( argv[2], L"in") != 0 )
- {
- append_format(stderr_buffer,
- BUILTIN_FOR_ERR_IN,
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- }
- else
- {
- res=0;
- }
-
-
- if( res )
- {
- parser.push_block( new fake_block_t() );
- }
- else
- {
+ int argc = builtin_count_args( argv );
+ int res=STATUS_BUILTIN_ERROR;
+
+
+ if( argc < 3)
+ {
+ append_format(stderr_buffer,
+ BUILTIN_FOR_ERR_COUNT,
+ argv[0] ,
+ argc );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ }
+ else if ( wcsvarname(argv[1]) )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_FOR_ERR_NAME,
+ argv[0],
+ argv[1] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ }
+ else if (wcscmp( argv[2], L"in") != 0 )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_FOR_ERR_IN,
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ }
+ else
+ {
+ res=0;
+ }
+
+
+ if( res )
+ {
+ parser.push_block( new fake_block_t() );
+ }
+ else
+ {
const wchar_t *for_variable = argv[1];
for_block_t *fb = new for_block_t(for_variable);
- parser.push_block( fb );
- fb->tok_pos = parser.get_pos();
+ parser.push_block( fb );
+ fb->tok_pos = parser.get_pos();
/* Note that we store the sequence of values in opposite order */
wcstring_list_t &for_vars = fb->sequence;
- for( int i=argc-1; i>3; i-- )
+ for( int i=argc-1; i>3; i-- )
for_vars.push_back(argv[i]);
- if( argc > 3 )
- {
- env_set( for_variable, argv[3], ENV_LOCAL );
- }
- else
- {
- parser.current_block->skip=1;
- }
- }
- return res;
+ if( argc > 3 )
+ {
+ env_set( for_variable, argv[3], ENV_LOCAL );
+ }
+ else
+ {
+ parser.current_block->skip=1;
+ }
+ }
+ return res;
}
/**
@@ -3377,9 +3377,9 @@ static int builtin_for( parser_t &parser, wchar_t **argv )
*/
static int builtin_begin( parser_t &parser, wchar_t **argv )
{
- parser.push_block( new scope_block_t(BEGIN) );
- parser.current_block->tok_pos = parser.get_pos();
- return proc_get_last_status();
+ parser.push_block( new scope_block_t(BEGIN) );
+ parser.current_block->tok_pos = parser.get_pos();
+ return proc_get_last_status();
}
@@ -3390,93 +3390,93 @@ static int builtin_begin( parser_t &parser, wchar_t **argv )
*/
static int builtin_end( parser_t &parser, wchar_t **argv )
{
- if( !parser.current_block->outer )
- {
- append_format(stderr_buffer,
- _( L"%ls: Not inside of block\n" ),
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- else
- {
- /**
- By default, 'end' kills the current block scope. But if we
- are rewinding a loop, this should be set to false, so that
- variables in the current loop scope won't die between laps.
- */
- int kill_block = 1;
-
- switch( parser.current_block->type() )
- {
- case WHILE:
- {
- /*
- If this is a while loop, we rewind the loop unless
- it's the last lap, in which case we continue.
- */
- if( !( parser.current_block->skip && (parser.current_block->loop_status != LOOP_CONTINUE )))
- {
- parser.current_block->loop_status = LOOP_NORMAL;
- parser.current_block->skip = 0;
- kill_block = 0;
- parser.set_pos( parser.current_block->tok_pos);
+ if( !parser.current_block->outer )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Not inside of block\n" ),
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ else
+ {
+ /**
+ By default, 'end' kills the current block scope. But if we
+ are rewinding a loop, this should be set to false, so that
+ variables in the current loop scope won't die between laps.
+ */
+ int kill_block = 1;
+
+ switch( parser.current_block->type() )
+ {
+ case WHILE:
+ {
+ /*
+ If this is a while loop, we rewind the loop unless
+ it's the last lap, in which case we continue.
+ */
+ if( !( parser.current_block->skip && (parser.current_block->loop_status != LOOP_CONTINUE )))
+ {
+ parser.current_block->loop_status = LOOP_NORMAL;
+ parser.current_block->skip = 0;
+ kill_block = 0;
+ parser.set_pos( parser.current_block->tok_pos);
while_block_t *blk = static_cast<while_block_t *>(parser.current_block);
blk->status = WHILE_TEST_AGAIN;
- }
+ }
- break;
- }
+ break;
+ }
- case IF:
- case SUBST:
- case BEGIN:
+ case IF:
+ case SUBST:
+ case BEGIN:
case SWITCH:
case FAKE:
- /*
- Nothing special happens at the end of these commands. The scope just ends.
- */
+ /*
+ Nothing special happens at the end of these commands. The scope just ends.
+ */
- break;
+ break;
- case FOR:
- {
- /*
- set loop variable to next element, and rewind to the beginning of the block.
- */
+ case FOR:
+ {
+ /*
+ set loop variable to next element, and rewind to the beginning of the block.
+ */
for_block_t *fb = static_cast<for_block_t *>(parser.current_block);
wcstring_list_t &for_vars = fb->sequence;
- if( parser.current_block->loop_status == LOOP_BREAK )
- {
+ if( parser.current_block->loop_status == LOOP_BREAK )
+ {
for_vars.clear();
- }
+ }
- if( ! for_vars.empty() )
- {
+ if( ! for_vars.empty() )
+ {
const wcstring val = for_vars.back();
for_vars.pop_back();
const wcstring &for_variable = fb->variable;
- env_set( for_variable.c_str(), val.c_str(), ENV_LOCAL);
- parser.current_block->loop_status = LOOP_NORMAL;
- parser.current_block->skip = 0;
-
- kill_block = 0;
- parser.set_pos( parser.current_block->tok_pos );
- }
- break;
- }
-
- case FUNCTION_DEF:
- {
- function_def_block_t *fdb = static_cast<function_def_block_t *>(parser.current_block);
- function_data_t &d = fdb->function_data;
-
+ env_set( for_variable.c_str(), val.c_str(), ENV_LOCAL);
+ parser.current_block->loop_status = LOOP_NORMAL;
+ parser.current_block->skip = 0;
+
+ kill_block = 0;
+ parser.set_pos( parser.current_block->tok_pos );
+ }
+ break;
+ }
+
+ case FUNCTION_DEF:
+ {
+ function_def_block_t *fdb = static_cast<function_def_block_t *>(parser.current_block);
+ function_data_t &d = fdb->function_data;
+
if (d.name.empty())
{
/* Disallow empty function names */
append_format(stderr_buffer, _( L"%ls: No function name given\n" ), argv[0] );
-
+
/* Return an error via a crummy way. Don't just return here, since we need to pop the block. */
proc_set_last_status(STATUS_BUILTIN_ERROR);
}
@@ -3491,28 +3491,28 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
wchar_t *def = wcsndup( parser.get_buffer()+parser.current_block->tok_pos,
parser.get_job_pos()-parser.current_block->tok_pos );
d.definition = def;
-
- function_add( d, parser );
+
+ function_add( d, parser );
free( def );
}
- }
- break;
-
+ }
+ break;
+
default:
assert(false); //should never get here
break;
- }
- if( kill_block )
- {
- parser.pop_block();
- }
-
- /*
- If everything goes ok, return status of last command to execute.
- */
- return proc_get_last_status();
- }
+ }
+ if( kill_block )
+ {
+ parser.pop_block();
+ }
+
+ /*
+ If everything goes ok, return status of last command to execute.
+ */
+ return proc_get_last_status();
+ }
}
/**
@@ -3531,29 +3531,29 @@ static int builtin_else( parser_t &parser, wchar_t **argv )
block_ok = true;
}
}
-
- if( ! block_ok )
- {
- append_format(stderr_buffer,
- _( L"%ls: Not inside of 'if' block\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- else
- {
+
+ if( ! block_ok )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Not inside of 'if' block\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ else
+ {
/* Run the else block if the IF expression was false and so were all the ELSEIF expressions (if any) */
bool run_else = ! if_block->any_branch_taken;
- if_block->skip = ! run_else;
+ if_block->skip = ! run_else;
if_block->else_evaluated = true;
- env_pop();
- env_push(0);
- }
-
- /*
- If everything goes ok, return status of last command to execute.
- */
- return proc_get_last_status();
+ env_pop();
+ env_push(0);
+ }
+
+ /*
+ If everything goes ok, return status of last command to execute.
+ */
+ return proc_get_last_status();
}
/**
@@ -3562,49 +3562,49 @@ static int builtin_else( parser_t &parser, wchar_t **argv )
*/
static int builtin_break_continue( parser_t &parser, wchar_t **argv )
{
- int is_break = (wcscmp(argv[0],L"break")==0);
- int argc = builtin_count_args( argv );
-
- block_t *b = parser.current_block;
-
- if( argc != 1 )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_UNKNOWN,
- argv[0],
- argv[1] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
-
- while( (b != 0) &&
- ( b->type() != WHILE) &&
- (b->type() != FOR ) )
- {
- b = b->outer;
- }
-
- if( b == 0 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Not inside of loop\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
- b = parser.current_block;
- while( ( b->type() != WHILE) &&
- (b->type() != FOR ) )
- {
- b->skip=1;
- b = b->outer;
- }
- b->skip=1;
- b->loop_status = is_break?LOOP_BREAK:LOOP_CONTINUE;
- return STATUS_BUILTIN_OK;
+ int is_break = (wcscmp(argv[0],L"break")==0);
+ int argc = builtin_count_args( argv );
+
+ block_t *b = parser.current_block;
+
+ if( argc != 1 )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_UNKNOWN,
+ argv[0],
+ argv[1] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+
+ while( (b != 0) &&
+ ( b->type() != WHILE) &&
+ (b->type() != FOR ) )
+ {
+ b = b->outer;
+ }
+
+ if( b == 0 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Not inside of loop\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ b = parser.current_block;
+ while( ( b->type() != WHILE) &&
+ (b->type() != FOR ) )
+ {
+ b->skip=1;
+ b = b->outer;
+ }
+ b->skip=1;
+ b->loop_status = is_break?LOOP_BREAK:LOOP_CONTINUE;
+ return STATUS_BUILTIN_OK;
}
/**
@@ -3614,13 +3614,13 @@ static int builtin_break_continue( parser_t &parser, wchar_t **argv )
static int builtin_breakpoint( parser_t &parser, wchar_t **argv )
{
- parser.push_block( new breakpoint_block_t() );
-
- reader_read( STDIN_FILENO, real_io ? *real_io : io_chain_t() );
-
- parser.pop_block();
-
- return proc_get_last_status();
+ parser.push_block( new breakpoint_block_t() );
+
+ reader_read( STDIN_FILENO, real_io ? *real_io : io_chain_t() );
+
+ parser.pop_block();
+
+ return proc_get_last_status();
}
@@ -3629,67 +3629,67 @@ static int builtin_breakpoint( parser_t &parser, wchar_t **argv )
*/
static int builtin_return( parser_t &parser, wchar_t **argv )
{
- int argc = builtin_count_args( argv );
- int status = proc_get_last_status();
-
- block_t *b = parser.current_block;
-
- switch( argc )
- {
- case 1:
- break;
- case 2:
- {
- wchar_t *end;
- errno = 0;
- status = fish_wcstoi(argv[1],&end,10);
- if( errno || *end != 0)
- {
- append_format(stderr_buffer,
- _( L"%ls: Argument '%ls' must be an integer\n" ),
- argv[0],
- argv[1] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
- break;
- }
- default:
- append_format(stderr_buffer,
- _( L"%ls: Too many arguments\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
-
- while( (b != 0) &&
- ( b->type() != FUNCTION_CALL &&
- b->type() != FUNCTION_CALL_NO_SHADOW) )
- {
- b = b->outer;
- }
-
- if( b == 0 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Not inside of function\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
- b = parser.current_block;
- while( ( b->type() != FUNCTION_CALL &&
- b->type() != FUNCTION_CALL_NO_SHADOW ) )
- {
+ int argc = builtin_count_args( argv );
+ int status = proc_get_last_status();
+
+ block_t *b = parser.current_block;
+
+ switch( argc )
+ {
+ case 1:
+ break;
+ case 2:
+ {
+ wchar_t *end;
+ errno = 0;
+ status = fish_wcstoi(argv[1],&end,10);
+ if( errno || *end != 0)
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Argument '%ls' must be an integer\n" ),
+ argv[0],
+ argv[1] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+ break;
+ }
+ default:
+ append_format(stderr_buffer,
+ _( L"%ls: Too many arguments\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+
+ while( (b != 0) &&
+ ( b->type() != FUNCTION_CALL &&
+ b->type() != FUNCTION_CALL_NO_SHADOW) )
+ {
+ b = b->outer;
+ }
+
+ if( b == 0 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Not inside of function\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ b = parser.current_block;
+ while( ( b->type() != FUNCTION_CALL &&
+ b->type() != FUNCTION_CALL_NO_SHADOW ) )
+ {
b->mark_as_fake();
- b->skip=1;
- b = b->outer;
- }
- b->skip=1;
+ b->skip=1;
+ b = b->outer;
+ }
+ b->skip=1;
- return status;
+ return status;
}
/**
@@ -3698,28 +3698,28 @@ static int builtin_return( parser_t &parser, wchar_t **argv )
*/
static int builtin_switch( parser_t &parser, wchar_t **argv )
{
- int res=STATUS_BUILTIN_OK;
- int argc = builtin_count_args( argv );
-
- if( argc != 2 )
- {
- append_format(stderr_buffer,
- _( L"%ls: Expected exactly one argument, got %d\n" ),
- argv[0],
- argc-1 );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- res=1;
- parser.push_block( new fake_block_t() );
- }
- else
- {
- parser.push_block( new switch_block_t(argv[1]) );
- parser.current_block->skip=1;
+ int res=STATUS_BUILTIN_OK;
+ int argc = builtin_count_args( argv );
+
+ if( argc != 2 )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Expected exactly one argument, got %d\n" ),
+ argv[0],
+ argc-1 );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ res=1;
+ parser.push_block( new fake_block_t() );
+ }
+ else
+ {
+ parser.push_block( new switch_block_t(argv[1]) );
+ parser.current_block->skip=1;
res = proc_get_last_status();
- }
-
- return res;
+ }
+
+ return res;
}
/**
@@ -3728,44 +3728,44 @@ static int builtin_switch( parser_t &parser, wchar_t **argv )
*/
static int builtin_case( parser_t &parser, wchar_t **argv )
{
- int argc = builtin_count_args( argv );
- int i;
- wchar_t *unescaped=0;
-
- if( parser.current_block->type() != SWITCH )
- {
- append_format(stderr_buffer,
- _( L"%ls: 'case' command while not in switch block\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return STATUS_BUILTIN_ERROR;
- }
-
- parser.current_block->skip = 1;
- switch_block_t *sb = static_cast<switch_block_t *>(parser.current_block);
- if( sb->switch_taken )
- {
- return proc_get_last_status();
- }
-
+ int argc = builtin_count_args( argv );
+ int i;
+ wchar_t *unescaped=0;
+
+ if( parser.current_block->type() != SWITCH )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: 'case' command while not in switch block\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ parser.current_block->skip = 1;
+ switch_block_t *sb = static_cast<switch_block_t *>(parser.current_block);
+ if( sb->switch_taken )
+ {
+ return proc_get_last_status();
+ }
+
const wcstring &switch_value = sb->switch_value;
- for( i=1; i<argc; i++ )
- {
- int match;
-
- unescaped = parse_util_unescape_wildcards( argv[i] );
- match = wildcard_match( switch_value, unescaped );
- free( unescaped );
-
- if( match )
- {
- parser.current_block->skip = 0;
- sb->switch_taken = true;
- break;
- }
- }
-
- return proc_get_last_status();
+ for( i=1; i<argc; i++ )
+ {
+ int match;
+
+ unescaped = parse_util_unescape_wildcards( argv[i] );
+ match = wildcard_match( switch_value, unescaped );
+ free( unescaped );
+
+ if( match )
+ {
+ parser.current_block->skip = 0;
+ sb->switch_taken = true;
+ break;
+ }
+ }
+
+ return proc_get_last_status();
}
@@ -3776,7 +3776,7 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
{
int argc = builtin_count_args(argv);
- bool search_history = false;
+ bool search_history = false;
bool delete_item = false;
bool search_prefix = false;
bool save_history = false;
@@ -3798,11 +3798,11 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
int opt_index = 0;
woptind = 0;
history_t *history = reader_get_history();
-
+
/* Use the default history if we have none (which happens if invoked non-interactively, e.g. from webconfig.py */
if (! history)
history = &history_t::history_with_name(L"fish");
-
+
while((opt = wgetopt_long_only( argc, argv, L"pdscvl", long_options, &opt_index )) != -1)
{
switch(opt)
@@ -3823,7 +3823,7 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
break;
case 'l':
clear_history = true;
- break;
+ break;
case 'h':
builtin_print_help( parser, argv[0], stdout_buffer );
return STATUS_BUILTIN_OK;
@@ -3839,7 +3839,7 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, argv[0], argv[woptind-1]);
return STATUS_BUILTIN_ERROR;
}
- }
+ }
/* Everything after is an argument */
const wcstring_list_t args(argv + woptind, argv + argc);
@@ -3869,7 +3869,7 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
while (searcher.go_backwards())
{
stdout_buffer.append(searcher.current_string());
- stdout_buffer.append(L"\n");
+ stdout_buffer.append(L"\n");
res = STATUS_BUILTIN_OK;
}
}
@@ -3883,7 +3883,7 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
wcstring delete_string = *iter;
if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"')
delete_string = delete_string.substr(1, delete_string.length() - 2);
-
+
history->remove(delete_string);
}
return STATUS_BUILTIN_OK;
@@ -3919,48 +3919,48 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
*/
static const builtin_data_t builtin_datas[]=
{
- { L".", &builtin_source, N_( L"Evaluate contents of file" ) },
- { L"and", &builtin_generic, N_( L"Execute command if previous command suceeded" ) },
- { L"begin", &builtin_begin, N_( L"Create a block of code" ) },
- { L"bg", &builtin_bg, N_( L"Send job to background" ) },
- { L"bind", &builtin_bind, N_( L"Handle fish key bindings" ) },
- { L"block", &builtin_block, N_( L"Temporarily block delivery of events" ) },
- { L"break", &builtin_break_continue, N_( L"Stop the innermost loop" ) },
- { L"breakpoint", &builtin_breakpoint, N_( L"Temporarily halt execution of a script and launch an interactive debug prompt" ) },
- { L"builtin", &builtin_builtin, N_( L"Run a builtin command instead of a function" ) },
- { L"case", &builtin_case, N_( L"Conditionally execute a block of commands" ) },
- { L"cd", &builtin_cd, N_( L"Change working directory" ) },
- { L"command", &builtin_generic, N_( L"Run a program instead of a function or builtin" ) },
- { L"commandline", &builtin_commandline, N_( L"Set or get the commandline" ) },
- { L"complete", &builtin_complete, N_( L"Edit command specific completions" ) },
- { L"contains", &builtin_contains, N_( L"Search for a specified string in a list" ) },
- { L"continue", &builtin_break_continue, N_( L"Skip the rest of the current lap of the innermost loop" ) },
- { L"count", &builtin_count, N_( L"Count the number of arguments" ) },
- { L"echo", &builtin_echo, N_( L"Print arguments" ) },
- { L"else", &builtin_else, N_( L"Evaluate block if condition is false" ) },
- { L"emit", &builtin_emit, N_( L"Emit an event" ) },
- { L"end", &builtin_end, N_( L"End a block of commands" ) },
- { L"exec", &builtin_generic, N_( L"Run command in current process" ) },
- { L"exit", &builtin_exit, N_( L"Exit the shell" ) },
- { L"fg", &builtin_fg, N_( L"Send job to foreground" ) },
- { L"for", &builtin_for, N_( L"Perform a set of commands multiple times" ) },
- { L"function", &builtin_function, N_( L"Define a new function" ) },
- { L"functions", &builtin_functions, N_( L"List or remove functions" ) },
- { L"history", &builtin_history, N_( L"History of commands executed by user" ) },
- { L"if", &builtin_generic, N_( L"Evaluate block if condition is true" ) },
- { L"jobs", &builtin_jobs, N_( L"Print currently running jobs" ) },
- { L"not", &builtin_generic, N_( L"Negate exit status of job" ) },
- { L"or", &builtin_generic, N_( L"Execute command if previous command failed" ) },
- { L"pwd", &builtin_pwd, N_( L"Print the working directory" ) },
- { L"random", &builtin_random, N_( L"Generate random number" ) },
- { L"read", &builtin_read, N_( L"Read a line of input into variables" ) },
- { L"return", &builtin_return, N_( L"Stop the currently evaluated function" ) },
- { L"set", &builtin_set, N_( L"Handle environment variables" ) },
- { L"status", &builtin_status, N_( L"Return status information about fish" ) },
- { L"switch", &builtin_switch, N_( L"Conditionally execute a block of commands" ) },
- { L"test", &builtin_test, N_( L"Test a condition" ) },
- { L"ulimit", &builtin_ulimit, N_( L"Set or get the shells resource usage limits" ) },
- { L"while", &builtin_generic, N_( L"Perform a command multiple times" ) }
+ { L".", &builtin_source, N_( L"Evaluate contents of file" ) },
+ { L"and", &builtin_generic, N_( L"Execute command if previous command suceeded" ) },
+ { L"begin", &builtin_begin, N_( L"Create a block of code" ) },
+ { L"bg", &builtin_bg, N_( L"Send job to background" ) },
+ { L"bind", &builtin_bind, N_( L"Handle fish key bindings" ) },
+ { L"block", &builtin_block, N_( L"Temporarily block delivery of events" ) },
+ { L"break", &builtin_break_continue, N_( L"Stop the innermost loop" ) },
+ { L"breakpoint", &builtin_breakpoint, N_( L"Temporarily halt execution of a script and launch an interactive debug prompt" ) },
+ { L"builtin", &builtin_builtin, N_( L"Run a builtin command instead of a function" ) },
+ { L"case", &builtin_case, N_( L"Conditionally execute a block of commands" ) },
+ { L"cd", &builtin_cd, N_( L"Change working directory" ) },
+ { L"command", &builtin_generic, N_( L"Run a program instead of a function or builtin" ) },
+ { L"commandline", &builtin_commandline, N_( L"Set or get the commandline" ) },
+ { L"complete", &builtin_complete, N_( L"Edit command specific completions" ) },
+ { L"contains", &builtin_contains, N_( L"Search for a specified string in a list" ) },
+ { L"continue", &builtin_break_continue, N_( L"Skip the rest of the current lap of the innermost loop" ) },
+ { L"count", &builtin_count, N_( L"Count the number of arguments" ) },
+ { L"echo", &builtin_echo, N_( L"Print arguments" ) },
+ { L"else", &builtin_else, N_( L"Evaluate block if condition is false" ) },
+ { L"emit", &builtin_emit, N_( L"Emit an event" ) },
+ { L"end", &builtin_end, N_( L"End a block of commands" ) },
+ { L"exec", &builtin_generic, N_( L"Run command in current process" ) },
+ { L"exit", &builtin_exit, N_( L"Exit the shell" ) },
+ { L"fg", &builtin_fg, N_( L"Send job to foreground" ) },
+ { L"for", &builtin_for, N_( L"Perform a set of commands multiple times" ) },
+ { L"function", &builtin_function, N_( L"Define a new function" ) },
+ { L"functions", &builtin_functions, N_( L"List or remove functions" ) },
+ { L"history", &builtin_history, N_( L"History of commands executed by user" ) },
+ { L"if", &builtin_generic, N_( L"Evaluate block if condition is true" ) },
+ { L"jobs", &builtin_jobs, N_( L"Print currently running jobs" ) },
+ { L"not", &builtin_generic, N_( L"Negate exit status of job" ) },
+ { L"or", &builtin_generic, N_( L"Execute command if previous command failed" ) },
+ { L"pwd", &builtin_pwd, N_( L"Print the working directory" ) },
+ { L"random", &builtin_random, N_( L"Generate random number" ) },
+ { L"read", &builtin_read, N_( L"Read a line of input into variables" ) },
+ { L"return", &builtin_return, N_( L"Stop the currently evaluated function" ) },
+ { L"set", &builtin_set, N_( L"Handle environment variables" ) },
+ { L"status", &builtin_status, N_( L"Return status information about fish" ) },
+ { L"switch", &builtin_switch, N_( L"Conditionally execute a block of commands" ) },
+ { L"test", &builtin_test, N_( L"Test a condition" ) },
+ { L"ulimit", &builtin_ulimit, N_( L"Set or get the shells resource usage limits" ) },
+ { L"while", &builtin_generic, N_( L"Perform a command multiple times" ) }
};
#define BUILTIN_COUNT (sizeof builtin_datas / sizeof *builtin_datas)
@@ -3977,12 +3977,12 @@ static const builtin_data_t *builtin_lookup(const wcstring &name) {
void builtin_init()
{
-
- wopterr = 0;
- for( size_t i=0; i < BUILTIN_COUNT; i++ )
- {
- intern_static( builtin_datas[i].name );
- }
+
+ wopterr = 0;
+ for( size_t i=0; i < BUILTIN_COUNT; i++ )
+ {
+ intern_static( builtin_datas[i].name );
+ }
}
void builtin_destroy()
@@ -3991,7 +3991,7 @@ void builtin_destroy()
int builtin_exists( const wcstring &cmd )
{
- return !!builtin_lookup(cmd);
+ return !!builtin_lookup(cmd);
}
/**
@@ -4000,45 +4000,45 @@ int builtin_exists( const wcstring &cmd )
*/
static int internal_help( const wchar_t *cmd )
{
- CHECK( cmd, 0 );
- return contains( cmd, L"for", L"while", L"function",
- L"if", L"end", L"switch", L"case", L"count" );
+ CHECK( cmd, 0 );
+ return contains( cmd, L"for", L"while", L"function",
+ L"if", L"end", L"switch", L"case", L"count" );
}
int builtin_run( parser_t &parser, const wchar_t * const *argv, const io_chain_t &io )
{
- int (*cmd)(parser_t &parser, const wchar_t * const *argv)=0;
- real_io = &io;
-
- CHECK( argv, STATUS_BUILTIN_ERROR );
- CHECK( argv[0], STATUS_BUILTIN_ERROR );
-
+ int (*cmd)(parser_t &parser, const wchar_t * const *argv)=0;
+ real_io = &io;
+
+ CHECK( argv, STATUS_BUILTIN_ERROR );
+ CHECK( argv[0], STATUS_BUILTIN_ERROR );
+
const builtin_data_t *data = builtin_lookup(argv[0]);
- cmd = (int (*)(parser_t &parser, const wchar_t * const*))(data ? data->func : NULL);
-
- if( argv[1] != 0 && !internal_help(argv[0]) )
- {
- if( argv[2] == 0 && (parser.is_help( argv[1], 0 ) ) )
- {
- builtin_print_help( parser, argv[0], stdout_buffer );
- return STATUS_BUILTIN_OK;
- }
- }
-
- if( data != NULL )
- {
- int status;
-
- status = cmd(parser, argv);
- return status;
-
- }
- else
- {
- debug( 0, _( L"Unknown builtin '%ls'" ), argv[0] );
- }
- return STATUS_BUILTIN_ERROR;
+ cmd = (int (*)(parser_t &parser, const wchar_t * const*))(data ? data->func : NULL);
+
+ if( argv[1] != 0 && !internal_help(argv[0]) )
+ {
+ if( argv[2] == 0 && (parser.is_help( argv[1], 0 ) ) )
+ {
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return STATUS_BUILTIN_OK;
+ }
+ }
+
+ if( data != NULL )
+ {
+ int status;
+
+ status = cmd(parser, argv);
+ return status;
+
+ }
+ else
+ {
+ debug( 0, _( L"Unknown builtin '%ls'" ), argv[0] );
+ }
+ return STATUS_BUILTIN_ERROR;
}
@@ -4053,15 +4053,15 @@ wcstring_list_t builtin_get_names(void)
}
void builtin_get_names(std::vector<completion_t> &list) {
- for (size_t i=0; i < BUILTIN_COUNT; i++) {
- list.push_back(completion_t(builtin_datas[i].name));
- }
+ for (size_t i=0; i < BUILTIN_COUNT; i++) {
+ list.push_back(completion_t(builtin_datas[i].name));
+ }
}
wcstring builtin_get_desc( const wcstring &name )
{
wcstring result;
- const builtin_data_t *builtin = builtin_lookup(name);
+ const builtin_data_t *builtin = builtin_lookup(name);
if (builtin) {
result = _(builtin->desc);
}
@@ -4071,12 +4071,12 @@ wcstring builtin_get_desc( const wcstring &name )
void builtin_push_io( parser_t &parser, int in )
{
ASSERT_IS_MAIN_THREAD();
- if( builtin_stdin != -1 )
- {
+ if( builtin_stdin != -1 )
+ {
struct io_stack_elem_t elem = {builtin_stdin, stdout_buffer, stderr_buffer};
io_stack.push(elem);
- }
- builtin_stdin = in;
+ }
+ builtin_stdin = in;
stdout_buffer.clear();
stderr_buffer.clear();
}
@@ -4084,20 +4084,20 @@ void builtin_push_io( parser_t &parser, int in )
void builtin_pop_io(parser_t &parser)
{
ASSERT_IS_MAIN_THREAD();
- builtin_stdin = 0;
- if( ! io_stack.empty() )
- {
+ builtin_stdin = 0;
+ if( ! io_stack.empty() )
+ {
struct io_stack_elem_t &elem = io_stack.top();
- stderr_buffer = elem.err;
- stdout_buffer = elem.out;
- builtin_stdin = elem.in;
+ stderr_buffer = elem.err;
+ stdout_buffer = elem.out;
+ builtin_stdin = elem.in;
io_stack.pop();
- }
- else
- {
+ }
+ else
+ {
stdout_buffer.clear();
stderr_buffer.clear();
- builtin_stdin = 0;
- }
+ builtin_stdin = 0;
+ }
}
diff --git a/builtin.h b/builtin.h
index e4683f00..cb648338 100644
--- a/builtin.h
+++ b/builtin.h
@@ -1,5 +1,5 @@
/** \file builtin.h
- Prototypes for functions for executing builtin functions.
+ Prototypes for functions for executing builtin functions.
*/
#ifndef FISH_BUILTIN_H
@@ -15,9 +15,9 @@ class parser_t;
enum
{
- COMMAND_NOT_BUILTIN,
- BUILTIN_REGULAR,
- BUILTIN_FUNCTION
+ COMMAND_NOT_BUILTIN,
+ BUILTIN_REGULAR,
+ BUILTIN_FUNCTION
}
;
@@ -49,7 +49,7 @@ enum
/**
Error message for unknown switch
*/
-#define BUILTIN_ERR_UNKNOWN _( L"%ls: Unknown option '%ls'\n" )
+#define BUILTIN_ERR_UNKNOWN _( L"%ls: Unknown option '%ls'\n" )
/**
Error message for invalid character in variable name
@@ -67,7 +67,7 @@ enum
#define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" )
/**
- Error message for insufficient number of arguments
+ Error message for insufficient number of arguments
*/
#define BUILTIN_FOR_ERR_COUNT _( L"%ls: Expected at least two arguments, got %d\n")
@@ -113,7 +113,7 @@ extern int builtin_err_redirect;
/**
- Initialize builtin data.
+ Initialize builtin data.
*/
void builtin_init();
@@ -128,12 +128,12 @@ void builtin_destroy();
int builtin_exists( const wcstring &cmd );
/**
- Execute a builtin command
+ Execute a builtin command
\param parser The parser being used
- \param argv Array containing the command and parameters
+ \param argv Array containing the command and parameters
of the builtin. The list is terminated by a
- null pointer. This syntax resembles the syntax
+ null pointer. This syntax resembles the syntax
for exec.
\param io the io redirections to perform on this builtin.
diff --git a/builtin_commandline.cpp b/builtin_commandline.cpp
index 3a0547d2..21289384 100644
--- a/builtin_commandline.cpp
+++ b/builtin_commandline.cpp
@@ -1,6 +1,6 @@
/** \file builtin_commandline.c Functions defining the commandline builtin
-Functions used for implementing the commandline builtin.
+Functions used for implementing the commandline builtin.
*/
#include "config.h"
@@ -34,23 +34,23 @@ Functions used for implementing the commandline builtin.
*/
enum
{
- STRING_MODE=1, /**< Operate on entire buffer */
- JOB_MODE, /**< Operate on job under cursor */
- PROCESS_MODE, /**< Operate on process under cursor */
- TOKEN_MODE /**< Operate on token under cursor */
+ STRING_MODE=1, /**< Operate on entire buffer */
+ JOB_MODE, /**< Operate on job under cursor */
+ PROCESS_MODE, /**< Operate on process under cursor */
+ TOKEN_MODE /**< Operate on token under cursor */
}
- ;
+ ;
/**
For text insertion, how should it be done
*/
enum
{
- REPLACE_MODE=1, /**< Replace current text */
- INSERT_MODE, /**< Insert at cursor position */
- APPEND_MODE /**< Insert at end of current token/command/buffer */
+ REPLACE_MODE=1, /**< Replace current text */
+ INSERT_MODE, /**< Insert at cursor position */
+ APPEND_MODE /**< Insert at end of current token/command/buffer */
}
- ;
+ ;
/**
Pointer to what the commandline builtin considers to be the current
@@ -68,7 +68,7 @@ static size_t current_cursor_pos = (size_t)(-1);
*/
static const wchar_t *get_buffer()
{
- return current_buffer;
+ return current_buffer;
}
/**
@@ -76,7 +76,7 @@ static const wchar_t *get_buffer()
*/
static size_t get_cursor_pos()
{
- return current_cursor_pos;
+ return current_cursor_pos;
}
@@ -89,47 +89,47 @@ static size_t get_cursor_pos()
\param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the test update is performed
*/
static void replace_part( const wchar_t *begin,
- const wchar_t *end,
- const wchar_t *insert,
- int append_mode )
+ const wchar_t *end,
+ const wchar_t *insert,
+ int append_mode )
{
- const wchar_t *buff = get_buffer();
- size_t out_pos = get_cursor_pos();
-
+ const wchar_t *buff = get_buffer();
+ size_t out_pos = get_cursor_pos();
+
wcstring out;
out.append(buff, begin - buff);
-
- switch( append_mode)
- {
- case REPLACE_MODE:
- {
-
- out.append(insert);
- out_pos = wcslen( insert ) + (begin-buff);
- break;
-
- }
- case APPEND_MODE:
- {
- out.append( begin, end-begin );
- out.append( insert );
- break;
- }
- case INSERT_MODE:
- {
- long cursor = get_cursor_pos() -(begin-buff);
- out.append( begin, cursor );
- out.append( insert );
- out.append( begin+cursor, end-begin-cursor );
- out_pos += wcslen( insert );
- break;
- }
- }
- out.append( end );
- reader_set_buffer( out, out_pos );
+
+ switch( append_mode)
+ {
+ case REPLACE_MODE:
+ {
+
+ out.append(insert);
+ out_pos = wcslen( insert ) + (begin-buff);
+ break;
+
+ }
+ case APPEND_MODE:
+ {
+ out.append( begin, end-begin );
+ out.append( insert );
+ break;
+ }
+ case INSERT_MODE:
+ {
+ long cursor = get_cursor_pos() -(begin-buff);
+ out.append( begin, cursor );
+ out.append( insert );
+ out.append( begin+cursor, end-begin-cursor );
+ out_pos += wcslen( insert );
+ break;
+ }
+ }
+ out.append( end );
+ reader_set_buffer( out, out_pos );
}
-
+
/**
Output the specified selection.
@@ -138,62 +138,62 @@ static void replace_part( const wchar_t *begin,
\param cut_at_cursor whether printing should stop at the surrent cursor position
\param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens
*/
-static void write_part( const wchar_t *begin,
- const wchar_t *end,
- int cut_at_cursor,
- int tokenize )
-{
- tokenizer tok;
- wcstring out;
- wchar_t *buff;
- size_t pos;
-
- pos = get_cursor_pos()-(begin-get_buffer());
-
- if( tokenize )
- {
- buff = wcsndup( begin, end-begin );
-// fwprintf( stderr, L"Subshell: %ls, end char %lc\n", buff, *end );
- out.clear();
-
- for( tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED );
- tok_has_next( &tok );
- tok_next( &tok ) )
- {
- if( (cut_at_cursor) &&
- (tok_get_pos( &tok)+wcslen(tok_last( &tok)) >= pos) )
- break;
-
- switch( tok_last_type( &tok ) )
- {
- case TOK_STRING:
- {
+static void write_part( const wchar_t *begin,
+ const wchar_t *end,
+ int cut_at_cursor,
+ int tokenize )
+{
+ tokenizer tok;
+ wcstring out;
+ wchar_t *buff;
+ size_t pos;
+
+ pos = get_cursor_pos()-(begin-get_buffer());
+
+ if( tokenize )
+ {
+ buff = wcsndup( begin, end-begin );
+// fwprintf( stderr, L"Subshell: %ls, end char %lc\n", buff, *end );
+ out.clear();
+
+ for( tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED );
+ tok_has_next( &tok );
+ tok_next( &tok ) )
+ {
+ if( (cut_at_cursor) &&
+ (tok_get_pos( &tok)+wcslen(tok_last( &tok)) >= pos) )
+ break;
+
+ switch( tok_last_type( &tok ) )
+ {
+ case TOK_STRING:
+ {
out.append(escape_string(tok_last( &tok ), UNESCAPE_INCOMPLETE));
out.push_back(L'\n');
- break;
- }
-
- }
- }
+ break;
+ }
+
+ }
+ }
stdout_buffer.append(out);
-
- free( buff );
- tok_destroy( &tok );
- }
- else
- {
- if( cut_at_cursor )
- {
- end = begin+pos;
- }
-
-// debug( 0, L"woot2 %ls -> %ls", buff, esc );
+
+ free( buff );
+ tok_destroy( &tok );
+ }
+ else
+ {
+ if( cut_at_cursor )
+ {
+ end = begin+pos;
+ }
+
+// debug( 0, L"woot2 %ls -> %ls", buff, esc );
stdout_buffer.append(begin, end - begin);
stdout_buffer.append(L"\n");
-
- }
+
+ }
}
@@ -204,443 +204,443 @@ static void write_part( const wchar_t *begin,
static int builtin_commandline( parser_t &parser, wchar_t **argv )
{
- int buffer_part=0;
- int cut_at_cursor=0;
-
- int argc = builtin_count_args( argv );
- int append_mode=0;
-
- int function_mode = 0;
-
- int tokenize = 0;
-
- int cursor_mode = 0;
- int line_mode = 0;
- int search_mode = 0;
- const wchar_t *begin, *end;
-
- current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
- if( current_buffer )
- {
- current_cursor_pos = wcslen( current_buffer );
- }
- else
- {
- current_buffer = reader_get_buffer();
- current_cursor_pos = reader_get_cursor_pos();
- }
-
- if( !get_buffer() )
- {
- if (is_interactive_session)
- {
- /*
- Prompt change requested while we don't have
- a prompt, most probably while reading the
- init files. Just ignore it.
- */
- return 1;
- }
-
+ int buffer_part=0;
+ int cut_at_cursor=0;
+
+ int argc = builtin_count_args( argv );
+ int append_mode=0;
+
+ int function_mode = 0;
+
+ int tokenize = 0;
+
+ int cursor_mode = 0;
+ int line_mode = 0;
+ int search_mode = 0;
+ const wchar_t *begin, *end;
+
+ current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
+ if( current_buffer )
+ {
+ current_cursor_pos = wcslen( current_buffer );
+ }
+ else
+ {
+ current_buffer = reader_get_buffer();
+ current_cursor_pos = reader_get_cursor_pos();
+ }
+
+ if( !get_buffer() )
+ {
+ if (is_interactive_session)
+ {
+ /*
+ Prompt change requested while we don't have
+ a prompt, most probably while reading the
+ init files. Just ignore it.
+ */
+ return 1;
+ }
+
stderr_buffer.append(argv[0]);
stderr_buffer.append(L": Can not set commandline in non-interactive mode\n");
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- woptind=0;
-
- while( 1 )
- {
- static const struct woption
- long_options[] =
- {
- {
- L"append", no_argument, 0, 'a'
- }
- ,
- {
- L"insert", no_argument, 0, 'i'
- }
- ,
- {
- L"replace", no_argument, 0, 'r'
- }
- ,
- {
- L"current-job", no_argument, 0, 'j'
- }
- ,
- {
- L"current-process", no_argument, 0, 'p'
- }
- ,
- {
- L"current-token", no_argument, 0, 't'
- }
- ,
- {
- L"current-buffer", no_argument, 0, 'b'
- }
- ,
- {
- L"cut-at-cursor", no_argument, 0, 'c'
- }
- ,
- {
- L"function", no_argument, 0, 'f'
- }
- ,
- {
- L"tokenize", no_argument, 0, 'o'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- L"input", required_argument, 0, 'I'
- }
- ,
- {
- L"cursor", no_argument, 0, 'C'
- }
- ,
- {
- L"line", no_argument, 0, 'L'
- }
- ,
- {
- L"search-mode", no_argument, 0, 'S'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"abijpctwforhI:CLS",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ woptind=0;
+
+ while( 1 )
+ {
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"append", no_argument, 0, 'a'
+ }
+ ,
+ {
+ L"insert", no_argument, 0, 'i'
+ }
+ ,
+ {
+ L"replace", no_argument, 0, 'r'
+ }
+ ,
+ {
+ L"current-job", no_argument, 0, 'j'
+ }
+ ,
+ {
+ L"current-process", no_argument, 0, 'p'
+ }
+ ,
+ {
+ L"current-token", no_argument, 0, 't'
+ }
+ ,
+ {
+ L"current-buffer", no_argument, 0, 'b'
+ }
+ ,
+ {
+ L"cut-at-cursor", no_argument, 0, 'c'
+ }
+ ,
+ {
+ L"function", no_argument, 0, 'f'
+ }
+ ,
+ {
+ L"tokenize", no_argument, 0, 'o'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ L"input", required_argument, 0, 'I'
+ }
+ ,
+ {
+ L"cursor", no_argument, 0, 'C'
+ }
+ ,
+ {
+ L"line", no_argument, 0, 'L'
+ }
+ ,
+ {
+ L"search-mode", no_argument, 0, 'S'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"abijpctwforhI:CLS",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format( stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return 1;
-
- case L'a':
- append_mode = APPEND_MODE;
- break;
-
- case L'b':
- buffer_part = STRING_MODE;
- break;
-
-
- case L'i':
- append_mode = INSERT_MODE;
- break;
-
- case L'r':
- append_mode = REPLACE_MODE;
- break;
-
- case 'c':
- cut_at_cursor=1;
- break;
-
- case 't':
- buffer_part = TOKEN_MODE;
- break;
-
- case 'j':
- buffer_part = JOB_MODE;
- break;
-
- case 'p':
- buffer_part = PROCESS_MODE;
- break;
-
- case 'f':
- function_mode=1;
- break;
-
- case 'o':
- tokenize=1;
- break;
-
- case 'I':
- current_buffer = woptarg;
- current_cursor_pos = wcslen( woptarg );
- break;
-
- case 'C':
- cursor_mode = 1;
- break;
-
- case 'L':
- line_mode = 1;
- break;
-
- case 'S':
- search_mode = 1;
- break;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return 0;
-
- case L'?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return 1;
- }
- }
-
- if( function_mode )
- {
- int i;
-
- /*
- Check for invalid switch combinations
- */
- if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode || search_mode )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_COMBO,
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
-
- if( argc == woptind )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_MISSING,
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
- for( i=woptind; i<argc; i++ )
- {
- wint_t c = input_function_get_code( argv[i] );
- if( c != -1 )
- {
- /*
- input_unreadch inserts the specified keypress or
- readline function at the top of the stack of unused
- keypresses
- */
- input_unreadch(c);
- }
- else
- {
- append_format(stderr_buffer,
- _(L"%ls: Unknown input function '%ls'\n"),
- argv[0],
- argv[i] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
- }
-
- return 0;
- }
-
- /*
- Check for invalid switch combinations
- */
- if( (search_mode || line_mode || cursor_mode) && (argc-woptind > 1) )
- {
-
- append_format(stderr_buffer,
- argv[0],
- L": Too many arguments\n",
- NULL );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- if( (buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode) )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_COMBO,
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
-
- if( (tokenize || cut_at_cursor) && (argc-woptind) )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_COMBO2,
- argv[0],
- L"--cut-at-cursor and --tokenize can not be used when setting the commandline" );
-
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- if( append_mode && !(argc-woptind) )
- {
- append_format(stderr_buffer,
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return 1;
+
+ case L'a':
+ append_mode = APPEND_MODE;
+ break;
+
+ case L'b':
+ buffer_part = STRING_MODE;
+ break;
+
+
+ case L'i':
+ append_mode = INSERT_MODE;
+ break;
+
+ case L'r':
+ append_mode = REPLACE_MODE;
+ break;
+
+ case 'c':
+ cut_at_cursor=1;
+ break;
+
+ case 't':
+ buffer_part = TOKEN_MODE;
+ break;
+
+ case 'j':
+ buffer_part = JOB_MODE;
+ break;
+
+ case 'p':
+ buffer_part = PROCESS_MODE;
+ break;
+
+ case 'f':
+ function_mode=1;
+ break;
+
+ case 'o':
+ tokenize=1;
+ break;
+
+ case 'I':
+ current_buffer = woptarg;
+ current_cursor_pos = wcslen( woptarg );
+ break;
+
+ case 'C':
+ cursor_mode = 1;
+ break;
+
+ case 'L':
+ line_mode = 1;
+ break;
+
+ case 'S':
+ search_mode = 1;
+ break;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return 0;
+
+ case L'?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return 1;
+ }
+ }
+
+ if( function_mode )
+ {
+ int i;
+
+ /*
+ Check for invalid switch combinations
+ */
+ if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode || search_mode )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_COMBO,
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+
+ if( argc == woptind )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_MISSING,
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+ for( i=woptind; i<argc; i++ )
+ {
+ wint_t c = input_function_get_code( argv[i] );
+ if( c != -1 )
+ {
+ /*
+ input_unreadch inserts the specified keypress or
+ readline function at the top of the stack of unused
+ keypresses
+ */
+ input_unreadch(c);
+ }
+ else
+ {
+ append_format(stderr_buffer,
+ _(L"%ls: Unknown input function '%ls'\n"),
+ argv[0],
+ argv[i] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ Check for invalid switch combinations
+ */
+ if( (search_mode || line_mode || cursor_mode) && (argc-woptind > 1) )
+ {
+
+ append_format(stderr_buffer,
+ argv[0],
+ L": Too many arguments\n",
+ NULL );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ if( (buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode) )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_COMBO,
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+
+ if( (tokenize || cut_at_cursor) && (argc-woptind) )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_COMBO2,
+ argv[0],
+ L"--cut-at-cursor and --tokenize can not be used when setting the commandline" );
+
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ if( append_mode && !(argc-woptind) )
+ {
+ append_format(stderr_buffer,
BUILTIN_ERR_COMBO2,
argv[0],
- L"insertion mode switches can not be used when not in insertion mode" );
+ L"insertion mode switches can not be used when not in insertion mode" );
- builtin_print_help( parser, argv[0], stderr_buffer );
+ builtin_print_help( parser, argv[0], stderr_buffer );
return 1;
- }
-
- /*
- Set default modes
- */
- if( !append_mode )
- {
- append_mode = REPLACE_MODE;
- }
-
- if( !buffer_part )
- {
- buffer_part = STRING_MODE;
- }
-
- if( cursor_mode )
- {
- if( argc-woptind )
- {
- wchar_t *endptr;
- long new_pos;
- errno = 0;
-
- new_pos = wcstol( argv[woptind], &endptr, 10 );
- if( *endptr || errno )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_NOT_NUMBER,
- argv[0],
- argv[woptind] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- }
-
- current_buffer = reader_get_buffer();
- new_pos = maxi( 0L, mini( new_pos, (long)wcslen( current_buffer ) ) );
- reader_set_buffer( current_buffer, (size_t)new_pos );
- return 0;
- }
- else
- {
- append_format(stdout_buffer, L"%lu\n", (unsigned long)reader_get_cursor_pos() );
- return 0;
- }
-
- }
-
- if( line_mode )
- {
- size_t pos = reader_get_cursor_pos();
- const wchar_t *buff = reader_get_buffer();
- append_format(stdout_buffer, L"%lu\n", (unsigned long)parse_util_lineno( buff, pos ) );
- return 0;
-
- }
-
- if( search_mode )
- {
- return !reader_search_mode();
- }
-
-
- switch( buffer_part )
- {
- case STRING_MODE:
- {
- begin = get_buffer();
- end = begin+wcslen(begin);
- break;
- }
-
- case PROCESS_MODE:
- {
- parse_util_process_extent( get_buffer(),
- get_cursor_pos(),
- &begin,
- &end );
- break;
- }
-
- case JOB_MODE:
- {
- parse_util_job_extent( get_buffer(),
- get_cursor_pos(),
- &begin,
- &end );
- break;
- }
-
- case TOKEN_MODE:
- {
- parse_util_token_extent( get_buffer(),
- get_cursor_pos(),
- &begin,
- &end,
- 0, 0 );
- break;
- }
-
- }
-
- switch(argc-woptind)
- {
- case 0:
- {
- write_part( begin, end, cut_at_cursor, tokenize );
- break;
- }
-
- case 1:
- {
- replace_part( begin, end, argv[woptind], append_mode );
- break;
- }
-
- default:
- {
- wcstring sb = argv[woptind];
- int i;
-
- for( i=woptind+1; i<argc; i++ )
- {
+ }
+
+ /*
+ Set default modes
+ */
+ if( !append_mode )
+ {
+ append_mode = REPLACE_MODE;
+ }
+
+ if( !buffer_part )
+ {
+ buffer_part = STRING_MODE;
+ }
+
+ if( cursor_mode )
+ {
+ if( argc-woptind )
+ {
+ wchar_t *endptr;
+ long new_pos;
+ errno = 0;
+
+ new_pos = wcstol( argv[woptind], &endptr, 10 );
+ if( *endptr || errno )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_NOT_NUMBER,
+ argv[0],
+ argv[woptind] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ }
+
+ current_buffer = reader_get_buffer();
+ new_pos = maxi( 0L, mini( new_pos, (long)wcslen( current_buffer ) ) );
+ reader_set_buffer( current_buffer, (size_t)new_pos );
+ return 0;
+ }
+ else
+ {
+ append_format(stdout_buffer, L"%lu\n", (unsigned long)reader_get_cursor_pos() );
+ return 0;
+ }
+
+ }
+
+ if( line_mode )
+ {
+ size_t pos = reader_get_cursor_pos();
+ const wchar_t *buff = reader_get_buffer();
+ append_format(stdout_buffer, L"%lu\n", (unsigned long)parse_util_lineno( buff, pos ) );
+ return 0;
+
+ }
+
+ if( search_mode )
+ {
+ return !reader_search_mode();
+ }
+
+
+ switch( buffer_part )
+ {
+ case STRING_MODE:
+ {
+ begin = get_buffer();
+ end = begin+wcslen(begin);
+ break;
+ }
+
+ case PROCESS_MODE:
+ {
+ parse_util_process_extent( get_buffer(),
+ get_cursor_pos(),
+ &begin,
+ &end );
+ break;
+ }
+
+ case JOB_MODE:
+ {
+ parse_util_job_extent( get_buffer(),
+ get_cursor_pos(),
+ &begin,
+ &end );
+ break;
+ }
+
+ case TOKEN_MODE:
+ {
+ parse_util_token_extent( get_buffer(),
+ get_cursor_pos(),
+ &begin,
+ &end,
+ 0, 0 );
+ break;
+ }
+
+ }
+
+ switch(argc-woptind)
+ {
+ case 0:
+ {
+ write_part( begin, end, cut_at_cursor, tokenize );
+ break;
+ }
+
+ case 1:
+ {
+ replace_part( begin, end, argv[woptind], append_mode );
+ break;
+ }
+
+ default:
+ {
+ wcstring sb = argv[woptind];
+ int i;
+
+ for( i=woptind+1; i<argc; i++ )
+ {
sb.push_back(L'\n');
sb.append(argv[i]);
- }
-
- replace_part( begin, end, sb.c_str(), append_mode );
-
- break;
- }
- }
-
- return 0;
+ }
+
+ replace_part( begin, end, sb.c_str(), append_mode );
+
+ break;
+ }
+ }
+
+ return 0;
}
diff --git a/builtin_complete.cpp b/builtin_complete.cpp
index b08407f4..870a3f41 100644
--- a/builtin_complete.cpp
+++ b/builtin_complete.cpp
@@ -1,6 +1,6 @@
/** \file builtin_complete.c Functions defining the complete builtin
-Functions used for implementing the complete builtin.
+Functions used for implementing the complete builtin.
*/
#include "config.h"
@@ -42,239 +42,239 @@ static const wchar_t *temporary_buffer;
/**
Silly function
*/
-static void builtin_complete_add2( const wchar_t *cmd,
- int cmd_type,
- const wchar_t *short_opt,
- const wcstring_list_t &gnu_opt,
- const wcstring_list_t &old_opt,
- int result_mode,
- const wchar_t *condition,
- const wchar_t *comp,
- const wchar_t *desc,
- int flags )
+static void builtin_complete_add2( const wchar_t *cmd,
+ int cmd_type,
+ const wchar_t *short_opt,
+ const wcstring_list_t &gnu_opt,
+ const wcstring_list_t &old_opt,
+ int result_mode,
+ const wchar_t *condition,
+ const wchar_t *comp,
+ const wchar_t *desc,
+ int flags )
{
- size_t i;
- const wchar_t *s;
-
- for( s=short_opt; *s; s++ )
- {
- complete_add( cmd,
- cmd_type,
- *s,
- 0,
- 0,
- result_mode,
- condition,
- comp,
- desc,
- flags );
- }
-
- for( i=0; i<gnu_opt.size(); i++ )
- {
- complete_add( cmd,
- cmd_type,
- 0,
- gnu_opt.at(i).c_str(),
- 0,
- result_mode,
- condition,
- comp,
- desc,
- flags );
- }
-
- for( i=0; i<old_opt.size(); i++ )
- {
- complete_add( cmd,
- cmd_type,
- 0,
- old_opt.at(i).c_str(),
- 1,
- result_mode,
- condition,
- comp,
- desc,
- flags );
- }
-
- if( old_opt.size() == 0 && gnu_opt.size() == 0 && wcslen(short_opt) == 0 )
- {
- complete_add( cmd,
- cmd_type,
- 0,
- 0,
- 0,
- result_mode,
- condition,
- comp,
- desc,
- flags );
- }
+ size_t i;
+ const wchar_t *s;
+
+ for( s=short_opt; *s; s++ )
+ {
+ complete_add( cmd,
+ cmd_type,
+ *s,
+ 0,
+ 0,
+ result_mode,
+ condition,
+ comp,
+ desc,
+ flags );
+ }
+
+ for( i=0; i<gnu_opt.size(); i++ )
+ {
+ complete_add( cmd,
+ cmd_type,
+ 0,
+ gnu_opt.at(i).c_str(),
+ 0,
+ result_mode,
+ condition,
+ comp,
+ desc,
+ flags );
+ }
+
+ for( i=0; i<old_opt.size(); i++ )
+ {
+ complete_add( cmd,
+ cmd_type,
+ 0,
+ old_opt.at(i).c_str(),
+ 1,
+ result_mode,
+ condition,
+ comp,
+ desc,
+ flags );
+ }
+
+ if( old_opt.size() == 0 && gnu_opt.size() == 0 && wcslen(short_opt) == 0 )
+ {
+ complete_add( cmd,
+ cmd_type,
+ 0,
+ 0,
+ 0,
+ result_mode,
+ condition,
+ comp,
+ desc,
+ flags );
+ }
}
/**
Silly function
*/
-static void builtin_complete_add( const wcstring_list_t &cmd,
- const wcstring_list_t &path,
- const wchar_t *short_opt,
- wcstring_list_t &gnu_opt,
- wcstring_list_t &old_opt,
- int result_mode,
- int authoritative,
- const wchar_t *condition,
- const wchar_t *comp,
- const wchar_t *desc,
- int flags )
+static void builtin_complete_add( const wcstring_list_t &cmd,
+ const wcstring_list_t &path,
+ const wchar_t *short_opt,
+ wcstring_list_t &gnu_opt,
+ wcstring_list_t &old_opt,
+ int result_mode,
+ int authoritative,
+ const wchar_t *condition,
+ const wchar_t *comp,
+ const wchar_t *desc,
+ int flags )
{
- for( size_t i=0; i<cmd.size(); i++ )
- {
- builtin_complete_add2( cmd.at(i).c_str(),
- COMMAND,
- short_opt,
- gnu_opt,
- old_opt,
- result_mode,
- condition,
- comp,
- desc,
- flags );
-
- if( authoritative != -1 )
- {
- complete_set_authoritative( cmd.at(i).c_str(),
- COMMAND,
- authoritative );
- }
-
- }
-
- for( size_t i=0; i<path.size(); i++ )
- {
- builtin_complete_add2( path.at(i).c_str(),
- PATH,
- short_opt,
- gnu_opt,
- old_opt,
- result_mode,
- condition,
- comp,
- desc,
- flags );
-
- if( authoritative != -1 )
- {
- complete_set_authoritative( path.at(i).c_str(),
- PATH,
- authoritative );
- }
-
- }
+ for( size_t i=0; i<cmd.size(); i++ )
+ {
+ builtin_complete_add2( cmd.at(i).c_str(),
+ COMMAND,
+ short_opt,
+ gnu_opt,
+ old_opt,
+ result_mode,
+ condition,
+ comp,
+ desc,
+ flags );
+
+ if( authoritative != -1 )
+ {
+ complete_set_authoritative( cmd.at(i).c_str(),
+ COMMAND,
+ authoritative );
+ }
+
+ }
+
+ for( size_t i=0; i<path.size(); i++ )
+ {
+ builtin_complete_add2( path.at(i).c_str(),
+ PATH,
+ short_opt,
+ gnu_opt,
+ old_opt,
+ result_mode,
+ condition,
+ comp,
+ desc,
+ flags );
+
+ if( authoritative != -1 )
+ {
+ complete_set_authoritative( path.at(i).c_str(),
+ PATH,
+ authoritative );
+ }
+
+ }
}
/**
Silly function
*/
static void builtin_complete_remove3( const wchar_t *cmd,
- int cmd_type,
- wchar_t short_opt,
- const wcstring_list_t &long_opt )
+ int cmd_type,
+ wchar_t short_opt,
+ const wcstring_list_t &long_opt )
{
- for( size_t i=0; i<long_opt.size(); i++ )
- {
- complete_remove( cmd,
- cmd_type,
- short_opt,
- long_opt.at(i).c_str());
- }
+ for( size_t i=0; i<long_opt.size(); i++ )
+ {
+ complete_remove( cmd,
+ cmd_type,
+ short_opt,
+ long_opt.at(i).c_str());
+ }
}
/**
Silly function
*/
-static void builtin_complete_remove2( const wchar_t *cmd,
- int cmd_type,
- const wchar_t *short_opt,
- const wcstring_list_t &gnu_opt,
- const wcstring_list_t &old_opt )
+static void builtin_complete_remove2( const wchar_t *cmd,
+ int cmd_type,
+ const wchar_t *short_opt,
+ const wcstring_list_t &gnu_opt,
+ const wcstring_list_t &old_opt )
{
- const wchar_t *s = (wchar_t *)short_opt;
- if( *s )
- {
- for( ; *s; s++ )
- {
- if( old_opt.size() == 0 && gnu_opt.size() == 0 )
- {
- complete_remove(cmd,
- cmd_type,
- *s,
- 0 );
-
- }
- else
- {
- builtin_complete_remove3( cmd,
- cmd_type,
- *s,
- gnu_opt );
- builtin_complete_remove3( cmd,
- cmd_type,
- *s,
- old_opt );
- }
- }
- }
- else
- {
- builtin_complete_remove3( cmd,
- cmd_type,
- 0,
- gnu_opt );
- builtin_complete_remove3( cmd,
- cmd_type,
- 0,
- old_opt );
-
- }
-
-
+ const wchar_t *s = (wchar_t *)short_opt;
+ if( *s )
+ {
+ for( ; *s; s++ )
+ {
+ if( old_opt.size() == 0 && gnu_opt.size() == 0 )
+ {
+ complete_remove(cmd,
+ cmd_type,
+ *s,
+ 0 );
+
+ }
+ else
+ {
+ builtin_complete_remove3( cmd,
+ cmd_type,
+ *s,
+ gnu_opt );
+ builtin_complete_remove3( cmd,
+ cmd_type,
+ *s,
+ old_opt );
+ }
+ }
+ }
+ else
+ {
+ builtin_complete_remove3( cmd,
+ cmd_type,
+ 0,
+ gnu_opt );
+ builtin_complete_remove3( cmd,
+ cmd_type,
+ 0,
+ old_opt );
+
+ }
+
+
}
/**
Silly function
*/
-static void builtin_complete_remove( const wcstring_list_t &cmd,
- const wcstring_list_t &path,
- const wchar_t *short_opt,
- const wcstring_list_t &gnu_opt,
- const wcstring_list_t &old_opt )
-{
- for( size_t i=0; i<cmd.size(); i++ )
- {
- builtin_complete_remove2( cmd.at(i).c_str(),
- COMMAND,
- short_opt,
- gnu_opt,
- old_opt );
- }
-
- for( size_t i=0; i<path.size(); i++ )
- {
- builtin_complete_remove2( path.at(i).c_str(),
- PATH,
- short_opt,
- gnu_opt,
- old_opt );
- }
-
+static void builtin_complete_remove( const wcstring_list_t &cmd,
+ const wcstring_list_t &path,
+ const wchar_t *short_opt,
+ const wcstring_list_t &gnu_opt,
+ const wcstring_list_t &old_opt )
+{
+ for( size_t i=0; i<cmd.size(); i++ )
+ {
+ builtin_complete_remove2( cmd.at(i).c_str(),
+ COMMAND,
+ short_opt,
+ gnu_opt,
+ old_opt );
+ }
+
+ for( size_t i=0; i<path.size(); i++ )
+ {
+ builtin_complete_remove2( path.at(i).c_str(),
+ PATH,
+ short_opt,
+ gnu_opt,
+ old_opt );
+ }
+
}
const wchar_t *builtin_complete_get_temporary_buffer()
{
ASSERT_IS_MAIN_THREAD();
- return temporary_buffer;
+ return temporary_buffer;
}
/**
@@ -285,342 +285,342 @@ const wchar_t *builtin_complete_get_temporary_buffer()
static int builtin_complete( parser_t &parser, wchar_t **argv )
{
ASSERT_IS_MAIN_THREAD();
- bool res=false;
- int argc=0;
- int result_mode=SHARED;
- int remove = 0;
- int authoritative = -1;
- int flags = COMPLETE_AUTO_SPACE;
-
- wcstring short_opt;
- wcstring_list_t gnu_opt, old_opt;
- const wchar_t *comp=L"", *desc=L"", *condition=L"";
+ bool res=false;
+ int argc=0;
+ int result_mode=SHARED;
+ int remove = 0;
+ int authoritative = -1;
+ int flags = COMPLETE_AUTO_SPACE;
+
+ wcstring short_opt;
+ wcstring_list_t gnu_opt, old_opt;
+ const wchar_t *comp=L"", *desc=L"", *condition=L"";
bool do_complete = false;
wcstring do_complete_param;
-
- wcstring_list_t cmd;
- wcstring_list_t path;
-
- static int recursion_level=0;
-
- argc = builtin_count_args( argv );
-
- woptind=0;
-
- while( ! res )
- {
- static const struct woption
- long_options[] =
- {
- {
- L"exclusive", no_argument, 0, 'x'
- }
- ,
- {
- L"no-files", no_argument, 0, 'f'
- }
- ,
- {
- L"require-parameter", no_argument, 0, 'r'
- }
- ,
- {
- L"path", required_argument, 0, 'p'
- }
- ,
- {
- L"command", required_argument, 0, 'c'
- }
- ,
- {
- L"short-option", required_argument, 0, 's'
- }
- ,
- {
- L"long-option", required_argument, 0, 'l'
- }
- ,
- {
- L"old-option", required_argument, 0, 'o'
- }
- ,
- {
- L"description", required_argument, 0, 'd'
- }
- ,
- {
- L"arguments", required_argument, 0, 'a'
- }
- ,
- {
- L"erase", no_argument, 0, 'e'
- }
- ,
- {
- L"unauthoritative", no_argument, 0, 'u'
- }
- ,
- {
- L"authoritative", no_argument, 0, 'A'
- }
- ,
- {
- L"condition", required_argument, 0, 'n'
- }
- ,
- {
- L"do-complete", optional_argument, 0, 'C'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"a:c:p:s:l:o:d:frxeuAn:C::h",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+
+ wcstring_list_t cmd;
+ wcstring_list_t path;
+
+ static int recursion_level=0;
+
+ argc = builtin_count_args( argv );
+
+ woptind=0;
+
+ while( ! res )
+ {
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"exclusive", no_argument, 0, 'x'
+ }
+ ,
+ {
+ L"no-files", no_argument, 0, 'f'
+ }
+ ,
+ {
+ L"require-parameter", no_argument, 0, 'r'
+ }
+ ,
+ {
+ L"path", required_argument, 0, 'p'
+ }
+ ,
+ {
+ L"command", required_argument, 0, 'c'
+ }
+ ,
+ {
+ L"short-option", required_argument, 0, 's'
+ }
+ ,
+ {
+ L"long-option", required_argument, 0, 'l'
+ }
+ ,
+ {
+ L"old-option", required_argument, 0, 'o'
+ }
+ ,
+ {
+ L"description", required_argument, 0, 'd'
+ }
+ ,
+ {
+ L"arguments", required_argument, 0, 'a'
+ }
+ ,
+ {
+ L"erase", no_argument, 0, 'e'
+ }
+ ,
+ {
+ L"unauthoritative", no_argument, 0, 'u'
+ }
+ ,
+ {
+ L"authoritative", no_argument, 0, 'A'
+ }
+ ,
+ {
+ L"condition", required_argument, 0, 'n'
+ }
+ ,
+ {
+ L"do-complete", optional_argument, 0, 'C'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"a:c:p:s:l:o:d:frxeuAn:C::h",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
-
- res = true;
- break;
-
- case 'x':
- result_mode |= EXCLUSIVE;
- break;
-
- case 'f':
- result_mode |= NO_FILES;
- break;
-
- case 'r':
- result_mode |= NO_COMMON;
- break;
-
- case 'p':
- case 'c':
- {
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+
+ res = true;
+ break;
+
+ case 'x':
+ result_mode |= EXCLUSIVE;
+ break;
+
+ case 'f':
+ result_mode |= NO_FILES;
+ break;
+
+ case 'r':
+ result_mode |= NO_COMMON;
+ break;
+
+ case 'p':
+ case 'c':
+ {
wcstring tmp = woptarg;
if (unescape_string(tmp, 1))
- {
+ {
if (opt=='p')
path.push_back(tmp);
else
cmd.push_back(tmp);
- }
- else
- {
- append_format(stderr_buffer, L"%ls: Invalid token '%ls'\n", argv[0], woptarg );
- res = true;
- }
- break;
- }
-
- case 'd':
- desc = woptarg;
- break;
-
- case 'u':
- authoritative=0;
- break;
-
- case 'A':
- authoritative=1;
- break;
-
- case 's':
+ }
+ else
+ {
+ append_format(stderr_buffer, L"%ls: Invalid token '%ls'\n", argv[0], woptarg );
+ res = true;
+ }
+ break;
+ }
+
+ case 'd':
+ desc = woptarg;
+ break;
+
+ case 'u':
+ authoritative=0;
+ break;
+
+ case 'A':
+ authoritative=1;
+ break;
+
+ case 's':
short_opt.append(woptarg);
- break;
-
- case 'l':
+ break;
+
+ case 'l':
gnu_opt.push_back(woptarg);
- break;
-
- case 'o':
+ break;
+
+ case 'o':
old_opt.push_back(woptarg);
- break;
-
- case 'a':
- comp = woptarg;
- break;
-
- case 'e':
- remove = 1;
- break;
-
- case 'n':
- condition = woptarg;
- break;
-
- case 'C':
+ break;
+
+ case 'a':
+ comp = woptarg;
+ break;
+
+ case 'e':
+ remove = 1;
+ break;
+
+ case 'n':
+ condition = woptarg;
+ break;
+
+ case 'C':
do_complete = true;
- do_complete_param = woptarg ? woptarg : reader_get_buffer();
- break;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return 0;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- res = true;
- break;
-
- }
-
- }
-
- if( !res )
- {
- if( condition && wcslen( condition ) )
- {
- if( parser.test( condition, 0, 0, 0 ) )
- {
- append_format(stderr_buffer,
- L"%ls: Condition '%ls' contained a syntax error\n",
- argv[0],
- condition );
-
- parser.test( condition, 0, &stderr_buffer, argv[0] );
-
- res = true;
- }
- }
- }
-
- if( !res )
- {
- if( comp && wcslen( comp ) )
- {
- if( parser.test_args( comp, 0, 0 ) )
- {
- append_format(stderr_buffer,
- L"%ls: Completion '%ls' contained a syntax error\n",
- argv[0],
- comp );
-
- parser.test_args( comp, &stderr_buffer, argv[0] );
-
- res = true;
- }
- }
- }
-
- if( !res )
- {
- if( do_complete )
- {
- const wchar_t *token;
-
- parse_util_token_extent( do_complete_param.c_str(), do_complete_param.size(), &token, 0, 0, 0 );
-
- const wchar_t *prev_temporary_buffer = temporary_buffer;
- temporary_buffer = do_complete_param.c_str();
-
- if( recursion_level < 1 )
- {
- recursion_level++;
-
+ do_complete_param = woptarg ? woptarg : reader_get_buffer();
+ break;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return 0;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ res = true;
+ break;
+
+ }
+
+ }
+
+ if( !res )
+ {
+ if( condition && wcslen( condition ) )
+ {
+ if( parser.test( condition, 0, 0, 0 ) )
+ {
+ append_format(stderr_buffer,
+ L"%ls: Condition '%ls' contained a syntax error\n",
+ argv[0],
+ condition );
+
+ parser.test( condition, 0, &stderr_buffer, argv[0] );
+
+ res = true;
+ }
+ }
+ }
+
+ if( !res )
+ {
+ if( comp && wcslen( comp ) )
+ {
+ if( parser.test_args( comp, 0, 0 ) )
+ {
+ append_format(stderr_buffer,
+ L"%ls: Completion '%ls' contained a syntax error\n",
+ argv[0],
+ comp );
+
+ parser.test_args( comp, &stderr_buffer, argv[0] );
+
+ res = true;
+ }
+ }
+ }
+
+ if( !res )
+ {
+ if( do_complete )
+ {
+ const wchar_t *token;
+
+ parse_util_token_extent( do_complete_param.c_str(), do_complete_param.size(), &token, 0, 0, 0 );
+
+ const wchar_t *prev_temporary_buffer = temporary_buffer;
+ temporary_buffer = do_complete_param.c_str();
+
+ if( recursion_level < 1 )
+ {
+ recursion_level++;
+
std::vector<completion_t> comp;
- complete( do_complete_param, comp, COMPLETE_DEFAULT );
-
- for( size_t i=0; i< comp.size() ; i++ )
- {
- const completion_t &next = comp.at( i );
-
- const wchar_t *prepend;
-
- if( next.flags & COMPLETE_NO_CASE )
- {
- prepend = L"";
- }
- else
- {
- prepend = token;
- }
-
-
- if( !(next.description).empty() )
- {
- append_format(stdout_buffer, L"%ls%ls\t%ls\n", prepend, next.completion.c_str(), next.description.c_str() );
- }
- else
- {
- append_format(stdout_buffer, L"%ls%ls\n", prepend, next.completion.c_str() );
- }
- }
-
- recursion_level--;
- }
-
- temporary_buffer = prev_temporary_buffer;
-
- }
- else if( woptind != argc )
- {
- append_format(stderr_buffer,
- _( L"%ls: Too many arguments\n" ),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- res = true;
- }
- else if( cmd.empty() && path.empty() )
- {
- /* No arguments specified, meaning we print the definitions of
- * all specified completions to stdout.*/
- complete_print( stdout_buffer );
- }
- else
- {
- if( remove )
- {
- builtin_complete_remove( cmd,
- path,
- short_opt.c_str(),
- gnu_opt,
- old_opt );
- }
- else
- {
- builtin_complete_add( cmd,
- path,
- short_opt.c_str(),
- gnu_opt,
- old_opt,
- result_mode,
- authoritative,
- condition,
- comp,
- desc,
- flags );
- }
-
- }
- }
-
- return res ? 1 : 0;
+ complete( do_complete_param, comp, COMPLETE_DEFAULT );
+
+ for( size_t i=0; i< comp.size() ; i++ )
+ {
+ const completion_t &next = comp.at( i );
+
+ const wchar_t *prepend;
+
+ if( next.flags & COMPLETE_NO_CASE )
+ {
+ prepend = L"";
+ }
+ else
+ {
+ prepend = token;
+ }
+
+
+ if( !(next.description).empty() )
+ {
+ append_format(stdout_buffer, L"%ls%ls\t%ls\n", prepend, next.completion.c_str(), next.description.c_str() );
+ }
+ else
+ {
+ append_format(stdout_buffer, L"%ls%ls\n", prepend, next.completion.c_str() );
+ }
+ }
+
+ recursion_level--;
+ }
+
+ temporary_buffer = prev_temporary_buffer;
+
+ }
+ else if( woptind != argc )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: Too many arguments\n" ),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ res = true;
+ }
+ else if( cmd.empty() && path.empty() )
+ {
+ /* No arguments specified, meaning we print the definitions of
+ * all specified completions to stdout.*/
+ complete_print( stdout_buffer );
+ }
+ else
+ {
+ if( remove )
+ {
+ builtin_complete_remove( cmd,
+ path,
+ short_opt.c_str(),
+ gnu_opt,
+ old_opt );
+ }
+ else
+ {
+ builtin_complete_add( cmd,
+ path,
+ short_opt.c_str(),
+ gnu_opt,
+ old_opt,
+ result_mode,
+ authoritative,
+ condition,
+ comp,
+ desc,
+ flags );
+ }
+
+ }
+ }
+
+ return res ? 1 : 0;
}
diff --git a/builtin_jobs.cpp b/builtin_jobs.cpp
index 1f01514c..4725f5dd 100644
--- a/builtin_jobs.cpp
+++ b/builtin_jobs.cpp
@@ -1,5 +1,5 @@
/** \file builtin_jobs.c
- Functions for executing the jobs builtin.
+ Functions for executing the jobs builtin.
*/
#include "config.h"
@@ -30,12 +30,12 @@
*/
enum
{
- JOBS_DEFAULT, /**< Print lots of general info */
- JOBS_PRINT_PID, /**< Print pid of each process in job */
- JOBS_PRINT_COMMAND, /**< Print command name of each process in job */
- JOBS_PRINT_GROUP, /**< Print group id of job */
+ JOBS_DEFAULT, /**< Print lots of general info */
+ JOBS_PRINT_PID, /**< Print pid of each process in job */
+ JOBS_PRINT_COMMAND, /**< Print command name of each process in job */
+ JOBS_PRINT_GROUP, /**< Print group id of job */
}
- ;
+ ;
@@ -45,26 +45,26 @@ enum
*/
static int cpu_use( const job_t *j )
{
- double u=0;
- process_t *p;
+ double u=0;
+ process_t *p;
- for( p=j->first_process; p; p=p->next )
- {
- struct timeval t;
- int jiffies;
- gettimeofday( &t, 0 );
- jiffies = proc_get_jiffies( p );
+ for( p=j->first_process; p; p=p->next )
+ {
+ struct timeval t;
+ int jiffies;
+ gettimeofday( &t, 0 );
+ jiffies = proc_get_jiffies( p );
- double t1 = 1000000.0*p->last_time.tv_sec+p->last_time.tv_usec;
- double t2 = 1000000.0*t.tv_sec+t.tv_usec;
+ double t1 = 1000000.0*p->last_time.tv_sec+p->last_time.tv_usec;
+ double t2 = 1000000.0*t.tv_sec+t.tv_usec;
-/* fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n",
+/* fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n",
t1, t2, jiffies, p->last_jiffies );
*/
- u += ((double)(jiffies-p->last_jiffies))/(t2-t1);
- }
- return u*1000000;
+ u += ((double)(jiffies-p->last_jiffies))/(t2-t1);
+ }
+ return u*1000000;
}
#endif
@@ -73,83 +73,83 @@ static int cpu_use( const job_t *j )
*/
static void builtin_jobs_print( const job_t *j, int mode, int header )
{
- process_t *p;
- switch( mode )
- {
- case JOBS_DEFAULT:
- {
-
- if( header )
- {
- /*
- Print table header before first job
- */
- stdout_buffer.append( _( L"Job\tGroup\t" ));
+ process_t *p;
+ switch( mode )
+ {
+ case JOBS_DEFAULT:
+ {
+
+ if( header )
+ {
+ /*
+ Print table header before first job
+ */
+ stdout_buffer.append( _( L"Job\tGroup\t" ));
#ifdef HAVE__PROC_SELF_STAT
- stdout_buffer.append( _( L"CPU\t" ) );
+ stdout_buffer.append( _( L"CPU\t" ) );
#endif
- stdout_buffer.append( _( L"State\tCommand\n" ) );
- }
+ stdout_buffer.append( _( L"State\tCommand\n" ) );
+ }
- append_format(stdout_buffer, L"%d\t%d\t", j->job_id, j->pgid );
+ append_format(stdout_buffer, L"%d\t%d\t", j->job_id, j->pgid );
#ifdef HAVE__PROC_SELF_STAT
- append_format(stdout_buffer, L"%d%%\t", cpu_use(j) );
+ append_format(stdout_buffer, L"%d%%\t", cpu_use(j) );
#endif
- stdout_buffer.append(job_is_stopped(j)?_(L"stopped"):_(L"running"));
+ stdout_buffer.append(job_is_stopped(j)?_(L"stopped"):_(L"running"));
stdout_buffer.append(L"\t");
stdout_buffer.append(j->command_wcstr());
stdout_buffer.append(L"\n");
- break;
- }
-
- case JOBS_PRINT_GROUP:
- {
- if( header )
- {
- /*
- Print table header before first job
- */
- stdout_buffer.append( _( L"Group\n" ));
- }
- append_format(stdout_buffer, L"%d\n", j->pgid );
- break;
- }
-
- case JOBS_PRINT_PID:
- {
- if( header )
- {
- /*
- Print table header before first job
- */
- stdout_buffer.append( _( L"Procces\n" ));
- }
-
- for( p=j->first_process; p; p=p->next )
- {
- append_format(stdout_buffer, L"%d\n", p->pid );
- }
- break;
- }
-
- case JOBS_PRINT_COMMAND:
- {
- if( header )
- {
- /*
- Print table header before first job
- */
- stdout_buffer.append( _( L"Command\n" ));
- }
-
- for( p=j->first_process; p; p=p->next )
- {
- append_format(stdout_buffer, L"%ls\n", p->argv0() );
- }
- break;
- }
- }
+ break;
+ }
+
+ case JOBS_PRINT_GROUP:
+ {
+ if( header )
+ {
+ /*
+ Print table header before first job
+ */
+ stdout_buffer.append( _( L"Group\n" ));
+ }
+ append_format(stdout_buffer, L"%d\n", j->pgid );
+ break;
+ }
+
+ case JOBS_PRINT_PID:
+ {
+ if( header )
+ {
+ /*
+ Print table header before first job
+ */
+ stdout_buffer.append( _( L"Procces\n" ));
+ }
+
+ for( p=j->first_process; p; p=p->next )
+ {
+ append_format(stdout_buffer, L"%d\n", p->pid );
+ }
+ break;
+ }
+
+ case JOBS_PRINT_COMMAND:
+ {
+ if( header )
+ {
+ /*
+ Print table header before first job
+ */
+ stdout_buffer.append( _( L"Command\n" ));
+ }
+
+ for( p=j->first_process; p; p=p->next )
+ {
+ append_format(stdout_buffer, L"%ls\n", p->argv0() );
+ }
+ break;
+ }
+ }
}
@@ -160,192 +160,192 @@ static void builtin_jobs_print( const job_t *j, int mode, int header )
*/
static int builtin_jobs( parser_t &parser, wchar_t **argv )
{
- int argc=0;
- int found=0;
- int mode=JOBS_DEFAULT;
- int print_last = 0;
- const job_t *j;
-
- argc = builtin_count_args( argv );
- woptind=0;
-
- while( 1 )
- {
- static const struct woption
- long_options[] =
- {
- {
- L"pid", no_argument, 0, 'p'
- }
- ,
- {
- L"command", no_argument, 0, 'c'
- }
- ,
- {
- L"group", no_argument, 0, 'g'
- }
- ,
- {
- L"last", no_argument, 0, 'l'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"pclgh",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ int argc=0;
+ int found=0;
+ int mode=JOBS_DEFAULT;
+ int print_last = 0;
+ const job_t *j;
+
+ argc = builtin_count_args( argv );
+ woptind=0;
+
+ while( 1 )
+ {
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"pid", no_argument, 0, 'p'
+ }
+ ,
+ {
+ L"command", no_argument, 0, 'c'
+ }
+ ,
+ {
+ L"group", no_argument, 0, 'g'
+ }
+ ,
+ {
+ L"last", no_argument, 0, 'l'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"pclgh",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
+ builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
+ return 1;
- case 'p':
- mode=JOBS_PRINT_PID;
- break;
+ case 'p':
+ mode=JOBS_PRINT_PID;
+ break;
- case 'c':
- mode=JOBS_PRINT_COMMAND;
- break;
+ case 'c':
+ mode=JOBS_PRINT_COMMAND;
+ break;
- case 'g':
- mode=JOBS_PRINT_GROUP;
- break;
+ case 'g':
+ mode=JOBS_PRINT_GROUP;
+ break;
- case 'l':
- {
- print_last = 1;
- break;
- }
+ case 'l':
+ {
+ print_last = 1;
+ break;
+ }
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return 0;
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return 0;
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return 1;
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return 1;
- }
- }
+ }
+ }
- /*
- Do not babble if not interactive
- */
- if( builtin_out_redirect )
- {
- found=1;
- }
+ /*
+ Do not babble if not interactive
+ */
+ if( builtin_out_redirect )
+ {
+ found=1;
+ }
- if( print_last )
- {
- /*
- Ignore unconstructed jobs, i.e. ourself.
- */
+ if( print_last )
+ {
+ /*
+ Ignore unconstructed jobs, i.e. ourself.
+ */
job_iterator_t jobs;
const job_t *j;
while ((j = jobs.next()))
- {
-
- if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
- {
- builtin_jobs_print( j, mode, !found );
- return 0;
- }
- }
-
- }
- else
- {
- if( woptind < argc )
- {
- int i;
-
- found = 1;
-
- for( i=woptind; i<argc; i++ )
- {
- int pid;
- wchar_t *end;
- errno=0;
- pid=fish_wcstoi( argv[i], &end, 10 );
- if( errno || *end )
- {
- append_format(stderr_buffer,
- _( L"%ls: '%ls' is not a job\n" ),
- argv[0],
- argv[i] );
- return 1;
- }
-
- j = job_get_from_pid( pid );
-
- if( j && !job_is_completed( j ) )
- {
- builtin_jobs_print( j, mode, !found );
- }
- else
- {
- append_format(stderr_buffer,
- _( L"%ls: No suitable job: %d\n" ),
- argv[0],
- pid );
- return 1;
- }
- }
- }
- else
- {
+ {
+
+ if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
+ {
+ builtin_jobs_print( j, mode, !found );
+ return 0;
+ }
+ }
+
+ }
+ else
+ {
+ if( woptind < argc )
+ {
+ int i;
+
+ found = 1;
+
+ for( i=woptind; i<argc; i++ )
+ {
+ int pid;
+ wchar_t *end;
+ errno=0;
+ pid=fish_wcstoi( argv[i], &end, 10 );
+ if( errno || *end )
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: '%ls' is not a job\n" ),
+ argv[0],
+ argv[i] );
+ return 1;
+ }
+
+ j = job_get_from_pid( pid );
+
+ if( j && !job_is_completed( j ) )
+ {
+ builtin_jobs_print( j, mode, !found );
+ }
+ else
+ {
+ append_format(stderr_buffer,
+ _( L"%ls: No suitable job: %d\n" ),
+ argv[0],
+ pid );
+ return 1;
+ }
+ }
+ }
+ else
+ {
job_iterator_t jobs;
const job_t *j;
while ((j = jobs.next()))
{
- /*
- Ignore unconstructed jobs, i.e. ourself.
- */
- if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
- {
- builtin_jobs_print( j, mode, !found );
- found = 1;
- }
- }
- }
- }
-
- if( !found )
- {
- append_format(stdout_buffer,
- _( L"%ls: There are no jobs\n" ),
- argv[0] );
- }
-
- return 0;
+ /*
+ Ignore unconstructed jobs, i.e. ourself.
+ */
+ if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
+ {
+ builtin_jobs_print( j, mode, !found );
+ found = 1;
+ }
+ }
+ }
+ }
+
+ if( !found )
+ {
+ append_format(stdout_buffer,
+ _( L"%ls: There are no jobs\n" ),
+ argv[0] );
+ }
+
+ return 0;
}
diff --git a/builtin_set.cpp b/builtin_set.cpp
index a4a2d53e..5b34227e 100644
--- a/builtin_set.cpp
+++ b/builtin_set.cpp
@@ -1,6 +1,6 @@
/** \file builtin_set.c Functions defining the set builtin
-Functions used for implementing the set builtin.
+Functions used for implementing the set builtin.
*/
#include "config.h"
@@ -49,7 +49,7 @@ extern wcstring stdout_buffer, stderr_buffer;
*/
static int is_path_variable( const wchar_t *env )
{
- return contains(env, L"PATH", L"CDPATH" );
+ return contains(env, L"PATH", L"CDPATH" );
}
/**
@@ -61,32 +61,32 @@ static int my_env_set( const wchar_t *key, const wcstring_list_t &val, int scope
size_t i;
int retcode = 0;
const wchar_t *val_str=NULL;
-
+
if( is_path_variable( key ) )
{
/* Fix for https://github.com/fish-shell/fish-shell/issues/199 . Return success if any path setting succeeds. */
bool any_success = false, any_error = false;
-
+
for( i=0; i< val.size() ; i++ )
{
bool show_perror = false;
int show_hint = 0;
bool error = false;
-
+
struct stat buff;
const wchar_t *dir = val[i].c_str();
-
+
if( wstat( dir, &buff ) )
{
error = true;
show_perror = true;
}
-
+
if( !( S_ISDIR(buff.st_mode) ) )
{
error = true;
}
-
+
if( !error )
{
any_success = true;
@@ -97,34 +97,34 @@ static int my_env_set( const wchar_t *key, const wcstring_list_t &val, int scope
const wchar_t *colon;
append_format(stderr_buffer, _(BUILTIN_SET_PATH_ERROR), L"set", dir, key);
colon = wcschr( dir, L':' );
-
- if( colon && *(colon+1) )
+
+ if( colon && *(colon+1) )
{
show_hint = 1;
}
-
+
}
-
+
if( show_perror )
{
builtin_wperror( L"set" );
}
-
+
if( show_hint )
{
append_format(stderr_buffer, _(BUILTIN_SET_PATH_HINT), L"set", key, key, wcschr( dir, L':' )+1);
}
-
+
}
-
+
/* Fail at setting the path if we tried to set it to something non-empty, but it wound up empty. */
if( ! val.empty() && ! any_success )
{
return 1;
}
-
+
}
-
+
wcstring sb;
if( val.size() )
{
@@ -138,7 +138,7 @@ static int my_env_set( const wchar_t *key, const wcstring_list_t &val, int scope
}
val_str = sb.c_str();
}
-
+
switch( env_set( key, val_str, scope | ENV_USER ) )
{
case ENV_PERM:
@@ -147,7 +147,7 @@ static int my_env_set( const wchar_t *key, const wcstring_list_t &val, int scope
retcode=1;
break;
}
-
+
case ENV_INVALID:
{
append_format(stderr_buffer, _(L"%ls: Unknown error"), L"set" );
@@ -155,160 +155,160 @@ static int my_env_set( const wchar_t *key, const wcstring_list_t &val, int scope
break;
}
}
-
+
return retcode;
}
-/**
- Extract indexes from a destination argument of the form name[index1 index2...]
+/**
+ Extract indexes from a destination argument of the form name[index1 index2...]
- \param indexes the list to insert the new indexes into
- \param src the source string to parse
- \param name the name of the element. Return null if the name in \c src does not match this name
- \param var_count the number of elements in the array to parse.
+ \param indexes the list to insert the new indexes into
+ \param src the source string to parse
+ \param name the name of the element. Return null if the name in \c src does not match this name
+ \param var_count the number of elements in the array to parse.
- \return the total number of indexes parsed, or -1 on error
+ \return the total number of indexes parsed, or -1 on error
*/
static int parse_index( std::vector<long> &indexes,
- const wchar_t *src,
- const wchar_t *name,
- size_t var_count )
+ const wchar_t *src,
+ const wchar_t *name,
+ size_t var_count )
{
- size_t len;
-
- int count = 0;
- const wchar_t *src_orig = src;
-
- if (src == 0)
- {
- return 0;
- }
-
- while (*src != L'\0' && (iswalnum(*src) || *src == L'_'))
- {
- src++;
- }
-
- if (*src != L'[')
- {
- append_format(stderr_buffer, _(BUILTIN_SET_ARG_COUNT), L"set" );
- return 0;
- }
-
- len = src-src_orig;
-
- if( (wcsncmp( src_orig, name, len )!=0) || (wcslen(name) != (len)) )
- {
- append_format(stderr_buffer,
- _(L"%ls: Multiple variable names specified in single call (%ls and %.*ls)\n"),
- L"set",
- name,
- len,
- src_orig);
- return 0;
- }
-
- src++;
-
- while (iswspace(*src))
- {
- src++;
- }
-
- while (*src != L']')
- {
- wchar_t *end;
-
- long l_ind;
-
- errno = 0;
-
- l_ind = wcstol(src, &end, 10);
-
- if( end==src || errno )
- {
- append_format(stderr_buffer, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
- return 0;
- }
-
- if( l_ind < 0 )
- {
- l_ind = var_count+l_ind+1;
- }
-
- src = end;
- if ( *src==L'.' && *(src+1)==L'.' ){
- src+=2;
- long l_ind2 = wcstol( src, &end, 10 );
- if( end==src || errno )
- {
- return 1;
- }
- src = end;
-
- if( l_ind2 < 0 )
- {
- l_ind2 = var_count+l_ind2+1;
- }
- int direction = l_ind2<l_ind ? -1 : 1 ;
- for (long jjj = l_ind; jjj*direction <= l_ind2*direction; jjj+=direction) {
- // debug(0, L"Expand range [set]: %i\n", jjj);
- indexes.push_back( jjj );
- count++;
- }
- }
- else {
- indexes.push_back( l_ind );
- count++;
- }
- while (iswspace(*src)) src++;
- }
-
- return count;
+ size_t len;
+
+ int count = 0;
+ const wchar_t *src_orig = src;
+
+ if (src == 0)
+ {
+ return 0;
+ }
+
+ while (*src != L'\0' && (iswalnum(*src) || *src == L'_'))
+ {
+ src++;
+ }
+
+ if (*src != L'[')
+ {
+ append_format(stderr_buffer, _(BUILTIN_SET_ARG_COUNT), L"set" );
+ return 0;
+ }
+
+ len = src-src_orig;
+
+ if( (wcsncmp( src_orig, name, len )!=0) || (wcslen(name) != (len)) )
+ {
+ append_format(stderr_buffer,
+ _(L"%ls: Multiple variable names specified in single call (%ls and %.*ls)\n"),
+ L"set",
+ name,
+ len,
+ src_orig);
+ return 0;
+ }
+
+ src++;
+
+ while (iswspace(*src))
+ {
+ src++;
+ }
+
+ while (*src != L']')
+ {
+ wchar_t *end;
+
+ long l_ind;
+
+ errno = 0;
+
+ l_ind = wcstol(src, &end, 10);
+
+ if( end==src || errno )
+ {
+ append_format(stderr_buffer, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
+ return 0;
+ }
+
+ if( l_ind < 0 )
+ {
+ l_ind = var_count+l_ind+1;
+ }
+
+ src = end;
+ if ( *src==L'.' && *(src+1)==L'.' ){
+ src+=2;
+ long l_ind2 = wcstol( src, &end, 10 );
+ if( end==src || errno )
+ {
+ return 1;
+ }
+ src = end;
+
+ if( l_ind2 < 0 )
+ {
+ l_ind2 = var_count+l_ind2+1;
+ }
+ int direction = l_ind2<l_ind ? -1 : 1 ;
+ for (long jjj = l_ind; jjj*direction <= l_ind2*direction; jjj+=direction) {
+ // debug(0, L"Expand range [set]: %i\n", jjj);
+ indexes.push_back( jjj );
+ count++;
+ }
+ }
+ else {
+ indexes.push_back( l_ind );
+ count++;
+ }
+ while (iswspace(*src)) src++;
+ }
+
+ return count;
}
-static int update_values( wcstring_list_t &list,
- std::vector<long> &indexes,
- wcstring_list_t &values )
+static int update_values( wcstring_list_t &list,
+ std::vector<long> &indexes,
+ wcstring_list_t &values )
{
- size_t i;
-
- /* Replace values where needed */
- for( i = 0; i < indexes.size(); i++ )
- {
- /*
- The '- 1' below is because the indices in fish are
- one-based, but the vector uses zero-based indices
- */
- long ind = indexes[i] - 1;
- const wcstring newv = values[ i ];
- if( ind < 0 )
- {
- return 1;
- }
+ size_t i;
+
+ /* Replace values where needed */
+ for( i = 0; i < indexes.size(); i++ )
+ {
+ /*
+ The '- 1' below is because the indices in fish are
+ one-based, but the vector uses zero-based indices
+ */
+ long ind = indexes[i] - 1;
+ const wcstring newv = values[ i ];
+ if( ind < 0 )
+ {
+ return 1;
+ }
if ( (size_t)ind >= list.size() )
{
list.resize( ind+1 );
}
-
-// free((void *) al_get(list, ind));
- list[ ind ] = newv;
- }
-
- return 0;
+
+// free((void *) al_get(list, ind));
+ list[ ind ] = newv;
+ }
+
+ return 0;
}
/**
- Erase from a list of wcstring values at specified indexes
+ Erase from a list of wcstring values at specified indexes
*/
-static void erase_values(wcstring_list_t &list, const std::vector<long> &indexes)
+static void erase_values(wcstring_list_t &list, const std::vector<long> &indexes)
{
// Make a set of indexes.
// This both sorts them into ascending order and removes duplicates.
const std::set<long> indexes_set(indexes.begin(), indexes.end());
-
+
// Now walk the set backwards, so we encounter larger indexes first, and remove elements at the given (1-based) indexes.
std::set<long>::const_reverse_iterator iter;
for (iter = indexes_set.rbegin(); iter != indexes_set.rend(); iter++) {
@@ -325,46 +325,46 @@ static void erase_values(wcstring_list_t &list, const std::vector<long> &indexes
Print the names of all environment variables in the scope, with or without shortening,
with or without values, with or without escaping
*/
-static void print_variables(int include_values, int esc, bool shorten_ok, int scope)
+static void print_variables(int include_values, int esc, bool shorten_ok, int scope)
{
wcstring_list_t names = env_get_names(scope);
sort(names.begin(), names.end());
-
- for( size_t i = 0; i < names.size(); i++ )
- {
- const wcstring key = names.at(i);
+
+ for( size_t i = 0; i < names.size(); i++ )
+ {
+ const wcstring key = names.at(i);
const wcstring e_key = escape_string(key, 0);
- stdout_buffer.append(e_key);
-
- if( include_values )
- {
- env_var_t value = env_get_string(key);
- if( !value.missing() )
- {
- int shorten = 0;
-
- if( shorten_ok && value.length() > 64 )
- {
- shorten = 1;
- value.resize(60);
- }
-
- wcstring e_value = esc ? expand_escape_variable(value) : value;
-
+ stdout_buffer.append(e_key);
+
+ if( include_values )
+ {
+ env_var_t value = env_get_string(key);
+ if( !value.missing() )
+ {
+ int shorten = 0;
+
+ if( shorten_ok && value.length() > 64 )
+ {
+ shorten = 1;
+ value.resize(60);
+ }
+
+ wcstring e_value = esc ? expand_escape_variable(value) : value;
+
stdout_buffer.append(L" ");
stdout_buffer.append(e_value);
-
- if( shorten )
- {
- stdout_buffer.append(L"\u2026");
- }
-
- }
- }
-
- stdout_buffer.append(L"\n");
- }
+
+ if( shorten )
+ {
+ stdout_buffer.append(L"\u2026");
+ }
+
+ }
+ }
+
+ stdout_buffer.append(L"\n");
+ }
}
@@ -373,464 +373,464 @@ static void print_variables(int include_values, int esc, bool shorten_ok, int sc
The set builtin. Creates, updates and erases environment variables
and environemnt variable arrays.
*/
-static int builtin_set( parser_t &parser, wchar_t **argv )
+static int builtin_set( parser_t &parser, wchar_t **argv )
{
-
- /**
- Variables used for parsing the argument list
- */
- static const struct woption
- long_options[] =
- {
- {
- L"export", no_argument, 0, 'x'
- }
- ,
- {
- L"global", no_argument, 0, 'g'
- }
- ,
- {
- L"local", no_argument, 0, 'l'
- }
- ,
- {
- L"erase", no_argument, 0, 'e'
- }
- ,
- {
- L"names", no_argument, 0, 'n'
- }
- ,
- {
- L"unexport", no_argument, 0, 'u'
- }
- ,
- {
- L"universal", no_argument, 0, 'U'
- }
+
+ /**
+ Variables used for parsing the argument list
+ */
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"export", no_argument, 0, 'x'
+ }
+ ,
+ {
+ L"global", no_argument, 0, 'g'
+ }
+ ,
+ {
+ L"local", no_argument, 0, 'l'
+ }
+ ,
+ {
+ L"erase", no_argument, 0, 'e'
+ }
+ ,
+ {
+ L"names", no_argument, 0, 'n'
+ }
+ ,
+ {
+ L"unexport", no_argument, 0, 'u'
+ }
+ ,
+ {
+ L"universal", no_argument, 0, 'U'
+ }
,
- {
- L"long", no_argument, 0, 'L'
- }
- ,
- {
- L"query", no_argument, 0, 'q'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- const wchar_t *short_options = L"+xglenuULqh";
-
- int argc = builtin_count_args(argv);
-
- /*
- Flags to set the work mode
- */
- int local = 0, global = 0, exportv = 0;
- int erase = 0, list = 0, unexport=0;
- int universal = 0, query=0;
- bool shorten_ok = true;
-
- /*
- Variables used for performing the actual work
- */
- wchar_t *dest = 0;
- int retcode=0;
- int scope;
- int slice=0;
- int i;
-
- wchar_t *bad_char;
-
-
- /* Parse options to obtain the requested operation and the modifiers */
- woptind = 0;
- while (1)
- {
- int c = wgetopt_long(argc, argv, short_options, long_options, 0);
-
- if (c == -1)
- {
- break;
- }
-
- switch(c)
- {
- case 0:
- break;
-
- case 'e':
- erase = 1;
- break;
-
- case 'n':
- list = 1;
- break;
-
- case 'x':
- exportv = 1;
- break;
-
- case 'l':
- local = 1;
- break;
-
- case 'g':
- global = 1;
- break;
-
- case 'u':
- unexport = 1;
- break;
-
- case 'U':
- universal = 1;
- break;
-
+ {
+ L"long", no_argument, 0, 'L'
+ }
+ ,
+ {
+ L"query", no_argument, 0, 'q'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ const wchar_t *short_options = L"+xglenuULqh";
+
+ int argc = builtin_count_args(argv);
+
+ /*
+ Flags to set the work mode
+ */
+ int local = 0, global = 0, exportv = 0;
+ int erase = 0, list = 0, unexport=0;
+ int universal = 0, query=0;
+ bool shorten_ok = true;
+
+ /*
+ Variables used for performing the actual work
+ */
+ wchar_t *dest = 0;
+ int retcode=0;
+ int scope;
+ int slice=0;
+ int i;
+
+ wchar_t *bad_char;
+
+
+ /* Parse options to obtain the requested operation and the modifiers */
+ woptind = 0;
+ while (1)
+ {
+ int c = wgetopt_long(argc, argv, short_options, long_options, 0);
+
+ if (c == -1)
+ {
+ break;
+ }
+
+ switch(c)
+ {
+ case 0:
+ break;
+
+ case 'e':
+ erase = 1;
+ break;
+
+ case 'n':
+ list = 1;
+ break;
+
+ case 'x':
+ exportv = 1;
+ break;
+
+ case 'l':
+ local = 1;
+ break;
+
+ case 'g':
+ global = 1;
+ break;
+
+ case 'u':
+ unexport = 1;
+ break;
+
+ case 'U':
+ universal = 1;
+ break;
+
case 'L':
shorten_ok = false;
break;
- case 'q':
- query = 1;
- break;
-
- case 'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return 0;
-
- case '?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return 1;
-
- default:
- break;
- }
- }
-
- /*
- Ok, all arguments have been parsed, let's validate them
- */
-
- /*
- If we are checking the existance of a variable (-q) we can not
- also specify scope
- */
-
- if( query && (erase || list) )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_COMBO,
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
-
- /* We can't both list and erase varaibles */
- if( erase && list )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_COMBO,
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- /*
- Variables can only have one scope
- */
- if( local + global + universal > 1 )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_GLOCAL,
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- /*
- Variables can only have one export status
- */
- if( exportv && unexport )
- {
- append_format(stderr_buffer,
- BUILTIN_ERR_EXPUNEXP,
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- /*
- Calculate the scope value for variable assignement
- */
- scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (exportv ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
-
- if( query )
- {
- /*
- Query mode. Return the number of variables that do not exist
- out of the specified variables.
- */
- int i;
- for( i=woptind; i<argc; i++ )
- {
- wchar_t *arg = argv[i];
- int slice=0;
-
- if( !(dest = wcsdup(arg)))
- {
- DIE_MEM();
- }
-
- if( wcschr( dest, L'[' ) )
- {
- slice = 1;
- *wcschr( dest, L'[' )=0;
- }
-
- if( slice )
- {
- std::vector<long> indexes;
- wcstring_list_t result;
- size_t j;
-
+ case 'q':
+ query = 1;
+ break;
+
+ case 'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return 0;
+
+ case '?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return 1;
+
+ default:
+ break;
+ }
+ }
+
+ /*
+ Ok, all arguments have been parsed, let's validate them
+ */
+
+ /*
+ If we are checking the existance of a variable (-q) we can not
+ also specify scope
+ */
+
+ if( query && (erase || list) )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_COMBO,
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+
+ /* We can't both list and erase varaibles */
+ if( erase && list )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_COMBO,
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ /*
+ Variables can only have one scope
+ */
+ if( local + global + universal > 1 )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_GLOCAL,
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ /*
+ Variables can only have one export status
+ */
+ if( exportv && unexport )
+ {
+ append_format(stderr_buffer,
+ BUILTIN_ERR_EXPUNEXP,
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ /*
+ Calculate the scope value for variable assignement
+ */
+ scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (exportv ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
+
+ if( query )
+ {
+ /*
+ Query mode. Return the number of variables that do not exist
+ out of the specified variables.
+ */
+ int i;
+ for( i=woptind; i<argc; i++ )
+ {
+ wchar_t *arg = argv[i];
+ int slice=0;
+
+ if( !(dest = wcsdup(arg)))
+ {
+ DIE_MEM();
+ }
+
+ if( wcschr( dest, L'[' ) )
+ {
+ slice = 1;
+ *wcschr( dest, L'[' )=0;
+ }
+
+ if( slice )
+ {
+ std::vector<long> indexes;
+ wcstring_list_t result;
+ size_t j;
+
env_var_t dest_str = env_get_string(dest);
if (! dest_str.missing())
tokenize_variable_array( dest_str, result );
-
- if( !parse_index( indexes, arg, dest, result.size() ) )
- {
- builtin_print_help( parser, argv[0], stderr_buffer );
- retcode = 1;
- break;
- }
- for( j=0; j < indexes.size() ; j++ )
- {
- long idx = indexes[j];
- if( idx < 1 || (size_t)idx > result.size() )
- {
- retcode++;
- }
- }
- }
- else
- {
- if( !env_exist( arg, scope ) )
- {
- retcode++;
- }
- }
-
- free( dest );
-
- }
- return retcode;
- }
-
- if( list )
- {
- /* Maybe we should issue an error if there are any other arguments? */
- print_variables(0, 0, shorten_ok, scope);
- return 0;
- }
-
- if( woptind == argc )
- {
- /*
- Print values of variables
- */
-
- if( erase )
- {
- append_format(stderr_buffer,
- _(L"%ls: Erase needs a variable name\n"),
- argv[0] );
-
- builtin_print_help( parser, argv[0], stderr_buffer );
- retcode = 1;
- }
- else
- {
- print_variables( 1, 1, shorten_ok, scope );
- }
-
- return retcode;
- }
-
- if( !(dest = wcsdup(argv[woptind])))
- {
- DIE_MEM();
- }
-
- if( wcschr( dest, L'[' ) )
- {
- slice = 1;
- *wcschr( dest, L'[' )=0;
- }
-
- if( !wcslen( dest ) )
- {
- free( dest );
- append_format(stderr_buffer, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- if( (bad_char = wcsvarname( dest ) ) )
- {
- append_format(stderr_buffer, BUILTIN_ERR_VARCHAR, argv[0], *bad_char );
- builtin_print_help( parser, argv[0], stderr_buffer );
- free( dest );
- return 1;
- }
-
- if( slice && erase && (scope != ENV_USER) )
- {
- free( dest );
- append_format(stderr_buffer, _(L"%ls: Can not specify scope when erasing array slice\n"), argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- /*
- set assignment can work in two modes, either using slices or
- using the whole array. We detect which mode is used here.
- */
-
- if( slice )
- {
-
- /*
- Slice mode
- */
- size_t idx_count, val_count;
- wcstring_list_t values;
- std::vector<long> indexes;
- wcstring_list_t result;
-
+
+ if( !parse_index( indexes, arg, dest, result.size() ) )
+ {
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ retcode = 1;
+ break;
+ }
+ for( j=0; j < indexes.size() ; j++ )
+ {
+ long idx = indexes[j];
+ if( idx < 1 || (size_t)idx > result.size() )
+ {
+ retcode++;
+ }
+ }
+ }
+ else
+ {
+ if( !env_exist( arg, scope ) )
+ {
+ retcode++;
+ }
+ }
+
+ free( dest );
+
+ }
+ return retcode;
+ }
+
+ if( list )
+ {
+ /* Maybe we should issue an error if there are any other arguments? */
+ print_variables(0, 0, shorten_ok, scope);
+ return 0;
+ }
+
+ if( woptind == argc )
+ {
+ /*
+ Print values of variables
+ */
+
+ if( erase )
+ {
+ append_format(stderr_buffer,
+ _(L"%ls: Erase needs a variable name\n"),
+ argv[0] );
+
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ retcode = 1;
+ }
+ else
+ {
+ print_variables( 1, 1, shorten_ok, scope );
+ }
+
+ return retcode;
+ }
+
+ if( !(dest = wcsdup(argv[woptind])))
+ {
+ DIE_MEM();
+ }
+
+ if( wcschr( dest, L'[' ) )
+ {
+ slice = 1;
+ *wcschr( dest, L'[' )=0;
+ }
+
+ if( !wcslen( dest ) )
+ {
+ free( dest );
+ append_format(stderr_buffer, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ if( (bad_char = wcsvarname( dest ) ) )
+ {
+ append_format(stderr_buffer, BUILTIN_ERR_VARCHAR, argv[0], *bad_char );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ free( dest );
+ return 1;
+ }
+
+ if( slice && erase && (scope != ENV_USER) )
+ {
+ free( dest );
+ append_format(stderr_buffer, _(L"%ls: Can not specify scope when erasing array slice\n"), argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ /*
+ set assignment can work in two modes, either using slices or
+ using the whole array. We detect which mode is used here.
+ */
+
+ if( slice )
+ {
+
+ /*
+ Slice mode
+ */
+ size_t idx_count, val_count;
+ wcstring_list_t values;
+ std::vector<long> indexes;
+ wcstring_list_t result;
+
const env_var_t dest_str = env_get_string(dest);
if (! dest_str.missing())
tokenize_variable_array( dest_str, result );
-
- for( ; woptind<argc; woptind++ )
- {
- if( !parse_index( indexes, argv[woptind], dest, result.size() ) )
- {
- builtin_print_help( parser, argv[0], stderr_buffer );
- retcode = 1;
- break;
- }
-
- val_count = argc-woptind-1;
- idx_count = indexes.size();
-
- if( !erase )
- {
- if( val_count < idx_count )
- {
- append_format(stderr_buffer, _(BUILTIN_SET_ARG_COUNT), argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- retcode=1;
- break;
- }
- if( val_count == idx_count )
- {
- woptind++;
- break;
- }
- }
- }
-
- if( !retcode )
- {
- /*
- Slice indexes have been calculated, do the actual work
- */
-
- if( erase )
- {
- erase_values(result, indexes);
- my_env_set( dest, result, scope);
- }
- else
- {
- wcstring_list_t value;
-// al_init(&value);
-
- while( woptind < argc )
- {
- value.push_back( argv[woptind++] );
- }
-
- if( update_values( result,
- indexes,
- value ) )
- {
- append_format(stderr_buffer, L"%ls: ", argv[0] );
- append_format(stderr_buffer, ARRAY_BOUNDS_ERR );
- stderr_buffer.push_back(L'\n');
- }
-
- my_env_set(dest, result, scope);
-
-// al_destroy( &value );
-
- }
- }
-
-// al_foreach( &result, &free );
-// al_destroy( &result );
-
-// al_destroy(&indexes);
-// al_destroy(&values);
-
- }
- else
- {
- woptind++;
-
- /*
- No slicing
- */
- if( erase )
- {
- if( woptind != argc )
- {
- append_format(stderr_buffer,
- _(L"%ls: Values cannot be specfied with erase\n"),
- argv[0] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- retcode=1;
- }
- else
- {
- retcode = env_remove( dest, scope );
- }
- }
- else
- {
+
+ for( ; woptind<argc; woptind++ )
+ {
+ if( !parse_index( indexes, argv[woptind], dest, result.size() ) )
+ {
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ retcode = 1;
+ break;
+ }
+
+ val_count = argc-woptind-1;
+ idx_count = indexes.size();
+
+ if( !erase )
+ {
+ if( val_count < idx_count )
+ {
+ append_format(stderr_buffer, _(BUILTIN_SET_ARG_COUNT), argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ retcode=1;
+ break;
+ }
+ if( val_count == idx_count )
+ {
+ woptind++;
+ break;
+ }
+ }
+ }
+
+ if( !retcode )
+ {
+ /*
+ Slice indexes have been calculated, do the actual work
+ */
+
+ if( erase )
+ {
+ erase_values(result, indexes);
+ my_env_set( dest, result, scope);
+ }
+ else
+ {
+ wcstring_list_t value;
+// al_init(&value);
+
+ while( woptind < argc )
+ {
+ value.push_back( argv[woptind++] );
+ }
+
+ if( update_values( result,
+ indexes,
+ value ) )
+ {
+ append_format(stderr_buffer, L"%ls: ", argv[0] );
+ append_format(stderr_buffer, ARRAY_BOUNDS_ERR );
+ stderr_buffer.push_back(L'\n');
+ }
+
+ my_env_set(dest, result, scope);
+
+// al_destroy( &value );
+
+ }
+ }
+
+// al_foreach( &result, &free );
+// al_destroy( &result );
+
+// al_destroy(&indexes);
+// al_destroy(&values);
+
+ }
+ else
+ {
+ woptind++;
+
+ /*
+ No slicing
+ */
+ if( erase )
+ {
+ if( woptind != argc )
+ {
+ append_format(stderr_buffer,
+ _(L"%ls: Values cannot be specfied with erase\n"),
+ argv[0] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ retcode=1;
+ }
+ else
+ {
+ retcode = env_remove( dest, scope );
+ }
+ }
+ else
+ {
wcstring_list_t val;
- for( i=woptind; i<argc; i++ )
+ for( i=woptind; i<argc; i++ )
val.push_back(argv[i]);
- retcode = my_env_set( dest, val, scope );
- }
- }
-
- free( dest );
-
- return retcode;
+ retcode = my_env_set( dest, val, scope );
+ }
+ }
+
+ free( dest );
+
+ return retcode;
}
diff --git a/builtin_test.cpp b/builtin_test.cpp
index 193b1d94..449d199a 100644
--- a/builtin_test.cpp
+++ b/builtin_test.cpp
@@ -1,6 +1,6 @@
/** \file builtin_test.cpp Functions defining the test builtin
-Functions used for implementing the test builtin.
+Functions used for implementing the test builtin.
Implemented from scratch (yes, really) by way of IEEE 1003.1 as reference.
*/
@@ -28,12 +28,12 @@ static const wchar_t * const condstr[] = {
};
namespace test_expressions {
-
+
enum token_t {
test_unknown, // arbitrary string
-
+
test_bang, // "!", inverts sense
-
+
test_filetype_b, // "-b", for block special files
test_filetype_c, // "-c" for character special files
test_filetype_d, // "-d" for directories
@@ -44,44 +44,44 @@ namespace test_expressions {
test_filetype_L, // "-L", same as -h
test_filetype_p, // "-p", for FIFO
test_filetype_S, // "-S", socket
-
+
test_filesize_s, // "-s", size greater than zero
-
+
test_filedesc_t, // "-t", whether the fd is associated with a terminal
-
+
test_fileperm_r, // "-r", read permission
test_fileperm_u, // "-u", whether file is setuid
test_fileperm_w, // "-w", whether file write permission is allowed
test_fileperm_x, // "-x", whether file execute/search is allowed
-
+
test_string_n, // "-n", non-empty string
test_string_z, // "-z", true if length of string is 0
test_string_equal, // "=", true if strings are identical
test_string_not_equal, // "!=", true if strings are not identical
-
+
test_number_equal, // "-eq", true if numbers are equal
test_number_not_equal, // "-ne", true if numbers are not equal
test_number_greater, // "-gt", true if first number is larger than second
test_number_greater_equal, // "-ge", true if first number is at least second
test_number_lesser, // "-lt", true if first number is smaller than second
test_number_lesser_equal, // "-le", true if first number is at most second
-
+
test_combine_and, // "-a", true if left and right are both true
test_combine_or, // "-o", true if either left or right is true
-
+
test_paren_open, // "(", open paren
test_paren_close, // ")", close paren
};
-
+
static bool binary_primary_evaluate(test_expressions::token_t token, const wcstring &left, const wcstring &right, wcstring_list_t &errors);
static bool unary_primary_evaluate(test_expressions::token_t token, const wcstring &arg, wcstring_list_t &errors);
-
+
enum {
UNARY_PRIMARY = 1 << 0,
BINARY_PRIMARY = 1 << 1
};
-
+
static const struct token_info_t { token_t tok; const wchar_t *string; unsigned int flags; } token_infos[] =
{
{test_unknown, L"", 0},
@@ -117,7 +117,7 @@ namespace test_expressions {
{test_paren_open, L"(", 0},
{test_paren_close, L")", 0}
};
-
+
const token_info_t *token_for_string(const wcstring &str) {
for (size_t i=0; i < sizeof token_infos / sizeof *token_infos; i++) {
if (str == token_infos[i].string) {
@@ -127,55 +127,55 @@ namespace test_expressions {
return &token_infos[0]; //unknown
}
-
+
/* Grammar.
-
+
<expr> = <combining_expr>
-
+
<combining_expr> = <unary_expr> and/or <combining_expr> |
<unary_expr>
-
+
<unary_expr> = bang <unary_expr> |
<primary>
-
+
<primary> = <unary_primary> arg |
arg <binary_primary> arg |
'(' <expr> ')'
-
+
*/
-
+
class expression;
class test_parser {
private:
wcstring_list_t strings;
wcstring_list_t errors;
-
+
expression *error(const wchar_t *fmt, ...);
void add_error(const wchar_t *fmt, ...);
-
+
const wcstring &arg(unsigned int idx) { return strings.at(idx); }
-
+
public:
test_parser(const wcstring_list_t &val) : strings(val)
{ }
-
+
expression *parse_expression(unsigned int start, unsigned int end);
expression *parse_combining_expression(unsigned int start, unsigned int end);
expression *parse_unary_expression(unsigned int start, unsigned int end);
-
+
expression *parse_primary(unsigned int start, unsigned int end);
expression *parse_parenthentical(unsigned int start, unsigned int end);
expression *parse_unary_primary(unsigned int start, unsigned int end);
expression *parse_binary_primary(unsigned int start, unsigned int end);
expression *parse_just_a_string(unsigned int start, unsigned int end);
-
+
static expression *parse_args(const wcstring_list_t &args, wcstring &err);
};
-
+
struct range_t {
unsigned int start;
unsigned int end;
-
+
range_t(unsigned s, unsigned e) : start(s), end(e) { }
};
@@ -184,13 +184,13 @@ namespace test_expressions {
class expression {
protected:
expression(token_t what, range_t where) : token(what), range(where) { }
-
+
public:
const token_t token;
range_t range;
-
+
virtual ~expression() { }
-
+
// evaluate returns true if the expression is true (i.e. BUILTIN_TEST_SUCCESS)
virtual bool evaluate(wcstring_list_t &errors) = 0;
};
@@ -210,59 +210,59 @@ namespace test_expressions {
public:
wcstring arg_left;
wcstring arg_right;
-
+
binary_primary(token_t tok, range_t where, const wcstring &left, const wcstring &right) : expression(tok, where), arg_left(left), arg_right(right)
{ }
bool evaluate(wcstring_list_t &errors);
};
-
+
/* Unary operator like bang */
class unary_operator : public expression {
public:
- expr_ref_t subject;
+ expr_ref_t subject;
unary_operator(token_t tok, range_t where, expr_ref_t &exp) : expression(tok, where), subject(exp) { }
bool evaluate(wcstring_list_t &errors);
};
-
+
/* Combining expression. Contains a list of AND or OR expressions. It takes more than two so that we don't have to worry about precedence in the parser. */
class combining_expression : public expression {
public:
const std::vector<expression *> subjects;
const std::vector<token_t> combiners;
-
+
combining_expression(token_t tok, range_t where, const std::vector<expression *> &exprs, const std::vector<token_t> &combs) : expression(tok, where), subjects(exprs), combiners(combs)
{
/* We should have one more subject than combiner */
assert(subjects.size() == combiners.size() + 1);
}
-
+
/* We are responsible for destroying our expressions */
virtual ~combining_expression() {
for (size_t i=0; i < subjects.size(); i++) {
delete subjects[i];
}
}
-
+
bool evaluate(wcstring_list_t &errors);
};
-
+
/* Parenthetical expression */
class parenthetical_expression : public expression {
public:
expr_ref_t contents;
parenthetical_expression(token_t tok, range_t where, expr_ref_t &expr) : expression(tok, where), contents(expr) { }
-
+
virtual bool evaluate(wcstring_list_t &errors);
};
-
+
void test_parser::add_error(const wchar_t *fmt, ...) {
assert(fmt != NULL);
va_list va;
va_start(va, fmt);
this->errors.push_back(vformat_string(fmt, va));
- va_end(va);
+ va_end(va);
}
-
+
expression *test_parser::error(const wchar_t *fmt, ...) {
assert(fmt != NULL);
va_list va;
@@ -271,7 +271,7 @@ namespace test_expressions {
va_end(va);
return NULL;
}
-
+
expression *test_parser::parse_unary_expression(unsigned int start, unsigned int end) {
if (start >= end) {
return error(L"Missing argument at index %u", start);
@@ -288,18 +288,18 @@ namespace test_expressions {
return parse_primary(start, end);
}
}
-
+
/* Parse a combining expression (AND, OR) */
expression *test_parser::parse_combining_expression(unsigned int start, unsigned int end) {
if (start >= end)
return NULL;
-
+
std::vector<expression *> subjects;
std::vector<token_t> combiners;
unsigned int idx = start;
-
+
while (idx < end) {
-
+
if (! subjects.empty()) {
/* This is not the first expression, so we expect a combiner. */
token_t combiner = token_for_string(arg(idx))->tok;
@@ -310,19 +310,19 @@ namespace test_expressions {
combiners.push_back(combiner);
idx++;
}
-
+
/* Parse another expression */
expression *expr = parse_unary_expression(idx, end);
if (! expr) {
add_error(L"Missing argument at index %u", idx);
break;
}
-
+
/* Go to the end of this expression */
idx = expr->range.end;
subjects.push_back(expr);
}
-
+
if (! subjects.empty()) {
/* Our new expression takes ownership of all expressions we created. The token we pass is irrelevant. */
return new combining_expression(test_combine_and, range_t(start, idx), subjects, combiners);
@@ -331,7 +331,7 @@ namespace test_expressions {
return NULL;
}
}
-
+
expression *test_parser::parse_unary_primary(unsigned int start, unsigned int end) {
/* We need two arguments */
if (start >= end) {
@@ -340,54 +340,54 @@ namespace test_expressions {
if (start + 1 >= end) {
return error(L"Missing argument at index %u", start + 1);
}
-
+
/* All our unary primaries are prefix, so the operator is at start. */
const token_info_t *info = token_for_string(arg(start));
if (! (info->flags & UNARY_PRIMARY))
return NULL;
-
+
return new unary_primary(info->tok, range_t(start, start + 2), arg(start + 1));
}
-
+
expression *test_parser::parse_just_a_string(unsigned int start, unsigned int end) {
/* Handle a string as a unary primary that is not a token of any other type.
e.g. 'test foo -a bar' should evaluate to true
We handle this with a unary primary of test_string_n
*/
-
+
/* We need one arguments */
if (start >= end) {
return error(L"Missing argument at index %u", start);
}
-
+
const token_info_t *info = token_for_string(arg(start));
if (info->tok != test_unknown) {
return error(L"Unexpected argument type at index %u", start);
}
-
+
/* This is hackish; a nicer way to implement this would be with a "just a string" expression type */
return new unary_primary(test_string_n, range_t(start, start + 1), arg(start));
}
-
+
#if 0
expression *test_parser::parse_unary_primary(unsigned int start, unsigned int end) {
/* We need either one or two arguments */
if (start >= end) {
return error(L"Missing argument at index %u", start);
}
-
+
/* The index of the argument to the unary primary */
unsigned int arg_idx;
-
+
/* All our unary primaries are prefix, so any operator is at start. But it also may just be a string, with no operator. */
const token_info_t *info = token_for_string(arg(start));
if (info->flags & UNARY_PRIMARY) {
/* We have an operator. Skip the operator argument */
arg_idx = start + 1;
-
+
/* We have some freedom here...do we allow other tokens for the argument to operate on?
For example, should 'test -n =' work? I say yes. So no typechecking on the next token. */
-
+
} else if (info->tok == test_unknown) {
/* "Just a string. */
arg_idx = start;
@@ -395,16 +395,16 @@ namespace test_expressions {
/* Here we don't allow arbitrary tokens as "just a string." I.e. 'test = -a =' should have a parse error. We could relax this at some point. */
return error(L"Parse error at argument index %u", start);
}
-
+
/* Verify we have the argument we want, i.e. test -n should fail to parse */
if (arg_idx >= end) {
return error(L"Missing argument at index %u", arg_idx);
}
-
+
return new unary_primary(info->tok, range_t(start, arg_idx + 1), arg(arg_idx));
}
#endif
-
+
expression *test_parser::parse_binary_primary(unsigned int start, unsigned int end) {
/* We need three arguments */
for (unsigned int idx = start; idx < start + 3; idx++) {
@@ -412,31 +412,31 @@ namespace test_expressions {
return error(L"Missing argument at index %u", idx);
}
}
-
+
/* All our binary primaries are infix, so the operator is at start + 1. */
const token_info_t *info = token_for_string(arg(start + 1));
if (! (info->flags & BINARY_PRIMARY))
return NULL;
-
+
return new binary_primary(info->tok, range_t(start, start + 3), arg(start), arg(start + 2));
}
-
+
expression *test_parser::parse_parenthentical(unsigned int start, unsigned int end) {
/* We need at least three arguments: open paren, argument, close paren */
if (start + 3 >= end)
return NULL;
-
+
/* Must start with an open expression */
const token_info_t *open_paren = token_for_string(arg(start));
if (open_paren->tok != test_paren_open)
return NULL;
-
+
/* Parse a subexpression */
expression *subexr_ptr = parse_expression(start + 1, end);
if (! subexr_ptr)
return NULL;
expr_ref_t subexpr(subexr_ptr);
-
+
/* Parse a close paren */
unsigned close_index = subexpr->range.end;
assert(close_index <= end);
@@ -447,7 +447,7 @@ namespace test_expressions {
if (close_paren->tok != test_paren_close) {
return error(L"Expected close paren at index %u", close_index);
}
-
+
/* Success */
return new parenthetical_expression(test_paren_open, range_t(start, close_index+1), subexpr);
}
@@ -456,7 +456,7 @@ namespace test_expressions {
if (start >= end) {
return error(L"Missing argument at index %u", start);
}
-
+
expression *expr = NULL;
if (! expr) expr = parse_parenthentical(start, end);
if (! expr) expr = parse_unary_primary(start, end);
@@ -469,17 +469,17 @@ namespace test_expressions {
if (start >= end) {
return error(L"Missing argument at index %u", start);
}
-
+
return parse_combining_expression(start, end);
}
-
+
expression *test_parser::parse_args(const wcstring_list_t &args, wcstring &err) {
/* Empty list and one-arg list should be handled by caller */
assert(args.size() > 1);
-
+
test_parser parser(args);
expression *result = parser.parse_expression(0, (unsigned int)args.size());
-
+
/* Handle errors */
bool errored = false;
for (size_t i = 0; i < parser.errors.size(); i++) {
@@ -490,7 +490,7 @@ namespace test_expressions {
// For now we only show the first error
break;
}
-
+
if (! errored && result) {
/* It's also an error if there are any unused arguments. This is not detected by parse_expression() */
assert(result->range.end <= args.size());
@@ -501,19 +501,19 @@ namespace test_expressions {
errored = true;
}
}
-
-
+
+
return result;
}
-
+
bool unary_primary::evaluate(wcstring_list_t &errors) {
return unary_primary_evaluate(token, arg, errors);
}
-
+
bool binary_primary::evaluate(wcstring_list_t &errors) {
return binary_primary_evaluate(token, arg_left, arg_right, errors);
}
-
+
bool unary_operator::evaluate(wcstring_list_t &errors) {
switch (token) {
case test_bang:
@@ -525,7 +525,7 @@ namespace test_expressions {
}
}
-
+
bool combining_expression::evaluate(wcstring_list_t &errors) {
switch (token) {
case test_combine_and:
@@ -534,11 +534,11 @@ namespace test_expressions {
/* One-element case */
if (subjects.size() == 1)
return subjects.at(0)->evaluate(errors);
-
+
/* Evaluate our lists, remembering that AND has higher precedence than OR. We can visualize this as a sequence of OR expressions of AND expressions. */
assert(combiners.size() + 1 == subjects.size());
assert(! subjects.empty());
-
+
size_t idx = 0, max = subjects.size();
bool or_result = false;
while (idx < max) {
@@ -546,33 +546,33 @@ namespace test_expressions {
/* Short circuit */
break;
}
-
+
/* Evaluate a stream of AND starting at given subject index. It may only have one element. */
bool and_result = true;
for (; idx < max; idx++) {
/* Evaluate it, short-circuiting */
and_result = and_result && subjects.at(idx)->evaluate(errors);
-
+
/* If the combiner at this index (which corresponding to how we combine with the next subject) is not AND, then exit the loop */
if (idx + 1 < max && combiners.at(idx) != test_combine_and) {
idx++;
break;
}
}
-
+
/* OR it in */
or_result = or_result || and_result;
}
return or_result;
}
-
+
default:
errors.push_back(format_string(L"Unknown token type in %s", __func__));
return BUILTIN_TEST_FAIL;
}
}
-
+
bool parenthetical_expression::evaluate(wcstring_list_t &errors) {
return contents->evaluate(errors);
}
@@ -591,28 +591,28 @@ namespace test_expressions {
switch (token) {
case test_string_equal:
return left == right;
-
+
case test_string_not_equal:
return left != right;
-
+
case test_number_equal:
return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num == right_num;
-
+
case test_number_not_equal:
return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num != right_num;
-
+
case test_number_greater:
return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num > right_num;
-
+
case test_number_greater_equal:
return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num >= right_num;
-
+
case test_number_lesser:
return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num < right_num;
-
+
case test_number_lesser_equal:
return parse_number(left, &left_num) && parse_number(right, &right_num) && left_num <= right_num;
-
+
default:
errors.push_back(format_string(L"Unknown token type in %s", __func__));
return false;
@@ -627,60 +627,60 @@ namespace test_expressions {
switch (token) {
case test_filetype_b: // "-b", for block special files
return !wstat(arg, &buf) && S_ISBLK(buf.st_mode);
-
+
case test_filetype_c: // "-c" for character special files
return !wstat(arg, &buf) && S_ISCHR(buf.st_mode);
-
+
case test_filetype_d: // "-d" for directories
return !wstat(arg, &buf) && S_ISDIR(buf.st_mode);
-
+
case test_filetype_e: // "-e" for files that exist
return !wstat(arg, &buf);
-
+
case test_filetype_f: // "-f" for for regular files
return !wstat(arg, &buf) && S_ISREG(buf.st_mode);
-
+
case test_filetype_g: // "-g" for set-group-id
return !wstat(arg, &buf) && (S_ISGID & buf.st_mode);
-
+
case test_filetype_h: // "-h" for symbolic links
case test_filetype_L: // "-L", same as -h
return !lwstat(arg, &buf) && S_ISLNK(buf.st_mode);
case test_filetype_p: // "-p", for FIFO
return !wstat(arg, &buf) && S_ISFIFO(buf.st_mode);
-
+
case test_filetype_S: // "-S", socket
return !wstat(arg, &buf) && S_ISSOCK(buf.st_mode);
-
+
case test_filesize_s: // "-s", size greater than zero
return !wstat(arg, &buf) && buf.st_size > 0;
-
+
case test_filedesc_t: // "-t", whether the fd is associated with a terminal
return parse_number(arg, &num) && num == (int)num && isatty((int)num);
-
+
case test_fileperm_r: // "-r", read permission
return !waccess(arg, R_OK);
-
+
case test_fileperm_u: // "-u", whether file is setuid
return !wstat(arg, &buf) && (S_ISUID & buf.st_mode);
-
+
case test_fileperm_w: // "-w", whether file write permission is allowed
return !waccess(arg, W_OK);
-
+
case test_fileperm_x: // "-x", whether file execute/search is allowed
return !waccess(arg, X_OK);
-
+
case test_string_n: // "-n", non-empty string
return ! arg.empty();
-
+
case test_string_z: // "-z", true if length of string is 0
return arg.empty();
-
+
default:
errors.push_back(format_string(L"Unknown token type in %s", __func__));
return false;
- }
+ }
}
};
@@ -698,11 +698,11 @@ namespace test_expressions {
int builtin_test( parser_t &parser, wchar_t **argv )
{
using namespace test_expressions;
-
+
/* The first argument should be the name of the command ('test') */
if (! argv[0])
return BUILTIN_TEST_FAIL;
-
+
size_t argc = 0;
while (argv[argc + 1])
argc++;
diff --git a/builtin_ulimit.cpp b/builtin_ulimit.cpp
index 93e37cc5..d20abeed 100644
--- a/builtin_ulimit.cpp
+++ b/builtin_ulimit.cpp
@@ -1,6 +1,6 @@
/** \file builtin_ulimit.c Functions defining the ulimit builtin
-Functions used for implementing the ulimit builtin.
+Functions used for implementing the ulimit builtin.
*/
#include "config.h"
@@ -27,99 +27,99 @@ Functions used for implementing the ulimit builtin.
*/
struct resource_t
{
- /**
- Resource id
- */
- int resource;
- /**
- Description of resource
- */
- const wchar_t *desc;
- /**
- Switch used on commandline to specify resource
- */
- wchar_t switch_char;
- /**
- The implicit multiplier used when setting getting values
- */
- int multiplier;
+ /**
+ Resource id
+ */
+ int resource;
+ /**
+ Description of resource
+ */
+ const wchar_t *desc;
+ /**
+ Switch used on commandline to specify resource
+ */
+ wchar_t switch_char;
+ /**
+ The implicit multiplier used when setting getting values
+ */
+ int multiplier;
}
- ;
+ ;
/**
Array of resource_t structs, describing all known resource types.
*/
static const struct resource_t resource_arr[] =
{
- {
- RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024
- }
- ,
- {
- RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd', 1024
- }
- ,
- {
- RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
- }
- ,
+ {
+ RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024
+ }
+ ,
+ {
+ RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd', 1024
+ }
+ ,
+ {
+ RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
+ }
+ ,
#ifdef RLIMIT_MEMLOCK
- {
- RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
- }
- ,
+ {
+ RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
+ }
+ ,
#endif
#ifdef RLIMIT_RSS
- {
- RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
- }
- ,
+ {
+ RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
+ }
+ ,
#endif
- {
- RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n', 1
- }
- ,
- {
- RLIMIT_STACK, L"Maximum stack size", L's', 1024
- }
- ,
- {
- RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
- }
- ,
+ {
+ RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n', 1
+ }
+ ,
+ {
+ RLIMIT_STACK, L"Maximum stack size", L's', 1024
+ }
+ ,
+ {
+ RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
+ }
+ ,
#ifdef RLIMIT_NPROC
- {
- RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
- }
- ,
+ {
+ RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
+ }
+ ,
#endif
#ifdef RLIMIT_AS
- {
- RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
- }
- ,
+ {
+ RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
+ }
+ ,
#endif
- {
- 0, 0, 0, 0
- }
+ {
+ 0, 0, 0, 0
+ }
}
- ;
+ ;
/**
Get the implicit multiplication factor for the specified resource limit
*/
static int get_multiplier( int what )
{
- int i;
-
- for( i=0; resource_arr[i].desc; i++ )
- {
- if( resource_arr[i].resource == what )
- {
- return resource_arr[i].multiplier;
- }
- }
- return -1;
+ int i;
+
+ for( i=0; resource_arr[i].desc; i++ )
+ {
+ if( resource_arr[i].resource == what )
+ {
+ return resource_arr[i].multiplier;
+ }
+ }
+ return -1;
}
/**
@@ -129,11 +129,11 @@ static int get_multiplier( int what )
*/
static rlim_t get( int resource, int hard )
{
- struct rlimit ls;
-
- getrlimit( resource, &ls );
-
- return hard ? ls.rlim_max:ls.rlim_cur;
+ struct rlimit ls;
+
+ getrlimit( resource, &ls );
+
+ return hard ? ls.rlim_max:ls.rlim_cur;
}
/**
@@ -141,13 +141,13 @@ static rlim_t get( int resource, int hard )
*/
static void print( int resource, int hard )
{
- rlim_t l = get( resource, hard );
+ rlim_t l = get( resource, hard );
+
+ if( l == RLIM_INFINITY )
+ stdout_buffer.append( L"unlimited\n" );
+ else
+ append_format(stdout_buffer, L"%d\n", l / get_multiplier( resource ) );
- if( l == RLIM_INFINITY )
- stdout_buffer.append( L"unlimited\n" );
- else
- append_format(stdout_buffer, L"%d\n", l / get_multiplier( resource ) );
-
}
/**
@@ -155,40 +155,40 @@ static void print( int resource, int hard )
*/
static void print_all( int hard )
{
- int i;
- int w=0;
-
- for( i=0; resource_arr[i].desc; i++ )
- {
- w=maxi( w, my_wcswidth(resource_arr[i].desc));
- }
-
- for( i=0; resource_arr[i].desc; i++ )
- {
- struct rlimit ls;
- rlim_t l;
- getrlimit( resource_arr[i].resource, &ls );
- l = hard ? ls.rlim_max:ls.rlim_cur;
-
- const wchar_t *unit = ((resource_arr[i].resource==RLIMIT_CPU)?L"(seconds, ":(get_multiplier(resource_arr[i].resource)==1?L"(":L"(kB, "));
-
- append_format(stdout_buffer,
- L"%-*ls %10ls-%lc) ",
- w,
- resource_arr[i].desc,
- unit,
- resource_arr[i].switch_char);
-
- if( l == RLIM_INFINITY )
- {
- stdout_buffer.append( L"unlimited\n" );
- }
- else
- {
- append_format(stdout_buffer, L"%d\n", l/get_multiplier(resource_arr[i].resource) );
- }
- }
-
+ int i;
+ int w=0;
+
+ for( i=0; resource_arr[i].desc; i++ )
+ {
+ w=maxi( w, my_wcswidth(resource_arr[i].desc));
+ }
+
+ for( i=0; resource_arr[i].desc; i++ )
+ {
+ struct rlimit ls;
+ rlim_t l;
+ getrlimit( resource_arr[i].resource, &ls );
+ l = hard ? ls.rlim_max:ls.rlim_cur;
+
+ const wchar_t *unit = ((resource_arr[i].resource==RLIMIT_CPU)?L"(seconds, ":(get_multiplier(resource_arr[i].resource)==1?L"(":L"(kB, "));
+
+ append_format(stdout_buffer,
+ L"%-*ls %10ls-%lc) ",
+ w,
+ resource_arr[i].desc,
+ unit,
+ resource_arr[i].switch_char);
+
+ if( l == RLIM_INFINITY )
+ {
+ stdout_buffer.append( L"unlimited\n" );
+ }
+ else
+ {
+ append_format(stdout_buffer, L"%d\n", l/get_multiplier(resource_arr[i].resource) );
+ }
+ }
+
}
/**
@@ -196,16 +196,16 @@ static void print_all( int hard )
*/
static const wchar_t *get_desc( int what )
{
- int i;
-
- for( i=0; resource_arr[i].desc; i++ )
- {
- if( resource_arr[i].resource == what )
- {
- return resource_arr[i].desc;
- }
- }
- return L"Not a resource";
+ int i;
+
+ for( i=0; resource_arr[i].desc; i++ )
+ {
+ if( resource_arr[i].resource == what )
+ {
+ return resource_arr[i].desc;
+ }
+ }
+ return L"Not a resource";
}
/**
@@ -215,37 +215,37 @@ static const wchar_t *get_desc( int what )
*/
static int set( int resource, int hard, int soft, rlim_t value )
{
- struct rlimit ls;
- getrlimit( resource, &ls );
-
- if( hard )
- {
- ls.rlim_max = value;
- }
-
- if( soft )
- {
- ls.rlim_cur = value;
-
- /*
- Do not attempt to set the soft limit higher than the hard limit
- */
- if( ( value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY ) ||
- ( value != RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY && value > ls.rlim_max))
- {
- ls.rlim_cur = ls.rlim_max;
- }
- }
-
- if( setrlimit( resource, &ls ) )
- {
- if( errno == EPERM )
- append_format(stderr_buffer, L"ulimit: Permission denied when changing resource of type '%ls'\n", get_desc( resource ) );
- else
- builtin_wperror( L"ulimit" );
- return 1;
- }
- return 0;
+ struct rlimit ls;
+ getrlimit( resource, &ls );
+
+ if( hard )
+ {
+ ls.rlim_max = value;
+ }
+
+ if( soft )
+ {
+ ls.rlim_cur = value;
+
+ /*
+ Do not attempt to set the soft limit higher than the hard limit
+ */
+ if( ( value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY ) ||
+ ( value != RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY && value > ls.rlim_max))
+ {
+ ls.rlim_cur = ls.rlim_max;
+ }
+ }
+
+ if( setrlimit( resource, &ls ) )
+ {
+ if( errno == EPERM )
+ append_format(stderr_buffer, L"ulimit: Permission denied when changing resource of type '%ls'\n", get_desc( resource ) );
+ else
+ builtin_wperror( L"ulimit" );
+ return 1;
+ }
+ return 0;
}
/**
@@ -254,259 +254,259 @@ static int set( int resource, int hard, int soft, rlim_t value )
*/
static int builtin_ulimit( parser_t &parser, wchar_t ** argv )
{
- int hard=0;
- int soft=0;
-
- int what = RLIMIT_FSIZE;
- int report_all = 0;
-
- int argc = builtin_count_args( argv );
-
- woptind=0;
-
- while( 1 )
- {
- static const struct woption
- long_options[] =
- {
- {
- L"all", no_argument, 0, 'a'
- }
- ,
- {
- L"hard", no_argument, 0, 'H'
- }
- ,
- {
- L"soft", no_argument, 0, 'S'
- }
- ,
- {
- L"core-size", no_argument, 0, 'c'
- }
- ,
- {
- L"data-size", no_argument, 0, 'd'
- }
- ,
- {
- L"file-size", no_argument, 0, 'f'
- }
- ,
- {
- L"lock-size", no_argument, 0, 'l'
- }
- ,
- {
- L"resident-set-size", no_argument, 0, 'm'
- }
- ,
- {
- L"file-descriptor-count", no_argument, 0, 'n'
- }
- ,
- {
- L"stack-size", no_argument, 0, 's'
- }
- ,
- {
- L"cpu-time", no_argument, 0, 't'
- }
- ,
- {
- L"process-count", no_argument, 0, 'u'
- }
- ,
- {
- L"virtual-memory-size", no_argument, 0, 'v'
- }
- ,
- {
- L"help", no_argument, 0, 'h'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
-
- int opt_index = 0;
-
- int opt = wgetopt_long( argc,
- argv,
- L"aHScdflmnstuvh",
- long_options,
- &opt_index );
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- if(long_options[opt_index].flag != 0)
- break;
+ int hard=0;
+ int soft=0;
+
+ int what = RLIMIT_FSIZE;
+ int report_all = 0;
+
+ int argc = builtin_count_args( argv );
+
+ woptind=0;
+
+ while( 1 )
+ {
+ static const struct woption
+ long_options[] =
+ {
+ {
+ L"all", no_argument, 0, 'a'
+ }
+ ,
+ {
+ L"hard", no_argument, 0, 'H'
+ }
+ ,
+ {
+ L"soft", no_argument, 0, 'S'
+ }
+ ,
+ {
+ L"core-size", no_argument, 0, 'c'
+ }
+ ,
+ {
+ L"data-size", no_argument, 0, 'd'
+ }
+ ,
+ {
+ L"file-size", no_argument, 0, 'f'
+ }
+ ,
+ {
+ L"lock-size", no_argument, 0, 'l'
+ }
+ ,
+ {
+ L"resident-set-size", no_argument, 0, 'm'
+ }
+ ,
+ {
+ L"file-descriptor-count", no_argument, 0, 'n'
+ }
+ ,
+ {
+ L"stack-size", no_argument, 0, 's'
+ }
+ ,
+ {
+ L"cpu-time", no_argument, 0, 't'
+ }
+ ,
+ {
+ L"process-count", no_argument, 0, 'u'
+ }
+ ,
+ {
+ L"virtual-memory-size", no_argument, 0, 'v'
+ }
+ ,
+ {
+ L"help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+
+ int opt_index = 0;
+
+ int opt = wgetopt_long( argc,
+ argv,
+ L"aHScdflmnstuvh",
+ long_options,
+ &opt_index );
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ if(long_options[opt_index].flag != 0)
+ break;
append_format(stderr_buffer,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
- builtin_print_help( parser, argv[0], stderr_buffer );
-
- return 1;
-
- case L'a':
- report_all=1;
- break;
-
- case L'H':
- hard=1;
- break;
-
- case L'S':
- soft=1;
- break;
-
- case L'c':
- what=RLIMIT_CORE;
- break;
-
- case L'd':
- what=RLIMIT_DATA;
- break;
-
- case L'f':
- what=RLIMIT_FSIZE;
- break;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+
+ return 1;
+
+ case L'a':
+ report_all=1;
+ break;
+
+ case L'H':
+ hard=1;
+ break;
+
+ case L'S':
+ soft=1;
+ break;
+
+ case L'c':
+ what=RLIMIT_CORE;
+ break;
+
+ case L'd':
+ what=RLIMIT_DATA;
+ break;
+
+ case L'f':
+ what=RLIMIT_FSIZE;
+ break;
#ifdef RLIMIT_MEMLOCK
- case L'l':
- what=RLIMIT_MEMLOCK;
- break;
+ case L'l':
+ what=RLIMIT_MEMLOCK;
+ break;
#endif
-#ifdef RLIMIT_RSS
- case L'm':
- what=RLIMIT_RSS;
- break;
+#ifdef RLIMIT_RSS
+ case L'm':
+ what=RLIMIT_RSS;
+ break;
#endif
-
- case L'n':
- what=RLIMIT_NOFILE;
- break;
-
- case L's':
- what=RLIMIT_STACK;
- break;
-
- case L't':
- what=RLIMIT_CPU;
- break;
-
-#ifdef RLIMIT_NPROC
- case L'u':
- what=RLIMIT_NPROC;
- break;
+
+ case L'n':
+ what=RLIMIT_NOFILE;
+ break;
+
+ case L's':
+ what=RLIMIT_STACK;
+ break;
+
+ case L't':
+ what=RLIMIT_CPU;
+ break;
+
+#ifdef RLIMIT_NPROC
+ case L'u':
+ what=RLIMIT_NPROC;
+ break;
#endif
-
-#ifdef RLIMIT_AS
- case L'v':
- what=RLIMIT_AS;
- break;
+
+#ifdef RLIMIT_AS
+ case L'v':
+ what=RLIMIT_AS;
+ break;
#endif
-
- case L'h':
- builtin_print_help( parser, argv[0], stdout_buffer );
- return 0;
-
- case L'?':
- builtin_unknown_option( parser, argv[0], argv[woptind-1] );
- return 1;
- }
- }
-
- if( report_all )
- {
- if( argc - woptind == 0 )
- {
- print_all( hard );
- }
- else
- {
+
+ case L'h':
+ builtin_print_help( parser, argv[0], stdout_buffer );
+ return 0;
+
+ case L'?':
+ builtin_unknown_option( parser, argv[0], argv[woptind-1] );
+ return 1;
+ }
+ }
+
+ if( report_all )
+ {
+ if( argc - woptind == 0 )
+ {
+ print_all( hard );
+ }
+ else
+ {
stderr_buffer.append(argv[0]);
stderr_buffer.append(L": Too many arguments\n");
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- return 0;
- }
-
- switch( argc - woptind )
- {
- case 0:
- {
- /*
- Show current limit value
- */
- print( what, hard );
- break;
- }
-
- case 1:
- {
- /*
- Change current limit value
- */
- rlim_t new_limit;
- wchar_t *end;
-
- /*
- Set both hard and soft limits if nothing else was specified
- */
- if( !(hard+soft) )
- {
- hard=soft=1;
- }
-
- if( wcscasecmp( argv[woptind], L"unlimited" )==0)
- {
- new_limit = RLIM_INFINITY;
- }
- else if( wcscasecmp( argv[woptind], L"hard" )==0)
- {
- new_limit = get( what, 1 );
- }
- else if( wcscasecmp( argv[woptind], L"soft" )==0)
- {
- new_limit = get( what, soft );
- }
- else
- {
- errno=0;
- new_limit = wcstol( argv[woptind], &end, 10 );
- if( errno || *end )
- {
- append_format(stderr_buffer,
- L"%ls: Invalid limit '%ls'\n",
- argv[0],
- argv[woptind] );
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
- new_limit *= get_multiplier( what );
- }
-
- return set( what, hard, soft, new_limit );
- }
-
- default:
- {
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ return 0;
+ }
+
+ switch( argc - woptind )
+ {
+ case 0:
+ {
+ /*
+ Show current limit value
+ */
+ print( what, hard );
+ break;
+ }
+
+ case 1:
+ {
+ /*
+ Change current limit value
+ */
+ rlim_t new_limit;
+ wchar_t *end;
+
+ /*
+ Set both hard and soft limits if nothing else was specified
+ */
+ if( !(hard+soft) )
+ {
+ hard=soft=1;
+ }
+
+ if( wcscasecmp( argv[woptind], L"unlimited" )==0)
+ {
+ new_limit = RLIM_INFINITY;
+ }
+ else if( wcscasecmp( argv[woptind], L"hard" )==0)
+ {
+ new_limit = get( what, 1 );
+ }
+ else if( wcscasecmp( argv[woptind], L"soft" )==0)
+ {
+ new_limit = get( what, soft );
+ }
+ else
+ {
+ errno=0;
+ new_limit = wcstol( argv[woptind], &end, 10 );
+ if( errno || *end )
+ {
+ append_format(stderr_buffer,
+ L"%ls: Invalid limit '%ls'\n",
+ argv[0],
+ argv[woptind] );
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+ new_limit *= get_multiplier( what );
+ }
+
+ return set( what, hard, soft, new_limit );
+ }
+
+ default:
+ {
stderr_buffer.append(argv[0]);
stderr_buffer.append(L": Too many arguments\n");
- builtin_print_help( parser, argv[0], stderr_buffer );
- return 1;
- }
-
- }
- return 0;
+ builtin_print_help( parser, argv[0], stderr_buffer );
+ return 1;
+ }
+
+ }
+ return 0;
}
diff --git a/color.cpp b/color.cpp
index dce115aa..f590bcd8 100644
--- a/color.cpp
+++ b/color.cpp
@@ -72,13 +72,13 @@ bool rgb_color_t::try_parse_rgb(const wcstring &name) {
FA3
F3A035
*/
-
+
size_t digit_idx = 0, len = name.size();
-
+
/* Skip any leading # */
if (len > 0 && name.at(0) == L'#')
digit_idx++;
-
+
bool success = false;
size_t i;
if (len - digit_idx == 3) {
@@ -98,7 +98,7 @@ bool rgb_color_t::try_parse_rgb(const wcstring &name) {
data.rgb[i] = hi*16+lo;
}
success = (i == 3);
- }
+ }
if (success) {
this->type = type_rgb;
}
@@ -152,7 +152,7 @@ rgb_color_t::rgb_color_t(unsigned char t, unsigned char i) : type(t), flags(), d
data.name_idx = i;
}
-rgb_color_t rgb_color_t::normal() { return rgb_color_t(type_normal); }
+rgb_color_t rgb_color_t::normal() { return rgb_color_t(type_normal); }
rgb_color_t rgb_color_t::reset() { return rgb_color_t(type_reset); }
rgb_color_t rgb_color_t::ignore() { return rgb_color_t(type_ignore); }
rgb_color_t rgb_color_t::none() { return rgb_color_t(type_none); }
@@ -184,26 +184,26 @@ static unsigned char term256_color_for_rgb(const unsigned char rgb[3]) {
0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
- 0x870000, 0x87005f, 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
- 0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af,
- 0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
- 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
- 0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
- 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
- 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
- 0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
- 0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
- 0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
- 0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af,
- 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
- 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
- 0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af,
- 0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
- 0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
- 0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
- 0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
- 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
- 0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
+ 0x870000, 0x87005f, 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
+ 0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af,
+ 0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
+ 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
+ 0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
+ 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
+ 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
+ 0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
+ 0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
+ 0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
+ 0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af,
+ 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
+ 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
+ 0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af,
+ 0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
+ 0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
+ 0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
+ 0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
+ 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
+ 0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
};
return 16 + convert_color(rgb, kColors, sizeof kColors / sizeof *kColors);
diff --git a/color.h b/color.h
index 23e5ba77..bcfbfcd0 100644
--- a/color.h
+++ b/color.h
@@ -22,22 +22,22 @@ class rgb_color_t {
type_ignore
};
unsigned char type:4;
-
+
/* Flags */
enum {
flag_bold = 1 << 0,
flag_underline = 1 << 1
};
unsigned char flags:4;
-
+
union {
unsigned char name_idx; //0-10
unsigned char rgb[3];
} data;
-
+
/** Try parsing a special color name like "normal" */
bool try_parse_special(const wcstring &str);
-
+
/** Try parsing an rgb color like "#F0A030" */
bool try_parse_rgb(const wcstring &str);
@@ -49,52 +49,52 @@ class rgb_color_t {
/** Private constructor */
explicit rgb_color_t(unsigned char t, unsigned char i=0);
-
+
public:
-
+
/** Default constructor of type none */
explicit rgb_color_t() : type(type_none), flags(), data() {}
-
+
/** Parse a color from a string */
explicit rgb_color_t(const wcstring &str);
explicit rgb_color_t(const std::string &str);
- /** Returns white */
+ /** Returns white */
static rgb_color_t white();
-
+
/** Returns black */
static rgb_color_t black();
-
+
/** Returns the reset special color */
static rgb_color_t reset();
-
+
/** Returns the normal special color */
static rgb_color_t normal();
-
+
/** Returns the ignore special color */
static rgb_color_t ignore();
-
+
/** Returns the none special color */
static rgb_color_t none();
-
+
/** Returns whether the color is the ignore special color */
bool is_ignore(void) const { return type == type_ignore; }
/** Returns whether the color is the normal special color */
bool is_normal(void) const { return type == type_normal; }
-
+
/** Returns whether the color is the reset special color */
bool is_reset(void) const { return type == type_reset; }
-
+
/** Returns whether the color is the none special color */
bool is_none(void) const { return type == type_none; }
-
+
/** Returns whether the color is a named color (like "magenta") */
bool is_named(void) const { return type == type_named; }
-
+
/** Returns whether the color is specified via RGB components */
bool is_rgb(void) const { return type == type_rgb; }
-
+
/** Returns whether the color is special, that is, not rgb or named */
bool is_special(void) const { return type != type_named && type != type_rgb; }
@@ -103,27 +103,27 @@ class rgb_color_t {
/** Returns the name index for the given color. Requires that the color be named or RGB. */
unsigned char to_name_index() const;
-
+
/** Returns the term256 index for the given color. Requires that the color be named or RGB. */
unsigned char to_term256_index() const;
-
+
/** Returns whether the color is bold */
bool is_bold() const { return flags & flag_bold; }
-
+
/** Set whether the color is bold */
void set_bold(bool x) { if (x) flags |= flag_bold; else flags &= ~flag_bold; }
-
+
/** Returns whether the color is underlined */
bool is_underline() const { return !! (flags & flag_underline); }
-
+
/** Set whether the color is underlined */
void set_underline(bool x) { if (x) flags |= flag_underline; else flags &= ~flag_underline; }
-
+
/** Compare two colors for equality */
bool operator==(const rgb_color_t &other) const {
return type == other.type && ! memcmp(&data, &other.data, sizeof data);
}
-
+
/** Compare two colors for inequality */
bool operator!=(const rgb_color_t &other) const {
return !(*this == other);
diff --git a/common.cpp b/common.cpp
index de1c0612..3d9a7e47 100644
--- a/common.cpp
+++ b/common.cpp
@@ -1,5 +1,5 @@
/** \file common.c
-
+
Various functions, mostly string utilities, that are used by most
parts of fish.
*/
@@ -38,7 +38,7 @@ parts of fish.
#include <wctype.h>
#include <errno.h>
#include <limits.h>
-#include <stdarg.h>
+#include <stdarg.h>
#include <locale.h>
#include <time.h>
#include <sys/time.h>
@@ -82,7 +82,7 @@ parts of fish.
-struct termios shell_modes;
+struct termios shell_modes;
// Note we foolishly assume that pthread_t is just a primitive. But it might be a struct.
static pthread_t main_thread_id = 0;
@@ -102,78 +102,78 @@ int debug_level=1;
static struct winsize termsize;
-void show_stackframe()
+void show_stackframe()
{
/* Hack to avoid showing backtraces in the tester */
if (program_name && ! wcscmp(program_name, L"(ignore)"))
return;
-
- void *trace[32];
- char **messages = (char **)NULL;
- int i, trace_size = 0;
- trace_size = backtrace(trace, 32);
- messages = backtrace_symbols(trace, trace_size);
+ void *trace[32];
+ char **messages = (char **)NULL;
+ int i, trace_size = 0;
+
+ trace_size = backtrace(trace, 32);
+ messages = backtrace_symbols(trace, trace_size);
- if( messages )
- {
- debug( 0, L"Backtrace:" );
- for( i=0; i<trace_size; i++ )
- {
- fwprintf( stderr, L"%s\n", messages[i]);
- }
- free( messages );
- }
+ if( messages )
+ {
+ debug( 0, L"Backtrace:" );
+ for( i=0; i<trace_size; i++ )
+ {
+ fwprintf( stderr, L"%s\n", messages[i]);
+ }
+ free( messages );
+ }
}
int fgetws2(wcstring *s, FILE *f)
{
- int i=0;
- wint_t c;
-
- while( 1 )
- {
- errno=0;
-
- c = getwc( f );
-
- if( errno == EILSEQ )
- {
- continue;
- }
-
- switch( c )
- {
- /* End of line */
- case WEOF:
- case L'\n':
- case L'\0':
- return i;
- /* Ignore carriage returns */
- case L'\r':
- break;
-
- default:
+ int i=0;
+ wint_t c;
+
+ while( 1 )
+ {
+ errno=0;
+
+ c = getwc( f );
+
+ if( errno == EILSEQ )
+ {
+ continue;
+ }
+
+ switch( c )
+ {
+ /* End of line */
+ case WEOF:
+ case L'\n':
+ case L'\0':
+ return i;
+ /* Ignore carriage returns */
+ case L'\r':
+ break;
+
+ default:
i++;
- s->push_back((wchar_t)c);
- break;
- }
- }
+ s->push_back((wchar_t)c);
+ break;
+ }
+ }
}
wchar_t *str2wcs( const char *in )
{
- wchar_t *out;
- size_t len = strlen(in);
-
- out = (wchar_t *)malloc( sizeof(wchar_t)*(len+1) );
+ wchar_t *out;
+ size_t len = strlen(in);
- if( !out )
- {
- DIE_MEM();
- }
+ out = (wchar_t *)malloc( sizeof(wchar_t)*(len+1) );
- return str2wcs_internal( in, out );
+ if( !out )
+ {
+ DIE_MEM();
+ }
+
+ return str2wcs_internal( in, out );
}
wcstring str2wcstring( const char *in )
@@ -194,71 +194,71 @@ wcstring str2wcstring( const std::string &in )
wchar_t *str2wcs_internal( const char *in, wchar_t *out )
{
- size_t res=0;
- size_t in_pos=0;
- size_t out_pos = 0;
- mbstate_t state;
- size_t len;
-
- CHECK( in, 0 );
- CHECK( out, 0 );
-
- len = strlen(in);
-
- memset( &state, 0, sizeof(state) );
-
- while( in[in_pos] )
- {
- res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state );
-
- if( ( ( out[out_pos] >= ENCODE_DIRECT_BASE) &&
- ( out[out_pos] < ENCODE_DIRECT_BASE+256)) ||
- ( out[out_pos] == INTERNAL_SEPARATOR ) )
- {
- out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
- in_pos++;
- memset( &state, 0, sizeof(state) );
- out_pos++;
- }
- else
- {
-
- switch( res )
- {
- case (size_t)(-2):
- case (size_t)(-1):
- {
- out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
- in_pos++;
- memset( &state, 0, sizeof(state) );
- break;
- }
-
- case 0:
- {
- return out;
- }
-
- default:
- {
- in_pos += res;
- break;
- }
- }
- out_pos++;
- }
-
- }
- out[out_pos] = 0;
-
- return out;
+ size_t res=0;
+ size_t in_pos=0;
+ size_t out_pos = 0;
+ mbstate_t state;
+ size_t len;
+
+ CHECK( in, 0 );
+ CHECK( out, 0 );
+
+ len = strlen(in);
+
+ memset( &state, 0, sizeof(state) );
+
+ while( in[in_pos] )
+ {
+ res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state );
+
+ if( ( ( out[out_pos] >= ENCODE_DIRECT_BASE) &&
+ ( out[out_pos] < ENCODE_DIRECT_BASE+256)) ||
+ ( out[out_pos] == INTERNAL_SEPARATOR ) )
+ {
+ out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
+ in_pos++;
+ memset( &state, 0, sizeof(state) );
+ out_pos++;
+ }
+ else
+ {
+
+ switch( res )
+ {
+ case (size_t)(-2):
+ case (size_t)(-1):
+ {
+ out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
+ in_pos++;
+ memset( &state, 0, sizeof(state) );
+ break;
+ }
+
+ case 0:
+ {
+ return out;
+ }
+
+ default:
+ {
+ in_pos += res;
+ break;
+ }
+ }
+ out_pos++;
+ }
+
+ }
+ out[out_pos] = 0;
+
+ return out;
}
char *wcs2str( const wchar_t *in )
{
if (! in)
return NULL;
- char *out;
+ char *out;
size_t desired_size = MAX_UTF8_BYTES*wcslen(in)+1;
char local_buff[512];
if (desired_size <= sizeof local_buff / sizeof *local_buff) {
@@ -272,7 +272,7 @@ char *wcs2str( const wchar_t *in )
}
}
return result;
-
+
} else {
// here we fall into the bad case of allocating a buffer probably much larger than necessary
out = (char *)malloc( MAX_UTF8_BYTES*wcslen(in)+1 );
@@ -282,7 +282,7 @@ char *wcs2str( const wchar_t *in )
return wcs2str_internal( in, out );
}
- return wcs2str_internal( in, out );
+ return wcs2str_internal( in, out );
}
std::string wcs2string(const wcstring &input)
@@ -295,85 +295,85 @@ std::string wcs2string(const wcstring &input)
char *wcs2str_internal( const wchar_t *in, char *out )
{
- size_t res=0;
- size_t in_pos=0;
- size_t out_pos = 0;
- mbstate_t state;
-
- CHECK( in, 0 );
- CHECK( out, 0 );
-
- memset( &state, 0, sizeof(state) );
-
- while( in[in_pos] )
- {
- if( in[in_pos] == INTERNAL_SEPARATOR )
- {
- }
- else if( ( in[in_pos] >= ENCODE_DIRECT_BASE) &&
- ( in[in_pos] < ENCODE_DIRECT_BASE+256) )
- {
- out[out_pos++] = in[in_pos]- ENCODE_DIRECT_BASE;
- }
- else
- {
- res = wcrtomb( &out[out_pos], in[in_pos], &state );
-
- if( res == (size_t)(-1) )
- {
- debug( 1, L"Wide character %d has no narrow representation", in[in_pos] );
- memset( &state, 0, sizeof(state) );
- }
- else
- {
- out_pos += res;
- }
- }
- in_pos++;
- }
- out[out_pos] = 0;
-
- return out;
+ size_t res=0;
+ size_t in_pos=0;
+ size_t out_pos = 0;
+ mbstate_t state;
+
+ CHECK( in, 0 );
+ CHECK( out, 0 );
+
+ memset( &state, 0, sizeof(state) );
+
+ while( in[in_pos] )
+ {
+ if( in[in_pos] == INTERNAL_SEPARATOR )
+ {
+ }
+ else if( ( in[in_pos] >= ENCODE_DIRECT_BASE) &&
+ ( in[in_pos] < ENCODE_DIRECT_BASE+256) )
+ {
+ out[out_pos++] = in[in_pos]- ENCODE_DIRECT_BASE;
+ }
+ else
+ {
+ res = wcrtomb( &out[out_pos], in[in_pos], &state );
+
+ if( res == (size_t)(-1) )
+ {
+ debug( 1, L"Wide character %d has no narrow representation", in[in_pos] );
+ memset( &state, 0, sizeof(state) );
+ }
+ else
+ {
+ out_pos += res;
+ }
+ }
+ in_pos++;
+ }
+ out[out_pos] = 0;
+
+ return out;
}
char **wcsv2strv( const wchar_t * const *in )
{
- size_t i, count = 0;
+ size_t i, count = 0;
- while( in[count] != 0 )
- count++;
- char **res = (char **)malloc( sizeof( char *)*(count+1));
- if( res == 0 )
- {
- DIE_MEM();
- }
+ while( in[count] != 0 )
+ count++;
+ char **res = (char **)malloc( sizeof( char *)*(count+1));
+ if( res == 0 )
+ {
+ DIE_MEM();
+ }
- for( i=0; i<count; i++ )
- {
- res[i]=wcs2str(in[i]);
- }
- res[count]=0;
- return res;
+ for( i=0; i<count; i++ )
+ {
+ res[i]=wcs2str(in[i]);
+ }
+ res[count]=0;
+ return res;
}
wcstring format_string(const wchar_t *format, ...)
{
- va_list va;
- va_start( va, format );
+ va_list va;
+ va_start( va, format );
wcstring result = vformat_string(format, va);
- va_end( va );
+ va_end( va );
return result;
}
wcstring vformat_string(const wchar_t *format, va_list va_orig)
-{
+{
const int saved_err = errno;
/*
As far as I know, there is no way to check if a
vswprintf-call failed because of a badly formated string
option or because the supplied destination string was to
- small. In GLIBC, errno seems to be set to EINVAL either way.
+ small. In GLIBC, errno seems to be set to EINVAL either way.
Because of this, on failiure we try to
increase the buffer size until the free space is
@@ -403,19 +403,19 @@ wcstring vformat_string(const wchar_t *format, va_list va_orig)
DIE_MEM();
}
}
-
+
/* Try printing */
- va_list va;
- va_copy( va, va_orig );
+ va_list va;
+ va_copy( va, va_orig );
status = vswprintf(buff, size / sizeof(wchar_t), format, va);
- va_end(va);
+ va_end(va);
}
-
+
wcstring result = wcstring(buff);
-
+
if (buff != static_buff)
free(buff);
-
+
errno = saved_err;
return result;
}
@@ -424,180 +424,180 @@ void append_format(wcstring &str, const wchar_t *format, ...)
{
/* Preserve errno across this call since it likes to stomp on it */
int err = errno;
- va_list va;
- va_start( va, format );
+ va_list va;
+ va_start( va, format );
str.append(vformat_string(format, va));
- va_end( va );
+ va_end( va );
errno = err;
}
wchar_t *wcsvarname( const wchar_t *str )
{
- while( *str )
- {
- if( (!iswalnum(*str)) && (*str != L'_' ) )
- {
- return (wchar_t *)str;
- }
- str++;
- }
- return 0;
+ while( *str )
+ {
+ if( (!iswalnum(*str)) && (*str != L'_' ) )
+ {
+ return (wchar_t *)str;
+ }
+ str++;
+ }
+ return 0;
}
const wchar_t *wcsfuncname( const wchar_t *str )
{
- return wcschr( str, L'/' );
+ return wcschr( str, L'/' );
}
int wcsvarchr( wchar_t chr )
{
- return iswalnum(chr) || chr == L'_';
+ return iswalnum(chr) || chr == L'_';
}
-/**
- The glibc version of wcswidth seems to hang on some strings. fish uses this replacement.
+/**
+ The glibc version of wcswidth seems to hang on some strings. fish uses this replacement.
*/
int my_wcswidth( const wchar_t *c )
{
- return fish_wcswidth(c, wcslen(c));
+ return fish_wcswidth(c, wcslen(c));
}
wchar_t *quote_end( const wchar_t *pos )
{
- wchar_t c = *pos;
-
- while( 1 )
- {
- pos++;
-
- if( !*pos )
- return 0;
-
- if( *pos == L'\\')
- {
- pos++;
- if( !*pos )
- return 0;
- }
- else
- {
- if( *pos == c )
- {
- return (wchar_t *)pos;
- }
- }
- }
- return 0;
-
-}
-
-
+ wchar_t c = *pos;
+
+ while( 1 )
+ {
+ pos++;
+
+ if( !*pos )
+ return 0;
+
+ if( *pos == L'\\')
+ {
+ pos++;
+ if( !*pos )
+ return 0;
+ }
+ else
+ {
+ if( *pos == c )
+ {
+ return (wchar_t *)pos;
+ }
+ }
+ }
+ return 0;
+
+}
+
+
wcstring wsetlocale(int category, const wchar_t *locale)
{
- char *lang = NULL;
- if (locale){
- lang = wcs2str( locale );
- }
- char * res = setlocale(category,lang);
- free( lang );
-
- /*
- Use ellipsis if on known unicode system, otherwise use $
- */
- char *ctype = setlocale( LC_CTYPE, NULL );
- ellipsis_char = (strstr( ctype, ".UTF")||strstr( ctype, ".utf") )?L'\x2026':L'$';
-
- if( !res )
- return wcstring();
+ char *lang = NULL;
+ if (locale){
+ lang = wcs2str( locale );
+ }
+ char * res = setlocale(category,lang);
+ free( lang );
+
+ /*
+ Use ellipsis if on known unicode system, otherwise use $
+ */
+ char *ctype = setlocale( LC_CTYPE, NULL );
+ ellipsis_char = (strstr( ctype, ".UTF")||strstr( ctype, ".utf") )?L'\x2026':L'$';
+
+ if( !res )
+ return wcstring();
else
- return format_string(L"%s", res);
+ return format_string(L"%s", res);
}
bool contains_internal( const wchar_t *a, ... )
{
- const wchar_t *arg;
- va_list va;
- bool res = false;
-
- CHECK( a, 0 );
-
- va_start( va, a );
- while( (arg=va_arg(va, const wchar_t *) )!= 0 )
- {
- if( wcscmp( a,arg) == 0 )
- {
- res = true;
- break;
- }
-
- }
- va_end( va );
- return res;
+ const wchar_t *arg;
+ va_list va;
+ bool res = false;
+
+ CHECK( a, 0 );
+
+ va_start( va, a );
+ while( (arg=va_arg(va, const wchar_t *) )!= 0 )
+ {
+ if( wcscmp( a,arg) == 0 )
+ {
+ res = true;
+ break;
+ }
+
+ }
+ va_end( va );
+ return res;
}
/* wcstring variant of contains_internal. The first parameter is a wcstring, the rest are const wchar_t* */
__sentinel bool contains_internal( const wcstring &needle, ... )
{
- const wchar_t *arg;
- va_list va;
- int res = 0;
-
- va_start( va, needle );
- while( (arg=va_arg(va, const wchar_t *) )!= 0 )
- {
- if( needle == arg)
- {
- res=1;
- break;
- }
-
- }
- va_end( va );
- return res;
+ const wchar_t *arg;
+ va_list va;
+ int res = 0;
+
+ va_start( va, needle );
+ while( (arg=va_arg(va, const wchar_t *) )!= 0 )
+ {
+ if( needle == arg)
+ {
+ res=1;
+ break;
+ }
+
+ }
+ va_end( va );
+ return res;
}
long read_blocked(int fd, void *buf, size_t count)
{
- ssize_t res;
- sigset_t chldset, oldset;
+ ssize_t res;
+ sigset_t chldset, oldset;
- sigemptyset( &chldset );
- sigaddset( &chldset, SIGCHLD );
- VOMIT_ON_FAILURE(pthread_sigmask(SIG_BLOCK, &chldset, &oldset));
- res = read( fd, buf, count );
- VOMIT_ON_FAILURE(pthread_sigmask(SIG_SETMASK, &oldset, NULL));
- return res;
+ sigemptyset( &chldset );
+ sigaddset( &chldset, SIGCHLD );
+ VOMIT_ON_FAILURE(pthread_sigmask(SIG_BLOCK, &chldset, &oldset));
+ res = read( fd, buf, count );
+ VOMIT_ON_FAILURE(pthread_sigmask(SIG_SETMASK, &oldset, NULL));
+ return res;
}
ssize_t write_loop(int fd, const char *buff, size_t count)
{
- ssize_t out=0;
- size_t out_cum=0;
- while( 1 )
- {
- out = write( fd,
- &buff[out_cum],
- count - out_cum );
- if (out < 0)
- {
- if(errno != EAGAIN && errno != EINTR)
- {
- return -1;
- }
- }
- else
- {
- out_cum += (size_t)out;
- }
- if( out_cum >= count )
- {
- break;
- }
- }
- return (ssize_t)out_cum;
+ ssize_t out=0;
+ size_t out_cum=0;
+ while( 1 )
+ {
+ out = write( fd,
+ &buff[out_cum],
+ count - out_cum );
+ if (out < 0)
+ {
+ if(errno != EAGAIN && errno != EINTR)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ out_cum += (size_t)out;
+ }
+ if( out_cum >= count )
+ {
+ break;
+ }
+ }
+ return (ssize_t)out_cum;
}
ssize_t read_loop(int fd, void *buff, size_t count)
@@ -611,22 +611,22 @@ ssize_t read_loop(int fd, void *buff, size_t count)
static bool should_debug(int level)
{
- if( level > debug_level )
- return false;
+ if( level > debug_level )
+ return false;
/* Hack to not print error messages in the tests */
if ( program_name && ! wcscmp(program_name, L"(ignore)") )
return false;
-
+
return true;
}
static void debug_shared( const wcstring &msg )
{
const wcstring sb = wcstring(program_name) + L": " + msg;
- wcstring sb2;
- write_screen( sb, sb2 );
- fwprintf( stderr, L"%ls", sb2.c_str() );
+ wcstring sb2;
+ write_screen( sb, sb2 );
+ fwprintf( stderr, L"%ls", sb2.c_str() );
}
void debug( int level, const wchar_t *msg, ... )
@@ -635,9 +635,9 @@ void debug( int level, const wchar_t *msg, ... )
return;
int errno_old = errno;
va_list va;
- va_start(va, msg);
+ va_start(va, msg);
wcstring local_msg = vformat_string(msg, va);
- va_end(va);
+ va_end(va);
debug_shared(local_msg);
errno = errno_old;
}
@@ -649,9 +649,9 @@ void debug( int level, const char *msg, ... )
int errno_old = errno;
char local_msg[512];
va_list va;
- va_start(va, msg);
+ va_start(va, msg);
vsnprintf(local_msg, sizeof local_msg, msg, va);
- va_end(va);
+ va_end(va);
debug_shared(str2wcstring(local_msg));
errno = errno_old;
}
@@ -662,26 +662,26 @@ void debug_safe(int level, const char *msg, const char *param1, const char *para
const char * const params[] = {param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12};
if (! msg)
return;
-
+
/* Can't call printf, that may allocate memory Just call write() over and over. */
if (level > debug_level)
return;
int errno_old = errno;
-
+
size_t param_idx = 0;
const char *cursor = msg;
while (*cursor != '\0') {
const char *end = strchr(cursor, '%');
if (end == NULL)
end = cursor + strlen(cursor);
-
+
write(STDERR_FILENO, cursor, end - cursor);
if (end[0] == '%' && end[1] == 's') {
/* Handle a format string */
assert(param_idx < sizeof params / sizeof *params);
const char *format = params[param_idx++];
- if (! format)
+ if (! format)
format = "(null)";
write(STDERR_FILENO, format, strlen(format));
cursor = end + 2;
@@ -693,10 +693,10 @@ void debug_safe(int level, const char *msg, const char *param1, const char *para
cursor = end + 1;
}
}
-
+
// We always append a newline
write(STDERR_FILENO, "\n", 1);
-
+
errno = errno_old;
}
@@ -707,7 +707,7 @@ void format_long_safe(char buff[128], long val) {
/* Generate the string in reverse */
size_t idx = 0;
bool negative = (val < 0);
-
+
/* Note that we can't just negate val if it's negative, because it may be the most negative value. We do rely on round-towards-zero division though. */
while (val != 0) {
@@ -718,7 +718,7 @@ void format_long_safe(char buff[128], long val) {
if (negative)
buff[idx++] = '-';
buff[idx] = 0;
-
+
size_t left = 0, right = idx - 1;
while (left < right) {
char tmp = buff[left];
@@ -745,7 +745,7 @@ void format_long_safe(wchar_t buff[128], long val) {
if (negative)
buff[idx++] = L'-';
buff[idx] = 0;
-
+
size_t left = 0, right = idx - 1;
while (left < right) {
wchar_t tmp = buff[left];
@@ -757,90 +757,90 @@ void format_long_safe(wchar_t buff[128], long val) {
void write_screen( const wcstring &msg, wcstring &buff )
{
- const wchar_t *start, *pos;
- int line_width = 0;
- int tok_width = 0;
- int screen_width = common_get_width();
-
- if( screen_width )
- {
- start = pos = msg.c_str();
- while( 1 )
- {
- int overflow = 0;
-
- tok_width=0;
-
- /*
- Tokenize on whitespace, and also calculate the width of the token
- */
- while( *pos && ( !wcschr( L" \n\r\t", *pos ) ) )
- {
-
- /*
- Check is token is wider than one line.
- If so we mark it as an overflow and break the token.
- */
- if((tok_width + fish_wcwidth(*pos)) > (screen_width-1))
- {
- overflow = 1;
- break;
- }
-
- tok_width += fish_wcwidth( *pos );
- pos++;
- }
-
- /*
- If token is zero character long, we don't do anything
- */
- if( pos == start )
- {
- start = pos = pos+1;
- }
- else if( overflow )
- {
- /*
- In case of overflow, we print a newline, except if we already are at position 0
- */
- wchar_t *token = wcsndup( start, pos-start );
- if( line_width != 0 )
+ const wchar_t *start, *pos;
+ int line_width = 0;
+ int tok_width = 0;
+ int screen_width = common_get_width();
+
+ if( screen_width )
+ {
+ start = pos = msg.c_str();
+ while( 1 )
+ {
+ int overflow = 0;
+
+ tok_width=0;
+
+ /*
+ Tokenize on whitespace, and also calculate the width of the token
+ */
+ while( *pos && ( !wcschr( L" \n\r\t", *pos ) ) )
+ {
+
+ /*
+ Check is token is wider than one line.
+ If so we mark it as an overflow and break the token.
+ */
+ if((tok_width + fish_wcwidth(*pos)) > (screen_width-1))
+ {
+ overflow = 1;
+ break;
+ }
+
+ tok_width += fish_wcwidth( *pos );
+ pos++;
+ }
+
+ /*
+ If token is zero character long, we don't do anything
+ */
+ if( pos == start )
+ {
+ start = pos = pos+1;
+ }
+ else if( overflow )
+ {
+ /*
+ In case of overflow, we print a newline, except if we already are at position 0
+ */
+ wchar_t *token = wcsndup( start, pos-start );
+ if( line_width != 0 )
buff.push_back(L'\n');
buff.append(format_string(L"%ls-\n", token));
- free( token );
- line_width=0;
- }
- else
- {
- /*
- Print the token
- */
- wchar_t *token = wcsndup( start, pos-start );
- if( (line_width + (line_width!=0?1:0) + tok_width) > screen_width )
- {
+ free( token );
+ line_width=0;
+ }
+ else
+ {
+ /*
+ Print the token
+ */
+ wchar_t *token = wcsndup( start, pos-start );
+ if( (line_width + (line_width!=0?1:0) + tok_width) > screen_width )
+ {
buff.push_back(L'\n');
- line_width=0;
- }
+ line_width=0;
+ }
buff.append(format_string(L"%ls%ls", line_width?L" ":L"", token ));
- free( token );
- line_width += (line_width!=0?1:0) + tok_width;
- }
-
- /*
- Break on end of string
- */
- if( !*pos )
- {
- break;
- }
-
- start=pos;
- }
- }
- else
- {
+ free( token );
+ line_width += (line_width!=0?1:0) + tok_width;
+ }
+
+ /*
+ Break on end of string
+ */
+ if( !*pos )
+ {
+ break;
+ }
+
+ start=pos;
+ }
+ }
+ else
+ {
buff.append(msg);
- }
+ }
buff.push_back(L'\n');
}
@@ -851,198 +851,198 @@ void write_screen( const wcstring &msg, wcstring &buff )
*/
static wchar_t *escape_simple( const wchar_t *in )
{
- wchar_t *out;
- size_t len = wcslen(in);
- out = (wchar_t *)malloc( sizeof(wchar_t)*(len+3));
- if( !out )
- DIE_MEM();
-
- out[0] = L'\'';
- wcscpy(&out[1], in );
- out[len+1]=L'\'';
- out[len+2]=0;
- return out;
+ wchar_t *out;
+ size_t len = wcslen(in);
+ out = (wchar_t *)malloc( sizeof(wchar_t)*(len+3));
+ if( !out )
+ DIE_MEM();
+
+ out[0] = L'\'';
+ wcscpy(&out[1], in );
+ out[len+1]=L'\'';
+ out[len+2]=0;
+ return out;
}
wchar_t *escape( const wchar_t *in_orig, escape_flags_t flags )
{
- const wchar_t *in = in_orig;
-
- bool escape_all = !! (flags & ESCAPE_ALL);
- bool no_quoted = !! (flags & ESCAPE_NO_QUOTED);
+ const wchar_t *in = in_orig;
+
+ bool escape_all = !! (flags & ESCAPE_ALL);
+ bool no_quoted = !! (flags & ESCAPE_NO_QUOTED);
bool no_tilde = !! (flags & ESCAPE_NO_TILDE);
-
- wchar_t *out;
- wchar_t *pos;
-
- int need_escape=0;
- int need_complex_escape=0;
-
- if( !in )
- {
- debug( 0, L"%s called with null input", __func__ );
- FATAL_EXIT();
- }
-
- if( !no_quoted && (wcslen( in ) == 0) )
- {
- out = wcsdup(L"''");
- if( !out )
- DIE_MEM();
- return out;
- }
-
-
- out = (wchar_t *)malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1));
- pos = out;
-
- if( !out )
- DIE_MEM();
-
- while( *in != 0 )
- {
-
- if( ( *in >= ENCODE_DIRECT_BASE) &&
- ( *in < ENCODE_DIRECT_BASE+256) )
- {
- int val = *in - ENCODE_DIRECT_BASE;
- int tmp;
-
- *(pos++) = L'\\';
- *(pos++) = L'X';
-
- tmp = val/16;
- *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
-
- tmp = val%16;
- *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
- need_escape=need_complex_escape=1;
-
- }
- else
- {
+
+ wchar_t *out;
+ wchar_t *pos;
+
+ int need_escape=0;
+ int need_complex_escape=0;
+
+ if( !in )
+ {
+ debug( 0, L"%s called with null input", __func__ );
+ FATAL_EXIT();
+ }
+
+ if( !no_quoted && (wcslen( in ) == 0) )
+ {
+ out = wcsdup(L"''");
+ if( !out )
+ DIE_MEM();
+ return out;
+ }
+
+
+ out = (wchar_t *)malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1));
+ pos = out;
+
+ if( !out )
+ DIE_MEM();
+
+ while( *in != 0 )
+ {
+
+ if( ( *in >= ENCODE_DIRECT_BASE) &&
+ ( *in < ENCODE_DIRECT_BASE+256) )
+ {
+ int val = *in - ENCODE_DIRECT_BASE;
+ int tmp;
+
+ *(pos++) = L'\\';
+ *(pos++) = L'X';
+
+ tmp = val/16;
+ *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
+
+ tmp = val%16;
+ *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
+ need_escape=need_complex_escape=1;
+
+ }
+ else
+ {
wchar_t c = *in;
- switch( c )
- {
- case L'\t':
- *(pos++) = L'\\';
- *(pos++) = L't';
- need_escape=need_complex_escape=1;
- break;
-
- case L'\n':
- *(pos++) = L'\\';
- *(pos++) = L'n';
- need_escape=need_complex_escape=1;
- break;
-
- case L'\b':
- *(pos++) = L'\\';
- *(pos++) = L'b';
- need_escape=need_complex_escape=1;
- break;
-
- case L'\r':
- *(pos++) = L'\\';
- *(pos++) = L'r';
- need_escape=need_complex_escape=1;
- break;
-
- case L'\x1b':
- *(pos++) = L'\\';
- *(pos++) = L'e';
- need_escape=need_complex_escape=1;
- break;
-
-
- case L'\\':
- case L'\'':
- {
- need_escape=need_complex_escape=1;
- if( escape_all )
- *pos++ = L'\\';
- *pos++ = *in;
- break;
- }
-
- case L'&':
- case L'$':
- case L' ':
- case L'#':
- case L'^':
- case L'<':
- case L'>':
- case L'(':
- case L')':
- case L'[':
- case L']':
- case L'{':
- case L'}':
- case L'?':
- case L'*':
- case L'|':
- case L';':
- case L'"':
- case L'%':
- case L'~':
- {
+ switch( c )
+ {
+ case L'\t':
+ *(pos++) = L'\\';
+ *(pos++) = L't';
+ need_escape=need_complex_escape=1;
+ break;
+
+ case L'\n':
+ *(pos++) = L'\\';
+ *(pos++) = L'n';
+ need_escape=need_complex_escape=1;
+ break;
+
+ case L'\b':
+ *(pos++) = L'\\';
+ *(pos++) = L'b';
+ need_escape=need_complex_escape=1;
+ break;
+
+ case L'\r':
+ *(pos++) = L'\\';
+ *(pos++) = L'r';
+ need_escape=need_complex_escape=1;
+ break;
+
+ case L'\x1b':
+ *(pos++) = L'\\';
+ *(pos++) = L'e';
+ need_escape=need_complex_escape=1;
+ break;
+
+
+ case L'\\':
+ case L'\'':
+ {
+ need_escape=need_complex_escape=1;
+ if( escape_all )
+ *pos++ = L'\\';
+ *pos++ = *in;
+ break;
+ }
+
+ case L'&':
+ case L'$':
+ case L' ':
+ case L'#':
+ case L'^':
+ case L'<':
+ case L'>':
+ case L'(':
+ case L')':
+ case L'[':
+ case L']':
+ case L'{':
+ case L'}':
+ case L'?':
+ case L'*':
+ case L'|':
+ case L';':
+ case L'"':
+ case L'%':
+ case L'~':
+ {
if (! no_tilde || c != L'~')
{
need_escape=1;
if( escape_all )
*pos++ = L'\\';
}
- *pos++ = *in;
- break;
- }
-
- default:
- {
- if( *in < 32 )
- {
- if( *in <27 && *in > 0 )
- {
- *(pos++) = L'\\';
- *(pos++) = L'c';
- *(pos++) = L'a' + *in -1;
-
- need_escape=need_complex_escape=1;
- break;
-
- }
-
-
- int tmp = (*in)%16;
- *pos++ = L'\\';
- *pos++ = L'x';
- *pos++ = ((*in>15)? L'1' : L'0');
- *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
- need_escape=need_complex_escape=1;
- }
- else
- {
- *pos++ = *in;
- }
- break;
- }
- }
- }
-
- in++;
- }
- *pos = 0;
-
- /*
- Use quoted escaping if possible, since most people find it
- easier to read.
- */
- if( !no_quoted && need_escape && !need_complex_escape && escape_all )
- {
- free( out );
- out = escape_simple( in_orig );
- }
-
- return out;
+ *pos++ = *in;
+ break;
+ }
+
+ default:
+ {
+ if( *in < 32 )
+ {
+ if( *in <27 && *in > 0 )
+ {
+ *(pos++) = L'\\';
+ *(pos++) = L'c';
+ *(pos++) = L'a' + *in -1;
+
+ need_escape=need_complex_escape=1;
+ break;
+
+ }
+
+
+ int tmp = (*in)%16;
+ *pos++ = L'\\';
+ *pos++ = L'x';
+ *pos++ = ((*in>15)? L'1' : L'0');
+ *pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
+ need_escape=need_complex_escape=1;
+ }
+ else
+ {
+ *pos++ = *in;
+ }
+ break;
+ }
+ }
+ }
+
+ in++;
+ }
+ *pos = 0;
+
+ /*
+ Use quoted escaping if possible, since most people find it
+ easier to read.
+ */
+ if( !no_quoted && need_escape && !need_complex_escape && escape_all )
+ {
+ free( out );
+ out = escape_simple( in_orig );
+ }
+
+ return out;
}
wcstring escape_string( const wcstring &in, escape_flags_t flags ) {
@@ -1054,542 +1054,542 @@ wcstring escape_string( const wcstring &in, escape_flags_t flags ) {
wchar_t *unescape( const wchar_t * orig, int flags )
{
-
- int mode = 0;
+
+ int mode = 0;
int out_pos;
- size_t in_pos;
+ size_t in_pos;
size_t len;
- int c;
- int bracket_count=0;
- wchar_t prev=0;
- wchar_t *in;
- int unescape_special = flags & UNESCAPE_SPECIAL;
- int allow_incomplete = flags & UNESCAPE_INCOMPLETE;
-
- CHECK( orig, 0 );
-
- len = wcslen( orig );
- in = wcsdup( orig );
-
- if( !in )
- DIE_MEM();
-
- for( in_pos=0, out_pos=0;
- in_pos<len;
- (prev=(out_pos>=0)?in[out_pos]:0), out_pos++, in_pos++ )
- {
- c = in[in_pos];
- switch( mode )
- {
-
- /*
- Mode 0 means unquoted string
- */
- case 0:
- {
- if( c == L'\\' )
- {
- switch( in[++in_pos] )
- {
-
- /*
- A null character after a backslash is an
- error, return null
- */
- case L'\0':
- {
- if( !allow_incomplete )
- {
- free(in);
- return 0;
- }
- }
-
- /*
- Numeric escape sequences. No prefix means
- octal escape, otherwise hexadecimal.
- */
-
- case L'0':
- case L'1':
- case L'2':
- case L'3':
- case L'4':
- case L'5':
- case L'6':
- case L'7':
- case L'u':
- case L'U':
- case L'x':
- case L'X':
- {
- int i;
- long long res=0;
- int chars=2;
- int base=16;
-
- int byte = 0;
- wchar_t max_val = ASCII_MAX;
-
- switch( in[in_pos] )
- {
- case L'u':
- {
- chars=4;
- max_val = UCS2_MAX;
- break;
- }
-
- case L'U':
- {
- chars=8;
- max_val = WCHAR_MAX;
- break;
- }
-
- case L'x':
- {
- break;
- }
-
- case L'X':
- {
- byte=1;
- max_val = BYTE_MAX;
- break;
- }
-
- default:
- {
- base=8;
- chars=3;
+ int c;
+ int bracket_count=0;
+ wchar_t prev=0;
+ wchar_t *in;
+ int unescape_special = flags & UNESCAPE_SPECIAL;
+ int allow_incomplete = flags & UNESCAPE_INCOMPLETE;
+
+ CHECK( orig, 0 );
+
+ len = wcslen( orig );
+ in = wcsdup( orig );
+
+ if( !in )
+ DIE_MEM();
+
+ for( in_pos=0, out_pos=0;
+ in_pos<len;
+ (prev=(out_pos>=0)?in[out_pos]:0), out_pos++, in_pos++ )
+ {
+ c = in[in_pos];
+ switch( mode )
+ {
+
+ /*
+ Mode 0 means unquoted string
+ */
+ case 0:
+ {
+ if( c == L'\\' )
+ {
+ switch( in[++in_pos] )
+ {
+
+ /*
+ A null character after a backslash is an
+ error, return null
+ */
+ case L'\0':
+ {
+ if( !allow_incomplete )
+ {
+ free(in);
+ return 0;
+ }
+ }
+
+ /*
+ Numeric escape sequences. No prefix means
+ octal escape, otherwise hexadecimal.
+ */
+
+ case L'0':
+ case L'1':
+ case L'2':
+ case L'3':
+ case L'4':
+ case L'5':
+ case L'6':
+ case L'7':
+ case L'u':
+ case L'U':
+ case L'x':
+ case L'X':
+ {
+ int i;
+ long long res=0;
+ int chars=2;
+ int base=16;
+
+ int byte = 0;
+ wchar_t max_val = ASCII_MAX;
+
+ switch( in[in_pos] )
+ {
+ case L'u':
+ {
+ chars=4;
+ max_val = UCS2_MAX;
+ break;
+ }
+
+ case L'U':
+ {
+ chars=8;
+ max_val = WCHAR_MAX;
+ break;
+ }
+
+ case L'x':
+ {
+ break;
+ }
+
+ case L'X':
+ {
+ byte=1;
+ max_val = BYTE_MAX;
+ break;
+ }
+
+ default:
+ {
+ base=8;
+ chars=3;
// note in_pod must be larger than 0 since we incremented it above
assert(in_pos > 0);
- in_pos--;
- break;
- }
- }
-
- for( i=0; i<chars; i++ )
- {
- long d = convert_digit( in[++in_pos],base);
-
- if( d < 0 )
- {
- in_pos--;
- break;
- }
-
- res=(res*base)|d;
- }
-
- if( (res <= max_val) )
- {
- in[out_pos] = (wchar_t)((byte?ENCODE_DIRECT_BASE:0)+res);
- }
- else
- {
- free(in);
- return 0;
- }
-
- break;
- }
-
- /*
- \a means bell (alert)
- */
- case L'a':
- {
- in[out_pos]=L'\a';
- break;
- }
-
- /*
- \b means backspace
- */
- case L'b':
- {
- in[out_pos]=L'\b';
- break;
- }
-
- /*
- \cX means control sequence X
- */
- case L'c':
- {
- in_pos++;
- if( in[in_pos] >= L'a' &&
- in[in_pos] <= (L'a'+32) )
- {
- in[out_pos]=in[in_pos]-L'a'+1;
- }
- else if( in[in_pos] >= L'A' &&
- in[in_pos] <= (L'A'+32) )
- {
- in[out_pos]=in[in_pos]-L'A'+1;
- }
- else
- {
- free(in);
- return 0;
- }
- break;
-
- }
-
- /*
- \x1b means escape
- */
- case L'e':
- {
- in[out_pos]=L'\x1b';
- break;
- }
-
- /*
- \f means form feed
- */
- case L'f':
- {
- in[out_pos]=L'\f';
- break;
- }
-
- /*
- \n means newline
- */
- case L'n':
- {
- in[out_pos]=L'\n';
- break;
- }
-
- /*
- \r means carriage return
- */
- case L'r':
- {
- in[out_pos]=L'\r';
- break;
- }
-
- /*
- \t means tab
- */
- case L't':
- {
- in[out_pos]=L'\t';
- break;
- }
-
- /*
- \v means vertical tab
- */
- case L'v':
- {
- in[out_pos]=L'\v';
- break;
- }
-
- default:
- {
- if( unescape_special )
- in[out_pos++] = INTERNAL_SEPARATOR;
- in[out_pos]=in[in_pos];
- break;
- }
- }
- }
- else
- {
- switch( in[in_pos])
- {
- case L'~':
- {
- if( unescape_special && (in_pos == 0) )
- {
- in[out_pos]=HOME_DIRECTORY;
- }
- else
- {
- in[out_pos] = L'~';
- }
- break;
- }
-
- case L'%':
- {
- if( unescape_special && (in_pos == 0) )
- {
- in[out_pos]=PROCESS_EXPAND;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L'*':
- {
- if( unescape_special )
- {
- if( out_pos > 0 && in[out_pos-1]==ANY_STRING )
- {
- out_pos--;
- in[out_pos] = ANY_STRING_RECURSIVE;
- }
- else
- in[out_pos]=ANY_STRING;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L'?':
- {
- if( unescape_special )
- {
- in[out_pos]=ANY_CHAR;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L'$':
- {
- if( unescape_special )
- {
- in[out_pos]=VARIABLE_EXPAND;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L'{':
- {
- if( unescape_special )
- {
- bracket_count++;
- in[out_pos]=BRACKET_BEGIN;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L'}':
- {
- if( unescape_special )
- {
- bracket_count--;
- in[out_pos]=BRACKET_END;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L',':
- {
- if( unescape_special && bracket_count && prev!=BRACKET_SEP)
- {
- in[out_pos]=BRACKET_SEP;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- case L'\'':
- {
- mode = 1;
- if( unescape_special )
- in[out_pos] = INTERNAL_SEPARATOR;
- else
- out_pos--;
- break;
- }
-
- case L'\"':
- {
- mode = 2;
- if( unescape_special )
- in[out_pos] = INTERNAL_SEPARATOR;
- else
- out_pos--;
- break;
- }
-
- default:
- {
- in[out_pos] = in[in_pos];
- break;
- }
- }
- }
- break;
- }
-
- /*
- Mode 1 means single quoted string, i.e 'foo'
- */
- case 1:
- {
- if( c == L'\\' )
- {
- switch( in[++in_pos] )
- {
- case '\\':
- case L'\'':
- case L'\n':
- {
- in[out_pos]=in[in_pos];
- break;
- }
-
- case 0:
- {
- if( !allow_incomplete )
- {
- free(in);
- return 0;
- }
- else
- {
- //We may ever escape a NULL character, but still appending a \ in case I am wrong.
- in[out_pos] = L'\\';
- }
- }
- break;
- default:
- {
- in[out_pos++] = L'\\';
- in[out_pos]= in[in_pos];
- }
- }
-
- }
- if( c == L'\'' )
- {
- if( unescape_special )
- in[out_pos] = INTERNAL_SEPARATOR;
- else
- out_pos--;
- mode = 0;
- }
- else
- {
- in[out_pos] = in[in_pos];
- }
-
- break;
- }
-
- /*
- Mode 2 means double quoted string, i.e. "foo"
- */
- case 2:
- {
- switch( c )
- {
- case '"':
- {
- mode = 0;
- if( unescape_special )
- in[out_pos] = INTERNAL_SEPARATOR;
- else
- out_pos--;
- break;
- }
-
- case '\\':
- {
- switch( in[++in_pos] )
- {
- case L'\0':
- {
- if( !allow_incomplete )
- {
- free(in);
- return 0;
- }
- else
- {
- //We probably don't need it since NULL character is always appended before ending this function.
- in[out_pos]=in[in_pos];
- }
- }
- break;
- case '\\':
- case L'$':
- case '"':
- case '\n':
- {
- in[out_pos]=in[in_pos];
- break;
- }
-
- default:
- {
- in[out_pos++] = L'\\';
- in[out_pos] = in[in_pos];
- break;
- }
- }
- break;
- }
-
- case '$':
- {
- if( unescape_special )
- {
- in[out_pos]=VARIABLE_EXPAND_SINGLE;
- }
- else
- {
- in[out_pos]=in[in_pos];
- }
- break;
- }
-
- default:
- {
- in[out_pos] = in[in_pos];
- break;
- }
-
- }
- break;
- }
- }
- }
-
- if( !allow_incomplete && mode )
- {
- free( in );
- return 0;
- }
-
- in[out_pos]=L'\0';
- return in;
+ in_pos--;
+ break;
+ }
+ }
+
+ for( i=0; i<chars; i++ )
+ {
+ long d = convert_digit( in[++in_pos],base);
+
+ if( d < 0 )
+ {
+ in_pos--;
+ break;
+ }
+
+ res=(res*base)|d;
+ }
+
+ if( (res <= max_val) )
+ {
+ in[out_pos] = (wchar_t)((byte?ENCODE_DIRECT_BASE:0)+res);
+ }
+ else
+ {
+ free(in);
+ return 0;
+ }
+
+ break;
+ }
+
+ /*
+ \a means bell (alert)
+ */
+ case L'a':
+ {
+ in[out_pos]=L'\a';
+ break;
+ }
+
+ /*
+ \b means backspace
+ */
+ case L'b':
+ {
+ in[out_pos]=L'\b';
+ break;
+ }
+
+ /*
+ \cX means control sequence X
+ */
+ case L'c':
+ {
+ in_pos++;
+ if( in[in_pos] >= L'a' &&
+ in[in_pos] <= (L'a'+32) )
+ {
+ in[out_pos]=in[in_pos]-L'a'+1;
+ }
+ else if( in[in_pos] >= L'A' &&
+ in[in_pos] <= (L'A'+32) )
+ {
+ in[out_pos]=in[in_pos]-L'A'+1;
+ }
+ else
+ {
+ free(in);
+ return 0;
+ }
+ break;
+
+ }
+
+ /*
+ \x1b means escape
+ */
+ case L'e':
+ {
+ in[out_pos]=L'\x1b';
+ break;
+ }
+
+ /*
+ \f means form feed
+ */
+ case L'f':
+ {
+ in[out_pos]=L'\f';
+ break;
+ }
+
+ /*
+ \n means newline
+ */
+ case L'n':
+ {
+ in[out_pos]=L'\n';
+ break;
+ }
+
+ /*
+ \r means carriage return
+ */
+ case L'r':
+ {
+ in[out_pos]=L'\r';
+ break;
+ }
+
+ /*
+ \t means tab
+ */
+ case L't':
+ {
+ in[out_pos]=L'\t';
+ break;
+ }
+
+ /*
+ \v means vertical tab
+ */
+ case L'v':
+ {
+ in[out_pos]=L'\v';
+ break;
+ }
+
+ default:
+ {
+ if( unescape_special )
+ in[out_pos++] = INTERNAL_SEPARATOR;
+ in[out_pos]=in[in_pos];
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch( in[in_pos])
+ {
+ case L'~':
+ {
+ if( unescape_special && (in_pos == 0) )
+ {
+ in[out_pos]=HOME_DIRECTORY;
+ }
+ else
+ {
+ in[out_pos] = L'~';
+ }
+ break;
+ }
+
+ case L'%':
+ {
+ if( unescape_special && (in_pos == 0) )
+ {
+ in[out_pos]=PROCESS_EXPAND;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L'*':
+ {
+ if( unescape_special )
+ {
+ if( out_pos > 0 && in[out_pos-1]==ANY_STRING )
+ {
+ out_pos--;
+ in[out_pos] = ANY_STRING_RECURSIVE;
+ }
+ else
+ in[out_pos]=ANY_STRING;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L'?':
+ {
+ if( unescape_special )
+ {
+ in[out_pos]=ANY_CHAR;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L'$':
+ {
+ if( unescape_special )
+ {
+ in[out_pos]=VARIABLE_EXPAND;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L'{':
+ {
+ if( unescape_special )
+ {
+ bracket_count++;
+ in[out_pos]=BRACKET_BEGIN;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L'}':
+ {
+ if( unescape_special )
+ {
+ bracket_count--;
+ in[out_pos]=BRACKET_END;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L',':
+ {
+ if( unescape_special && bracket_count && prev!=BRACKET_SEP)
+ {
+ in[out_pos]=BRACKET_SEP;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ case L'\'':
+ {
+ mode = 1;
+ if( unescape_special )
+ in[out_pos] = INTERNAL_SEPARATOR;
+ else
+ out_pos--;
+ break;
+ }
+
+ case L'\"':
+ {
+ mode = 2;
+ if( unescape_special )
+ in[out_pos] = INTERNAL_SEPARATOR;
+ else
+ out_pos--;
+ break;
+ }
+
+ default:
+ {
+ in[out_pos] = in[in_pos];
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ /*
+ Mode 1 means single quoted string, i.e 'foo'
+ */
+ case 1:
+ {
+ if( c == L'\\' )
+ {
+ switch( in[++in_pos] )
+ {
+ case '\\':
+ case L'\'':
+ case L'\n':
+ {
+ in[out_pos]=in[in_pos];
+ break;
+ }
+
+ case 0:
+ {
+ if( !allow_incomplete )
+ {
+ free(in);
+ return 0;
+ }
+ else
+ {
+ //We may ever escape a NULL character, but still appending a \ in case I am wrong.
+ in[out_pos] = L'\\';
+ }
+ }
+ break;
+ default:
+ {
+ in[out_pos++] = L'\\';
+ in[out_pos]= in[in_pos];
+ }
+ }
+
+ }
+ if( c == L'\'' )
+ {
+ if( unescape_special )
+ in[out_pos] = INTERNAL_SEPARATOR;
+ else
+ out_pos--;
+ mode = 0;
+ }
+ else
+ {
+ in[out_pos] = in[in_pos];
+ }
+
+ break;
+ }
+
+ /*
+ Mode 2 means double quoted string, i.e. "foo"
+ */
+ case 2:
+ {
+ switch( c )
+ {
+ case '"':
+ {
+ mode = 0;
+ if( unescape_special )
+ in[out_pos] = INTERNAL_SEPARATOR;
+ else
+ out_pos--;
+ break;
+ }
+
+ case '\\':
+ {
+ switch( in[++in_pos] )
+ {
+ case L'\0':
+ {
+ if( !allow_incomplete )
+ {
+ free(in);
+ return 0;
+ }
+ else
+ {
+ //We probably don't need it since NULL character is always appended before ending this function.
+ in[out_pos]=in[in_pos];
+ }
+ }
+ break;
+ case '\\':
+ case L'$':
+ case '"':
+ case '\n':
+ {
+ in[out_pos]=in[in_pos];
+ break;
+ }
+
+ default:
+ {
+ in[out_pos++] = L'\\';
+ in[out_pos] = in[in_pos];
+ break;
+ }
+ }
+ break;
+ }
+
+ case '$':
+ {
+ if( unescape_special )
+ {
+ in[out_pos]=VARIABLE_EXPAND_SINGLE;
+ }
+ else
+ {
+ in[out_pos]=in[in_pos];
+ }
+ break;
+ }
+
+ default:
+ {
+ in[out_pos] = in[in_pos];
+ break;
+ }
+
+ }
+ break;
+ }
+ }
+ }
+
+ if( !allow_incomplete && mode )
+ {
+ free( in );
+ return 0;
+ }
+
+ in[out_pos]=L'\0';
+ return in;
}
bool unescape_string(wcstring &str, int escape_special)
@@ -1609,25 +1609,25 @@ bool unescape_string(wcstring &str, int escape_special)
void common_handle_winch( int signal )
{
#ifdef HAVE_WINSIZE
- if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
- {
- return;
- }
+ if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
+ {
+ return;
+ }
#else
- termsize.ws_col = 80;
- termsize.ws_row = 24;
+ termsize.ws_col = 80;
+ termsize.ws_row = 24;
#endif
}
int common_get_width()
{
- return termsize.ws_col;
+ return termsize.ws_col;
}
int common_get_height()
{
- return termsize.ws_row;
+ return termsize.ws_row;
}
void tokenize_variable_array( const wcstring &val, std::vector<wcstring> &out)
@@ -1677,88 +1677,88 @@ bool list_contains_string(const wcstring_list_t &list, const wcstring &str)
int create_directory( const wcstring &d )
{
- int ok = 0;
- struct stat buf;
- int stat_res = 0;
-
- while( (stat_res = wstat(d, &buf ) ) != 0 )
- {
- if( errno != EAGAIN )
- break;
- }
-
- if( stat_res == 0 )
- {
- if( S_ISDIR( buf.st_mode ) )
- {
- ok = 1;
- }
- }
- else
- {
- if( errno == ENOENT )
- {
+ int ok = 0;
+ struct stat buf;
+ int stat_res = 0;
+
+ while( (stat_res = wstat(d, &buf ) ) != 0 )
+ {
+ if( errno != EAGAIN )
+ break;
+ }
+
+ if( stat_res == 0 )
+ {
+ if( S_ISDIR( buf.st_mode ) )
+ {
+ ok = 1;
+ }
+ }
+ else
+ {
+ if( errno == ENOENT )
+ {
wcstring dir = wdirname(d);
- if( !create_directory( dir ) )
- {
- if( !wmkdir( d, 0700 ) )
- {
- ok = 1;
- }
- }
- }
- }
-
- return ok?0:-1;
+ if( !create_directory( dir ) )
+ {
+ if( !wmkdir( d, 0700 ) )
+ {
+ ok = 1;
+ }
+ }
+ }
+ }
+
+ return ok?0:-1;
}
__attribute__((noinline))
void bugreport()
{
- debug( 1,
- _( L"This is a bug. Break on bugreport to debug."
- L"If you can reproduce it, please send a bug report to %s." ),
- PACKAGE_BUGREPORT );
+ debug( 1,
+ _( L"This is a bug. Break on bugreport to debug."
+ L"If you can reproduce it, please send a bug report to %s." ),
+ PACKAGE_BUGREPORT );
}
wcstring format_size(long long sz)
{
wcstring result;
- const wchar_t *sz_name[]= {
- L"kB", L"MB", L"GB", L"TB", L"PB", L"EB", L"ZB", L"YB", 0
+ const wchar_t *sz_name[]= {
+ L"kB", L"MB", L"GB", L"TB", L"PB", L"EB", L"ZB", L"YB", 0
};
- if( sz < 0 )
- {
- result.append( L"unknown" );
- }
- else if( sz < 1 )
- {
- result.append( _( L"empty" ) );
- }
- else if( sz < 1024 )
- {
- result.append(format_string( L"%lldB", sz ));
- }
- else
- {
- int i;
-
- for( i=0; sz_name[i]; i++ )
- {
- if( sz < (1024*1024) || !sz_name[i+1] )
- {
- long isz = ((long)sz)/1024;
- if( isz > 9 )
- result.append( format_string( L"%d%ls", isz, sz_name[i] ));
- else
- result.append( format_string( L"%.1f%ls", (double)sz/1024, sz_name[i] ));
- break;
- }
- sz /= 1024;
-
- }
- }
+ if( sz < 0 )
+ {
+ result.append( L"unknown" );
+ }
+ else if( sz < 1 )
+ {
+ result.append( _( L"empty" ) );
+ }
+ else if( sz < 1024 )
+ {
+ result.append(format_string( L"%lldB", sz ));
+ }
+ else
+ {
+ int i;
+
+ for( i=0; sz_name[i]; i++ )
+ {
+ if( sz < (1024*1024) || !sz_name[i+1] )
+ {
+ long isz = ((long)sz)/1024;
+ if( isz > 9 )
+ result.append( format_string( L"%d%ls", isz, sz_name[i] ));
+ else
+ result.append( format_string( L"%.1f%ls", (double)sz/1024, sz_name[i] ));
+ break;
+ }
+ sz /= 1024;
+
+ }
+ }
return result;
}
@@ -1793,10 +1793,10 @@ void format_size_safe(char buff[128], unsigned long long sz) {
const size_t max_len = buff_size - 1; //need to leave room for a null terminator
bzero(buff, buff_size);
size_t idx = 0;
- const char * const sz_name[]= {
+ const char * const sz_name[]= {
"kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL
};
- if (sz < 1)
+ if (sz < 1)
{
strncpy(buff, "empty", buff_size);
}
@@ -1807,16 +1807,16 @@ void format_size_safe(char buff[128], unsigned long long sz) {
}
else
{
- for( size_t i=0; sz_name[i]; i++ )
- {
- if( sz < (1024*1024) || !sz_name[i+1] )
- {
- unsigned long long isz = sz/1024;
- if( isz > 9 )
+ for( size_t i=0; sz_name[i]; i++ )
+ {
+ if( sz < (1024*1024) || !sz_name[i+1] )
+ {
+ unsigned long long isz = sz/1024;
+ if( isz > 9 )
{
append_ull(buff, isz, &idx, max_len);
}
- else
+ else
{
if (isz == 0)
{
@@ -1826,7 +1826,7 @@ void format_size_safe(char buff[128], unsigned long long sz) {
{
append_ull(buff, isz, &idx, max_len);
}
-
+
// Maybe append a single fraction digit
unsigned long long remainder = sz % 1024;
if (remainder > 0)
@@ -1836,33 +1836,33 @@ void format_size_safe(char buff[128], unsigned long long sz) {
}
}
append_str(buff, sz_name[i], &idx, max_len);
- break;
- }
- sz /= 1024;
- }
+ break;
+ }
+ sz /= 1024;
+ }
}
}
double timef()
{
- int time_res;
- struct timeval tv;
-
- time_res = gettimeofday(&tv, 0);
-
- if( time_res )
- {
- /*
- Fixme: What on earth is the correct parameter value for NaN?
- The man pages and the standard helpfully state that this
- parameter is implementation defined. Gcc gives a warning if
- a null pointer is used. But not even all mighty Google gives
- a hint to what value should actually be returned.
- */
- return nan("");
- }
-
- return (double)tv.tv_sec + 0.000001*tv.tv_usec;
+ int time_res;
+ struct timeval tv;
+
+ time_res = gettimeofday(&tv, 0);
+
+ if( time_res )
+ {
+ /*
+ Fixme: What on earth is the correct parameter value for NaN?
+ The man pages and the standard helpfully state that this
+ parameter is implementation defined. Gcc gives a warning if
+ a null pointer is used. But not even all mighty Google gives
+ a hint to what value should actually be returned.
+ */
+ return nan("");
+ }
+
+ return (double)tv.tv_sec + 0.000001*tv.tv_usec;
}
void exit_without_destructors(int code) {
@@ -1874,7 +1874,7 @@ null_terminated_array_t<char> convert_wide_array_to_narrow(const null_terminated
const wchar_t *const *arr = wide_arr.get();
if (! arr)
return null_terminated_array_t<char>();
-
+
std::vector<std::string> list;
for (size_t i=0; arr[i]; i++) {
list.push_back(wcs2string(arr[i]));
@@ -1905,9 +1905,9 @@ extern "C" {
__attribute__((noinline)) void debug_thread_error(void) { while (1) sleep(9999999); }
}
-
+
void set_main_thread() {
- main_thread_id = pthread_self();
+ main_thread_id = pthread_self();
}
void configure_thread_assertions_for_testing(void) {
@@ -1920,7 +1920,7 @@ static pid_t initial_pid = 0;
bool is_forked_child(void) {
/* Just bail if nobody's called setup_fork_guards - e.g. fishd */
if (! initial_pid) return false;
-
+
bool is_child_of_fork = (getpid() != initial_pid);
if (is_child_of_fork) {
printf("Uh-oh: %d\n", getpid());
@@ -1935,8 +1935,8 @@ void setup_fork_guards(void) {
}
bool is_main_thread() {
- assert (main_thread_id != 0);
- return main_thread_id == pthread_self();
+ assert (main_thread_id != 0);
+ return main_thread_id == pthread_self();
}
void assert_is_main_thread(const char *who)
@@ -2012,7 +2012,7 @@ bool wcstokenizer::next(wcstring &result) {
if (tmp) result = tmp;
return tmp != NULL;
}
-
+
wcstokenizer::~wcstokenizer() {
free(buffer);
}
diff --git a/common.h b/common.h
index b0bf0593..96e95d32 100644
--- a/common.h
+++ b/common.h
@@ -1,5 +1,5 @@
/** \file common.h
- Prototypes for various functions, mostly string utilities, that are used by most parts of fish.
+ Prototypes for various functions, mostly string utilities, that are used by most parts of fish.
*/
#ifndef FISH_COMMON_H
@@ -67,10 +67,10 @@ typedef std::vector<wcstring> wcstring_list_t;
enum {
/** Escape all characters, including magic characters like the semicolon */
ESCAPE_ALL = 1 << 0,
-
+
/** Do not try to use 'simplified' quoted escapes, and do not use empty quotes as the empty string */
ESCAPE_NO_QUOTED = 1 << 1,
-
+
/** Do not escape tildes */
ESCAPE_NO_TILDE = 1 << 2
};
@@ -84,10 +84,10 @@ typedef unsigned int escape_flags_t;
/** Exits without invoking destructors (via _exit), useful for code after fork. */
void exit_without_destructors(int code) __attribute__ ((noreturn));
-/**
- Save the shell mode on startup so we can restore them on exit
+/**
+ Save the shell mode on startup so we can restore them on exit
*/
-extern struct termios shell_modes;
+extern struct termios shell_modes;
/**
The character to use where the text has been truncated. Is an
@@ -118,57 +118,57 @@ extern const wchar_t *program_name;
failiure, the current function is ended at once. The second
parameter is the return value of the current function on failiure.
*/
-#define CHECK( arg, retval ) \
- if( !(arg) ) \
- { \
- debug( 0, \
- "function %s called with null value for argument %s. ", \
- __func__, \
- #arg ); \
- bugreport(); \
- show_stackframe(); \
- return retval; \
- }
+#define CHECK( arg, retval ) \
+ if( !(arg) ) \
+ { \
+ debug( 0, \
+ "function %s called with null value for argument %s. ", \
+ __func__, \
+ #arg ); \
+ bugreport(); \
+ show_stackframe(); \
+ return retval; \
+ }
/**
Pause for input, then exit the program. If supported, print a backtrace first.
*/
-#define FATAL_EXIT() \
- { \
- char exit_read_buff; \
- show_stackframe(); \
- read( 0, &exit_read_buff, 1 ); \
- exit_without_destructors( 1 ); \
- } \
-
+#define FATAL_EXIT() \
+ { \
+ char exit_read_buff; \
+ show_stackframe(); \
+ read( 0, &exit_read_buff, 1 ); \
+ exit_without_destructors( 1 ); \
+ } \
+
/**
Exit program at once, leaving an error message about running out of memory.
*/
-#define DIE_MEM() \
- { \
- fwprintf( stderr, \
- L"fish: Out of memory on line %ld of file %s, shutting down fish\n", \
- (long)__LINE__, \
- __FILE__ ); \
- FATAL_EXIT(); \
- }
+#define DIE_MEM() \
+ { \
+ fwprintf( stderr, \
+ L"fish: Out of memory on line %ld of file %s, shutting down fish\n", \
+ (long)__LINE__, \
+ __FILE__ ); \
+ FATAL_EXIT(); \
+ }
/**
Check if signals are blocked. If so, print an error message and
return from the function performing this check.
*/
-#define CHECK_BLOCK( retval ) \
- if( signal_is_blocked() ) \
- { \
- debug( 0, \
- "function %s called while blocking signals. ", \
- __func__); \
- bugreport(); \
- show_stackframe(); \
- return retval; \
- }
-
+#define CHECK_BLOCK( retval ) \
+ if( signal_is_blocked() ) \
+ { \
+ debug( 0, \
+ "function %s called while blocking signals. ", \
+ __func__); \
+ bugreport(); \
+ show_stackframe(); \
+ return retval; \
+ }
+
/**
Shorthand for wgettext call
*/
@@ -176,7 +176,7 @@ extern const wchar_t *program_name;
/**
Noop, used to tell xgettext that a string should be translated,
- even though it is not directly sent to wgettext.
+ even though it is not directly sent to wgettext.
*/
#define N_(wstr) wstr
@@ -192,7 +192,7 @@ void show_stackframe();
/**
- Read a line from the stream f into the string. Returns
+ Read a line from the stream f into the string. Returns
the number of bytes read or -1 on failiure.
If the carriage return character is encountered, it is
@@ -214,7 +214,7 @@ wchar_t *str2wcs( const char *in );
/**
Returns a newly allocated wide character string equivalent of the
specified multibyte character string
-
+
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
@@ -344,7 +344,7 @@ inline wcstring to_string(const int &x) {
template <typename CharType_t>
class null_terminated_array_t {
CharType_t **array;
-
+
typedef std::basic_string<CharType_t> string_t;
typedef std::vector<string_t> string_list_t;
@@ -356,7 +356,7 @@ class null_terminated_array_t {
size_t len;
for (len=0; arr[len] != T(0); len++)
;
- return len;
+ return len;
}
size_t size() const {
@@ -372,24 +372,24 @@ class null_terminated_array_t {
array = NULL;
}
}
-
+
public:
null_terminated_array_t() : array(NULL) { }
null_terminated_array_t(const string_list_t &argv) : array(NULL) { this->set(argv); }
~null_terminated_array_t() { this->free(); }
-
+
/** operator=. Notice the pass-by-value parameter. */
null_terminated_array_t& operator=(null_terminated_array_t rhs) {
if (this != &rhs)
this->swap(rhs);
return *this;
}
-
+
/* Copy constructor. */
null_terminated_array_t(const null_terminated_array_t &him) : array(NULL) {
this->set(him.array);
}
-
+
void set(const string_list_t &argv) {
/* Get rid of the old argv */
this->free();
@@ -405,14 +405,14 @@ class null_terminated_array_t {
}
this->array[count] = NULL;
}
-
+
void set(const CharType_t * const *new_array) {
if (new_array == array)
return;
-
+
/* Get rid of the old argv */
this->free();
-
+
/* Copy the new one */
if (new_array) {
size_t i, count = count_not_null(new_array);
@@ -426,10 +426,10 @@ class null_terminated_array_t {
this->array[count] = NULL;
}
}
-
+
CharType_t **get() { return array; }
const CharType_t * const *get() const { return array; }
-
+
string_list_t to_list() const {
string_list_t lst;
if (array != NULL) {
@@ -448,23 +448,23 @@ null_terminated_array_t<char> convert_wide_array_to_narrow(const null_terminated
class narrow_string_rep_t {
private:
const char *str;
-
+
/* No copying */
narrow_string_rep_t &operator=(const narrow_string_rep_t &);
narrow_string_rep_t(const narrow_string_rep_t &x);
-
+
public:
~narrow_string_rep_t() {
free((void *)str);
}
-
+
narrow_string_rep_t() : str(NULL) {}
-
+
void set(const wcstring &s) {
free((void *)str);
str = wcs2str(s.c_str());
}
-
+
const char *get() const {
return str;
}
@@ -476,7 +476,7 @@ bool is_forked_child();
class scoped_lock {
pthread_mutex_t *lock_obj;
bool locked;
-
+
/* No copying */
scoped_lock &operator=(const scoped_lock &);
scoped_lock(const scoped_lock &);
@@ -492,18 +492,18 @@ public:
class wcstokenizer {
wchar_t *buffer, *str, *state;
const wcstring sep;
-
+
/* No copying */
wcstokenizer &operator=(const wcstokenizer &);
wcstokenizer(const wcstokenizer &);
-
+
public:
wcstokenizer(const wcstring &s, const wcstring &separator);
bool next(wcstring &result);
~wcstokenizer();
};
-/**
+/**
Appends a path component, with a / if necessary
*/
void append_path_component(wcstring &path, const wcstring &component);
@@ -519,7 +519,7 @@ void append_format(wcstring &str, const wchar_t *format, ...);
char **wcsv2strv( const wchar_t * const *in );
/**
- Test if the given string is a valid variable name.
+ Test if the given string is a valid variable name.
\return null if this is a valid name, and a pointer to the first invalid character otherwise
*/
@@ -528,7 +528,7 @@ wchar_t *wcsvarname( const wchar_t *str );
/**
- Test if the given string is a valid function name.
+ Test if the given string is a valid function name.
\return null if this is a valid name, and a pointer to the first invalid character otherwise
*/
@@ -536,7 +536,7 @@ wchar_t *wcsvarname( const wchar_t *str );
const wchar_t *wcsfuncname( const wchar_t *str );
/**
- Test if the given string is valid in a variable name
+ Test if the given string is valid in a variable name
\return 1 if this is a valid name, 0 otherwise
*/
@@ -572,14 +572,14 @@ void error_reset();
This function behaves exactly like a wide character equivalent of
the C function setlocale, except that it will also try to detect if
the user is using a Unicode character set, and if so, use the
- unicode ellipsis character as ellipsis, instead of '$'.
+ unicode ellipsis character as ellipsis, instead of '$'.
*/
wcstring wsetlocale( int category, const wchar_t *locale );
/**
Checks if \c needle is included in the list of strings specified. A warning is printed if needle is zero.
- \param needle the string to search for in the list
+ \param needle the string to search for in the list
\return zero if needle is not found, of if needle is null, non-zero otherwise
*/
@@ -614,9 +614,9 @@ ssize_t read_loop(int fd, void *buff, size_t count);
Because debug is often called to tell the user about an error,
before using wperror to give a specific error message, debug will
never ever modify the value of errno.
-
+
\param level the priority of the message. Lower number means higher priority. Messages with a priority_number higher than \c debug_level will be ignored..
- \param msg the message format string.
+ \param msg the message format string.
Example:
@@ -629,7 +629,7 @@ void debug( int level, const wchar_t *msg, ... );
/**
Replace special characters with backslash escape sequences. Newline is
- replaced with \n, etc.
+ replaced with \n, etc.
\param in The string to be escaped
\param escape_all Whether all characters wich hold special meaning in fish (Pipe, semicolon, etc,) should be escaped, or only unprintable characters
@@ -650,14 +650,14 @@ wcstring escape_string( const wcstring &in, escape_flags_t flags );
an invalid sequence is specified, 0 is returned.
*/
-wchar_t *unescape( const wchar_t * in,
- int escape_special );
+wchar_t *unescape( const wchar_t * in,
+ int escape_special );
-bool unescape_string( wcstring &str,
+bool unescape_string( wcstring &str,
int escape_special );
-/**
+/**
Returns the width of the terminal window, so that not all
functions that use these values continually have to keep track of
it separately.
@@ -688,9 +688,9 @@ void common_handle_winch( int signal );
void write_screen( const wcstring &msg, wcstring &buff );
/**
- Tokenize the specified string into the specified wcstring_list_t.
+ Tokenize the specified string into the specified wcstring_list_t.
\param val the input string. The contents of this string is not changed.
- \param out the list in which to place the elements.
+ \param out the list in which to place the elements.
*/
void tokenize_variable_array( const wcstring &val, wcstring_list_t &out);
@@ -717,7 +717,7 @@ void bugreport();
double timef();
/**
- Call the following function early in main to set the main thread.
+ Call the following function early in main to set the main thread.
This is our replacement for pthread_main_np().
*/
void set_main_thread();
diff --git a/complete.cpp b/complete.cpp
index 491e2168..50fcb51f 100644
--- a/complete.cpp
+++ b/complete.cpp
@@ -1,6 +1,6 @@
/** \file complete.c Functions related to tab-completion.
- These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion.
+ These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion.
*/
#include "config.h"
@@ -123,29 +123,29 @@
If either short_opt or long_opt are non-zero, they specify a switch
for the command. If \c comp is also not empty, it contains a list
of non-switch arguments that may only follow directly after the
- specified switch.
+ specified switch.
*/
typedef struct complete_entry_opt
{
- /** Short style option */
- wchar_t short_opt;
- /** Long style option */
- wcstring long_opt;
- /** Arguments to the option */
- wcstring comp;
- /** Description of the completion */
- wcstring desc;
- /** Condition under which to use the option */
- wcstring condition;
- /** Must be one of the values SHARED, NO_FILES, NO_COMMON,
- EXCLUSIVE, and determines how completions should be performed
- on the argument after the switch. */
- int result_mode;
- /** True if old style long options are used */
- int old_mode;
- /** Completion flags */
- complete_flags_t flags;
-
+ /** Short style option */
+ wchar_t short_opt;
+ /** Long style option */
+ wcstring long_opt;
+ /** Arguments to the option */
+ wcstring comp;
+ /** Description of the completion */
+ wcstring desc;
+ /** Condition under which to use the option */
+ wcstring condition;
+ /** Must be one of the values SHARED, NO_FILES, NO_COMMON,
+ EXCLUSIVE, and determines how completions should be performed
+ on the argument after the switch. */
+ int result_mode;
+ /** True if old style long options are used */
+ int old_mode;
+ /** Completion flags */
+ complete_flags_t flags;
+
const wchar_t *localized_desc() const
{
const wchar_t *tmp = desc.c_str();
@@ -161,39 +161,39 @@ static unsigned int kCompleteOrder = 0;
*/
typedef std::list<complete_entry_opt_t> option_list_t;
class completion_entry_t
-{
+{
public:
- /** List of all options */
- option_list_t options;
-
- /** String containing all short option characters */
- wcstring short_opt_str;
-
+ /** List of all options */
+ option_list_t options;
+
+ /** String containing all short option characters */
+ wcstring short_opt_str;
+
public:
-
- /** Command string */
- const wcstring cmd;
-
- /** True if command is a path */
- const bool cmd_is_path;
-
- /** True if no other options than the ones supplied are possible */
- bool authoritative;
-
+
+ /** Command string */
+ const wcstring cmd;
+
+ /** True if command is a path */
+ const bool cmd_is_path;
+
+ /** True if no other options than the ones supplied are possible */
+ bool authoritative;
+
/** Order for when this completion was created. This aids in outputting completions sorted by time. */
const unsigned int order;
-
+
/** Getters for option list. */
const option_list_t &get_options() const;
-
+
/** Adds or removes an option. */
void add_option(const complete_entry_opt_t &opt);
bool remove_option(wchar_t short_opt, const wchar_t *long_opt);
-
+
/** Getter for short_opt_str. */
- wcstring &get_short_opt_str();
+ wcstring &get_short_opt_str();
const wcstring &get_short_opt_str() const;
-
+
completion_entry_t(const wcstring &c, bool type, const wcstring &options, bool author) :
short_opt_str(options),
cmd(c),
@@ -248,7 +248,7 @@ wcstring &completion_entry_t::get_short_opt_str() {
const wcstring &completion_entry_t::get_short_opt_str() const {
ASSERT_IS_LOCKED(completion_entry_lock);
- return short_opt_str;
+ return short_opt_str;
}
/* completion_t functions */
@@ -315,21 +315,21 @@ class completer_t {
const wcstring initial_cmd;
std::vector<completion_t> completions;
wcstring_list_t commands_to_load;
-
+
/** Table of completions conditions that have already been tested and the corresponding test results */
typedef std::map<wcstring, bool> condition_cache_t;
condition_cache_t condition_cache;
-
+
public:
completer_t(const wcstring &c, complete_type_t t) :
type(t),
initial_cmd(c)
{
}
-
+
bool empty() const { return completions.empty(); }
const std::vector<completion_t> &get_completions(void) { return completions; }
-
+
bool try_complete_variable( const wcstring &str );
bool try_complete_user( const wcstring &str );
@@ -337,33 +337,33 @@ class completer_t {
const wcstring &popt,
const wcstring &str,
bool use_switches);
-
+
void complete_param_expand(const wcstring &str, bool do_file);
-
+
void debug_print_completions();
-
+
void complete_cmd( const wcstring &str,
bool use_function,
bool use_builtin,
bool use_command);
-
+
void complete_from_args( const wcstring &str,
const wcstring &args,
const wcstring &desc,
complete_flags_t flags );
-
+
void complete_cmd_desc( const wcstring &str );
-
+
bool complete_variable(const wcstring &str, size_t start_offset);
-
+
bool condition_test( const wcstring &condition );
-
+
void complete_strings( const wcstring &wc_escaped,
const wchar_t *desc,
wcstring (*desc_func)(const wcstring &),
std::vector<completion_t> &possible_comp,
complete_flags_t flags );
-
+
expand_flags_t expand_flags() const {
/* Never do command substitution in autosuggestions. Sadly, we also can't yet do job expansion because it's not thread safe. */
expand_flags_t result = 0;
@@ -371,7 +371,7 @@ class completer_t {
result |= EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_JOBS;
return result;
}
-
+
void get_commands_to_load(wcstring_list_t *lst) {
if (lst)
lst->insert(lst->end(), commands_to_load.begin(), commands_to_load.end());
@@ -417,13 +417,13 @@ void append_completion(std::vector<completion_t> &completions, const wcstring &c
completion run to make sure that there are no stale completions.
*/
bool completer_t::condition_test( const wcstring &condition )
-{
- if( condition.empty() )
- {
-// fwprintf( stderr, L"No condition specified\n" );
- return 1;
- }
-
+{
+ if( condition.empty() )
+ {
+// fwprintf( stderr, L"No condition specified\n" );
+ return 1;
+ }
+
if (this->type == COMPLETE_AUTOSUGGEST)
{
/* Autosuggestion can't support conditions */
@@ -431,7 +431,7 @@ bool completer_t::condition_test( const wcstring &condition )
}
ASSERT_IS_MAIN_THREAD();
-
+
bool test_res;
condition_cache_t::iterator cached_entry = condition_cache.find(condition);
if (cached_entry == condition_cache.end()) {
@@ -456,83 +456,83 @@ static completion_entry_t *complete_find_exact_entry( const wcstring &cmd, const
if (iter != completion_set.end()) {
result = *iter;
}
- return result;
+ return result;
}
/** Locate the specified entry. Create it if it doesn't exist. Must be called while locked. */
static completion_entry_t *complete_get_exact_entry( const wcstring &cmd, bool cmd_is_path )
{
ASSERT_IS_LOCKED(completion_lock);
- completion_entry_t *c;
+ completion_entry_t *c;
- c = complete_find_exact_entry( cmd, cmd_is_path );
+ c = complete_find_exact_entry( cmd, cmd_is_path );
- if( c == NULL )
- {
+ if( c == NULL )
+ {
c = new completion_entry_t(cmd, cmd_is_path, L"", false);
completion_set.insert(c);
- }
+ }
- return c;
+ return c;
}
void complete_set_authoritative( const wchar_t *cmd, bool cmd_is_path, bool authoritative )
{
- completion_entry_t *c;
+ completion_entry_t *c;
- CHECK( cmd, );
+ CHECK( cmd, );
scoped_lock lock(completion_lock);
- c = complete_get_exact_entry( cmd, cmd_is_path );
- c->authoritative = authoritative;
+ c = complete_get_exact_entry( cmd, cmd_is_path );
+ c->authoritative = authoritative;
}
void complete_add( const wchar_t *cmd,
- bool cmd_is_path,
- wchar_t short_opt,
- const wchar_t *long_opt,
- int old_mode,
- int result_mode,
- const wchar_t *condition,
- const wchar_t *comp,
- const wchar_t *desc,
- complete_flags_t flags )
+ bool cmd_is_path,
+ wchar_t short_opt,
+ const wchar_t *long_opt,
+ int old_mode,
+ int result_mode,
+ const wchar_t *condition,
+ const wchar_t *comp,
+ const wchar_t *desc,
+ complete_flags_t flags )
{
- CHECK( cmd, );
-
+ CHECK( cmd, );
+
/* Lock the lock that allows us to edit the completion entry list */
scoped_lock lock(completion_lock);
-
+
/* Lock the lock that allows us to edit individual completion entries */
scoped_lock lock2(completion_entry_lock);
-
- completion_entry_t *c;
- c = complete_get_exact_entry( cmd, cmd_is_path );
-
+
+ completion_entry_t *c;
+ c = complete_get_exact_entry( cmd, cmd_is_path );
+
/* Create our new option */
complete_entry_opt_t opt;
- if( short_opt != L'\0' )
- {
- int len = 1 + ((result_mode & NO_COMMON) != 0);
-
+ if( short_opt != L'\0' )
+ {
+ int len = 1 + ((result_mode & NO_COMMON) != 0);
+
c->get_short_opt_str().push_back(short_opt);
- if( len == 2 )
- {
+ if( len == 2 )
+ {
c->get_short_opt_str().push_back(L':');
- }
- }
-
- opt.short_opt = short_opt;
- opt.result_mode = result_mode;
- opt.old_mode=old_mode;
+ }
+ }
+
+ opt.short_opt = short_opt;
+ opt.result_mode = result_mode;
+ opt.old_mode=old_mode;
if (comp) opt.comp = comp;
if (condition) opt.condition = condition;
if (long_opt) opt.long_opt = long_opt;
if (desc) opt.desc = desc;
- opt.flags = flags;
-
+ opt.flags = flags;
+
c->add_option(opt);
}
@@ -545,24 +545,24 @@ bool completion_entry_t::remove_option( wchar_t short_opt, const wchar_t *long_o
{
ASSERT_IS_LOCKED(completion_lock);
ASSERT_IS_LOCKED(completion_entry_lock);
- if(( short_opt == 0 ) && (long_opt == 0 ) )
- {
+ if(( short_opt == 0 ) && (long_opt == 0 ) )
+ {
this->options.clear();
- }
- else
- {
+ }
+ else
+ {
for (option_list_t::iterator iter = this->options.begin(); iter != this->options.end(); )
- {
+ {
complete_entry_opt_t &o = *iter;
- if(short_opt==o.short_opt || long_opt == o.long_opt)
- {
- /* fwprintf( stderr,
- L"remove option -%lc --%ls\n",
- o->short_opt?o->short_opt:L' ',
- o->long_opt );
- */
- if( o.short_opt )
- {
+ if(short_opt==o.short_opt || long_opt == o.long_opt)
+ {
+ /* fwprintf( stderr,
+ L"remove option -%lc --%ls\n",
+ o->short_opt?o->short_opt:L' ',
+ o->long_opt );
+ */
+ if( o.short_opt )
+ {
wcstring &short_opt_str = this->get_short_opt_str();
size_t idx = short_opt_str.find(o.short_opt);
if (idx != wcstring::npos)
@@ -573,31 +573,31 @@ bool completion_entry_t::remove_option( wchar_t short_opt, const wchar_t *long_o
first_non_colon++;
short_opt_str.erase(idx, first_non_colon - idx);
}
- }
-
+ }
+
/* Destroy this option and go to the next one */
- iter = this->options.erase(iter);
- }
- else
- {
+ iter = this->options.erase(iter);
+ }
+ else
+ {
/* Just go to the next one */
- ++iter;
- }
- }
- }
+ ++iter;
+ }
+ }
+ }
return this->options.empty();
}
void complete_remove( const wchar_t *cmd,
- bool cmd_is_path,
- wchar_t short_opt,
- const wchar_t *long_opt )
+ bool cmd_is_path,
+ wchar_t short_opt,
+ const wchar_t *long_opt )
{
- CHECK( cmd, );
+ CHECK( cmd, );
scoped_lock lock(completion_lock);
scoped_lock lock2(completion_entry_lock);
-
+
completion_entry_t tmp_entry(cmd, cmd_is_path, L"", false);
completion_entry_set_t::iterator iter = completion_set.find(&tmp_entry);
if (iter != completion_set.end()) {
@@ -625,10 +625,10 @@ static wcstring format_error(const wchar_t *prefix, const wcstring &str) {
*/
static void parse_cmd_string(const wcstring &str, wcstring &path, wcstring &cmd) {
if (! path_get_path(str, &path)) {
- /** Use the empty string as the 'path' for commands that can not be found. */
+ /** Use the empty string as the 'path' for commands that can not be found. */
path = L"";
}
-
+
/* Make sure the path is not included in the command */
size_t last_slash = str.find_last_of(L'/');
if (last_slash != wcstring::npos) {
@@ -639,221 +639,221 @@ static void parse_cmd_string(const wcstring &str, wcstring &path, wcstring &cmd)
}
int complete_is_valid_option( const wcstring &str,
- const wcstring &opt,
- wcstring_list_t *errors,
- bool allow_autoload )
+ const wcstring &opt,
+ wcstring_list_t *errors,
+ bool allow_autoload )
{
wcstring cmd, path;
- bool found_match = false;
- bool authoritative = true;
- int opt_found=0;
- std::set<wcstring> gnu_match_set;
- bool is_gnu_opt=false;
- bool is_old_opt=false;
- bool is_short_opt=false;
- bool is_gnu_exact=false;
- size_t gnu_opt_len=0;
-
+ bool found_match = false;
+ bool authoritative = true;
+ int opt_found=0;
+ std::set<wcstring> gnu_match_set;
+ bool is_gnu_opt=false;
+ bool is_old_opt=false;
+ bool is_short_opt=false;
+ bool is_gnu_exact=false;
+ size_t gnu_opt_len=0;
+
if (opt.empty())
return false;
-
+
std::vector<bool> short_validated;
- /*
- Check some generic things like -- and - options.
- */
- switch( opt.size() )
- {
-
- case 0:
- case 1:
- {
- return true;
- }
-
- case 2:
- {
- if( opt == L"--" )
- {
- return true;
- }
- break;
- }
- }
-
- if( opt.at(0) != L'-' )
- {
- if( errors )
+ /*
+ Check some generic things like -- and - options.
+ */
+ switch( opt.size() )
+ {
+
+ case 0:
+ case 1:
+ {
+ return true;
+ }
+
+ case 2:
+ {
+ if( opt == L"--" )
+ {
+ return true;
+ }
+ break;
+ }
+ }
+
+ if( opt.at(0) != L'-' )
+ {
+ if( errors )
errors->push_back(L"Option does not begin with a '-'");
- return false;
- }
+ return false;
+ }
short_validated.resize(opt.size(), 0);
-
- is_gnu_opt = opt.at(1) == L'-';
- if( is_gnu_opt )
- {
+
+ is_gnu_opt = opt.at(1) == L'-';
+ if( is_gnu_opt )
+ {
size_t opt_end = opt.find(L'=');
- if( opt_end != wcstring::npos )
- {
- gnu_opt_len = opt_end-2;
- }
- else
- {
- gnu_opt_len = opt.size() - 2;
- }
- }
-
- parse_cmd_string( str, path, cmd );
-
- /*
- Make sure completions are loaded for the specified command
- */
- if (allow_autoload) {
+ if( opt_end != wcstring::npos )
+ {
+ gnu_opt_len = opt_end-2;
+ }
+ else
+ {
+ gnu_opt_len = opt.size() - 2;
+ }
+ }
+
+ parse_cmd_string( str, path, cmd );
+
+ /*
+ Make sure completions are loaded for the specified command
+ */
+ if (allow_autoload) {
complete_load( cmd, false );
}
- scoped_lock lock(completion_lock);
+ scoped_lock lock(completion_lock);
scoped_lock lock2(completion_entry_lock);
for (completion_entry_set_t::const_iterator iter = completion_set.begin(); iter != completion_set.end(); ++iter)
- {
+ {
const completion_entry_t *i = *iter;
- const wcstring &match = i->cmd_is_path ? path : cmd;
+ const wcstring &match = i->cmd_is_path ? path : cmd;
- if( !wildcard_match( match, i->cmd ) )
- {
- continue;
- }
-
- found_match = true;
+ if( !wildcard_match( match, i->cmd ) )
+ {
+ continue;
+ }
- if (! i->authoritative)
- {
- authoritative = false;
- break;
- }
+ found_match = true;
+
+ if (! i->authoritative)
+ {
+ authoritative = false;
+ break;
+ }
const option_list_t &options = i->get_options();
- if( is_gnu_opt )
- {
+ if( is_gnu_opt )
+ {
for (option_list_t::const_iterator iter = options.begin(); iter != options.end(); ++iter)
{
const complete_entry_opt_t &o = *iter;
- if (o.old_mode )
- {
- continue;
- }
-
+ if (o.old_mode )
+ {
+ continue;
+ }
+
if (opt.compare(2, gnu_opt_len, o.long_opt) == 0)
- {
+ {
gnu_match_set.insert(o.long_opt);
- if (opt.compare(2, o.long_opt.size(), o.long_opt))
- {
- is_gnu_exact = true;
- }
- }
- }
- }
- else
- {
- /* Check for old style options */
+ if (opt.compare(2, o.long_opt.size(), o.long_opt))
+ {
+ is_gnu_exact = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Check for old style options */
for (option_list_t::const_iterator iter = options.begin(); iter != options.end(); ++iter)
- {
+ {
const complete_entry_opt_t &o = *iter;
-
- if( !o.old_mode )
- continue;
+ if( !o.old_mode )
+ continue;
- if( opt.compare(1, wcstring::npos, o.long_opt )==0)
- {
- opt_found = true;
- is_old_opt = true;
- break;
- }
- }
+ if( opt.compare(1, wcstring::npos, o.long_opt )==0)
+ {
+ opt_found = true;
+ is_old_opt = true;
+ break;
+ }
- if( is_old_opt )
- break;
+ }
+
+ if( is_old_opt )
+ break;
for (size_t opt_idx = 1; opt_idx < opt.size(); opt_idx++)
- {
+ {
const wcstring &short_opt_str = i->get_short_opt_str();
size_t str_idx = short_opt_str.find(opt.at(opt_idx));
- if (str_idx != wcstring::npos )
- {
- if (str_idx + 1 < short_opt_str.size() && short_opt_str.at(str_idx + 1) == L':' )
- {
- /*
- This is a short option with an embedded argument,
- call complete_is_valid_argument on the argument.
- */
+ if (str_idx != wcstring::npos )
+ {
+ if (str_idx + 1 < short_opt_str.size() && short_opt_str.at(str_idx + 1) == L':' )
+ {
+ /*
+ This is a short option with an embedded argument,
+ call complete_is_valid_argument on the argument.
+ */
const wcstring nopt = L"-" + opt.substr(1, 1);
- short_validated.at(opt_idx) =
- complete_is_valid_argument( str, nopt, opt.substr(2));
- }
- else
- {
- short_validated.at(opt_idx) = true;
- }
- }
- }
- }
- }
-
- if( authoritative )
- {
-
- if( !is_gnu_opt && !is_old_opt )
- is_short_opt = 1;
-
-
- if( is_short_opt )
- {
- opt_found=1;
- for( size_t j=1; j<opt.size(); j++)
- {
- if ( !short_validated.at(j))
- {
- if( errors )
- {
+ short_validated.at(opt_idx) =
+ complete_is_valid_argument( str, nopt, opt.substr(2));
+ }
+ else
+ {
+ short_validated.at(opt_idx) = true;
+ }
+ }
+ }
+ }
+ }
+
+ if( authoritative )
+ {
+
+ if( !is_gnu_opt && !is_old_opt )
+ is_short_opt = 1;
+
+
+ if( is_short_opt )
+ {
+ opt_found=1;
+ for( size_t j=1; j<opt.size(); j++)
+ {
+ if ( !short_validated.at(j))
+ {
+ if( errors )
+ {
const wcstring str = opt.substr(j, 1);
errors->push_back(format_error(_(L"Unknown option: "), str.c_str()));
- }
+ }
- opt_found = 0;
- break;
- }
+ opt_found = 0;
+ break;
+ }
- }
- }
+ }
+ }
- if( is_gnu_opt )
- {
- opt_found = is_gnu_exact || (gnu_match_set.size() == 1);
- if( errors && !opt_found )
- {
+ if( is_gnu_opt )
+ {
+ opt_found = is_gnu_exact || (gnu_match_set.size() == 1);
+ if( errors && !opt_found )
+ {
const wchar_t *prefix;
if( gnu_match_set.empty())
- {
+ {
prefix = _(L"Unknown option: ");
- }
- else
- {
+ }
+ else
+ {
prefix = _(L"Multiple matches for option: ");
- }
+ }
errors->push_back(format_error(prefix, opt));
- }
- }
- }
+ }
+ }
+ }
return (authoritative && found_match)?opt_found:true;
}
bool complete_is_valid_argument( const wcstring &str, const wcstring &opt, const wcstring &arg )
{
- return true;
+ return true;
}
@@ -884,21 +884,21 @@ void completer_t::complete_strings( const wcstring &wc_escaped,
wcstring tmp = wc_escaped;
if (! expand_one(tmp, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_WILDCARDS | this->expand_flags()))
return;
-
- const wchar_t *wc = parse_util_unescape_wildcards( tmp.c_str() );
-
- for( size_t i=0; i< possible_comp.size(); i++ )
- {
- wcstring temp = possible_comp.at( i ).completion;
- const wchar_t *next_str = temp.empty()?NULL:temp.c_str();
-
- if( next_str )
- {
- wildcard_complete( next_str, wc, desc, desc_func, this->completions, flags );
- }
- }
-
- free( (void *)wc );
+
+ const wchar_t *wc = parse_util_unescape_wildcards( tmp.c_str() );
+
+ for( size_t i=0; i< possible_comp.size(); i++ )
+ {
+ wcstring temp = possible_comp.at( i ).completion;
+ const wchar_t *next_str = temp.empty()?NULL:temp.c_str();
+
+ if( next_str )
+ {
+ wildcard_complete( next_str, wc, desc, desc_func, this->completions, flags );
+ }
+ }
+
+ free( (void *)wc );
}
/**
@@ -908,118 +908,118 @@ void completer_t::complete_strings( const wcstring &wc_escaped,
void completer_t::complete_cmd_desc( const wcstring &str )
{
ASSERT_IS_MAIN_THREAD();
-
- const wchar_t *cmd_start;
- int skip;
-
+
+ const wchar_t *cmd_start;
+ int skip;
+
const wchar_t * const cmd = str.c_str();
- cmd_start=wcsrchr(cmd, L'/');
-
- if( cmd_start )
- cmd_start++;
- else
- cmd_start = cmd;
-
- /*
- Using apropos with a single-character search term produces far
- to many results - require at least two characters if we don't
- know the location of the whatis-database.
- */
- if (wcslen(cmd_start) < 2)
- return;
-
- if( wildcard_has( cmd_start, 0 ) )
- {
- return;
- }
-
- skip = 1;
-
- for( size_t i=0; i< this->completions.size(); i++ )
- {
- const completion_t &c = this->completions.at ( i );
-
- if( c.completion.empty() || (c.completion[c.completion.size()-1] != L'/' ))
- {
- skip = 0;
- break;
- }
-
- }
-
- if( skip )
- {
- return;
- }
-
+ cmd_start=wcsrchr(cmd, L'/');
+
+ if( cmd_start )
+ cmd_start++;
+ else
+ cmd_start = cmd;
+
+ /*
+ Using apropos with a single-character search term produces far
+ to many results - require at least two characters if we don't
+ know the location of the whatis-database.
+ */
+ if (wcslen(cmd_start) < 2)
+ return;
+
+ if( wildcard_has( cmd_start, 0 ) )
+ {
+ return;
+ }
+
+ skip = 1;
+
+ for( size_t i=0; i< this->completions.size(); i++ )
+ {
+ const completion_t &c = this->completions.at ( i );
+
+ if( c.completion.empty() || (c.completion[c.completion.size()-1] != L'/' ))
+ {
+ skip = 0;
+ break;
+ }
+
+ }
+
+ if( skip )
+ {
+ return;
+ }
+
wcstring lookup_cmd(L"__fish_describe_command ");
lookup_cmd.append(escape_string(cmd_start, 1));
std::map<wcstring, wcstring> lookup;
- /*
- First locate a list of possible descriptions using a single
- call to apropos or a direct search if we know the location
- of the whatis database. This can take some time on slower
- systems with a large set of manuals, but it should be ok
- since apropos is only called once.
- */
+ /*
+ First locate a list of possible descriptions using a single
+ call to apropos or a direct search if we know the location
+ of the whatis database. This can take some time on slower
+ systems with a large set of manuals, but it should be ok
+ since apropos is only called once.
+ */
wcstring_list_t list;
- if( exec_subshell( lookup_cmd, list ) != -1 )
- {
-
- /*
- Then discard anything that is not a possible completion and put
- the result into a hashtable with the completion as key and the
- description as value.
-
- Should be reasonably fast, since no memory allocations are needed.
- */
- for( size_t i=0; i < list.size(); i++ )
- {
+ if( exec_subshell( lookup_cmd, list ) != -1 )
+ {
+
+ /*
+ Then discard anything that is not a possible completion and put
+ the result into a hashtable with the completion as key and the
+ description as value.
+
+ Should be reasonably fast, since no memory allocations are needed.
+ */
+ for( size_t i=0; i < list.size(); i++ )
+ {
const wcstring &elstr = list.at(i);
-
+
const wcstring fullkey(elstr, wcslen(cmd_start));
-
+
size_t tab_idx = fullkey.find(L'\t');
- if( tab_idx == wcstring::npos )
- continue;
-
+ if( tab_idx == wcstring::npos )
+ continue;
+
const wcstring key(fullkey, 0, tab_idx);
wcstring val(fullkey, tab_idx + 1);
- /*
- And once again I make sure the first character is uppercased
- because I like it that way, and I get to decide these
- things.
- */
+ /*
+ And once again I make sure the first character is uppercased
+ because I like it that way, and I get to decide these
+ things.
+ */
if (! val.empty())
val[0]=towupper(val[0]);
-
+
lookup[key] = val;
- }
+ }
- /*
- Then do a lookup on every completion and if a match is found,
- change to the new description.
+ /*
+ Then do a lookup on every completion and if a match is found,
+ change to the new description.
- This needs to do a reallocation for every description added, but
- there shouldn't be that many completions, so it should be ok.
- */
- for( size_t i=0; i<this->completions.size(); i++ )
- {
+ This needs to do a reallocation for every description added, but
+ there shouldn't be that many completions, so it should be ok.
+ */
+ for( size_t i=0; i<this->completions.size(); i++ )
+ {
completion_t &completion = this->completions.at(i);
const wcstring &el = completion.completion;
if (el.empty())
continue;
-
+
std::map<wcstring, wcstring>::iterator new_desc_iter = lookup.find(el);
if (new_desc_iter != lookup.end())
completion.description = new_desc_iter->second;
- }
- }
-
+ }
+ }
+
}
/**
@@ -1032,7 +1032,7 @@ static wcstring complete_function_desc( const wcstring &fn )
if (! has_description) {
function_get_definition(fn, &result);
}
- return result;
+ return result;
}
@@ -1050,44 +1050,44 @@ void completer_t::complete_cmd( const wcstring &str_cmd, bool use_function, bool
/* Paranoia */
if (str_cmd.empty())
return;
-
- std::vector<completion_t> possible_comp;
+
+ std::vector<completion_t> possible_comp;
env_var_t cdpath = env_get_string(L"CDPATH");
if (cdpath.missing_or_empty())
cdpath = L".";
-
+
const bool wants_description = (type == COMPLETE_DEFAULT);
-
+
if (str_cmd.find(L'/') != wcstring::npos || str_cmd.at(0) == L'~')
- {
+ {
+
+ if( use_command )
+ {
- if( use_command )
- {
-
- if( expand_string(str_cmd, this->completions, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
- {
+ if( expand_string(str_cmd, this->completions, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
+ {
if (wants_description) {
this->complete_cmd_desc( str_cmd );
}
- }
- }
- }
- else
- {
- if( use_command )
- {
-
- const env_var_t path = env_get_string(L"PATH");
- if( !path.missing() )
- {
+ }
+ }
+ }
+ else
+ {
+ if( use_command )
+ {
+
+ const env_var_t path = env_get_string(L"PATH");
+ if( !path.missing() )
+ {
wcstring base_path;
wcstokenizer tokenizer(path, ARRAY_SEP_STR);
- while (tokenizer.next(base_path))
- {
+ while (tokenizer.next(base_path))
+ {
if (base_path.empty())
continue;
-
+
/* Make sure the base path ends with a slash */
if (base_path.at(base_path.size() - 1) != L'/')
base_path.push_back(L'/');
@@ -1096,51 +1096,51 @@ void completer_t::complete_cmd( const wcstring &str_cmd, bool use_function, bool
nxt_completion.append(str_cmd);
size_t prev_count = this->completions.size();
- if( expand_string( nxt_completion,
- this->completions,
- ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
- {
+ if( expand_string( nxt_completion,
+ this->completions,
+ ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
+ {
/* For all new completions, if COMPLETE_NO_CASE is set, then use only the last path component */
- for( size_t i=prev_count; i< this->completions.size(); i++ )
- {
- completion_t &c = this->completions.at( i );
- if(c.flags & COMPLETE_NO_CASE )
- {
-
- c.completion.erase(0, base_path.size());
- }
- }
- }
- }
- if (wants_description)
+ for( size_t i=prev_count; i< this->completions.size(); i++ )
+ {
+ completion_t &c = this->completions.at( i );
+ if(c.flags & COMPLETE_NO_CASE )
+ {
+
+ c.completion.erase(0, base_path.size());
+ }
+ }
+ }
+ }
+ if (wants_description)
this->complete_cmd_desc( str_cmd );
- }
- }
-
- /*
- These return the original strings - don't free them
- */
-
- if( use_function )
- {
- //function_get_names( &possible_comp, cmd[0] == L'_' );
+ }
+ }
+
+ /*
+ These return the original strings - don't free them
+ */
+
+ if( use_function )
+ {
+ //function_get_names( &possible_comp, cmd[0] == L'_' );
wcstring_list_t names = function_get_names(str_cmd.at(0) == L'_' );
for (size_t i=0; i < names.size(); i++) {
possible_comp.push_back(completion_t(names.at(i)));
}
-
- this->complete_strings( str_cmd, 0, &complete_function_desc, possible_comp, 0 );
- }
-
- possible_comp.clear();
-
- if( use_builtin )
- {
- builtin_get_names( possible_comp );
- this->complete_strings( str_cmd, 0, &builtin_get_desc, possible_comp, 0 );
- }
-
- }
+
+ this->complete_strings( str_cmd, 0, &complete_function_desc, possible_comp, 0 );
+ }
+
+ possible_comp.clear();
+
+ if( use_builtin )
+ {
+ builtin_get_names( possible_comp );
+ this->complete_strings( str_cmd, 0, &builtin_get_desc, possible_comp, 0 );
+ }
+
+ }
}
@@ -1161,73 +1161,73 @@ void completer_t::complete_from_args( const wcstring &str,
const wcstring &desc,
complete_flags_t flags )
{
-
- std::vector<completion_t> possible_comp;
+
+ std::vector<completion_t> possible_comp;
bool is_autosuggest = (this->type == COMPLETE_AUTOSUGGEST);
parser_t parser(is_autosuggest ? PARSER_TYPE_COMPLETIONS_ONLY : PARSER_TYPE_GENERAL, false);
- /* If type is COMPLETE_AUTOSUGGEST, it means we're on a background thread, so don't call proc_push_interactive */
+ /* If type is COMPLETE_AUTOSUGGEST, it means we're on a background thread, so don't call proc_push_interactive */
if (! is_autosuggest)
proc_push_interactive(0);
- parser.eval_args( args.c_str(), possible_comp );
+ parser.eval_args( args.c_str(), possible_comp );
if (! is_autosuggest)
proc_pop_interactive();
-
- this->complete_strings( str, desc.c_str(), 0, possible_comp, flags );
+
+ this->complete_strings( str, desc.c_str(), 0, possible_comp, flags );
}
/**
Match against an old style long option
*/
static int param_match_old( const complete_entry_opt_t *e,
- const wchar_t *optstr )
+ const wchar_t *optstr )
{
- return (optstr[0] == L'-') && (e->long_opt == &optstr[1]);
+ return (optstr[0] == L'-') && (e->long_opt == &optstr[1]);
}
/**
Match a parameter
*/
static int param_match( const complete_entry_opt_t *e,
- const wchar_t *optstr )
+ const wchar_t *optstr )
{
- if( e->short_opt != L'\0' &&
- e->short_opt == optstr[1] )
- return 1;
-
- if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0 ))
- {
- if( e->long_opt == &optstr[2])
- {
- return 1;
- }
- }
-
- return 0;
+ if( e->short_opt != L'\0' &&
+ e->short_opt == optstr[1] )
+ return 1;
+
+ if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0 ))
+ {
+ if( e->long_opt == &optstr[2])
+ {
+ return 1;
+ }
+ }
+
+ return 0;
}
/**
Test if a string is an option with an argument, like --color=auto or -I/usr/include
*/
static wchar_t *param_match2( const complete_entry_opt_t *e,
- const wchar_t *optstr )
+ const wchar_t *optstr )
{
- if( e->short_opt != L'\0' && e->short_opt == optstr[1] )
- return (wchar_t *)&optstr[2];
- if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0) )
- {
- size_t len = e->long_opt.size();
-
- if( wcsncmp( e->long_opt.c_str(), &optstr[2],len ) == 0 )
- {
- if( optstr[len+2] == L'=' )
- return (wchar_t *)&optstr[len+3];
- }
- }
- return 0;
+ if( e->short_opt != L'\0' && e->short_opt == optstr[1] )
+ return (wchar_t *)&optstr[2];
+ if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0) )
+ {
+ size_t len = e->long_opt.size();
+
+ if( wcsncmp( e->long_opt.c_str(), &optstr[2],len ) == 0 )
+ {
+ if( optstr[len+2] == L'=' )
+ return (wchar_t *)&optstr[len+3];
+ }
+ }
+ return 0;
}
/**
@@ -1237,41 +1237,41 @@ static int short_ok( const wcstring &arg_str, wchar_t nextopt, const wcstring &a
{
const wchar_t *arg = arg_str.c_str();
const wchar_t *allopt = allopt_str.c_str();
- const wchar_t *ptr;
+ const wchar_t *ptr;
- if( arg[0] != L'-')
- return arg[0] == L'\0';
- if( arg[1] == L'-' )
- return 0;
+ if( arg[0] != L'-')
+ return arg[0] == L'\0';
+ if( arg[1] == L'-' )
+ return 0;
- if( wcschr( arg, nextopt ) != 0 )
- return 0;
+ if( wcschr( arg, nextopt ) != 0 )
+ return 0;
- for( ptr = arg+1; *ptr; ptr++ )
- {
- const wchar_t *tmp = wcschr( allopt, *ptr );
- /* Unknown option */
- if( tmp == 0 )
- {
- /*fwprintf( stderr, L"Unknown option %lc", *ptr );*/
+ for( ptr = arg+1; *ptr; ptr++ )
+ {
+ const wchar_t *tmp = wcschr( allopt, *ptr );
+ /* Unknown option */
+ if( tmp == 0 )
+ {
+ /*fwprintf( stderr, L"Unknown option %lc", *ptr );*/
- return 0;
- }
+ return 0;
+ }
- if( *(tmp+1) == L':' )
- {
-/* fwprintf( stderr, L"Woot %ls", allopt );*/
- return 0;
- }
+ if( *(tmp+1) == L':' )
+ {
+/* fwprintf( stderr, L"Woot %ls", allopt );*/
+ return 0;
+ }
- }
+ }
- return 1;
+ return 1;
}
void complete_load( const wcstring &name, bool reload )
{
- completion_autoloader.load( name, reload );
+ completion_autoloader.load( name, reload );
}
/**
@@ -1288,7 +1288,7 @@ bool completer_t::complete_param( const wcstring &scmd_orig, const wcstring &spo
const wchar_t * const cmd_orig = scmd_orig.c_str(), * const popt = spopt.c_str(), * const str = sstr.c_str();
- bool use_common=1, use_files=1;
+ bool use_common=1, use_files=1;
wcstring cmd, path;
parse_cmd_string(cmd_orig, path, cmd);
@@ -1305,7 +1305,7 @@ bool completer_t::complete_param( const wcstring &scmd_orig, const wcstring &spo
this->commands_to_load.push_back(cmd);
}
}
-
+
/* Make a list of lists of all options that we care about */
std::vector<local_options_t> all_options;
{
@@ -1319,200 +1319,200 @@ bool completer_t::complete_param( const wcstring &scmd_orig, const wcstring &spo
{
continue;
}
-
+
/* Copy all of their options into our list */
all_options.push_back(local_options_t());
all_options.back().short_opt_str = i->get_short_opt_str();
all_options.back().options = i->get_options(); //Oof, this is a lot of copying
}
}
-
+
/* Now release the lock and test each option that we captured above.
We have to do this outside the lock because callouts (like the condition) may add or remove completions.
See https://github.com/ridiculousfish/fishfish/issues/2 */
for (std::vector<local_options_t>::const_iterator iter = all_options.begin(); iter != all_options.end(); iter++)
{
const option_list_t &options = iter->options;
- use_common=1;
- if( use_switches )
- {
-
- if( str[0] == L'-' )
- {
- /* Check if we are entering a combined option and argument
- (like --color=auto or -I/usr/include) */
+ use_common=1;
+ if( use_switches )
+ {
+
+ if( str[0] == L'-' )
+ {
+ /* Check if we are entering a combined option and argument
+ (like --color=auto or -I/usr/include) */
for (option_list_t::const_iterator oiter = options.begin(); oiter != options.end(); ++oiter)
- {
- const complete_entry_opt_t *o = &*oiter;
- wchar_t *arg;
- if( (arg=param_match2( o, str ))!=0 && this->condition_test( o->condition ))
- {
+ {
+ const complete_entry_opt_t *o = &*oiter;
+ wchar_t *arg;
+ if( (arg=param_match2( o, str ))!=0 && this->condition_test( o->condition ))
+ {
if (o->result_mode & NO_COMMON) use_common = false;
if (o->result_mode & NO_FILES) use_files = false;
- complete_from_args( arg, o->comp, o->localized_desc(), o->flags );
- }
-
- }
- }
- else if( popt[0] == L'-' )
- {
- /* Set to true if we found a matching old-style switch */
- int old_style_match = 0;
-
- /*
- If we are using old style long options, check for them
- first
- */
+ complete_from_args( arg, o->comp, o->localized_desc(), o->flags );
+ }
+
+ }
+ }
+ else if( popt[0] == L'-' )
+ {
+ /* Set to true if we found a matching old-style switch */
+ int old_style_match = 0;
+
+ /*
+ If we are using old style long options, check for them
+ first
+ */
for (option_list_t::const_iterator oiter = options.begin(); oiter != options.end(); ++oiter)
- {
+ {
const complete_entry_opt_t *o = &*oiter;
- if( o->old_mode )
- {
- if( param_match_old( o, popt ) && this->condition_test( o->condition ))
- {
- old_style_match = 1;
+ if( o->old_mode )
+ {
+ if( param_match_old( o, popt ) && this->condition_test( o->condition ))
+ {
+ old_style_match = 1;
if (o->result_mode & NO_COMMON) use_common = false;
if (o->result_mode & NO_FILES) use_files = false;
- complete_from_args( str, o->comp, o->localized_desc(), o->flags );
- }
- }
- }
-
- /*
- No old style option matched, or we are not using old
- style options. We check if any short (or gnu style
- options do.
- */
- if( !old_style_match )
- {
+ complete_from_args( str, o->comp, o->localized_desc(), o->flags );
+ }
+ }
+ }
+
+ /*
+ No old style option matched, or we are not using old
+ style options. We check if any short (or gnu style
+ options do.
+ */
+ if( !old_style_match )
+ {
for (option_list_t::const_iterator oiter = options.begin(); oiter != options.end(); ++oiter)
{
const complete_entry_opt_t *o = &*oiter;
- /*
- Gnu-style options with _optional_ arguments must
- be specified as a single token, so that it can
- be differed from a regular argument.
- */
- if( !o->old_mode && ! o->long_opt.empty() && !(o->result_mode & NO_COMMON) )
- continue;
-
- if( param_match( o, popt ) && this->condition_test( o->condition ))
- {
+ /*
+ Gnu-style options with _optional_ arguments must
+ be specified as a single token, so that it can
+ be differed from a regular argument.
+ */
+ if( !o->old_mode && ! o->long_opt.empty() && !(o->result_mode & NO_COMMON) )
+ continue;
+
+ if( param_match( o, popt ) && this->condition_test( o->condition ))
+ {
if (o->result_mode & NO_COMMON) use_common = false;
if (o->result_mode & NO_FILES) use_files = false;
- complete_from_args( str, o->comp.c_str(), o->localized_desc(), o->flags );
+ complete_from_args( str, o->comp.c_str(), o->localized_desc(), o->flags );
+
+ }
+ }
+ }
+ }
+ }
- }
- }
- }
- }
- }
-
- if( use_common )
- {
+ if( use_common )
+ {
for (option_list_t::const_iterator oiter = options.begin(); oiter != options.end(); ++oiter)
{
const complete_entry_opt_t *o = &*oiter;
- /*
- If this entry is for the base command,
- check if any of the arguments match
- */
-
- if( !this->condition_test( o->condition ))
- continue;
-
-
- if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
- {
- use_files &= ((o->result_mode & NO_FILES )==0);
- complete_from_args( str, o->comp, o->localized_desc(), o->flags );
- }
-
- if( wcslen(str) > 0 && use_switches )
- {
- /*
- Check if the short style option matches
- */
- if( o->short_opt != L'\0' &&
- short_ok(str, o->short_opt, iter->short_opt_str))
- {
- const wchar_t *desc = o->localized_desc();
- wchar_t completion[2];
- completion[0] = o->short_opt;
- completion[1] = 0;
-
- append_completion( this->completions, completion, desc, 0 );
-
- }
-
- /*
- Check if the long style option matches
- */
- if( o->long_opt[0] != L'\0' )
- {
- int match=0, match_no_case=0;
-
+ /*
+ If this entry is for the base command,
+ check if any of the arguments match
+ */
+
+ if( !this->condition_test( o->condition ))
+ continue;
+
+
+ if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
+ {
+ use_files &= ((o->result_mode & NO_FILES )==0);
+ complete_from_args( str, o->comp, o->localized_desc(), o->flags );
+ }
+
+ if( wcslen(str) > 0 && use_switches )
+ {
+ /*
+ Check if the short style option matches
+ */
+ if( o->short_opt != L'\0' &&
+ short_ok(str, o->short_opt, iter->short_opt_str))
+ {
+ const wchar_t *desc = o->localized_desc();
+ wchar_t completion[2];
+ completion[0] = o->short_opt;
+ completion[1] = 0;
+
+ append_completion( this->completions, completion, desc, 0 );
+
+ }
+
+ /*
+ Check if the long style option matches
+ */
+ if( o->long_opt[0] != L'\0' )
+ {
+ int match=0, match_no_case=0;
+
wcstring whole_opt;
whole_opt.append(o->old_mode?L"-":L"--");
whole_opt.append(o->long_opt);
match = string_prefixes_string(str, whole_opt);
- if( !match )
- {
- match_no_case = wcsncasecmp( str, whole_opt.c_str(), wcslen(str) )==0;
- }
-
- if( match || match_no_case )
- {
- int has_arg=0; /* Does this switch have any known arguments */
- int req_arg=0; /* Does this switch _require_ an argument */
-
- size_t offset = 0;
- complete_flags_t flags = 0;
-
-
- if( match )
- offset = wcslen( str );
- else
- flags = COMPLETE_NO_CASE;
-
- has_arg = ! o->comp.empty();
- req_arg = (o->result_mode & NO_COMMON );
-
- if( !o->old_mode && ( has_arg && !req_arg ) )
- {
-
- /*
- Optional arguments to a switch can
- only be handled using the '=', so we
- add it as a completion. By default
- we avoid using '=' and instead rely
- on '--switch switch-arg', since it
- is more commonly supported by
- homebrew getopt-like functions.
- */
- wcstring completion = format_string(L"%ls=", whole_opt.c_str()+offset);
- append_completion( this->completions,
- completion,
- C_(o->desc.c_str()),
- flags );
-
- }
-
- append_completion( this->completions,
- whole_opt.c_str() + offset,
- C_(o->desc.c_str()),
- flags );
- }
- }
- }
- }
- }
- }
-
- return use_files;
+ if( !match )
+ {
+ match_no_case = wcsncasecmp( str, whole_opt.c_str(), wcslen(str) )==0;
+ }
+
+ if( match || match_no_case )
+ {
+ int has_arg=0; /* Does this switch have any known arguments */
+ int req_arg=0; /* Does this switch _require_ an argument */
+
+ size_t offset = 0;
+ complete_flags_t flags = 0;
+
+
+ if( match )
+ offset = wcslen( str );
+ else
+ flags = COMPLETE_NO_CASE;
+
+ has_arg = ! o->comp.empty();
+ req_arg = (o->result_mode & NO_COMMON );
+
+ if( !o->old_mode && ( has_arg && !req_arg ) )
+ {
+
+ /*
+ Optional arguments to a switch can
+ only be handled using the '=', so we
+ add it as a completion. By default
+ we avoid using '=' and instead rely
+ on '--switch switch-arg', since it
+ is more commonly supported by
+ homebrew getopt-like functions.
+ */
+ wcstring completion = format_string(L"%ls=", whole_opt.c_str()+offset);
+ append_completion( this->completions,
+ completion,
+ C_(o->desc.c_str()),
+ flags );
+
+ }
+
+ append_completion( this->completions,
+ whole_opt.c_str() + offset,
+ C_(o->desc.c_str()),
+ flags );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return use_files;
}
/**
@@ -1521,32 +1521,32 @@ bool completer_t::complete_param( const wcstring &scmd_orig, const wcstring &spo
void completer_t::complete_param_expand( const wcstring &sstr, bool do_file)
{
const wchar_t * const str = sstr.c_str();
- const wchar_t *comp_str;
-
- if (string_prefixes_string( L"--", sstr) && (comp_str = wcschr(str, L'=' ) ) )
- {
- comp_str++;
- }
- else
- {
- comp_str = str;
- }
-
+ const wchar_t *comp_str;
+
+ if (string_prefixes_string( L"--", sstr) && (comp_str = wcschr(str, L'=' ) ) )
+ {
+ comp_str++;
+ }
+ else
+ {
+ comp_str = str;
+ }
+
expand_flags_t flags = EXPAND_SKIP_CMDSUBST | ACCEPT_INCOMPLETE;
-
+
if (! do_file)
flags |= EXPAND_SKIP_WILDCARDS;
-
+
/* Squelch file descriptions per issue 254 */
if (type == COMPLETE_AUTOSUGGEST || do_file)
flags |= EXPAND_NO_DESCRIPTIONS;
-
- if( expand_string( comp_str,
- this->completions,
- flags | this->expand_flags() ) == EXPAND_ERROR )
- {
- debug( 3, L"Error while expanding string '%ls'", comp_str );
- }
+
+ if( expand_string( comp_str,
+ this->completions,
+ flags | this->expand_flags() ) == EXPAND_ERROR )
+ {
+ debug( 3, L"Error while expanding string '%ls'", comp_str );
+ }
}
void completer_t::debug_print_completions()
@@ -1562,33 +1562,33 @@ void completer_t::debug_print_completions()
bool completer_t::complete_variable(const wcstring &str, size_t start_offset)
{
const wchar_t * const whole_var = str.c_str();
- const wchar_t *var = &whole_var[start_offset];
- size_t varlen = wcslen( var );
- int res = 0;
+ const wchar_t *var = &whole_var[start_offset];
+ size_t varlen = wcslen( var );
+ int res = 0;
bool wants_description = (type != COMPLETE_AUTOSUGGEST);
-
+
const wcstring_list_t names = env_get_names(0);
- for( size_t i=0; i<names.size(); i++ )
- {
- const wcstring & env_name = names.at(i);
- size_t namelen = env_name.size();
- int match=0, match_no_case=0;
-
- if( varlen > namelen )
- continue;
-
- match = string_prefixes_string(var, env_name);
-
- if( !match )
- {
- match_no_case = ( wcsncasecmp( var, env_name.c_str(), varlen) == 0 );
- }
-
- if( match || match_no_case )
- {
+ for( size_t i=0; i<names.size(); i++ )
+ {
+ const wcstring & env_name = names.at(i);
+ size_t namelen = env_name.size();
+ int match=0, match_no_case=0;
+
+ if( varlen > namelen )
+ continue;
+
+ match = string_prefixes_string(var, env_name);
+
+ if( !match )
+ {
+ match_no_case = ( wcsncasecmp( var, env_name.c_str(), varlen) == 0 );
+ }
+
+ if( match || match_no_case )
+ {
wcstring comp;
int flags = 0;
-
+
if( match )
{
comp.append(env_name.c_str() + varlen);
@@ -1599,51 +1599,51 @@ bool completer_t::complete_variable(const wcstring &str, size_t start_offset)
comp.append(env_name);
flags = COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE;
}
-
+
wcstring desc;
if (wants_description)
{
env_var_t value_unescaped = env_get_string( env_name );
if (value_unescaped.missing())
continue;
-
+
wcstring value = expand_escape_variable( value_unescaped );
if (type != COMPLETE_AUTOSUGGEST)
desc = format_string(COMPLETE_VAR_DESC_VAL, value.c_str());
}
-
+
append_completion( this->completions, comp.c_str(), desc.c_str(), flags );
res =1;
-
- }
- }
- return res;
+ }
+ }
+
+ return res;
}
/**
Search the specified string for the \$ sign. If found, try to
- complete as an environment variable.
+ complete as an environment variable.
\return 0 if unable to complete, 1 otherwise
*/
bool completer_t::try_complete_variable( const wcstring &str )
{
- size_t i = str.size();
- while (i--)
- {
+ size_t i = str.size();
+ while (i--)
+ {
wchar_t c = str.at(i);
- if( c == L'$' )
- {
-/* wprintf( L"Var prefix \'%ls\'\n", &cmd[i+1] );*/
- return this->complete_variable( str, i+1 );
- }
- if( !isalnum(c) && c != L'_' )
- {
- return false;
- }
- }
- return false;
+ if( c == L'$' )
+ {
+/* wprintf( L"Var prefix \'%ls\'\n", &cmd[i+1] );*/
+ return this->complete_variable( str, i+1 );
+ }
+ if( !isalnum(c) && c != L'_' )
+ {
+ return false;
+ }
+ }
+ return false;
}
/**
@@ -1655,300 +1655,300 @@ bool completer_t::try_complete_variable( const wcstring &str )
bool completer_t::try_complete_user( const wcstring &str )
{
const wchar_t *cmd = str.c_str();
- const wchar_t *first_char=cmd;
- int res=0;
- double start_time = timef();
-
- if( *first_char ==L'~' && !wcschr(first_char, L'/'))
- {
- const wchar_t *user_name = first_char+1;
- const wchar_t *name_end = wcschr( user_name, L'~' );
- if( name_end == 0 )
- {
- struct passwd *pw;
- size_t name_len = wcslen( user_name );
-
- setpwent();
-
- while((pw=getpwent()) != 0)
- {
- double current_time = timef();
- wchar_t *pw_name;
-
- if( current_time - start_time > 0.2 )
- {
- return 1;
- }
-
- pw_name = str2wcs( pw->pw_name );
-
- if( pw_name )
- {
- if( wcsncmp( user_name, pw_name, name_len )==0 )
- {
- wcstring desc = format_string(COMPLETE_USER_DESC, pw_name);
- append_completion( this->completions,
- &pw_name[name_len],
- desc,
- COMPLETE_NO_SPACE );
-
- res=1;
- }
- else if( wcsncasecmp( user_name, pw_name, name_len )==0 )
- {
- wcstring name = format_string(L"~%ls", pw_name);
+ const wchar_t *first_char=cmd;
+ int res=0;
+ double start_time = timef();
+
+ if( *first_char ==L'~' && !wcschr(first_char, L'/'))
+ {
+ const wchar_t *user_name = first_char+1;
+ const wchar_t *name_end = wcschr( user_name, L'~' );
+ if( name_end == 0 )
+ {
+ struct passwd *pw;
+ size_t name_len = wcslen( user_name );
+
+ setpwent();
+
+ while((pw=getpwent()) != 0)
+ {
+ double current_time = timef();
+ wchar_t *pw_name;
+
+ if( current_time - start_time > 0.2 )
+ {
+ return 1;
+ }
+
+ pw_name = str2wcs( pw->pw_name );
+
+ if( pw_name )
+ {
+ if( wcsncmp( user_name, pw_name, name_len )==0 )
+ {
+ wcstring desc = format_string(COMPLETE_USER_DESC, pw_name);
+ append_completion( this->completions,
+ &pw_name[name_len],
+ desc,
+ COMPLETE_NO_SPACE );
+
+ res=1;
+ }
+ else if( wcsncasecmp( user_name, pw_name, name_len )==0 )
+ {
+ wcstring name = format_string(L"~%ls", pw_name);
wcstring desc = format_string(COMPLETE_USER_DESC, pw_name);
-
- append_completion( this->completions,
- name,
- desc,
- COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE );
- res=1;
- }
- free( pw_name );
- }
- }
- endpwent();
- }
- }
-
- return res;
+
+ append_completion( this->completions,
+ name,
+ desc,
+ COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE );
+ res=1;
+ }
+ free( pw_name );
+ }
+ }
+ endpwent();
+ }
+ }
+
+ return res;
}
void complete( const wcstring &cmd, std::vector<completion_t> &comps, complete_type_t type, wcstring_list_t *commands_to_load )
{
/* Make our completer */
completer_t completer(cmd, type);
-
- const wchar_t *tok_begin, *tok_end, *cmdsubst_begin, *cmdsubst_end, *prev_begin, *prev_end;
- tokenizer tok;
- const wchar_t *current_token=0, *prev_token=0;
- wcstring current_command;
- int on_command=0;
- size_t pos;
- bool done=false;
- int use_command = 1;
- int use_function = 1;
- int use_builtin = 1;
- int had_ddash = 0;
-
-// debug( 1, L"Complete '%ls'", cmd );
-
- size_t cursor_pos = cmd.size();
-
+
+ const wchar_t *tok_begin, *tok_end, *cmdsubst_begin, *cmdsubst_end, *prev_begin, *prev_end;
+ tokenizer tok;
+ const wchar_t *current_token=0, *prev_token=0;
+ wcstring current_command;
+ int on_command=0;
+ size_t pos;
+ bool done=false;
+ int use_command = 1;
+ int use_function = 1;
+ int use_builtin = 1;
+ int had_ddash = 0;
+
+// debug( 1, L"Complete '%ls'", cmd );
+
+ size_t cursor_pos = cmd.size();
+
const wchar_t *cmd_cstr = cmd.c_str();
- parse_util_cmdsubst_extent( cmd_cstr, cursor_pos, &cmdsubst_begin, &cmdsubst_end );
- parse_util_token_extent( cmd_cstr, cursor_pos, &tok_begin, &tok_end, &prev_begin, &prev_end );
+ parse_util_cmdsubst_extent( cmd_cstr, cursor_pos, &cmdsubst_begin, &cmdsubst_end );
+ parse_util_token_extent( cmd_cstr, cursor_pos, &tok_begin, &tok_end, &prev_begin, &prev_end );
- if( !cmdsubst_begin )
- done=1;
-
+ if( !cmdsubst_begin )
+ done=1;
- /**
- If we are completing a variable name or a tilde expansion user
- name, we do that and return. No need for any other competions.
- */
- if( !done )
- {
+ /**
+ If we are completing a variable name or a tilde expansion user
+ name, we do that and return. No need for any other competions.
+ */
+
+ if( !done )
+ {
wcstring tmp = tok_begin;
done = completer.try_complete_variable( tmp ) || completer.try_complete_user( tmp );
- }
-
- if( !done )
- {
- pos = cursor_pos-(cmdsubst_begin-cmd_cstr);
-
- wcstring buff = wcstring( cmdsubst_begin, cmdsubst_end-cmdsubst_begin );
-
- int had_cmd=0;
- int end_loop=0;
-
- tok_init( &tok, buff.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
-
- while( tok_has_next( &tok) && !end_loop )
- {
-
- switch( tok_last_type( &tok ) )
- {
-
- case TOK_STRING:
- {
-
- const wcstring ncmd = tok_last( &tok );
- int is_ddash = (ncmd == L"--") && ( (tok_get_pos( &tok )+2) < (long)pos );
-
- if( !had_cmd )
- {
-
- if( parser_keywords_is_subcommand( ncmd ) )
- {
- if (ncmd == L"builtin" )
- {
- use_function = 0;
- use_command = 0;
- use_builtin = 1;
- }
- else if (ncmd == L"command")
- {
- use_command = 1;
- use_function = 0;
- use_builtin = 0;
- }
- break;
- }
-
-
- if( !is_ddash ||
- ( (use_command && use_function && use_builtin ) ) )
- {
- current_command = ncmd;
-
- size_t token_end = tok_get_pos( &tok ) + ncmd.size();
-
- on_command = (pos <= token_end );
- had_cmd=1;
- }
-
- }
- else
- {
- if( is_ddash )
- {
- had_ddash = 1;
- }
- }
-
- break;
- }
-
- case TOK_END:
- case TOK_PIPE:
- case TOK_BACKGROUND:
- {
- had_cmd=0;
- had_ddash = 0;
- use_command = 1;
- use_function = 1;
- use_builtin = 1;
- break;
- }
-
- case TOK_ERROR:
- {
- end_loop=1;
- break;
- }
-
- }
-
- if( tok_get_pos( &tok ) >= (long)pos )
- {
- end_loop=1;
- }
-
- tok_next( &tok );
-
- }
-
- tok_destroy( &tok );
-
- /*
- Get the string to complete
- */
-
- current_token = wcsndup( tok_begin, cursor_pos-(tok_begin-cmd_cstr) );
-
- prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
-
-// debug( 0, L"on_command: %d, %ls %ls\n", on_command, current_command, current_token );
-
- /*
- Check if we are using the 'command' or 'builtin' builtins
- _and_ we are writing a switch instead of a command. In that
- case, complete using the builtins completions, not using a
- subcommand.
- */
-
- if( (on_command || (wcscmp( current_token, L"--" ) == 0 ) ) &&
- (current_token[0] == L'-') &&
- !(use_command && use_function && use_builtin ) )
- {
- if( use_command == 0 )
- current_command = L"builtin";
- else
- current_command = L"command";
-
- had_cmd = 1;
- on_command = 0;
- }
-
- /*
- Use command completions if in between commands
- */
- if( !had_cmd )
- {
- on_command=1;
- }
-
- /*
- We don't want these to be null
- */
-
- if( !current_token )
- {
- current_token = wcsdup(L"");
- }
-
- if( !prev_token )
- {
- prev_token = wcsdup(L"");
- }
-
- if( current_token && prev_token )
- {
- if( on_command )
- {
- /* Complete command filename */
- completer.complete_cmd( current_token, use_function, use_builtin, use_command );
- }
- else
- {
- int do_file=0;
-
+ }
+
+ if( !done )
+ {
+ pos = cursor_pos-(cmdsubst_begin-cmd_cstr);
+
+ wcstring buff = wcstring( cmdsubst_begin, cmdsubst_end-cmdsubst_begin );
+
+ int had_cmd=0;
+ int end_loop=0;
+
+ tok_init( &tok, buff.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
+
+ while( tok_has_next( &tok) && !end_loop )
+ {
+
+ switch( tok_last_type( &tok ) )
+ {
+
+ case TOK_STRING:
+ {
+
+ const wcstring ncmd = tok_last( &tok );
+ int is_ddash = (ncmd == L"--") && ( (tok_get_pos( &tok )+2) < (long)pos );
+
+ if( !had_cmd )
+ {
+
+ if( parser_keywords_is_subcommand( ncmd ) )
+ {
+ if (ncmd == L"builtin" )
+ {
+ use_function = 0;
+ use_command = 0;
+ use_builtin = 1;
+ }
+ else if (ncmd == L"command")
+ {
+ use_command = 1;
+ use_function = 0;
+ use_builtin = 0;
+ }
+ break;
+ }
+
+
+ if( !is_ddash ||
+ ( (use_command && use_function && use_builtin ) ) )
+ {
+ current_command = ncmd;
+
+ size_t token_end = tok_get_pos( &tok ) + ncmd.size();
+
+ on_command = (pos <= token_end );
+ had_cmd=1;
+ }
+
+ }
+ else
+ {
+ if( is_ddash )
+ {
+ had_ddash = 1;
+ }
+ }
+
+ break;
+ }
+
+ case TOK_END:
+ case TOK_PIPE:
+ case TOK_BACKGROUND:
+ {
+ had_cmd=0;
+ had_ddash = 0;
+ use_command = 1;
+ use_function = 1;
+ use_builtin = 1;
+ break;
+ }
+
+ case TOK_ERROR:
+ {
+ end_loop=1;
+ break;
+ }
+
+ }
+
+ if( tok_get_pos( &tok ) >= (long)pos )
+ {
+ end_loop=1;
+ }
+
+ tok_next( &tok );
+
+ }
+
+ tok_destroy( &tok );
+
+ /*
+ Get the string to complete
+ */
+
+ current_token = wcsndup( tok_begin, cursor_pos-(tok_begin-cmd_cstr) );
+
+ prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
+
+// debug( 0, L"on_command: %d, %ls %ls\n", on_command, current_command, current_token );
+
+ /*
+ Check if we are using the 'command' or 'builtin' builtins
+ _and_ we are writing a switch instead of a command. In that
+ case, complete using the builtins completions, not using a
+ subcommand.
+ */
+
+ if( (on_command || (wcscmp( current_token, L"--" ) == 0 ) ) &&
+ (current_token[0] == L'-') &&
+ !(use_command && use_function && use_builtin ) )
+ {
+ if( use_command == 0 )
+ current_command = L"builtin";
+ else
+ current_command = L"command";
+
+ had_cmd = 1;
+ on_command = 0;
+ }
+
+ /*
+ Use command completions if in between commands
+ */
+ if( !had_cmd )
+ {
+ on_command=1;
+ }
+
+ /*
+ We don't want these to be null
+ */
+
+ if( !current_token )
+ {
+ current_token = wcsdup(L"");
+ }
+
+ if( !prev_token )
+ {
+ prev_token = wcsdup(L"");
+ }
+
+ if( current_token && prev_token )
+ {
+ if( on_command )
+ {
+ /* Complete command filename */
+ completer.complete_cmd( current_token, use_function, use_builtin, use_command );
+ }
+ else
+ {
+ int do_file=0;
+
wcstring current_command_unescape = current_command;
wcstring prev_token_unescape = prev_token;
wcstring current_token_unescape = current_token;
-
- if( unescape_string( current_command_unescape, 0 ) &&
+
+ if( unescape_string( current_command_unescape, 0 ) &&
unescape_string( prev_token_unescape, 0 ) &&
unescape_string( current_token_unescape, UNESCAPE_INCOMPLETE))
- {
- do_file = completer.complete_param( current_command_unescape,
- prev_token_unescape,
- current_token_unescape,
+ {
+ do_file = completer.complete_param( current_command_unescape,
+ prev_token_unescape,
+ current_token_unescape,
!had_ddash );
- }
-
+ }
+
/*
- If we have found no command specific completions at
- all, fall back to using file completions.
- */
- if( completer.empty() )
- do_file = 1;
-
- /*
- This function wants the unescaped string
- */
- completer.complete_param_expand( current_token, do_file );
- }
- }
- }
-
- free( (void *)current_token );
- free( (void *)prev_token );
-
- comps = completer.get_completions();
+ If we have found no command specific completions at
+ all, fall back to using file completions.
+ */
+ if( completer.empty() )
+ do_file = 1;
+
+ /*
+ This function wants the unescaped string
+ */
+ completer.complete_param_expand( current_token, do_file );
+ }
+ }
+ }
+
+ free( (void *)current_token );
+ free( (void *)prev_token );
+
+ comps = completer.get_completions();
completer.get_commands_to_load(commands_to_load);
}
@@ -1960,25 +1960,25 @@ void complete( const wcstring &cmd, std::vector<completion_t> &comps, complete_t
non-null and longer than 0 characters.
*/
static void append_switch( wcstring &out,
- const wcstring &opt,
- const wcstring &argument )
+ const wcstring &opt,
+ const wcstring &argument )
{
- if( argument.empty() )
- return;
+ if( argument.empty() )
+ return;
wcstring esc = escape_string( argument, 1 );
- append_format( out, L" --%ls %ls", opt.c_str(), esc.c_str() );
+ append_format( out, L" --%ls %ls", opt.c_str(), esc.c_str() );
}
void complete_print( wcstring &out )
{
scoped_lock locker(completion_lock);
scoped_lock locker2(completion_entry_lock);
-
+
// Get a list of all completions in a vector, then sort it by order
std::vector<const completion_entry_t *> all_completions(completion_set.begin(), completion_set.end());
sort(all_completions.begin(), all_completions.end(), compare_completions_by_order);
-
+
for (std::vector<const completion_entry_t *>::const_iterator iter = all_completions.begin(); iter != all_completions.end(); ++iter)
{
const completion_entry_t *e = *iter;
@@ -1986,49 +1986,49 @@ void complete_print( wcstring &out )
for (option_list_t::const_iterator oiter = options.begin(); oiter != options.end(); ++oiter)
{
const complete_entry_opt_t *o = &*oiter;
- const wchar_t *modestr[] =
- {
- L"",
- L" --no-files",
- L" --require-parameter",
- L" --exclusive"
- }
- ;
-
- append_format( out,
- L"complete%ls",
- modestr[o->result_mode] );
-
- append_switch( out,
- e->cmd_is_path ? L"path" : L"command",
- e->cmd );
-
-
- if( o->short_opt != 0 )
- {
- append_format( out,
- L" --short-option '%lc'",
- o->short_opt );
- }
-
-
- append_switch( out,
- o->old_mode?L"old-option":L"long-option",
- o->long_opt );
-
- append_switch( out,
- L"description",
- C_(o->desc.c_str()) );
-
- append_switch( out,
- L"arguments",
- o->comp );
-
- append_switch( out,
- L"condition",
- o->condition );
-
- out.append( L"\n" );
- }
- }
+ const wchar_t *modestr[] =
+ {
+ L"",
+ L" --no-files",
+ L" --require-parameter",
+ L" --exclusive"
+ }
+ ;
+
+ append_format( out,
+ L"complete%ls",
+ modestr[o->result_mode] );
+
+ append_switch( out,
+ e->cmd_is_path ? L"path" : L"command",
+ e->cmd );
+
+
+ if( o->short_opt != 0 )
+ {
+ append_format( out,
+ L" --short-option '%lc'",
+ o->short_opt );
+ }
+
+
+ append_switch( out,
+ o->old_mode?L"old-option":L"long-option",
+ o->long_opt );
+
+ append_switch( out,
+ L"description",
+ C_(o->desc.c_str()) );
+
+ append_switch( out,
+ L"arguments",
+ o->comp );
+
+ append_switch( out,
+ L"condition",
+ o->condition );
+
+ out.append( L"\n" );
+ }
+ }
}
diff --git a/complete.h b/complete.h
index d915a75b..8b72f2fc 100644
--- a/complete.h
+++ b/complete.h
@@ -1,8 +1,8 @@
/** \file complete.h
- Prototypes for functions related to tab-completion.
+ Prototypes for functions related to tab-completion.
- These functions are used for storing and retrieving tab-completion
- data, as well as for performing tab-completion.
+ These functions are used for storing and retrieving tab-completion
+ data, as well as for performing tab-completion.
*/
#ifndef FISH_COMPLETE_H
@@ -17,40 +17,40 @@
#include "util.h"
#include "common.h"
-/**
- Use all completions
+/**
+ Use all completions
*/
#define SHARED 0
-/**
- Do not use file completion
+/**
+ Do not use file completion
*/
#define NO_FILES 1
-/**
- Require a parameter after completion
+/**
+ Require a parameter after completion
*/
#define NO_COMMON 2
-/**
- Only use the argument list specifies with completion after
- option. This is the same as (NO_FILES & NO_COMMON)
+/**
+ Only use the argument list specifies with completion after
+ option. This is the same as (NO_FILES & NO_COMMON)
*/
#define EXCLUSIVE 3
-/**
- Command is a path
+/**
+ Command is a path
*/
#define PATH 1
-/**
- Command is not a path
+/**
+ Command is not a path
*/
#define COMMAND 0
-/**
- Separator between completion and description
+/**
+ Separator between completion and description
*/
#define COMPLETE_SEP L'\004'
-/**
- Separator between completion and description
+/**
+ Separator between completion and description
*/
#define COMPLETE_SEP_STR L"\004"
@@ -75,7 +75,7 @@ enum {
COMPLETE_NO_SPACE = 1 << 0,
/**
- This compeltion is case insensitive.
+ This compeltion is case insensitive.
Warning: The contents of the completion_t structure is actually
different if this flag is set! Specifically, the completion string
@@ -109,42 +109,42 @@ class completion_t
private:
/* No public default constructor */
- completion_t();
+ completion_t();
public:
- /**
- The completion string
- */
- wcstring completion;
+ /**
+ The completion string
+ */
+ wcstring completion;
+
+ /**
+ The description for this completion
+ */
+ wcstring description;
- /**
- The description for this completion
- */
- wcstring description;
+ /**
+ Flags determining the completion behaviour.
- /**
- Flags determining the completion behaviour.
+ Determines whether a space should be inserted after this
+ compeltion if it is the only possible completion using the
+ COMPLETE_NO_SPACE flag.
- Determines whether a space should be inserted after this
- compeltion if it is the only possible completion using the
- COMPLETE_NO_SPACE flag.
+ The COMPLETE_NO_CASE can be used to signal that this completion
+ is case insensitive.
+ */
+ int flags;
- The COMPLETE_NO_CASE can be used to signal that this completion
- is case insensitive.
- */
- int flags;
-
bool is_case_insensitive() const { return !! (flags & COMPLETE_NO_CASE); }
-
+
/* Construction. Note: defining these so that they are not inlined reduces the executable size. */
completion_t(const wcstring &comp, const wcstring &desc = L"", int flags_val = 0);
completion_t(const completion_t &);
completion_t &operator=(const completion_t &);
-
+
/* The following are needed for sorting and uniquing completions */
- bool operator < (const completion_t& rhs) const;
- bool operator == (const completion_t& rhs) const;
- bool operator != (const completion_t& rhs) const;
+ bool operator < (const completion_t& rhs) const;
+ bool operator == (const completion_t& rhs) const;
+ bool operator != (const completion_t& rhs) const;
};
enum complete_type_t {
@@ -160,17 +160,17 @@ void sort_completions( std::vector<completion_t> &completions);
/**
- Add a completion.
+ Add a completion.
All supplied values are copied, they should be freed by or otherwise
disposed by the caller.
- Examples:
-
+ Examples:
+
The command 'gcc -o' requires that a file follows it, so the
NO_COMMON option is suitable. This can be done using the following
line:
-
+
complete -c gcc -s o -r
The command 'grep -d' required that one of the strings 'read',
@@ -187,7 +187,7 @@ void sort_completions( std::vector<completion_t> &completions);
will be interpreted as the command name.
\param short_opt The single character name of an option. (-a is a short option, --all and -funroll are long options)
\param long_opt The multi character name of an option. (-a is a short option, --all and -funroll are long options)
- \param long_mode Whether to use old style, single dash long options.
+ \param long_mode Whether to use old style, single dash long options.
\param result_mode Whether to search further completions when this
completion has been succesfully matched. If result_mode is SHARED,
any other completions may also be used. If result_mode is NO_FILES,
@@ -200,7 +200,7 @@ void sort_completions( std::vector<completion_t> &completions);
\param condition a command to be run to check it this completion should be used. If \c condition is empty, the completion is always used.
\param flags A set of completion flags
*/
-void complete_add( const wchar_t *cmd,
+void complete_add( const wchar_t *cmd,
bool cmd_is_path,
wchar_t short_opt,
const wchar_t *long_opt,
@@ -209,7 +209,7 @@ void complete_add( const wchar_t *cmd,
const wchar_t *condition,
const wchar_t *comp,
const wchar_t *desc,
- int flags );
+ int flags );
/**
Sets whether the completion list for this command is complete. If
true, any options not matching one of the provided options will be
@@ -220,8 +220,8 @@ void complete_set_authoritative( const wchar_t *cmd, bool cmd_type, bool authori
/**
Remove a previously defined completion
*/
-void complete_remove( const wchar_t *cmd,
- bool cmd_is_path,
+void complete_remove( const wchar_t *cmd,
+ bool cmd_is_path,
wchar_t short_opt,
const wchar_t *long_opt );
@@ -230,7 +230,7 @@ void complete_remove( const wchar_t *cmd,
void complete( const wcstring &cmd, std::vector<completion_t> &comp, complete_type_t type, wcstring_list_t *to_load = NULL );
/**
- Print a list of all current completions into the string.
+ Print a list of all current completions into the string.
\param out The string to write completions to
*/
@@ -240,17 +240,17 @@ void complete_print( wcstring &out );
Tests if the specified option is defined for the specified command
*/
int complete_is_valid_option( const wcstring &str,
- const wcstring &opt,
- wcstring_list_t *inErrorsOrNull,
- bool allow_autoload );
+ const wcstring &opt,
+ wcstring_list_t *inErrorsOrNull,
+ bool allow_autoload );
/**
Tests if the specified argument is valid for the specified option
and command
*/
bool complete_is_valid_argument( const wcstring &str,
- const wcstring &opt,
- const wcstring &arg );
+ const wcstring &opt,
+ const wcstring &arg );
/**
diff --git a/configure.ac b/configure.ac
index ddb8a915..e413be09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,25 +51,25 @@ AC_SUBST(XSEL_MAN_PATH)
AC_MSG_CHECKING([if autoconf needs to be run])
if test configure -ot configure.ac; then
- AC_MSG_RESULT([yes])
- if which autoconf >/dev/null; then
- # No need to provide any error messages if autoconf fails, the
- # shell and autconf should take care of that themselves
- AC_MSG_NOTICE([running autoconf])
- if autoconf; then
- ./configure "$@"
- exit
- fi
- exit 1
- else
- AC_MSG_ERROR(
- [cannot find the autoconf program in your path.
+ AC_MSG_RESULT([yes])
+ if which autoconf >/dev/null; then
+ # No need to provide any error messages if autoconf fails, the
+ # shell and autconf should take care of that themselves
+ AC_MSG_NOTICE([running autoconf])
+ if autoconf; then
+ ./configure "$@"
+ exit
+ fi
+ exit 1
+ else
+ AC_MSG_ERROR(
+ [cannot find the autoconf program in your path.
This program needs to be run whenever the configure.ac file is modified.
Please install it and try again.]
- )
- fi
+ )
+ fi
else
- AC_MSG_RESULT([no])
+ AC_MSG_RESULT([no])
fi
@@ -82,19 +82,19 @@ fi
AC_MSG_CHECKING([if autoheader needs to be run])
if test ! -f ./config.h.in -o config.h.in -ot configure.ac; then
- AC_MSG_RESULT([yes])
- if which autoheader >/dev/null; then
- AC_MSG_NOTICE([running autoheader])
- autoheader || exit 1
- else
- AC_MSG_ERROR(
- [cannot find the autoheader program in your path.
+ AC_MSG_RESULT([yes])
+ if which autoheader >/dev/null; then
+ AC_MSG_NOTICE([running autoheader])
+ autoheader || exit 1
+ else
+ AC_MSG_ERROR(
+ [cannot find the autoheader program in your path.
This program needs to be run whenever the configure.ac file is modified.
Please install it and try again.]
- )
- fi
+ )
+ fi
else
- AC_MSG_RESULT([no])
+ AC_MSG_RESULT([no])
fi
@@ -110,30 +110,30 @@ fi
for i in /usr/pkg /sw /opt /opt/local /usr/local; do
- AC_MSG_CHECKING([for $i/include include directory])
- if test -d $i/include; then
- AC_MSG_RESULT(yes)
- CXXFLAGS="$CXXFLAGS -I$i/include/"
- CFLAGS="$CFLAGS -I$i/include/"
- else
- AC_MSG_RESULT(no)
- fi
-
- AC_MSG_CHECKING([for $i/lib library directory])
- if test -d $i/lib; then
- AC_MSG_RESULT(yes)
- LDFLAGS="$LDFLAGS -L$i/lib/ -Wl,-rpath,$i/lib/"
- else
- AC_MSG_RESULT(no)
- fi
-
- AC_MSG_CHECKING([for $i/bin command directory])
- if test -d $i/bin; then
- AC_MSG_RESULT(yes)
- optbindirs="$optbindirs $i/bin"
- else
- AC_MSG_RESULT(no)
- fi
+ AC_MSG_CHECKING([for $i/include include directory])
+ if test -d $i/include; then
+ AC_MSG_RESULT(yes)
+ CXXFLAGS="$CXXFLAGS -I$i/include/"
+ CFLAGS="$CFLAGS -I$i/include/"
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+ AC_MSG_CHECKING([for $i/lib library directory])
+ if test -d $i/lib; then
+ AC_MSG_RESULT(yes)
+ LDFLAGS="$LDFLAGS -L$i/lib/ -Wl,-rpath,$i/lib/"
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+ AC_MSG_CHECKING([for $i/bin command directory])
+ if test -d $i/bin; then
+ AC_MSG_RESULT(yes)
+ optbindirs="$optbindirs $i/bin"
+ else
+ AC_MSG_RESULT(no)
+ fi
done
@@ -176,24 +176,24 @@ AC_CHECK_PROG( SEQ_FALLBACK, seq, [ ], [seq])
if test "$SEQ_FALLBACK"; then
- #
- # We already have seq. Check if the seq version is installed by an
- # earlier fish version. If it is, we'll replace it.
- #
+ #
+ # We already have seq. Check if the seq version is installed by an
+ # earlier fish version. If it is, we'll replace it.
+ #
- file=`which seq`
- if test -f "$file"; then
+ file=`which seq`
+ if test -f "$file"; then
- AC_MSG_CHECKING([if seq comes from a previous fish version])
- shebang=`grep "\(^#!/.*/fish\|^#!/usr/bin/env fish\)" $file`
+ AC_MSG_CHECKING([if seq comes from a previous fish version])
+ shebang=`grep "\(^#!/.*/fish\|^#!/usr/bin/env fish\)" $file`
- if test "$shebang"; then
- SEQ_FALLBACK=seq
- AC_MSG_RESULT(yes, replace it)
- else
- AC_MSG_RESULT(no, keep it)
- fi
- fi
+ if test "$shebang"; then
+ SEQ_FALLBACK=seq
+ AC_MSG_RESULT(yes, replace it)
+ else
+ AC_MSG_RESULT(no, keep it)
+ fi
+ fi
fi
@@ -202,21 +202,21 @@ fi
#
AC_ARG_WITH(
- xsel,
- AC_HELP_STRING(
- [--without-xsel],
- [do not build the xsel program needed for X clipboard integration.
- If build xsel, it will be configured with the same options as fish.]
- ),
- [xsel=$withval],
- [xsel=with_xsel]
+ xsel,
+ AC_HELP_STRING(
+ [--without-xsel],
+ [do not build the xsel program needed for X clipboard integration.
+ If build xsel, it will be configured with the same options as fish.]
+ ),
+ [xsel=$withval],
+ [xsel=with_xsel]
)
if [[ "$xsel" = "with_xsel" ]]; then
- XSEL=xsel-1.2.0
- XSEL_BIN=$XSEL/xsel
- XSEL_MAN=xsel.1x
- XSEL_MAN_PATH=$XSEL/xsel.1x
+ XSEL=xsel-1.2.0
+ XSEL_BIN=$XSEL/xsel
+ XSEL_MAN=xsel.1x
+ XSEL_MAN_PATH=$XSEL/xsel.1x
fi
@@ -225,17 +225,17 @@ fi
#
AC_ARG_WITH(
- gettext,
- AC_HELP_STRING(
- [--without-gettext],
- [do not translate messages, even if gettext is available]
- ),
- [local_gettext=$withval],
- [local_gettext=yes]
+ gettext,
+ AC_HELP_STRING(
+ [--without-gettext],
+ [do not translate messages, even if gettext is available]
+ ),
+ [local_gettext=$withval],
+ [local_gettext=yes]
)
if test x$local_gettext != xno; then
- AC_DEFINE([USE_GETTEXT],[1],[Perform string translations with gettext])
+ AC_DEFINE([USE_GETTEXT],[1],[Perform string translations with gettext])
fi
@@ -254,31 +254,31 @@ CXXFLAGS="$CXXFLAGS -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64"
if test "$GCC" = yes; then
- #
- # -fno-optimize-sibling-calls seems to work around a bug where
- # sending a SIGWINCH to fish on NetBSD 3.0 causes fish to exit when
- # compiled with GCC 3.3.3. This is probably either a compiler bug
- # or a libc bug, but adding this flag seems to fix things for
- # now. Long term, the real problem should be tracked down and
- # truly fixed, at which point we can remove this silly flag. This
- # bug has been verified to not exist on Linux using GCC 3.3.3.
- #
+ #
+ # -fno-optimize-sibling-calls seems to work around a bug where
+ # sending a SIGWINCH to fish on NetBSD 3.0 causes fish to exit when
+ # compiled with GCC 3.3.3. This is probably either a compiler bug
+ # or a libc bug, but adding this flag seems to fix things for
+ # now. Long term, the real problem should be tracked down and
+ # truly fixed, at which point we can remove this silly flag. This
+ # bug has been verified to not exist on Linux using GCC 3.3.3.
+ #
- CXXFLAGS="$CXXFLAGS -fno-optimize-sibling-calls"
+ CXXFLAGS="$CXXFLAGS -fno-optimize-sibling-calls"
- #
- # -Wall is there to keep me on my toes
- #
+ #
+ # -Wall is there to keep me on my toes
+ #
- # Some day...
- CXXFLAGS="$CXXFLAGS -Wall"
+ # Some day...
+ CXXFLAGS="$CXXFLAGS -Wall"
- #
- # This is needed in order to get the really cool backtraces
- #
+ #
+ # This is needed in order to get the really cool backtraces
+ #
- LDFLAGS_FISH="$LDFLAGS_FISH -rdynamic"
+ LDFLAGS_FISH="$LDFLAGS_FISH -rdynamic"
fi
@@ -291,38 +291,38 @@ fi
AC_MSG_CHECKING([if we are compiling against glibc])
AC_RUN_IFELSE(
- [
- AC_LANG_PROGRAM(
- [
- #include <stdlib.h>
- #ifdef __GLIBC__
- #define STATUS 0
- #else
- #define STATUS 1
- #endif
- ],
- [
- return STATUS;
- ]
- )
- ],
- [glibc=yes],
- [glibc=no]
+ [
+ AC_LANG_PROGRAM(
+ [
+ #include <stdlib.h>
+ #ifdef __GLIBC__
+ #define STATUS 0
+ #else
+ #define STATUS 1
+ #endif
+ ],
+ [
+ return STATUS;
+ ]
+ )
+ ],
+ [glibc=yes],
+ [glibc=no]
)
if test "$glibc" = yes; then
- AC_MSG_RESULT(yes)
+ AC_MSG_RESULT(yes)
- #
- # This gives us access to prototypes for gnu extensions and C99
- # functions if we are compiling agains glibc. All GNU extensions
- # that are used must have a fallback implementation available in
- # fallback.h, in order to keep fish working on non-gnu platforms.
- #
+ #
+ # This gives us access to prototypes for gnu extensions and C99
+ # functions if we are compiling agains glibc. All GNU extensions
+ # that are used must have a fallback implementation available in
+ # fallback.h, in order to keep fish working on non-gnu platforms.
+ #
- CFLAGS="$CFLAGS -D_GNU_SOURCE=1 -D_ISO99_SOURCE=1"
+ CFLAGS="$CFLAGS -D_GNU_SOURCE=1 -D_ISO99_SOURCE=1"
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT(no)
fi
@@ -340,7 +340,7 @@ fi
AC_CANONICAL_TARGET
if test $target_cpu = powerpc; then
- AC_DEFINE([TPUTS_KLUDGE],[1],[Evil kludge to get Power based machines to work])
+ AC_DEFINE([TPUTS_KLUDGE],[1],[Evil kludge to get Power based machines to work])
fi
@@ -350,38 +350,38 @@ fi
AC_MSG_CHECKING([if we are under Solaris])
case $target_os in
- solaris*)
- AC_DEFINE( __EXTENSIONS__, 1, [Macro to enable additional prototypes under Solaris])
- AC_MSG_RESULT(yes)
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
+ solaris*)
+ AC_DEFINE( __EXTENSIONS__, 1, [Macro to enable additional prototypes under Solaris])
+ AC_MSG_RESULT(yes)
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
esac
# Check for Solaris curses tputs having fixed length parameter list.
AC_MSG_CHECKING([if we are using non varargs tparm.])
AC_COMPILE_IFELSE(
- [
- AC_LANG_PROGRAM(
- [
- #include <curses.h>
- #include <term.h>
- ],
- [
- tparm( "" );
- ]
- )
- ],
- [tparm_solaris_kludge=no],
- [tparm_solaris_kludge=yes]
+ [
+ AC_LANG_PROGRAM(
+ [
+ #include <curses.h>
+ #include <term.h>
+ ],
+ [
+ tparm( "" );
+ ]
+ )
+ ],
+ [tparm_solaris_kludge=no],
+ [tparm_solaris_kludge=yes]
)
if test "x$tparm_solaris_kludge" = "xyes"; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [TPARM_SOLARIS_KLUDGE],
- [1],
- [Define to 1 if tparm accepts a fixed amount of paramters.]
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(
+ [TPARM_SOLARIS_KLUDGE],
+ [1],
+ [Define to 1 if tparm accepts a fixed amount of paramters.]
)
else
AC_MSG_RESULT(no)
@@ -394,14 +394,14 @@ fi
AC_MSG_CHECKING([if we are under BSD])
case $target_os in
- *bsd*)
- AC_DEFINE( __BSD_VISIBLE, 1, [Macro to enable additional prototypes under BSD])
- AC_DEFINE( _NETBSD_SOURCE, 1, [Macro to enable additional prototypes under BSD])
- AC_MSG_RESULT(yes)
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
+ *bsd*)
+ AC_DEFINE( __BSD_VISIBLE, 1, [Macro to enable additional prototypes under BSD])
+ AC_DEFINE( _NETBSD_SOURCE, 1, [Macro to enable additional prototypes under BSD])
+ AC_MSG_RESULT(yes)
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
esac
@@ -413,7 +413,7 @@ esac
#
if [[ "$prefix" = NONE ]]; then
- prefix=/usr/local
+ prefix=/usr/local
fi
@@ -425,9 +425,9 @@ fi
AC_ARG_VAR( [docdir], [Documentation direcotry] )
if test -z $docdir; then
- docdir=$datadir/doc/fish
+ docdir=$datadir/doc/fish
else
- docdir=$docdir
+ docdir=$docdir
fi
@@ -453,9 +453,9 @@ AC_CHECK_FILES([/proc/self/stat])
#
AC_DEFINE(
- [HAVE_TRANSLATE_H],
- [1],
- [Define to 1 if the wgettext function should be used for translating strings.]
+ [HAVE_TRANSLATE_H],
+ [1],
+ [Define to 1 if the wgettext function should be used for translating strings.]
)
@@ -484,7 +484,7 @@ LIBS=$LIBS_COMMON
LIBS_COMMON=$LIBS
LIBS="$LIBS_SHARED"
if test x$local_gettext != xno; then
- AC_SEARCH_LIBS( gettext, intl,,)
+ AC_SEARCH_LIBS( gettext, intl,,)
fi
# Check for libiconv_open if we can't find iconv_open. Silly OS X does
@@ -501,7 +501,7 @@ LIBS=$LIBS_COMMON
LIBS_COMMON=$LIBS
LIBS="$LIBS_SHARED"
if test x$local_gettext != xno; then
- AC_SEARCH_LIBS( gettext, intl,,)
+ AC_SEARCH_LIBS( gettext, intl,,)
fi
LIBS_FISH_INDENT=$LIBS
LIBS=$LIBS_COMMON
@@ -513,7 +513,7 @@ LIBS=$LIBS_COMMON
LIBS_COMMON=$LIBS
LIBS="$LIBS_SHARED"
if test x$local_gettext != xno; then
- AC_SEARCH_LIBS( gettext, intl,,)
+ AC_SEARCH_LIBS( gettext, intl,,)
fi
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_SEARCH_LIBS( libiconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )] )
LIBS_FISH_PAGER=$LIBS
@@ -526,7 +526,7 @@ LIBS=$LIBS_COMMON
LIBS_COMMON=$LIBS
LIBS="$LIBS_SHARED"
if test x$local_gettext != xno; then
- AC_SEARCH_LIBS( gettext, intl,,)
+ AC_SEARCH_LIBS( gettext, intl,,)
fi
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_SEARCH_LIBS( libiconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )] )
LIBS_FISHD=$LIBS
@@ -539,7 +539,7 @@ LIBS=$LIBS_COMMON
LIBS_COMMON=$LIBS
LIBS="$LIBS_SHARED"
if test x$local_gettext != xno; then
- AC_SEARCH_LIBS( gettext, intl,,)
+ AC_SEARCH_LIBS( gettext, intl,,)
fi
LIBS_MIMEDB=$LIBS
LIBS=$LIBS_COMMON
@@ -552,7 +552,7 @@ LIBS=$LIBS_COMMON
LIBS_COMMON=$LIBS
LIBS="$LIBS_SHARED"
if test x$local_gettext != xno; then
- AC_SEARCH_LIBS( gettext, intl,,)
+ AC_SEARCH_LIBS( gettext, intl,,)
fi
LIBS_SET_COLOR=$LIBS
LIBS=$LIBS_COMMON
@@ -564,15 +564,15 @@ LIBS=$LIBS_COMMON
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h ncurses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h sys/termios.h libintl.h execinfo.h spawn.h])
AC_CHECK_HEADER(
- [regex.h],
- [
- AC_DEFINE(
- [HAVE_REGEX_H],
- [1],
- [Define to 1 if you have the <regex.h> header file.]
- )
- ],
- [AC_MSG_ERROR([Could not find the header regex.h, needed to build fish])]
+ [regex.h],
+ [
+ AC_DEFINE(
+ [HAVE_REGEX_H],
+ [1],
+ [Define to 1 if you have the <regex.h> header file.]
+ )
+ ],
+ [AC_MSG_ERROR([Could not find the header regex.h, needed to build fish])]
)
@@ -612,78 +612,78 @@ local_found_posix_switch=no
for i in "" "-D_POSIX_C_SOURCE=200112L" "-D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L"; do
- AC_MSG_CHECKING( if switches \"$i\" works)
- CFLAGS="$XCFLAGS $i"
-
- #
- # Try to run this program, which should test various extensions
- # and Posix functionality. If this program works, then everything
- # should work. Hopefully.
- #
-
- AC_TRY_LINK(
- [
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
-
- /* POSIX, C89 and C99: POSIX extends this header.
- * For: kill(), killpg(), siginfo_t, sigset_t,
- * struct sigaction, sigemptyset(), sigaction(),
- * SIGIO and SIGWINCH. */
- #include <signal.h>
-
- #ifdef HAVE_SIGINFO_H
- /* Neither POSIX, C89 nor C99: Solaris-specific (others?).
- * For: siginfo_t (also defined by signal.h when in
- * POSIX/extensions mode). */
- #include <siginfo.h>
- #endif
-
- #ifdef HAVE_SYS_TERMIOS_H
- /* Neither POSIX, C89 nor C99: a common extension.
- * For: TIOCGWINSZ and struct winsize (under at least
- * Solaris, NetBSD and (dual-listed) FreeBSD). */
- #include <sys/termios.h>
- #endif
-
- #ifdef HAVE_SYS_IOCTL_H
- /* As above (under at least Linux and FreeBSD). */
- #include <sys/ioctl.h>
- #endif
- ],
- [
- /* Avert high-level optimisation, by making the program's
- * return value depend on all tested identifiers. */
- long ret = 0;
- /* POSIX only: might be unhidden by _POSIX_C_SOURCE. */
- struct sigaction sa;
- sigset_t ss;
- siginfo_t info;
- ret += (long)(void *)&info + kill( 0, 0 ) +
- sigaction( 0, &sa, 0 ) + sigemptyset( &ss );
- /* Extended-POSIX: might be unhidden by _XOPEN_SOURCE. */
- ret += killpg( 0, 0 );
- /* Non-standard: might be hidden by the macros. */
- {
- struct winsize termsize;
- ret += (long)(void *)&termsize;
- ret += SIGWINCH + TIOCGWINSZ + SIGIO;
- }
- return ret;
-
- ],
- local_cv_use__posix_c_source=yes,
- local_cv_use__posix_c_source=no,
- )
-
- if test x$local_cv_use__posix_c_source = xyes; then
- AC_MSG_RESULT( yes )
- local_found_posix_switch=yes
- break;
- else
- AC_MSG_RESULT( no )
- fi
+ AC_MSG_CHECKING( if switches \"$i\" works)
+ CFLAGS="$XCFLAGS $i"
+
+ #
+ # Try to run this program, which should test various extensions
+ # and Posix functionality. If this program works, then everything
+ # should work. Hopefully.
+ #
+
+ AC_TRY_LINK(
+ [
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <sys/types.h>
+
+ /* POSIX, C89 and C99: POSIX extends this header.
+ * For: kill(), killpg(), siginfo_t, sigset_t,
+ * struct sigaction, sigemptyset(), sigaction(),
+ * SIGIO and SIGWINCH. */
+ #include <signal.h>
+
+ #ifdef HAVE_SIGINFO_H
+ /* Neither POSIX, C89 nor C99: Solaris-specific (others?).
+ * For: siginfo_t (also defined by signal.h when in
+ * POSIX/extensions mode). */
+ #include <siginfo.h>
+ #endif
+
+ #ifdef HAVE_SYS_TERMIOS_H
+ /* Neither POSIX, C89 nor C99: a common extension.
+ * For: TIOCGWINSZ and struct winsize (under at least
+ * Solaris, NetBSD and (dual-listed) FreeBSD). */
+ #include <sys/termios.h>
+ #endif
+
+ #ifdef HAVE_SYS_IOCTL_H
+ /* As above (under at least Linux and FreeBSD). */
+ #include <sys/ioctl.h>
+ #endif
+ ],
+ [
+ /* Avert high-level optimisation, by making the program's
+ * return value depend on all tested identifiers. */
+ long ret = 0;
+ /* POSIX only: might be unhidden by _POSIX_C_SOURCE. */
+ struct sigaction sa;
+ sigset_t ss;
+ siginfo_t info;
+ ret += (long)(void *)&info + kill( 0, 0 ) +
+ sigaction( 0, &sa, 0 ) + sigemptyset( &ss );
+ /* Extended-POSIX: might be unhidden by _XOPEN_SOURCE. */
+ ret += killpg( 0, 0 );
+ /* Non-standard: might be hidden by the macros. */
+ {
+ struct winsize termsize;
+ ret += (long)(void *)&termsize;
+ ret += SIGWINCH + TIOCGWINSZ + SIGIO;
+ }
+ return ret;
+
+ ],
+ local_cv_use__posix_c_source=yes,
+ local_cv_use__posix_c_source=no,
+ )
+
+ if test x$local_cv_use__posix_c_source = xyes; then
+ AC_MSG_RESULT( yes )
+ local_found_posix_switch=yes
+ break;
+ else
+ AC_MSG_RESULT( no )
+ fi
done
@@ -694,7 +694,7 @@ done
#
if test ! x$local_found_posix_switch = xyes; then
- CFLAGS="$XCFLAGS"
+ CFLAGS="$XCFLAGS"
fi
@@ -713,7 +713,7 @@ AC_CHECK_FUNCS( dcgettext backtrace backtrace_symbols sysconf )
#
if test x$local_gettext != xno; then
- AC_CHECK_FUNC( gettext, HAVE_GETTEXT=1, HAVE_GETTEXT=0 )
+ AC_CHECK_FUNC( gettext, HAVE_GETTEXT=1, HAVE_GETTEXT=0 )
fi
#
@@ -728,35 +728,35 @@ fi
AC_MSG_CHECKING([if realpath accepts null for its second argument])
AC_RUN_IFELSE(
- [
- AC_LANG_PROGRAM(
- [
- #include <limits.h>
- #include <errno.h>
- #include <stdlib.h>
- ],
- [
- int status;
- char *res;
- res = realpath( "somefile", 0 );
- status = !(res != 0 || errno == ENOENT);
- exit( status );
- ]
- )
- ],
- [have_realpath_null=yes],
- [have_realpath_null=no]
+ [
+ AC_LANG_PROGRAM(
+ [
+ #include <limits.h>
+ #include <errno.h>
+ #include <stdlib.h>
+ ],
+ [
+ int status;
+ char *res;
+ res = realpath( "somefile", 0 );
+ status = !(res != 0 || errno == ENOENT);
+ exit( status );
+ ]
+ )
+ ],
+ [have_realpath_null=yes],
+ [have_realpath_null=no]
)
if test "$have_realpath_null" = yes; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [HAVE_REALPATH_NULL],
- [1],
- [Define to 1 if realpath accepts null for its second argument.]
- )
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(
+ [HAVE_REALPATH_NULL],
+ [1],
+ [Define to 1 if realpath accepts null for its second argument.]
+ )
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT(no)
fi
@@ -766,30 +766,30 @@ fi
AC_MSG_CHECKING([if struct winsize and TIOCGWINSZ exist])
AC_LINK_IFELSE(
- [
- AC_LANG_PROGRAM(
- [
- #ifdef HAVE_SYS_TERMIOS_H
- #include <sys/termios.h>
- #endif
-
- #ifdef HAVE_SYS_IOCTL_H
- #include <sys/ioctl.h>
- #endif
- ],
- [
- struct winsize termsize = {0};
- TIOCGWINSZ;
- ]
- )
- ],
- [
- AC_MSG_RESULT(yes);
- AC_DEFINE([HAVE_WINSIZE], [1], [Define to 1 if the winsize struct and TIOCGWINSZ macro exist])
- ],
- [
- AC_MSG_RESULT(no)
- ]
+ [
+ AC_LANG_PROGRAM(
+ [
+ #ifdef HAVE_SYS_TERMIOS_H
+ #include <sys/termios.h>
+ #endif
+
+ #ifdef HAVE_SYS_IOCTL_H
+ #include <sys/ioctl.h>
+ #endif
+ ],
+ [
+ struct winsize termsize = {0};
+ TIOCGWINSZ;
+ ]
+ )
+ ],
+ [
+ AC_MSG_RESULT(yes);
+ AC_DEFINE([HAVE_WINSIZE], [1], [Define to 1 if the winsize struct and TIOCGWINSZ macro exist])
+ ],
+ [
+ AC_MSG_RESULT(no)
+ ]
)
@@ -800,30 +800,30 @@ AC_LINK_IFELSE(
if test "$ac_cv_func_fwprintf" = yes; then
- AC_MSG_CHECKING([if fwprintf is broken])
- AC_RUN_IFELSE(
- [
- AC_LANG_PROGRAM(
- [
- #include <stdlib.h>
- #include <stdio.h>
- #include <locale.h>
- #include <wchar.h>
- ],
- [
- setlocale( LC_ALL, "" );
- fwprintf( stderr, L"%ls%ls", L"", L"fish:" );
- ]
- )
- ],
- [
- AC_MSG_RESULT(no)
- ],
- [
- AC_MSG_RESULT([yes])
- AC_DEFINE([HAVE_BROKEN_FWPRINTF], [1], [Define to 1 one if the implemented fwprintf is broken])
- ]
- )
+ AC_MSG_CHECKING([if fwprintf is broken])
+ AC_RUN_IFELSE(
+ [
+ AC_LANG_PROGRAM(
+ [
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <locale.h>
+ #include <wchar.h>
+ ],
+ [
+ setlocale( LC_ALL, "" );
+ fwprintf( stderr, L"%ls%ls", L"", L"fish:" );
+ ]
+ )
+ ],
+ [
+ AC_MSG_RESULT(no)
+ ],
+ [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_BROKEN_FWPRINTF], [1], [Define to 1 one if the implemented fwprintf is broken])
+ ]
+ )
fi
@@ -831,89 +831,89 @@ fi
# Check for _nl_msg_cat_cntr symbol
AC_MSG_CHECKING([for _nl_msg_cat_cntr symbol])
AC_TRY_LINK(
- [
- #if HAVE_LIBINTL_H
- #include <libintl.h>
- #endif
- ],
- [
- extern int _nl_msg_cat_cntr;
- int tmp = _nl_msg_cat_cntr;
- exit(tmp);
- ],
- have__nl_msg_cat_cntr=yes,
- have__nl_msg_cat_cntr=no
+ [
+ #if HAVE_LIBINTL_H
+ #include <libintl.h>
+ #endif
+ ],
+ [
+ extern int _nl_msg_cat_cntr;
+ int tmp = _nl_msg_cat_cntr;
+ exit(tmp);
+ ],
+ have__nl_msg_cat_cntr=yes,
+ have__nl_msg_cat_cntr=no
)
if test "$have__nl_msg_cat_cntr" = yes; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [HAVE__NL_MSG_CAT_CNTR],
- [1],
- [Define to 1 if the _nl_msg_cat_cntr symbol is exported.]
- )
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(
+ [HAVE__NL_MSG_CAT_CNTR],
+ [1],
+ [Define to 1 if the _nl_msg_cat_cntr symbol is exported.]
+ )
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT(no)
fi
# Check for __environ symbol
AC_MSG_CHECKING([for __environ symbol])
AC_TRY_LINK(
- [
- #include <unistd.h>
- ],
- [
- extern char **__environ;
- char **tmp = __environ;
- exit(tmp!=0);
- ],
- have___environ=yes,
- have___environ=no
+ [
+ #include <unistd.h>
+ ],
+ [
+ extern char **__environ;
+ char **tmp = __environ;
+ exit(tmp!=0);
+ ],
+ have___environ=yes,
+ have___environ=no
)
if test "$have___environ" = yes; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [HAVE___ENVIRON],
- [1],
- [Define to 1 if the __environ symbol is exported.]
- )
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(
+ [HAVE___ENVIRON],
+ [1],
+ [Define to 1 if the __environ symbol is exported.]
+ )
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT(no)
fi
# Check if getopt_long exists and works
AC_MSG_CHECKING([if getopt_long exists and works])
AC_TRY_LINK(
- [
- #if HAVE_GETOPT_H
- #include <getopt.h>
- #endif
- ],
- [
- static struct option
- long_options[] =
- {
- 0, 0, 0, 0
- }
- ;
- int opt = getopt_long( 0,
- 0,
- 0,
- long_options,
- 0 );
-
- ],
- have_working_getopt_long=yes,
- have_working_getopt_long=no
+ [
+ #if HAVE_GETOPT_H
+ #include <getopt.h>
+ #endif
+ ],
+ [
+ static struct option
+ long_options[] =
+ {
+ 0, 0, 0, 0
+ }
+ ;
+ int opt = getopt_long( 0,
+ 0,
+ 0,
+ long_options,
+ 0 );
+
+ ],
+ have_working_getopt_long=yes,
+ have_working_getopt_long=no
)
if test "$have_working_getopt_long" = yes; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [HAVE_WORKING_GETOPT_LONG],
- [1],
- [Define to 1 if getopt_long exists and works.]
- )
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(
+ [HAVE_WORKING_GETOPT_LONG],
+ [1],
+ [Define to 1 if getopt_long exists and works.]
+ )
else
- AC_MSG_RESULT(no)
+ AC_MSG_RESULT(no)
fi
# Check if del_curterm is broken - in that case we redefine
@@ -921,17 +921,17 @@ fi
AC_MSG_CHECKING([If del_curterm is broken])
case $target_os in
- *bsd*)
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [HAVE_BROKEN_DEL_CURTERM],
- [1],
- [del_curterm is broken, redefine it to a no-op to avoid a double-free bug]
- )
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
+ *bsd*)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(
+ [HAVE_BROKEN_DEL_CURTERM],
+ [1],
+ [del_curterm is broken, redefine it to a no-op to avoid a double-free bug]
+ )
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
esac
# Tell the world what we know
@@ -939,15 +939,15 @@ AC_CONFIG_FILES([Makefile fish.spec Doxyfile.help seq])
AC_OUTPUT
if test ! x$local_found_posix_switch = xyes; then
- echo "Can't find a combination of switches to enable common extensions like detecting window size."
- echo "Some fish features may be disabled."
+ echo "Can't find a combination of switches to enable common extensions like detecting window size."
+ echo "Some fish features may be disabled."
fi
if [[ "$xsel" = "with_xsel" ]]; then
- echo "Now configure xsel with $conf_arg"
- rm -rf $XSEL
- tar xf $XSEL.tar.gz
- cd $XSEL && ./configure $conf_arg
+ echo "Now configure xsel with $conf_arg"
+ rm -rf $XSEL
+ tar xf $XSEL.tar.gz
+ cd $XSEL && ./configure $conf_arg
fi
echo "fish is now configured."
echo "Use 'make' and 'make install' to build and install fish."
diff --git a/env.cpp b/env.cpp
index 50cfbc6c..f6b097ce 100644
--- a/env.cpp
+++ b/env.cpp
@@ -1,5 +1,5 @@
/** \file env.c
- Functions for setting and getting environment variables.
+ Functions for setting and getting environment variables.
*/
#include "config.h"
@@ -92,10 +92,10 @@ extern char **__environ;
*/
struct var_entry_t
{
- bool exportv; /**< Whether the variable should be exported */
- wcstring val; /**< The value of the variable */
+ bool exportv; /**< Whether the variable should be exported */
+ wcstring val; /**< The value of the variable */
- var_entry_t() : exportv(false) { }
+ var_entry_t() : exportv(false) { }
};
typedef std::map<wcstring, var_entry_t*> var_table_t;
@@ -109,29 +109,29 @@ bool g_use_posix_spawn = false; //will usually be set to true
*/
struct env_node_t
{
- /**
- Variable table
- */
- var_table_t env;
- /**
- Does this node imply a new variable scope? If yes, all
- non-global variables below this one in the stack are
- invisible. If new_scope is set for the global variable node,
- the universe will explode.
- */
- int new_scope;
- /**
- Does this node contain any variables which are exported to subshells
- */
- int exportv;
-
- /**
- Pointer to next level
- */
- struct env_node_t *next;
-
-
- env_node_t() : new_scope(0), exportv(0), next(NULL) { }
+ /**
+ Variable table
+ */
+ var_table_t env;
+ /**
+ Does this node imply a new variable scope? If yes, all
+ non-global variables below this one in the stack are
+ invisible. If new_scope is set for the global variable node,
+ the universe will explode.
+ */
+ int new_scope;
+ /**
+ Does this node contain any variables which are exported to subshells
+ */
+ int exportv;
+
+ /**
+ Pointer to next level
+ */
+ struct env_node_t *next;
+
+
+ env_node_t() : new_scope(0), exportv(0), next(NULL) { }
};
class variable_entry_t {
@@ -216,15 +216,15 @@ static int get_names_show_unexported;
*/
static const wchar_t * const locale_variable[] =
{
- L"LANG",
- L"LC_ALL",
- L"LC_COLLATE",
- L"LC_CTYPE",
- L"LC_MESSAGES",
- L"LC_MONETARY",
- L"LC_NUMERIC",
- L"LC_TIME",
- NULL
+ L"LANG",
+ L"LC_ALL",
+ L"LC_COLLATE",
+ L"LC_CTYPE",
+ L"LC_MESSAGES",
+ L"LC_MONETARY",
+ L"LC_NUMERIC",
+ L"LC_TIME",
+ NULL
};
@@ -237,18 +237,18 @@ static const wchar_t * const locale_variable[] =
*/
static void start_fishd()
{
- struct passwd *pw = getpwuid(getuid());
-
- debug( 3, L"Spawning new copy of fishd" );
-
- if( !pw )
- {
- debug( 0, _( L"Could not get user information" ) );
- return;
- }
-
+ struct passwd *pw = getpwuid(getuid());
+
+ debug( 3, L"Spawning new copy of fishd" );
+
+ if( !pw )
+ {
+ debug( 0, _( L"Could not get user information" ) );
+ return;
+ }
+
wcstring cmd = format_string(FISHD_CMD, pw->pw_name);
-
+
/* Prefer the fishd in __fish_bin_dir, if exists */
const env_var_t bin_dir = env_get_string(L"__fish_bin_dir");
if (! bin_dir.missing_or_empty())
@@ -260,9 +260,9 @@ static void start_fishd()
cmd.insert(0, bin_dir + L"/");
}
}
-
+
parser_t &parser = parser_t::principal_parser();
- parser.eval( cmd, io_chain_t(), TOP );
+ parser.eval( cmd, io_chain_t(), TOP );
}
/**
@@ -270,20 +270,20 @@ static void start_fishd()
*/
static mode_t get_umask()
{
- mode_t res;
- res = umask( 0 );
- umask( res );
- return res;
+ mode_t res;
+ res = umask( 0 );
+ umask( res );
+ return res;
}
/** Checks if the specified variable is a locale variable */
static bool var_is_locale(const wcstring &key) {
- for (size_t i=0; locale_variable[i]; i++) {
- if (key == locale_variable[i]) {
- return true;
- }
- }
- return false;
+ for (size_t i=0; locale_variable[i]; i++) {
+ if (key == locale_variable[i]) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -291,71 +291,71 @@ static bool var_is_locale(const wcstring &key) {
*/
static void handle_locale()
{
- const env_var_t lc_all = env_get_string( L"LC_ALL" );
- int i;
+ const env_var_t lc_all = env_get_string( L"LC_ALL" );
+ int i;
const wcstring old_locale = wsetlocale( LC_MESSAGES, NULL );
- /*
- Array of locale constants corresponding to the local variable names defined in locale_variable
- */
- static const int cat[] =
- {
- 0,
- LC_ALL,
- LC_COLLATE,
- LC_CTYPE,
- LC_MESSAGES,
- LC_MONETARY,
- LC_NUMERIC,
- LC_TIME
- }
- ;
-
- if( !lc_all.missing() )
- {
- wsetlocale( LC_ALL, lc_all.c_str() );
- }
- else
- {
- const env_var_t lang = env_get_string( L"LANG" );
- if( !lang.missing() )
- {
- wsetlocale( LC_ALL, lang.c_str() );
- }
-
- for( i=2; locale_variable[i]; i++ )
- {
- const env_var_t val = env_get_string( locale_variable[i] );
-
- if( !val.missing() )
- {
- wsetlocale( cat[i], val.c_str() );
- }
- }
- }
-
+ /*
+ Array of locale constants corresponding to the local variable names defined in locale_variable
+ */
+ static const int cat[] =
+ {
+ 0,
+ LC_ALL,
+ LC_COLLATE,
+ LC_CTYPE,
+ LC_MESSAGES,
+ LC_MONETARY,
+ LC_NUMERIC,
+ LC_TIME
+ }
+ ;
+
+ if( !lc_all.missing() )
+ {
+ wsetlocale( LC_ALL, lc_all.c_str() );
+ }
+ else
+ {
+ const env_var_t lang = env_get_string( L"LANG" );
+ if( !lang.missing() )
+ {
+ wsetlocale( LC_ALL, lang.c_str() );
+ }
+
+ for( i=2; locale_variable[i]; i++ )
+ {
+ const env_var_t val = env_get_string( locale_variable[i] );
+
+ if( !val.missing() )
+ {
+ wsetlocale( cat[i], val.c_str() );
+ }
+ }
+ }
+
const wcstring new_locale = wsetlocale(LC_MESSAGES, NULL);
- if( old_locale != new_locale )
- {
-
- /*
- Try to make change known to gettext. Both changing
- _nl_msg_cat_cntr and calling dcgettext might potentially
- tell some gettext implementation that the translation
- strings should be reloaded. We do both and hope for the
- best.
- */
-
- extern int _nl_msg_cat_cntr;
- _nl_msg_cat_cntr++;
-
- dcgettext( "fish", "Changing language to English", LC_MESSAGES );
-
- if( get_is_interactive() )
- {
- debug( 0, _(L"Changing language to English") );
- }
- }
+ if( old_locale != new_locale )
+ {
+
+ /*
+ Try to make change known to gettext. Both changing
+ _nl_msg_cat_cntr and calling dcgettext might potentially
+ tell some gettext implementation that the translation
+ strings should be reloaded. We do both and hope for the
+ best.
+ */
+
+ extern int _nl_msg_cat_cntr;
+ _nl_msg_cat_cntr++;
+
+ dcgettext( "fish", "Changing language to English", LC_MESSAGES );
+
+ if( get_is_interactive() )
+ {
+ debug( 0, _(L"Changing language to English") );
+ }
+ }
}
@@ -376,43 +376,43 @@ static void react_to_variable_change(const wcstring &key) {
proper events are triggered when an event occurs.
*/
static void universal_callback( fish_message_type_t type,
- const wchar_t *name,
- const wchar_t *val )
+ const wchar_t *name,
+ const wchar_t *val )
{
- const wchar_t *str=0;
-
- switch( type )
- {
- case SET:
- case SET_EXPORT:
- {
- str=L"SET";
- break;
- }
-
- case ERASE:
- {
- str=L"ERASE";
- break;
- }
-
- default:
- break;
- }
-
- if( str )
- {
- mark_changed_exported();
-
+ const wchar_t *str=0;
+
+ switch( type )
+ {
+ case SET:
+ case SET_EXPORT:
+ {
+ str=L"SET";
+ break;
+ }
+
+ case ERASE:
+ {
+ str=L"ERASE";
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if( str )
+ {
+ mark_changed_exported();
+
event_t ev = event_t::variable_event(name);
ev.arguments.reset(new wcstring_list_t());
ev.arguments->push_back(L"VARIABLE");
ev.arguments->push_back(str);
ev.arguments->push_back(name);
- event_fire( &ev );
+ event_fire( &ev );
ev.arguments.reset(NULL);
- }
-
+ }
+
if (name)
react_to_variable_change(name);
}
@@ -421,82 +421,82 @@ static void universal_callback( fish_message_type_t type,
Make sure the PATH variable contains the essential directories
*/
static void setup_path()
-{
+{
size_t i;
- int j;
- wcstring_list_t lst;
-
- const wchar_t *path_el[] =
+ int j;
+ wcstring_list_t lst;
+
+ const wchar_t *path_el[] =
{
L"/bin",
L"/usr/bin",
PREFIX L"/bin",
0
}
- ;
-
- env_var_t path = env_get_string( L"PATH" );
-
- if( !path.missing() )
- {
- tokenize_variable_array( path, lst );
- }
-
- for( j=0; path_el[j]; j++ )
- {
-
- int has_el=0;
-
- for( i=0; i<lst.size(); i++ )
- {
- wcstring el = lst.at(i);
- size_t len = el.size();
-
- while( (len > 0) && (el[len-1]==L'/') )
- {
- len--;
- }
-
- if( (wcslen( path_el[j] ) == len) &&
+ ;
+
+ env_var_t path = env_get_string( L"PATH" );
+
+ if( !path.missing() )
+ {
+ tokenize_variable_array( path, lst );
+ }
+
+ for( j=0; path_el[j]; j++ )
+ {
+
+ int has_el=0;
+
+ for( i=0; i<lst.size(); i++ )
+ {
+ wcstring el = lst.at(i);
+ size_t len = el.size();
+
+ while( (len > 0) && (el[len-1]==L'/') )
+ {
+ len--;
+ }
+
+ if( (wcslen( path_el[j] ) == len) &&
(wcsncmp( el.c_str(), path_el[j], len)==0) )
- {
- has_el = 1;
- }
- }
-
- if( !has_el )
- {
- wcstring buffer;
-
- debug( 3, L"directory %ls was missing", path_el[j] );
-
- if( !path.missing() )
- {
+ {
+ has_el = 1;
+ }
+ }
+
+ if( !has_el )
+ {
+ wcstring buffer;
+
+ debug( 3, L"directory %ls was missing", path_el[j] );
+
+ if( !path.missing() )
+ {
buffer += path;
- }
-
+ }
+
buffer += ARRAY_SEP_STR;
buffer += path_el[j];
-
- env_set( L"PATH", buffer.empty()?NULL:buffer.c_str(), ENV_GLOBAL | ENV_EXPORT );
-
- path = env_get_string( L"PATH" );
+
+ env_set( L"PATH", buffer.empty()?NULL:buffer.c_str(), ENV_GLOBAL | ENV_EXPORT );
+
+ path = env_get_string( L"PATH" );
lst.resize(0);
- tokenize_variable_array( path, lst );
- }
- }
+ tokenize_variable_array( path, lst );
+ }
+ }
}
int env_set_pwd()
{
- wchar_t dir_path[4096];
- wchar_t *res = wgetcwd( dir_path, 4096 );
- if( !res )
- {
- return 0;
- }
- env_set( L"PWD", dir_path, ENV_EXPORT | ENV_GLOBAL );
- return 1;
+ wchar_t dir_path[4096];
+ wchar_t *res = wgetcwd( dir_path, 4096 );
+ if( !res )
+ {
+ return 0;
+ }
+ env_set( L"PWD", dir_path, ENV_EXPORT | ENV_GLOBAL );
+ return 1;
}
/**
@@ -505,27 +505,27 @@ int env_set_pwd()
static void env_set_defaults()
{
- if( env_get_string(L"USER").missing() )
- {
- struct passwd *pw = getpwuid( getuid());
- wchar_t *unam = str2wcs( pw->pw_name );
- env_set( L"USER", unam, ENV_GLOBAL );
- free( unam );
- }
-
- if( env_get_string(L"HOME").missing() )
- {
- const env_var_t unam = env_get_string( L"USER" );
- char *unam_narrow = wcs2str( unam.c_str() );
- struct passwd *pw = getpwnam( unam_narrow );
- wchar_t *dir = str2wcs( pw->pw_dir );
- env_set( L"HOME", dir, ENV_GLOBAL );
- free( dir );
- free( unam_narrow );
- }
-
- env_set_pwd();
-
+ if( env_get_string(L"USER").missing() )
+ {
+ struct passwd *pw = getpwuid( getuid());
+ wchar_t *unam = str2wcs( pw->pw_name );
+ env_set( L"USER", unam, ENV_GLOBAL );
+ free( unam );
+ }
+
+ if( env_get_string(L"HOME").missing() )
+ {
+ const env_var_t unam = env_get_string( L"USER" );
+ char *unam_narrow = wcs2str( unam.c_str() );
+ struct passwd *pw = getpwnam( unam_narrow );
+ wchar_t *dir = str2wcs( pw->pw_dir );
+ env_set( L"HOME", dir, ENV_GLOBAL );
+ free( dir );
+ free( unam_narrow );
+ }
+
+ env_set_pwd();
+
}
// Some variables should not be arrays. This used to be handled by a startup script, but we'd like to get down to 0 forks for startup, so handle it here.
@@ -539,15 +539,15 @@ static bool variable_can_be_array(const wchar_t *key) {
void env_init(const struct config_paths_t *paths /* or NULL */)
{
- char **p;
- struct passwd *pw;
- wchar_t *uname;
- wchar_t *version;
-
- /*
- env_read_only variables can not be altered directly by the user
- */
-
+ char **p;
+ struct passwd *pw;
+ wchar_t *uname;
+ wchar_t *version;
+
+ /*
+ env_read_only variables can not be altered directly by the user
+ */
+
const wchar_t * const ro_keys[] = {
L"status",
L"history",
@@ -562,58 +562,58 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) {
env_read_only.insert(ro_keys[i]);
}
-
- /*
- HOME and USER should be writeable by root, since this can be a
- convenient way to install software.
- */
- if( getuid() != 0 )
- {
+
+ /*
+ HOME and USER should be writeable by root, since this can be a
+ convenient way to install software.
+ */
+ if( getuid() != 0 )
+ {
env_read_only.insert(L"HOME");
env_read_only.insert(L"USER");
- }
-
- /*
+ }
+
+ /*
Names of all dynamically calculated variables
*/
env_electric.insert(L"history");
env_electric.insert(L"status");
env_electric.insert(L"umask");
-
- top = new env_node_t;
- global_env = top;
- global = &top->env;
-
- /*
- Now the environemnt variable handling is set up, the next step
- is to insert valid data
- */
-
- /*
- Import environment variables
- */
- for( p=environ?environ:__environ; p && *p; p++ )
- {
- wchar_t *key, *val;
-
- key = str2wcs(*p);
-
- if( !key )
- {
- continue;
- }
-
- val = wcschr( key, L'=' );
-
- if( val == 0 )
- {
- env_set( key, L"", ENV_EXPORT );
- }
- else
- {
- *val = L'\0';
- val++;
-
+
+ top = new env_node_t;
+ global_env = top;
+ global = &top->env;
+
+ /*
+ Now the environemnt variable handling is set up, the next step
+ is to insert valid data
+ */
+
+ /*
+ Import environment variables
+ */
+ for( p=environ?environ:__environ; p && *p; p++ )
+ {
+ wchar_t *key, *val;
+
+ key = str2wcs(*p);
+
+ if( !key )
+ {
+ continue;
+ }
+
+ val = wcschr( key, L'=' );
+
+ if( val == 0 )
+ {
+ env_set( key, L"", ENV_EXPORT );
+ }
+ else
+ {
+ *val = L'\0';
+ val++;
+
//fwprintf( stderr, L"Set $%ls to %ls\n", key, val );
if (variable_can_be_array(val)) {
for (size_t i=0; val[i] != L'\0'; i++) {
@@ -623,11 +623,11 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
}
}
- env_set( key, val, ENV_EXPORT | ENV_GLOBAL );
- }
- free(key);
- }
-
+ env_set( key, val, ENV_EXPORT | ENV_GLOBAL );
+ }
+ free(key);
+ }
+
/* Set the given paths in the environment, if we have any */
if (paths != NULL)
{
@@ -636,63 +636,63 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
env_set(FISH_HELPDIR_VAR, paths->doc.c_str(), ENV_GLOBAL | ENV_EXPORT);
env_set(FISH_BIN_DIR, paths->bin.c_str(), ENV_GLOBAL | ENV_EXPORT);
}
-
- /*
- Set up the PATH variable
- */
- setup_path();
-
- /*
- Set up the USER variable
- */
- pw = getpwuid( getuid() );
- if( pw )
- {
- uname = str2wcs( pw->pw_name );
- env_set( L"USER", uname, ENV_GLOBAL | ENV_EXPORT );
- free( uname );
- }
-
- /*
- Set up the version variables
- */
- version = str2wcs( PACKAGE_VERSION );
- env_set( L"version", version, ENV_GLOBAL );
- env_set( L"FISH_VERSION", version, ENV_GLOBAL );
- free( version );
-
- const env_var_t fishd_dir_wstr = env_get_string( L"FISHD_SOCKET_DIR");
- const env_var_t user_dir_wstr = env_get_string( L"USER" );
-
- wchar_t * fishd_dir = fishd_dir_wstr.missing()?NULL:const_cast<wchar_t*>(fishd_dir_wstr.c_str());
- wchar_t * user_dir = user_dir_wstr.missing()?NULL:const_cast<wchar_t*>(user_dir_wstr.c_str());
-
- env_universal_init(fishd_dir , user_dir ,
- &start_fishd,
- &universal_callback );
-
- /*
- Set up SHLVL variable
- */
- const env_var_t shlvl_str = env_get_string( L"SHLVL" );
+
+ /*
+ Set up the PATH variable
+ */
+ setup_path();
+
+ /*
+ Set up the USER variable
+ */
+ pw = getpwuid( getuid() );
+ if( pw )
+ {
+ uname = str2wcs( pw->pw_name );
+ env_set( L"USER", uname, ENV_GLOBAL | ENV_EXPORT );
+ free( uname );
+ }
+
+ /*
+ Set up the version variables
+ */
+ version = str2wcs( PACKAGE_VERSION );
+ env_set( L"version", version, ENV_GLOBAL );
+ env_set( L"FISH_VERSION", version, ENV_GLOBAL );
+ free( version );
+
+ const env_var_t fishd_dir_wstr = env_get_string( L"FISHD_SOCKET_DIR");
+ const env_var_t user_dir_wstr = env_get_string( L"USER" );
+
+ wchar_t * fishd_dir = fishd_dir_wstr.missing()?NULL:const_cast<wchar_t*>(fishd_dir_wstr.c_str());
+ wchar_t * user_dir = user_dir_wstr.missing()?NULL:const_cast<wchar_t*>(user_dir_wstr.c_str());
+
+ env_universal_init(fishd_dir , user_dir ,
+ &start_fishd,
+ &universal_callback );
+
+ /*
+ Set up SHLVL variable
+ */
+ const env_var_t shlvl_str = env_get_string( L"SHLVL" );
wcstring nshlvl_str = L"1";
- if (! shlvl_str.missing())
- {
+ if (! shlvl_str.missing())
+ {
long shlvl_i = wcstol(shlvl_str.c_str(), NULL, 10);
if (shlvl_i >= 0)
{
nshlvl_str = format_string(L"%ld", 1 + shlvl_i);
}
- }
+ }
env_set(L"SHLVL", nshlvl_str.c_str(), ENV_GLOBAL | ENV_EXPORT );
- /* Set correct defaults for e.g. USER and HOME variables */
- env_set_defaults();
-
+ /* Set correct defaults for e.g. USER and HOME variables */
+ env_set_defaults();
+
/* Set g_log_forks */
env_var_t log_forks = env_get_string(L"fish_log_forks");
g_log_forks = ! log_forks.missing_or_empty() && from_string<bool>(log_forks);
-
+
/* Set g_use_posix_spawn. Default to true. */
env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn");
g_use_posix_spawn = (use_posix_spawn.missing_or_empty() ? true : from_string<bool>(use_posix_spawn));
@@ -700,29 +700,29 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
void env_destroy()
{
- env_universal_destroy();
-
- while( &top->env != global )
- {
- env_pop();
- }
-
+ env_universal_destroy();
+
+ while( &top->env != global )
+ {
+ env_pop();
+ }
+
env_read_only.clear();
env_electric.clear();
-
- var_table_t::iterator iter;
- for (iter = global->begin(); iter != global->end(); ++iter) {
- var_entry_t *entry = iter->second;
- if( entry->exportv )
- {
- mark_changed_exported();
- }
- delete entry;
- }
+ var_table_t::iterator iter;
+ for (iter = global->begin(); iter != global->end(); ++iter) {
+ var_entry_t *entry = iter->second;
+ if( entry->exportv )
+ {
+ mark_changed_exported();
+ }
- delete top;
+ delete entry;
+ }
+
+ delete top;
}
/**
@@ -731,246 +731,246 @@ void env_destroy()
*/
static env_node_t *env_get_node( const wcstring &key )
{
- env_node_t *env = top;
- while( env != NULL )
- {
- if ( env->env.find( key ) != env->env.end() )
- {
- break;
- }
-
- if( env->new_scope )
- {
- env = global_env;
- }
- else
- {
- env = env->next;
- }
- }
- return env;
+ env_node_t *env = top;
+ while( env != NULL )
+ {
+ if ( env->env.find( key ) != env->env.end() )
+ {
+ break;
+ }
+
+ if( env->new_scope )
+ {
+ env = global_env;
+ }
+ else
+ {
+ env = env->next;
+ }
+ }
+ return env;
}
int env_set(const wcstring &key, const wchar_t *val, int var_mode)
{
ASSERT_IS_MAIN_THREAD();
- env_node_t *node = NULL;
- bool has_changed_old = has_changed_exported;
- bool has_changed_new = false;
- var_entry_t *e=0;
- int done=0;
-
- int is_universal = 0;
-
- if( val && contains( key, L"PWD", L"HOME" ) )
- {
+ env_node_t *node = NULL;
+ bool has_changed_old = has_changed_exported;
+ bool has_changed_new = false;
+ var_entry_t *e=0;
+ int done=0;
+
+ int is_universal = 0;
+
+ if( val && contains( key, L"PWD", L"HOME" ) )
+ {
/* Canoncalize our path; if it changes, recurse and try again. */
wcstring val_canonical = val;
path_make_canonical(val_canonical);
if (val != val_canonical) {
return env_set( key, val_canonical.c_str(), var_mode );
}
- }
-
- if( (var_mode & ENV_USER ) && is_read_only(key) )
- {
- return ENV_PERM;
- }
-
- if (key == L"umask")
- {
- wchar_t *end;
-
- /*
+ }
+
+ if( (var_mode & ENV_USER ) && is_read_only(key) )
+ {
+ return ENV_PERM;
+ }
+
+ if (key == L"umask")
+ {
+ wchar_t *end;
+
+ /*
Set the new umask
*/
- if( val && wcslen(val) )
- {
- errno=0;
- long mask = wcstol( val, &end, 8 );
-
- if( !errno && (!*end) && (mask <= 0777) && (mask >= 0) )
- {
- umask( mask );
- }
- }
- /*
+ if( val && wcslen(val) )
+ {
+ errno=0;
+ long mask = wcstol( val, &end, 8 );
+
+ if( !errno && (!*end) && (mask <= 0777) && (mask >= 0) )
+ {
+ umask( mask );
+ }
+ }
+ /*
Do not actually create a umask variable, on env_get, it will
be calculated dynamically
*/
- return 0;
- }
-
- /*
+ return 0;
+ }
+
+ /*
Zero element arrays are internaly not coded as null but as this
placeholder string
*/
- if( !val )
- {
- val = ENV_NULL;
- }
-
- if( var_mode & ENV_UNIVERSAL )
- {
- int exportv = 0;
-
- if( !(var_mode & ENV_EXPORT ) &&
+ if( !val )
+ {
+ val = ENV_NULL;
+ }
+
+ if( var_mode & ENV_UNIVERSAL )
+ {
+ int exportv = 0;
+
+ if( !(var_mode & ENV_EXPORT ) &&
!(var_mode & ENV_UNEXPORT ) )
- {
- env_universal_get_export( key );
- }
- else
- {
- exportv = (var_mode & ENV_EXPORT );
- }
-
- env_universal_set(key, val, exportv);
- is_universal = 1;
-
- }
- else
- {
-
- node = env_get_node( key );
- if( node )
- {
- var_table_t::iterator result = node->env.find(key);
+ {
+ env_universal_get_export( key );
+ }
+ else
+ {
+ exportv = (var_mode & ENV_EXPORT );
+ }
+
+ env_universal_set(key, val, exportv);
+ is_universal = 1;
+
+ }
+ else
+ {
+
+ node = env_get_node( key );
+ if( node )
+ {
+ var_table_t::iterator result = node->env.find(key);
assert(result != node->env.end());
e = result->second;
-
- if( e->exportv )
- {
- has_changed_new = true;
- }
- }
-
- if( (var_mode & ENV_LOCAL) ||
+
+ if( e->exportv )
+ {
+ has_changed_new = true;
+ }
+ }
+
+ if( (var_mode & ENV_LOCAL) ||
(var_mode & ENV_GLOBAL) )
- {
- node = ( var_mode & ENV_GLOBAL )?global_env:top;
- }
- else
- {
- if( node )
- {
- if( !(var_mode & ENV_EXPORT ) &&
+ {
+ node = ( var_mode & ENV_GLOBAL )?global_env:top;
+ }
+ else
+ {
+ if( node )
+ {
+ if( !(var_mode & ENV_EXPORT ) &&
!(var_mode & ENV_UNEXPORT ) )
- {
- var_mode = e->exportv?ENV_EXPORT:0;
- }
- }
- else
- {
- if( ! get_proc_had_barrier())
- {
- set_proc_had_barrier(true);
- env_universal_barrier();
- }
-
- if( env_universal_get( key ) )
- {
- int exportv = 0;
-
- if( !(var_mode & ENV_EXPORT ) &&
+ {
+ var_mode = e->exportv?ENV_EXPORT:0;
+ }
+ }
+ else
+ {
+ if( ! get_proc_had_barrier())
+ {
+ set_proc_had_barrier(true);
+ env_universal_barrier();
+ }
+
+ if( env_universal_get( key ) )
+ {
+ int exportv = 0;
+
+ if( !(var_mode & ENV_EXPORT ) &&
!(var_mode & ENV_UNEXPORT ) )
- {
- env_universal_get_export( key );
- }
- else
- {
- exportv = (var_mode & ENV_EXPORT );
- }
-
- env_universal_set(key, val, exportv);
- is_universal = 1;
-
- done = 1;
-
- }
- else
- {
- /*
+ {
+ env_universal_get_export( key );
+ }
+ else
+ {
+ exportv = (var_mode & ENV_EXPORT );
+ }
+
+ env_universal_set(key, val, exportv);
+ is_universal = 1;
+
+ done = 1;
+
+ }
+ else
+ {
+ /*
New variable with unspecified scope. The default
scope is the innermost scope that is shadowing,
which will be either the current function or the
- global scope.
+ global scope.
*/
- node = top;
- while( node->next && !node->new_scope )
- {
- node = node->next;
- }
- }
- }
- }
-
- if( !done )
+ node = top;
+ while( node->next && !node->new_scope )
+ {
+ node = node->next;
+ }
+ }
+ }
+ }
+
+ if( !done )
+ {
+ var_entry_t *old_entry = NULL;
+ var_table_t::iterator result = node->env.find(key);
+ if ( result != node->env.end() )
{
- var_entry_t *old_entry = NULL;
- var_table_t::iterator result = node->env.find(key);
- if ( result != node->env.end() )
- {
- old_entry = result->second;
- node->env.erase(result);
- }
-
- var_entry_t *entry = NULL;
- if( old_entry )
+ old_entry = result->second;
+ node->env.erase(result);
+ }
+
+ var_entry_t *entry = NULL;
+ if( old_entry )
{
- entry = old_entry;
-
- if( (var_mode & ENV_EXPORT) || entry->exportv )
+ entry = old_entry;
+
+ if( (var_mode & ENV_EXPORT) || entry->exportv )
{
entry->exportv = !!(var_mode & ENV_EXPORT);
- has_changed_new = true;
+ has_changed_new = true;
}
- }
- else
+ }
+ else
{
- entry = new var_entry_t;
-
- if( var_mode & ENV_EXPORT)
+ entry = new var_entry_t;
+
+ if( var_mode & ENV_EXPORT)
{
entry->exportv = 1;
- has_changed_new = true;
+ has_changed_new = true;
}
- else
+ else
{
entry->exportv = 0;
}
-
+
}
-
- entry->val = val;
- node->env[key] = entry;
-
- if( entry->exportv )
+
+ entry->val = val;
+ node->env[key] = entry;
+
+ if( entry->exportv )
{
- node->exportv=1;
+ node->exportv=1;
}
-
+
if (has_changed_old || has_changed_new)
mark_changed_exported();
}
-
+
}
-
+
if( !is_universal )
{
- event_t ev = event_t::variable_event(key);
+ event_t ev = event_t::variable_event(key);
ev.arguments.reset(new wcstring_list_t);
ev.arguments->push_back(L"VARIABLE");
ev.arguments->push_back(L"SET");
ev.arguments->push_back(key);
-
- // debug( 1, L"env_set: fire events on variable %ls", key );
+
+ // debug( 1, L"env_set: fire events on variable %ls", key );
event_fire( &ev );
- // debug( 1, L"env_set: return from event firing" );
+ // debug( 1, L"env_set: return from event firing" );
ev.arguments.reset(NULL);
}
-
+
react_to_variable_change(key);
-
+
return 0;
}
@@ -982,91 +982,91 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode)
\return zero if the variable was not found, non-zero otherwise
*/
static int try_remove( env_node_t *n,
- const wchar_t *key,
- int var_mode )
+ const wchar_t *key,
+ int var_mode )
{
- if( n == 0 )
- {
- return 0;
- }
-
- var_table_t::iterator result = n->env.find( key );
- if ( result != n->env.end() )
- {
- var_entry_t *v = result->second;
-
- if( v->exportv )
- {
- mark_changed_exported();
- }
-
- n->env.erase(result);
- delete v;
- return 1;
- }
-
- if( var_mode & ENV_LOCAL )
- {
- return 0;
- }
-
- if( n->new_scope )
- {
- return try_remove( global_env, key, var_mode );
- }
- else
- {
- return try_remove( n->next, key, var_mode );
- }
+ if( n == 0 )
+ {
+ return 0;
+ }
+
+ var_table_t::iterator result = n->env.find( key );
+ if ( result != n->env.end() )
+ {
+ var_entry_t *v = result->second;
+
+ if( v->exportv )
+ {
+ mark_changed_exported();
+ }
+
+ n->env.erase(result);
+ delete v;
+ return 1;
+ }
+
+ if( var_mode & ENV_LOCAL )
+ {
+ return 0;
+ }
+
+ if( n->new_scope )
+ {
+ return try_remove( global_env, key, var_mode );
+ }
+ else
+ {
+ return try_remove( n->next, key, var_mode );
+ }
}
int env_remove( const wcstring &key, int var_mode )
{
ASSERT_IS_MAIN_THREAD();
- env_node_t *first_node;
- int erased = 0;
-
- if( (var_mode & ENV_USER ) && is_read_only(key) )
- {
- return 2;
- }
-
- first_node = top;
-
- if( ! (var_mode & ENV_UNIVERSAL ) )
- {
-
- if( var_mode & ENV_GLOBAL )
- {
- first_node = global_env;
- }
-
- if( try_remove( first_node, key.c_str(), var_mode ) )
- {
- event_t ev = event_t::variable_event(key);
+ env_node_t *first_node;
+ int erased = 0;
+
+ if( (var_mode & ENV_USER ) && is_read_only(key) )
+ {
+ return 2;
+ }
+
+ first_node = top;
+
+ if( ! (var_mode & ENV_UNIVERSAL ) )
+ {
+
+ if( var_mode & ENV_GLOBAL )
+ {
+ first_node = global_env;
+ }
+
+ if( try_remove( first_node, key.c_str(), var_mode ) )
+ {
+ event_t ev = event_t::variable_event(key);
ev.arguments.reset(new wcstring_list_t);
ev.arguments->push_back(L"VARIABLE");
ev.arguments->push_back(L"ERASE");
ev.arguments->push_back(key);
-
- event_fire( &ev );
-
- ev.arguments.reset(NULL);
- erased = 1;
- }
- }
-
- if( !erased &&
- !(var_mode & ENV_GLOBAL) &&
- !(var_mode & ENV_LOCAL) )
- {
- erased = ! env_universal_remove( key.c_str() );
- }
+
+ event_fire( &ev );
+
+ ev.arguments.reset(NULL);
+ erased = 1;
+ }
+ }
+
+ if( !erased &&
+ !(var_mode & ENV_GLOBAL) &&
+ !(var_mode & ENV_LOCAL) )
+ {
+ erased = ! env_universal_remove( key.c_str() );
+ }
react_to_variable_change(key);
-
- return !erased;
+
+ return !erased;
}
env_var_t env_var_t::missing_var(void) {
@@ -1081,66 +1081,66 @@ const wchar_t *env_var_t::c_str(void) const {
}
env_var_t env_get_string( const wcstring &key )
-{
+{
/* Big hack...we only allow getting the history on the main thread. Note that history_t may ask for an environment variable, so don't take the lock here (we don't need it) */
const bool is_main = is_main_thread();
- if( key == L"history" && is_main)
- {
+ if( key == L"history" && is_main)
+ {
env_var_t result;
-
+
history_t *history = reader_get_history();
if (! history) {
history = &history_t::history_with_name(L"fish");
}
if (history)
- history->get_string_representation(result, ARRAY_SEP_STR);
- return result;
- }
- else if( key == L"COLUMNS" )
- {
+ history->get_string_representation(result, ARRAY_SEP_STR);
+ return result;
+ }
+ else if( key == L"COLUMNS" )
+ {
return to_string(common_get_width());
- }
- else if( key == L"LINES" )
- {
+ }
+ else if( key == L"LINES" )
+ {
return to_string(common_get_width());
- }
- else if( key == L"status" )
- {
+ }
+ else if( key == L"status" )
+ {
return to_string(proc_get_last_status());
- }
- else if( key == L"umask" )
- {
+ }
+ else if( key == L"umask" )
+ {
return format_string(L"0%0.3o", get_umask() );
- }
- else
+ }
+ else
{
{
/* Lock around a local region */
scoped_lock lock(env_lock);
-
+
var_entry_t *res = NULL;
env_node_t *env = top;
wcstring result;
-
+
while( env != NULL )
{
var_table_t::iterator result = env->env.find(key);
- if ( result != env->env.end() )
- res = result->second;
-
-
+ if ( result != env->env.end() )
+ res = result->second;
+
+
if( res != NULL )
{
- if( res->val == ENV_NULL )
+ if( res->val == ENV_NULL )
{
return env_var_t::missing_var();
}
else
{
- return res->val;
+ return res->val;
}
}
-
+
if( env->new_scope )
{
env = global_env;
@@ -1151,7 +1151,7 @@ env_var_t env_get_string( const wcstring &key )
}
}
}
-
+
/* Another big hack - only do a universal barrier on the main thread (since it can change variable values)
Make sure we do this outside the env_lock because it may itself call env_get_string */
if(is_main && ! get_proc_had_barrier())
@@ -1159,9 +1159,9 @@ env_var_t env_get_string( const wcstring &key )
set_proc_had_barrier(true);
env_universal_barrier();
}
-
+
wchar_t *item = env_universal_get( key );
-
+
if( !item || (wcscmp( item, ENV_NULL )==0))
{
return env_var_t::missing_var();
@@ -1175,20 +1175,20 @@ env_var_t env_get_string( const wcstring &key )
int env_exist( const wchar_t *key, int mode )
{
- var_entry_t *res;
- env_node_t *env;
- wchar_t *item=0;
-
- CHECK( key, 0 );
-
- /*
- Read only variables all exist, and they are all global. A local
- version can not exist.
- */
- if( ! (mode & ENV_LOCAL) && ! (mode & ENV_UNIVERSAL) )
- {
- if( is_read_only(key) || is_electric(key) )
- {
+ var_entry_t *res;
+ env_node_t *env;
+ wchar_t *item=0;
+
+ CHECK( key, 0 );
+
+ /*
+ Read only variables all exist, and they are all global. A local
+ version can not exist.
+ */
+ if( ! (mode & ENV_LOCAL) && ! (mode & ENV_UNIVERSAL) )
+ {
+ if( is_read_only(key) || is_electric(key) )
+ {
//Such variables are never exported
if (mode & ENV_EXPORT)
{
@@ -1198,21 +1198,21 @@ int env_exist( const wchar_t *key, int mode )
{
return 1;
}
- return 1;
- }
- }
+ return 1;
+ }
+ }
if( !(mode & ENV_UNIVERSAL) )
- {
- env = (mode & ENV_GLOBAL)?global_env:top;
-
- while( env != 0 )
- {
- var_table_t::iterator result = env->env.find( key );
+ {
+ env = (mode & ENV_GLOBAL)?global_env:top;
- if ( result != env->env.end() )
- {
- res = result->second;
+ while( env != 0 )
+ {
+ var_table_t::iterator result = env->env.find( key );
+
+ if ( result != env->env.end() )
+ {
+ res = result->second;
if (mode & ENV_EXPORT)
{
@@ -1222,50 +1222,50 @@ int env_exist( const wchar_t *key, int mode )
{
return res->exportv == 0;
}
-
+
return 1;
- }
-
+ }
+
if ( mode & ENV_LOCAL )
- break;
-
- if( env->new_scope )
- {
- env = global_env;
- }
- else
- {
- env = env->next;
- }
- }
- }
+ break;
+
+ if( env->new_scope )
+ {
+ env = global_env;
+ }
+ else
+ {
+ env = env->next;
+ }
+ }
+ }
if( !(mode & ENV_LOCAL) && !(mode & ENV_GLOBAL) )
- {
- if( ! get_proc_had_barrier())
- {
- set_proc_had_barrier(true);
- env_universal_barrier();
- }
-
- item = env_universal_get( key );
+ {
+ if( ! get_proc_had_barrier())
+ {
+ set_proc_had_barrier(true);
+ env_universal_barrier();
+ }
+
+ item = env_universal_get( key );
if (item != NULL)
{
if (mode & ENV_EXPORT)
{
- return env_universal_get_export(key) == 1;
+ return env_universal_get_export(key) == 1;
}
else if (mode & ENV_UNEXPORT)
{
- return env_universal_get_export(key) == 0;
+ return env_universal_get_export(key) == 0;
}
return 1;
}
- }
+ }
- return 0;
+ return 0;
}
/**
@@ -1273,85 +1273,85 @@ int env_exist( const wchar_t *key, int mode )
*/
static int local_scope_exports( env_node_t *n )
{
-
- if( n==global_env )
- return 0;
-
- if( n->exportv )
- return 1;
-
- if( n->new_scope )
- return 0;
-
- return local_scope_exports( n->next );
+
+ if( n==global_env )
+ return 0;
+
+ if( n->exportv )
+ return 1;
+
+ if( n->new_scope )
+ return 0;
+
+ return local_scope_exports( n->next );
}
void env_push( int new_scope )
{
- env_node_t *node = new env_node_t;
- node->next = top;
- node->new_scope=new_scope;
-
- if( new_scope )
- {
+ env_node_t *node = new env_node_t;
+ node->next = top;
+ node->new_scope=new_scope;
+
+ if( new_scope )
+ {
if (local_scope_exports(top))
mark_changed_exported();
- }
- top = node;
+ }
+ top = node;
}
void env_pop()
{
- if( &top->env != global )
- {
- int i;
- int locale_changed = 0;
-
- env_node_t *killme = top;
-
- for( i=0; locale_variable[i]; i++ )
- {
- var_table_t::iterator result = killme->env.find( locale_variable[i] );
- if ( result != killme->env.end() )
- {
- locale_changed = 1;
- break;
- }
- }
-
- if( killme->new_scope )
- {
+ if( &top->env != global )
+ {
+ int i;
+ int locale_changed = 0;
+
+ env_node_t *killme = top;
+
+ for( i=0; locale_variable[i]; i++ )
+ {
+ var_table_t::iterator result = killme->env.find( locale_variable[i] );
+ if ( result != killme->env.end() )
+ {
+ locale_changed = 1;
+ break;
+ }
+ }
+
+ if( killme->new_scope )
+ {
if (killme->exportv || local_scope_exports( killme->next ))
mark_changed_exported();
- }
-
- top = top->next;
-
- var_table_t::iterator iter;
- for (iter = killme->env.begin(); iter != killme->env.end(); ++iter)
- {
- var_entry_t *entry = iter->second;
- if( entry->exportv )
- {
- mark_changed_exported();
- }
- delete entry;
- }
-
- delete killme;
-
- if( locale_changed )
- handle_locale();
-
- }
- else
- {
- debug( 0,
- _( L"Tried to pop empty environment stack." ) );
- sanity_lose();
- }
+ }
+
+ top = top->next;
+
+ var_table_t::iterator iter;
+ for (iter = killme->env.begin(); iter != killme->env.end(); ++iter)
+ {
+ var_entry_t *entry = iter->second;
+ if( entry->exportv )
+ {
+ mark_changed_exported();
+ }
+ delete entry;
+ }
+
+ delete killme;
+
+ if( locale_changed )
+ handle_locale();
+
+ }
+ else
+ {
+ debug( 0,
+ _( L"Tried to pop empty environment stack." ) );
+ sanity_lose();
+ }
}
/**
@@ -1359,181 +1359,181 @@ void env_pop()
*/
static void add_key_to_string_set(const var_table_t &envs, std::set<wcstring> &strSet)
{
- var_table_t::const_iterator iter;
- for (iter = envs.begin(); iter != envs.end(); ++iter)
- {
- var_entry_t *e = iter->second;
-
- if( ( e->exportv && get_names_show_exported) ||
- ( !e->exportv && get_names_show_unexported) )
- {
- /*Insert Key*/
- strSet.insert(iter->first);
- }
-
- }
+ var_table_t::const_iterator iter;
+ for (iter = envs.begin(); iter != envs.end(); ++iter)
+ {
+ var_entry_t *e = iter->second;
+
+ if( ( e->exportv && get_names_show_exported) ||
+ ( !e->exportv && get_names_show_unexported) )
+ {
+ /*Insert Key*/
+ strSet.insert(iter->first);
+ }
+
+ }
}
wcstring_list_t env_get_names( int flags )
{
scoped_lock lock(env_lock);
-
+
wcstring_list_t result;
std::set<wcstring> names;
int show_local = flags & ENV_LOCAL;
- int show_global = flags & ENV_GLOBAL;
- int show_universal = flags & ENV_UNIVERSAL;
-
- env_node_t *n=top;
-
-
- get_names_show_exported =
- (flags & ENV_EXPORT) || !(flags & ENV_UNEXPORT);
- get_names_show_unexported =
- (flags & ENV_UNEXPORT) || !(flags & ENV_EXPORT);
-
- if( !show_local && !show_global && !show_universal )
- {
- show_local =show_universal = show_global=1;
- }
-
- if( show_local )
- {
- while( n )
- {
- if( n == global_env )
- break;
-
- add_key_to_string_set(n->env, names);
- if( n->new_scope )
- break;
- else
- n = n->next;
-
- }
- }
-
- if( show_global )
- {
- add_key_to_string_set(global_env->env, names);
- if( get_names_show_unexported ) {
+ int show_global = flags & ENV_GLOBAL;
+ int show_universal = flags & ENV_UNIVERSAL;
+
+ env_node_t *n=top;
+
+
+ get_names_show_exported =
+ (flags & ENV_EXPORT) || !(flags & ENV_UNEXPORT);
+ get_names_show_unexported =
+ (flags & ENV_UNEXPORT) || !(flags & ENV_EXPORT);
+
+ if( !show_local && !show_global && !show_universal )
+ {
+ show_local =show_universal = show_global=1;
+ }
+
+ if( show_local )
+ {
+ while( n )
+ {
+ if( n == global_env )
+ break;
+
+ add_key_to_string_set(n->env, names);
+ if( n->new_scope )
+ break;
+ else
+ n = n->next;
+
+ }
+ }
+
+ if( show_global )
+ {
+ add_key_to_string_set(global_env->env, names);
+ if( get_names_show_unexported ) {
result.insert(result.end(), env_electric.begin(), env_electric.end());
}
-
- if( get_names_show_exported )
- {
+
+ if( get_names_show_exported )
+ {
result.push_back(L"COLUMNS");
result.push_back(L"LINES");
- }
-
- }
-
- if( show_universal )
- {
-
+ }
+
+ }
+
+ if( show_universal )
+ {
+
wcstring_list_t uni_list;
env_universal_get_names2(uni_list,
get_names_show_exported,
- get_names_show_unexported);
+ get_names_show_unexported);
names.insert(uni_list.begin(), uni_list.end());
- }
-
+ }
+
result.insert(result.end(), names.begin(), names.end());
return result;
}
/**
- Get list of all exported variables
+ Get list of all exported variables
*/
static void get_exported( const env_node_t *n, std::map<wcstring, wcstring> &h )
{
- if( !n )
- return;
-
- if( n->new_scope )
- get_exported( global_env, h );
- else
- get_exported( n->next, h );
-
- var_table_t::const_iterator iter;
- for (iter = n->env.begin(); iter != n->env.end(); ++iter)
- {
- const wcstring &key = iter->first;
- var_entry_t *val_entry = iter->second;
- if( val_entry->exportv && (val_entry->val != ENV_NULL ) )
- {
+ if( !n )
+ return;
+
+ if( n->new_scope )
+ get_exported( global_env, h );
+ else
+ get_exported( n->next, h );
+
+ var_table_t::const_iterator iter;
+ for (iter = n->env.begin(); iter != n->env.end(); ++iter)
+ {
+ const wcstring &key = iter->first;
+ var_entry_t *val_entry = iter->second;
+ if( val_entry->exportv && (val_entry->val != ENV_NULL ) )
+ {
// Don't use std::map::insert here, since we need to overwrite existing values from previous scopes
h[key] = val_entry->val;
- }
- }
+ }
+ }
}
static void export_func(const std::map<wcstring, wcstring> &envs, std::vector<std::string> &out)
{
- std::map<wcstring, wcstring>::const_iterator iter;
- for (iter = envs.begin(); iter != envs.end(); ++iter)
- {
- char* ks = wcs2str(iter->first.c_str());
- char* vs = wcs2str(iter->second.c_str());
- char *pos = vs;
- while( *pos )
- {
- if( *pos == ARRAY_SEP )
- *pos = ':';
- pos++;
- }
-
+ std::map<wcstring, wcstring>::const_iterator iter;
+ for (iter = envs.begin(); iter != envs.end(); ++iter)
+ {
+ char* ks = wcs2str(iter->first.c_str());
+ char* vs = wcs2str(iter->second.c_str());
+ char *pos = vs;
+ while( *pos )
+ {
+ if( *pos == ARRAY_SEP )
+ *pos = ':';
+ pos++;
+ }
+
/* Put a string on the vector */
out.push_back(std::string());
std::string &str = out.back();
-
+
/* Append our environment variable data to it */
str.append(ks);
str.append("=");
str.append(vs);
- free(ks);
- free(vs);
- }
+ free(ks);
+ free(vs);
+ }
}
static void update_export_array_if_necessary(bool recalc) {
ASSERT_IS_MAIN_THREAD();
- if( recalc && ! get_proc_had_barrier())
- {
- set_proc_had_barrier(true);
- env_universal_barrier();
- }
-
- if( has_changed_exported )
- {
- std::map<wcstring, wcstring> vals;
- size_t i;
-
- debug( 4, L"env_export_arr() recalc" );
-
- get_exported( top, vals );
-
+ if( recalc && ! get_proc_had_barrier())
+ {
+ set_proc_had_barrier(true);
+ env_universal_barrier();
+ }
+
+ if( has_changed_exported )
+ {
+ std::map<wcstring, wcstring> vals;
+ size_t i;
+
+ debug( 4, L"env_export_arr() recalc" );
+
+ get_exported( top, vals );
+
wcstring_list_t uni;
- env_universal_get_names2( uni, 1, 0 );
- for( i=0; i<uni.size(); i++ )
- {
- const wcstring &key = uni.at(i);
- const wchar_t *val = env_universal_get( key.c_str() );
-
- if (wcscmp( val, ENV_NULL)) {
- // Note that std::map::insert does NOT overwrite a value already in the map,
- // which we depend on here
- vals.insert(std::pair<wcstring, wcstring>(key, val));
- }
- }
-
+ env_universal_get_names2( uni, 1, 0 );
+ for( i=0; i<uni.size(); i++ )
+ {
+ const wcstring &key = uni.at(i);
+ const wchar_t *val = env_universal_get( key.c_str() );
+
+ if (wcscmp( val, ENV_NULL)) {
+ // Note that std::map::insert does NOT overwrite a value already in the map,
+ // which we depend on here
+ vals.insert(std::pair<wcstring, wcstring>(key, val));
+ }
+ }
+
std::vector<std::string> local_export_buffer;
- export_func(vals, local_export_buffer );
+ export_func(vals, local_export_buffer );
export_array.set(local_export_buffer);
- has_changed_exported=false;
- }
+ has_changed_exported=false;
+ }
}
diff --git a/env.h b/env.h
index 2c32b6a0..9a00488f 100644
--- a/env.h
+++ b/env.h
@@ -1,5 +1,5 @@
/** \file env.h
- Prototypes for functions for setting and getting environment variables.
+ Prototypes for functions for setting and getting environment variables.
*/
#ifndef FISH_ENV_H
@@ -47,8 +47,8 @@
Error code for trying to alter read-only variable
*/
enum{
- ENV_PERM = 1,
- ENV_INVALID
+ ENV_PERM = 1,
+ ENV_INVALID
}
;
@@ -74,7 +74,7 @@ void env_destroy();
/**
- Set the value of the environment variable whose name matches key to val.
+ Set the value of the environment variable whose name matches key to val.
Memory policy: All keys and values are copied, the parameters can and should be freed by the caller afterwards
@@ -119,7 +119,7 @@ public:
wcstring::operator=(s);
return *this;
}
-
+
bool operator==(const env_var_t &s) const {
if (is_missing && s.is_missing)
return true;
@@ -146,7 +146,7 @@ int env_exist( const wchar_t *key, int mode );
/**
Remove environemnt variable
-
+
\param key The name of the variable to remove
\param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If this is a user request, read-only variables can not be removed. The mode may also specify the scope of the variable that should be erased.
@@ -188,12 +188,12 @@ class env_vars_snapshot_t {
public:
env_vars_snapshot_t(const wchar_t * const * keys);
env_vars_snapshot_t(void);
-
+
env_var_t get(const wcstring &key) const;
-
+
// Returns the fake snapshot representing the live variables array
static const env_vars_snapshot_t &current();
-
+
// vars necessary for highlighting
static const wchar_t * const highlighting_keys[];
};
diff --git a/env_universal.cpp b/env_universal.cpp
index 7a1564ed..c1729be1 100644
--- a/env_universal.cpp
+++ b/env_universal.cpp
@@ -72,7 +72,7 @@ void env_universal_barrier();
static int is_dead()
{
- return env_universal_server.fd < 0;
+ return env_universal_server.fd < 0;
}
@@ -81,101 +81,101 @@ static int is_dead()
*/
static int get_socket( int fork_ok )
{
- int s, len;
- struct sockaddr_un local;
-
- char *name;
- wchar_t *wdir;
- wchar_t *wuname;
- char *dir =0, *uname=0;
-
- get_socket_count++;
- wdir = path;
- wuname = user;
-
- if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
- {
- wperror(L"socket");
- return -1;
- }
-
- if( wdir )
- dir = wcs2str(wdir );
- else
- dir = strdup("/tmp");
-
- if( wuname )
- uname = wcs2str(wuname );
- else
- {
- struct passwd *pw;
- pw = getpwuid( getuid() );
- uname = strdup( pw->pw_name );
- }
-
- name = (char *)malloc( strlen(dir) +
- strlen(uname) +
- strlen(SOCK_FILENAME) +
- 2 );
-
- strcpy( name, dir );
- strcat( name, "/" );
- strcat( name, SOCK_FILENAME );
- strcat( name, uname );
-
- free( dir );
- free( uname );
-
- debug( 3, L"Connect to socket %s at fd %2", name, s );
-
- local.sun_family = AF_UNIX;
- strcpy(local.sun_path, name );
- free( name );
- len = sizeof(local);
-
- if( connect( s, (struct sockaddr *)&local, len) == -1 )
- {
- close( s );
- if( fork_ok && start_fishd )
- {
- debug( 2, L"Could not connect to socket %d, starting fishd", s );
-
- start_fishd();
-
- return get_socket( 0 );
- }
-
- debug( 1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?" );
- return -1;
- }
-
- if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) )
- {
- wperror( L"fcntl" );
- close( s );
-
- return -1;
- }
-
- debug( 3, L"Connected to fd %d", s );
-
- return s;
+ int s, len;
+ struct sockaddr_un local;
+
+ char *name;
+ wchar_t *wdir;
+ wchar_t *wuname;
+ char *dir =0, *uname=0;
+
+ get_socket_count++;
+ wdir = path;
+ wuname = user;
+
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ wperror(L"socket");
+ return -1;
+ }
+
+ if( wdir )
+ dir = wcs2str(wdir );
+ else
+ dir = strdup("/tmp");
+
+ if( wuname )
+ uname = wcs2str(wuname );
+ else
+ {
+ struct passwd *pw;
+ pw = getpwuid( getuid() );
+ uname = strdup( pw->pw_name );
+ }
+
+ name = (char *)malloc( strlen(dir) +
+ strlen(uname) +
+ strlen(SOCK_FILENAME) +
+ 2 );
+
+ strcpy( name, dir );
+ strcat( name, "/" );
+ strcat( name, SOCK_FILENAME );
+ strcat( name, uname );
+
+ free( dir );
+ free( uname );
+
+ debug( 3, L"Connect to socket %s at fd %2", name, s );
+
+ local.sun_family = AF_UNIX;
+ strcpy(local.sun_path, name );
+ free( name );
+ len = sizeof(local);
+
+ if( connect( s, (struct sockaddr *)&local, len) == -1 )
+ {
+ close( s );
+ if( fork_ok && start_fishd )
+ {
+ debug( 2, L"Could not connect to socket %d, starting fishd", s );
+
+ start_fishd();
+
+ return get_socket( 0 );
+ }
+
+ debug( 1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?" );
+ return -1;
+ }
+
+ if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) )
+ {
+ wperror( L"fcntl" );
+ close( s );
+
+ return -1;
+ }
+
+ debug( 3, L"Connected to fd %d", s );
+
+ return s;
}
/**
Callback function used whenever a new fishd message is recieved
*/
static void callback( fish_message_type_t type, const wchar_t *name, const wchar_t *val )
-{
- if( type == BARRIER_REPLY )
- {
- barrier_reply = 1;
- }
- else
- {
- if( external_callback )
- external_callback( type, name, val );
- }
+{
+ if( type == BARRIER_REPLY )
+ {
+ barrier_reply = 1;
+ }
+ else
+ {
+ if( external_callback )
+ external_callback( type, name, val );
+ }
}
/**
@@ -184,23 +184,23 @@ static void callback( fish_message_type_t type, const wchar_t *name, const wchar
*/
static void check_connection()
{
- if( !init )
- return;
-
- if( env_universal_server.killme )
- {
- debug( 3, L"Lost connection to universal variable server." );
-
- if( close( env_universal_server.fd ) )
- {
- wperror( L"close" );
- }
-
- env_universal_server.fd = -1;
- env_universal_server.killme=0;
- env_universal_server.input.clear();
- env_universal_read_all();
- }
+ if( !init )
+ return;
+
+ if( env_universal_server.killme )
+ {
+ debug( 3, L"Lost connection to universal variable server." );
+
+ if( close( env_universal_server.fd ) )
+ {
+ wperror( L"close" );
+ }
+
+ env_universal_server.fd = -1;
+ env_universal_server.killme=0;
+ env_universal_server.input.clear();
+ env_universal_read_all();
+ }
}
/**
@@ -208,18 +208,18 @@ static void check_connection()
*/
static void env_universal_remove_all()
{
- size_t i;
-
- wcstring_list_t lst;
- env_universal_common_get_names( lst,
- 1,
- 1 );
- for( i=0; i<lst.size(); i++ )
- {
- const wcstring &key = lst.at(i);
- env_universal_common_remove( key );
- }
-
+ size_t i;
+
+ wcstring_list_t lst;
+ env_universal_common_get_names( lst,
+ 1,
+ 1 );
+ for( i=0; i<lst.size(); i++ )
+ {
+ const wcstring &key = lst.at(i);
+ env_universal_common_remove( key );
+ }
+
}
@@ -230,63 +230,63 @@ static void env_universal_remove_all()
*/
static void reconnect()
{
- if( get_socket_count >= RECONNECT_COUNT )
- return;
-
- debug( 3, L"Get new fishd connection" );
-
- init = 0;
- env_universal_server.buffer_consumed = env_universal_server.buffer_used = 0;
- env_universal_server.fd = get_socket(1);
- init = 1;
- if( env_universal_server.fd >= 0 )
- {
- env_universal_remove_all();
- env_universal_barrier();
- }
+ if( get_socket_count >= RECONNECT_COUNT )
+ return;
+
+ debug( 3, L"Get new fishd connection" );
+
+ init = 0;
+ env_universal_server.buffer_consumed = env_universal_server.buffer_used = 0;
+ env_universal_server.fd = get_socket(1);
+ init = 1;
+ if( env_universal_server.fd >= 0 )
+ {
+ env_universal_remove_all();
+ env_universal_barrier();
+ }
}
-void env_universal_init( wchar_t * p,
- wchar_t *u,
- void (*sf)(),
- void (*cb)( fish_message_type_t type, const wchar_t *name, const wchar_t *val ))
+void env_universal_init( wchar_t * p,
+ wchar_t *u,
+ void (*sf)(),
+ void (*cb)( fish_message_type_t type, const wchar_t *name, const wchar_t *val ))
{
- path=p;
- user=u;
- start_fishd=sf;
- external_callback = cb;
-
- connection_init( &env_universal_server, -1 );
-
- env_universal_server.fd = get_socket(1);
- env_universal_common_init( &callback );
- env_universal_read_all();
- init = 1;
- if( env_universal_server.fd >= 0 )
- {
- env_universal_barrier();
- }
+ path=p;
+ user=u;
+ start_fishd=sf;
+ external_callback = cb;
+
+ connection_init( &env_universal_server, -1 );
+
+ env_universal_server.fd = get_socket(1);
+ env_universal_common_init( &callback );
+ env_universal_read_all();
+ init = 1;
+ if( env_universal_server.fd >= 0 )
+ {
+ env_universal_barrier();
+ }
}
void env_universal_destroy()
{
- /*
- Go into blocking mode and send all data before exiting
- */
- if( env_universal_server.fd >= 0 )
- {
- if( fcntl( env_universal_server.fd, F_SETFL, 0 ) != 0 )
- {
- wperror( L"fcntl" );
- }
- try_send_all( &env_universal_server );
- }
-
- connection_destroy( &env_universal_server );
- env_universal_server.fd =-1;
- env_universal_common_destroy();
- init = 0;
+ /*
+ Go into blocking mode and send all data before exiting
+ */
+ if( env_universal_server.fd >= 0 )
+ {
+ if( fcntl( env_universal_server.fd, F_SETFL, 0 ) != 0 )
+ {
+ wperror( L"fcntl" );
+ }
+ try_send_all( &env_universal_server );
+ }
+
+ connection_destroy( &env_universal_server );
+ env_universal_server.fd =-1;
+ env_universal_common_destroy();
+ init = 0;
}
@@ -295,177 +295,177 @@ void env_universal_destroy()
*/
int env_universal_read_all()
{
- if( !init)
- return 0;
-
- if( env_universal_server.fd == -1 )
- {
- reconnect();
- if( env_universal_server.fd == -1 )
- return 0;
- }
-
- if( env_universal_server.fd != -1 )
- {
- read_message( &env_universal_server );
- check_connection();
- return 1;
- }
- else
- {
- debug( 2, L"No connection to universal variable server" );
- return 0;
- }
+ if( !init)
+ return 0;
+
+ if( env_universal_server.fd == -1 )
+ {
+ reconnect();
+ if( env_universal_server.fd == -1 )
+ return 0;
+ }
+
+ if( env_universal_server.fd != -1 )
+ {
+ read_message( &env_universal_server );
+ check_connection();
+ return 1;
+ }
+ else
+ {
+ debug( 2, L"No connection to universal variable server" );
+ return 0;
+ }
}
wchar_t *env_universal_get( const wcstring &name )
{
- if( !init)
- return 0;
+ if( !init)
+ return 0;
- return env_universal_common_get( name );
+ return env_universal_common_get( name );
}
int env_universal_get_export( const wcstring &name )
{
- if( !init)
- return 0;
-
- return env_universal_common_get_export( name );
+ if( !init)
+ return 0;
+
+ return env_universal_common_get_export( name );
}
void env_universal_barrier()
{
ASSERT_IS_MAIN_THREAD();
- message_t *msg;
- fd_set fds;
+ message_t *msg;
+ fd_set fds;
- if( !init || is_dead() )
- return;
+ if( !init || is_dead() )
+ return;
- barrier_reply = 0;
+ barrier_reply = 0;
- /*
- Create barrier request
- */
- msg= create_message( BARRIER, 0, 0);
- msg->count=1;
+ /*
+ Create barrier request
+ */
+ msg= create_message( BARRIER, 0, 0);
+ msg->count=1;
env_universal_server.unsent->push(msg);
- /*
- Wait until barrier request has been sent
- */
- debug( 3, L"Create barrier" );
- while( 1 )
- {
- try_send_all( &env_universal_server );
- check_connection();
-
- if( env_universal_server.unsent->empty() )
- break;
-
- if( env_universal_server.fd == -1 )
- {
- reconnect();
- debug( 2, L"barrier interrupted, exiting" );
- return;
- }
-
- FD_ZERO( &fds );
- FD_SET( env_universal_server.fd, &fds );
- select( env_universal_server.fd+1, 0, &fds, 0, 0 );
- }
-
- /*
- Wait for barrier reply
- */
- debug( 3, L"Sent barrier request" );
- while( !barrier_reply )
- {
- if( env_universal_server.fd == -1 )
- {
- reconnect();
- debug( 2, L"barrier interrupted, exiting (2)" );
- return;
- }
- FD_ZERO( &fds );
- FD_SET( env_universal_server.fd, &fds );
+ /*
+ Wait until barrier request has been sent
+ */
+ debug( 3, L"Create barrier" );
+ while( 1 )
+ {
+ try_send_all( &env_universal_server );
+ check_connection();
+
+ if( env_universal_server.unsent->empty() )
+ break;
+
+ if( env_universal_server.fd == -1 )
+ {
+ reconnect();
+ debug( 2, L"barrier interrupted, exiting" );
+ return;
+ }
+
+ FD_ZERO( &fds );
+ FD_SET( env_universal_server.fd, &fds );
+ select( env_universal_server.fd+1, 0, &fds, 0, 0 );
+ }
+
+ /*
+ Wait for barrier reply
+ */
+ debug( 3, L"Sent barrier request" );
+ while( !barrier_reply )
+ {
+ if( env_universal_server.fd == -1 )
+ {
+ reconnect();
+ debug( 2, L"barrier interrupted, exiting (2)" );
+ return;
+ }
+ FD_ZERO( &fds );
+ FD_SET( env_universal_server.fd, &fds );
select( env_universal_server.fd+1, &fds, 0, 0, 0 );
- env_universal_read_all();
- }
- debug( 3, L"End barrier" );
+ env_universal_read_all();
+ }
+ debug( 3, L"End barrier" );
}
void env_universal_set( const wcstring &name, const wcstring &value, int exportv )
{
- message_t *msg;
-
- if( !init )
- return;
-
- debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name.c_str(), value.c_str() );
-
- if( is_dead() )
- {
- env_universal_common_set( name.c_str(), value.c_str(), exportv );
- }
- else
- {
- msg = create_message( exportv?SET_EXPORT:SET,
- name.c_str(),
- value.c_str());
-
- if( !msg )
- {
- debug( 1, L"Could not create universal variable message" );
- return;
- }
-
- msg->count=1;
+ message_t *msg;
+
+ if( !init )
+ return;
+
+ debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name.c_str(), value.c_str() );
+
+ if( is_dead() )
+ {
+ env_universal_common_set( name.c_str(), value.c_str(), exportv );
+ }
+ else
+ {
+ msg = create_message( exportv?SET_EXPORT:SET,
+ name.c_str(),
+ value.c_str());
+
+ if( !msg )
+ {
+ debug( 1, L"Could not create universal variable message" );
+ return;
+ }
+
+ msg->count=1;
env_universal_server.unsent->push(msg);
- env_universal_barrier();
- }
+ env_universal_barrier();
+ }
}
int env_universal_remove( const wchar_t *name )
{
- int res;
-
- message_t *msg;
- if( !init )
- return 1;
-
- CHECK( name, 1 );
-
- res = !env_universal_common_get( name );
- debug( 3,
- L"env_universal_remove( \"%ls\" )",
- name );
-
- if( is_dead() )
- {
- env_universal_common_remove( wcstring(name) );
- }
- else
- {
- msg= create_message( ERASE, name, 0);
- msg->count=1;
+ int res;
+
+ message_t *msg;
+ if( !init )
+ return 1;
+
+ CHECK( name, 1 );
+
+ res = !env_universal_common_get( name );
+ debug( 3,
+ L"env_universal_remove( \"%ls\" )",
+ name );
+
+ if( is_dead() )
+ {
+ env_universal_common_remove( wcstring(name) );
+ }
+ else
+ {
+ msg= create_message( ERASE, name, 0);
+ msg->count=1;
env_universal_server.unsent->push(msg);
- env_universal_barrier();
- }
-
- return res;
+ env_universal_barrier();
+ }
+
+ return res;
}
void env_universal_get_names2( wcstring_list_t &lst,
int show_exported,
int show_unexported )
{
- if( !init )
- return;
+ if( !init )
+ return;
- env_universal_common_get_names( lst,
- show_exported,
- show_unexported );
+ env_universal_common_get_names( lst,
+ show_exported,
+ show_unexported );
}
diff --git a/env_universal.h b/env_universal.h
index bfc45635..8c1b3925 100644
--- a/env_universal.h
+++ b/env_universal.h
@@ -1,5 +1,5 @@
/** \file env_universal.h
- Universal variable client library.
+ Universal variable client library.
*/
#ifndef ENV_UNIVERSAL_H
@@ -17,8 +17,8 @@ extern connection_t env_universal_server;
/**
Initialize the envuni library
*/
-void env_universal_init( wchar_t * p,
- wchar_t *u,
+void env_universal_init( wchar_t * p,
+ wchar_t *u,
void (*sf)(),
void (*cb)( fish_message_type_t type, const wchar_t *name, const wchar_t *val ));
/**
@@ -43,7 +43,7 @@ int env_universal_get_export( const wcstring &name );
void env_universal_set( const wcstring &name, const wcstring &val, int exportv );
/**
Erase a universal variable
-
+
\return zero if the variable existed, and non-zero if the variable did not exist
*/
int env_universal_remove( const wchar_t *name );
@@ -55,14 +55,14 @@ int env_universal_read_all();
/**
Get the names of all universal variables
-
+
\param l the list to insert the names into
\param show_exported whether exported variables should be shown
\param show_unexported whether unexported variables should be shown
*/
void env_universal_get_names2( wcstring_list_t &list,
- int show_exported,
- int show_unexported );
+ int show_exported,
+ int show_unexported );
/**
Synchronize with fishd
diff --git a/env_universal_common.cpp b/env_universal_common.cpp
index 5ed554be..47df1305 100644
--- a/env_universal_common.cpp
+++ b/env_universal_common.cpp
@@ -93,15 +93,15 @@
*/
typedef struct var_uni_entry
{
- int exportv; /**< Whether the variable should be exported */
- wcstring val; /**< The value of the variable */
- var_uni_entry():exportv(0), val() { }
+ int exportv; /**< Whether the variable should be exported */
+ wcstring val; /**< The value of the variable */
+ var_uni_entry():exportv(0), val() { }
}
var_uni_entry_t;
static void parse_message( wchar_t *msg,
- connection_t *src );
+ connection_t *src );
/**
The table of all universal variables
@@ -113,8 +113,8 @@ env_var_table_t env_universal_var;
Callback function, should be called on all events
*/
static void (*callback)( fish_message_type_t type,
- const wchar_t *key,
- const wchar_t *val );
+ const wchar_t *key,
+ const wchar_t *val );
/**
List of names for the UTF-8 character set.
@@ -132,8 +132,8 @@ static const char *iconv_utf8_names[]=
*/
static const char *iconv_wide_names_unknown[]=
{
- "wchar_t", "WCHAR_T",
- "wchar", "WCHAR",
+ "wchar_t", "WCHAR_T",
+ "wchar", "WCHAR",
0
}
;
@@ -143,12 +143,12 @@ static const char *iconv_wide_names_unknown[]=
*/
static const char *iconv_wide_names_4[]=
{
- "wchar_t", "WCHAR_T",
- "wchar", "WCHAR",
- "ucs-4", "UCS-4",
- "ucs4", "UCS4",
- "utf-32", "UTF-32",
- "utf32", "UTF32",
+ "wchar_t", "WCHAR_T",
+ "wchar", "WCHAR",
+ "ucs-4", "UCS-4",
+ "ucs4", "UCS4",
+ "utf-32", "UTF-32",
+ "utf32", "UTF32",
0
}
;
@@ -158,18 +158,18 @@ static const char *iconv_wide_names_4[]=
*/
static const char *iconv_wide_names_2[]=
{
- "wchar_t", "WCHAR_T",
- "wchar", "WCHAR",
- "ucs-2", "UCS-2",
- "ucs2", "UCS2",
- "utf-16", "UTF-16",
- "utf16", "UTF16",
+ "wchar_t", "WCHAR_T",
+ "wchar", "WCHAR",
+ "ucs-2", "UCS-2",
+ "ucs2", "UCS2",
+ "utf-16", "UTF-16",
+ "utf16", "UTF16",
0
}
;
template<class T>
-class sloppy {};
+class sloppy {};
static size_t hack_iconv(iconv_t cd, const char * const* inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
{
@@ -184,7 +184,7 @@ static size_t hack_iconv(iconv_t cd, const char * const* inbuf, size_t *inbytesl
operator char** () const { return (char **)t; }
operator const char** () const { return (const char**)t; }
} slop_inbuf = {inbuf};
-
+
return iconv( cd, slop_inbuf, inbytesleft, outbuf, outbytesleft );
}
@@ -193,117 +193,117 @@ static size_t hack_iconv(iconv_t cd, const char * const* inbuf, size_t *inbytesl
*/
static wchar_t *utf2wcs( const char *in )
{
- iconv_t cd=(iconv_t) -1;
- int i,j;
-
- wchar_t *out;
-
- /*
- Try to convert to wchar_t. If that is not a valid character set,
- try various names for ucs-4. We can't be sure that ucs-4 is
- really the character set used by wchar_t, but it is the best
- assumption we can make.
- */
- const char **to_name=0;
-
- switch (sizeof (wchar_t))
- {
-
- case 2:
- to_name = iconv_wide_names_2;
- break;
-
- case 4:
- to_name = iconv_wide_names_4;
- break;
-
- default:
- to_name = iconv_wide_names_unknown;
- break;
- }
-
-
- /*
- The line protocol fish uses is always utf-8.
- */
- const char **from_name = iconv_utf8_names;
-
- size_t in_len = strlen( in );
- size_t out_len = sizeof( wchar_t )*(in_len+2);
- size_t nconv;
- char *nout;
-
- out = (wchar_t *)malloc( out_len );
- nout = (char *)out;
-
- if( !out )
- return 0;
-
- for( i=0; to_name[i]; i++ )
- {
- for( j=0; from_name[j]; j++ )
- {
- cd = iconv_open ( to_name[i], from_name[j] );
-
- if( cd != (iconv_t) -1)
- {
- goto start_conversion;
-
- }
- }
- }
+ iconv_t cd=(iconv_t) -1;
+ int i,j;
+
+ wchar_t *out;
+
+ /*
+ Try to convert to wchar_t. If that is not a valid character set,
+ try various names for ucs-4. We can't be sure that ucs-4 is
+ really the character set used by wchar_t, but it is the best
+ assumption we can make.
+ */
+ const char **to_name=0;
+
+ switch (sizeof (wchar_t))
+ {
+
+ case 2:
+ to_name = iconv_wide_names_2;
+ break;
+
+ case 4:
+ to_name = iconv_wide_names_4;
+ break;
+
+ default:
+ to_name = iconv_wide_names_unknown;
+ break;
+ }
+
+
+ /*
+ The line protocol fish uses is always utf-8.
+ */
+ const char **from_name = iconv_utf8_names;
+
+ size_t in_len = strlen( in );
+ size_t out_len = sizeof( wchar_t )*(in_len+2);
+ size_t nconv;
+ char *nout;
+
+ out = (wchar_t *)malloc( out_len );
+ nout = (char *)out;
+
+ if( !out )
+ return 0;
+
+ for( i=0; to_name[i]; i++ )
+ {
+ for( j=0; from_name[j]; j++ )
+ {
+ cd = iconv_open ( to_name[i], from_name[j] );
+
+ if( cd != (iconv_t) -1)
+ {
+ goto start_conversion;
+
+ }
+ }
+ }
start_conversion:
- if (cd == (iconv_t) -1)
- {
- /* Something went wrong. */
- debug( 0, L"Could not perform utf-8 conversion" );
- if(errno != EINVAL)
- wperror( L"iconv_open" );
-
- /* Terminate the output string. */
- free(out);
- return 0;
- }
-
+ if (cd == (iconv_t) -1)
+ {
+ /* Something went wrong. */
+ debug( 0, L"Could not perform utf-8 conversion" );
+ if(errno != EINVAL)
+ wperror( L"iconv_open" );
+
+ /* Terminate the output string. */
+ free(out);
+ return 0;
+ }
+
/* FreeBSD has this prototype: size_t iconv (iconv_t, const char **...)
OS X and Linux this one: size_t iconv (iconv_t, char **...)
AFAIK there's no single type that can be passed as both char ** and const char **.
So we cast the function pointer instead (!)
*/
nconv = hack_iconv( cd, &in, &in_len, &nout, &out_len );
-
- if (nconv == (size_t) -1)
- {
- debug( 0, L"Error while converting from utf string" );
- return 0;
- }
-
- *((wchar_t *) nout) = L'\0';
-
- /*
- Check for silly iconv behaviour inserting an bytemark in the output
- string.
- */
- if (*out == L'\xfeff' || *out == L'\xffef' || *out == L'\xefbbbf')
- {
- wchar_t *out_old = out;
- out = wcsdup(out+1);
- if (! out )
- {
- debug(0, L"FNORD!!!!");
- free( out_old );
- return 0;
- }
- free( out_old );
- }
-
-
- if (iconv_close (cd) != 0)
- wperror (L"iconv_close");
-
- return out;
+
+ if (nconv == (size_t) -1)
+ {
+ debug( 0, L"Error while converting from utf string" );
+ return 0;
+ }
+
+ *((wchar_t *) nout) = L'\0';
+
+ /*
+ Check for silly iconv behaviour inserting an bytemark in the output
+ string.
+ */
+ if (*out == L'\xfeff' || *out == L'\xffef' || *out == L'\xefbbbf')
+ {
+ wchar_t *out_old = out;
+ out = wcsdup(out+1);
+ if (! out )
+ {
+ debug(0, L"FNORD!!!!");
+ free( out_old );
+ return 0;
+ }
+ free( out_old );
+ }
+
+
+ if (iconv_close (cd) != 0)
+ wperror (L"iconv_close");
+
+ return out;
}
@@ -313,113 +313,113 @@ static wchar_t *utf2wcs( const char *in )
*/
static char *wcs2utf( const wchar_t *in )
{
- iconv_t cd=(iconv_t) -1;
- int i,j;
-
- char *char_in = (char *)in;
- char *out;
-
- /*
- Try to convert to wchar_t. If that is not a valid character set,
- try various names for ucs-4. We can't be sure that ucs-4 is
- really the character set used by wchar_t, but it is the best
- assumption we can make.
- */
- const char **from_name=0;
-
- switch (sizeof (wchar_t))
- {
-
- case 2:
- from_name = iconv_wide_names_2;
- break;
-
- case 4:
- from_name = iconv_wide_names_4;
- break;
-
- default:
- from_name = iconv_wide_names_unknown;
- break;
- }
-
- const char **to_name = iconv_utf8_names;
-
- size_t in_len = wcslen( in );
- size_t out_len = sizeof( char )*( (MAX_UTF8_BYTES*in_len)+1);
- size_t nconv;
- char *nout;
-
- out = (char *)malloc( out_len );
- nout = (char *)out;
- in_len *= sizeof( wchar_t );
-
- if( !out )
- return 0;
-
- for( i=0; to_name[i]; i++ )
- {
- for( j=0; from_name[j]; j++ )
- {
- cd = iconv_open ( to_name[i], from_name[j] );
-
- if( cd != (iconv_t) -1)
- {
- goto start_conversion;
-
- }
- }
- }
+ iconv_t cd=(iconv_t) -1;
+ int i,j;
+
+ char *char_in = (char *)in;
+ char *out;
+
+ /*
+ Try to convert to wchar_t. If that is not a valid character set,
+ try various names for ucs-4. We can't be sure that ucs-4 is
+ really the character set used by wchar_t, but it is the best
+ assumption we can make.
+ */
+ const char **from_name=0;
+
+ switch (sizeof (wchar_t))
+ {
+
+ case 2:
+ from_name = iconv_wide_names_2;
+ break;
+
+ case 4:
+ from_name = iconv_wide_names_4;
+ break;
+
+ default:
+ from_name = iconv_wide_names_unknown;
+ break;
+ }
+
+ const char **to_name = iconv_utf8_names;
+
+ size_t in_len = wcslen( in );
+ size_t out_len = sizeof( char )*( (MAX_UTF8_BYTES*in_len)+1);
+ size_t nconv;
+ char *nout;
+
+ out = (char *)malloc( out_len );
+ nout = (char *)out;
+ in_len *= sizeof( wchar_t );
+
+ if( !out )
+ return 0;
+
+ for( i=0; to_name[i]; i++ )
+ {
+ for( j=0; from_name[j]; j++ )
+ {
+ cd = iconv_open ( to_name[i], from_name[j] );
+
+ if( cd != (iconv_t) -1)
+ {
+ goto start_conversion;
+
+ }
+ }
+ }
start_conversion:
- if (cd == (iconv_t) -1)
- {
- /* Something went wrong. */
- debug( 0, L"Could not perform utf-8 conversion" );
- if(errno != EINVAL)
- wperror( L"iconv_open" );
-
- /* Terminate the output string. */
- free(out);
- return 0;
- }
-
+ if (cd == (iconv_t) -1)
+ {
+ /* Something went wrong. */
+ debug( 0, L"Could not perform utf-8 conversion" );
+ if(errno != EINVAL)
+ wperror( L"iconv_open" );
+
+ /* Terminate the output string. */
+ free(out);
+ return 0;
+ }
+
nconv = hack_iconv( cd, &char_in, &in_len, &nout, &out_len );
-
-
- if (nconv == (size_t) -1)
- {
- debug( 0, L"%d %d", in_len, out_len );
- debug( 0, L"Error while converting from to string" );
- return 0;
- }
-
- *nout = '\0';
-
- if (iconv_close (cd) != 0)
- wperror (L"iconv_close");
-
- return out;
+
+
+ if (nconv == (size_t) -1)
+ {
+ debug( 0, L"%d %d", in_len, out_len );
+ debug( 0, L"Error while converting from to string" );
+ return 0;
+ }
+
+ *nout = '\0';
+
+ if (iconv_close (cd) != 0)
+ wperror (L"iconv_close");
+
+ return out;
}
void env_universal_common_init( void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val ) )
{
- callback = cb;
+ callback = cb;
}
void env_universal_common_destroy()
{
- env_var_table_t::iterator iter;
-
- for(iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
- {
- var_uni_entry_t* value = iter->second;
- delete value;
- }
+ env_var_table_t::iterator iter;
+
+ for(iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
+ {
+ var_uni_entry_t* value = iter->second;
+ delete value;
+ }
}
/**
@@ -428,115 +428,115 @@ void env_universal_common_destroy()
static int read_byte( connection_t *src )
{
- if( src->buffer_consumed >= src->buffer_used )
- {
-
- ssize_t res = read( src->fd, src->buffer, ENV_UNIVERSAL_BUFFER_SIZE );
-
-// debug(4, L"Read chunk '%.*s'", res, src->buffer );
-
- if( res < 0 )
- {
-
- if( errno == EAGAIN ||
- errno == EINTR )
- {
- return ENV_UNIVERSAL_AGAIN;
- }
-
- return ENV_UNIVERSAL_ERROR;
-
- }
-
- if( res == 0 )
- {
- return ENV_UNIVERSAL_EOF;
- }
-
- src->buffer_consumed = 0;
- src->buffer_used = res;
- }
-
- return src->buffer[src->buffer_consumed++];
+ if( src->buffer_consumed >= src->buffer_used )
+ {
+
+ ssize_t res = read( src->fd, src->buffer, ENV_UNIVERSAL_BUFFER_SIZE );
+
+// debug(4, L"Read chunk '%.*s'", res, src->buffer );
+
+ if( res < 0 )
+ {
+
+ if( errno == EAGAIN ||
+ errno == EINTR )
+ {
+ return ENV_UNIVERSAL_AGAIN;
+ }
+
+ return ENV_UNIVERSAL_ERROR;
+
+ }
+
+ if( res == 0 )
+ {
+ return ENV_UNIVERSAL_EOF;
+ }
+
+ src->buffer_consumed = 0;
+ src->buffer_used = res;
+ }
+
+ return src->buffer[src->buffer_consumed++];
}
void read_message( connection_t *src )
{
- while( 1 )
- {
-
- int ib = read_byte( src );
- char b;
-
- switch( ib )
- {
- case ENV_UNIVERSAL_AGAIN:
- {
- return;
- }
-
- case ENV_UNIVERSAL_ERROR:
- {
- debug( 2, L"Read error on fd %d, set killme flag", src->fd );
- if( debug_level > 2 )
- wperror( L"read" );
- src->killme = 1;
- return;
- }
-
- case ENV_UNIVERSAL_EOF:
- {
- src->killme = 1;
- debug( 3, L"Fd %d has reached eof, set killme flag", src->fd );
- if( src->input.size() > 0 )
- {
- char c = 0;
- src->input.push_back(c);
- debug( 1,
- L"Universal variable connection closed while reading command. Partial command recieved: '%s'",
- &src->input.at(0));
- }
- return;
- }
- }
-
- b = (char)ib;
-
- if( b == '\n' )
- {
- wchar_t *msg;
-
- b = 0;
+ while( 1 )
+ {
+
+ int ib = read_byte( src );
+ char b;
+
+ switch( ib )
+ {
+ case ENV_UNIVERSAL_AGAIN:
+ {
+ return;
+ }
+
+ case ENV_UNIVERSAL_ERROR:
+ {
+ debug( 2, L"Read error on fd %d, set killme flag", src->fd );
+ if( debug_level > 2 )
+ wperror( L"read" );
+ src->killme = 1;
+ return;
+ }
+
+ case ENV_UNIVERSAL_EOF:
+ {
+ src->killme = 1;
+ debug( 3, L"Fd %d has reached eof, set killme flag", src->fd );
+ if( src->input.size() > 0 )
+ {
+ char c = 0;
+ src->input.push_back(c);
+ debug( 1,
+ L"Universal variable connection closed while reading command. Partial command recieved: '%s'",
+ &src->input.at(0));
+ }
+ return;
+ }
+ }
+
+ b = (char)ib;
+
+ if( b == '\n' )
+ {
+ wchar_t *msg;
+
+ b = 0;
src->input.push_back(b);
-
- msg = utf2wcs( &src->input.at(0) );
-
- /*
- Before calling parse_message, we must empty reset
- everything, since the callback function could
- potentially call read_message.
- */
- src->input.clear();
-
- if( msg )
- {
- parse_message( msg, src );
- }
- else
- {
- debug( 0, _(L"Could not convert message '%s' to wide character string"), &src->input.at(0) );
- }
-
- free( msg );
-
- }
- else
- {
+
+ msg = utf2wcs( &src->input.at(0) );
+
+ /*
+ Before calling parse_message, we must empty reset
+ everything, since the callback function could
+ potentially call read_message.
+ */
+ src->input.clear();
+
+ if( msg )
+ {
+ parse_message( msg, src );
+ }
+ else
+ {
+ debug( 0, _(L"Could not convert message '%s' to wide character string"), &src->input.at(0) );
+ }
+
+ free( msg );
+
+ }
+ else
+ {
src->input.push_back(b);
- }
- }
+ }
+ }
}
/**
@@ -544,13 +544,13 @@ void read_message( connection_t *src )
*/
void env_universal_common_remove( const wcstring &name )
{
- env_var_table_t::iterator result = env_universal_var.find(name);
- if (result != env_universal_var.end())
- {
- var_uni_entry_t* v = result->second;
- env_universal_var.erase(result);
- delete v;
- }
+ env_var_table_t::iterator result = env_universal_var.find(name);
+ if (result != env_universal_var.end())
+ {
+ var_uni_entry_t* v = result->second;
+ env_universal_var.erase(result);
+ delete v;
+ }
}
/**
@@ -558,34 +558,34 @@ void env_universal_common_remove( const wcstring &name )
*/
static int match( const wchar_t *msg, const wchar_t *cmd )
{
- size_t len = wcslen( cmd );
- if( wcsncasecmp( msg, cmd, len ) != 0 )
- return 0;
-
- if( msg[len] && msg[len]!= L' ' && msg[len] != L'\t' )
- return 0;
-
- return 1;
+ size_t len = wcslen( cmd );
+ if( wcsncasecmp( msg, cmd, len ) != 0 )
+ return 0;
+
+ if( msg[len] && msg[len]!= L' ' && msg[len] != L'\t' )
+ return 0;
+
+ return 1;
}
void env_universal_common_set( const wchar_t *key, const wchar_t *val, int exportv )
{
- var_uni_entry_t *entry;
+ var_uni_entry_t *entry;
+
+ CHECK( key, );
+ CHECK( val, );
- CHECK( key, );
- CHECK( val, );
-
- entry = new var_uni_entry_t;
+ entry = new var_uni_entry_t;
+
+ entry->exportv=exportv;
+ entry->val = val;
+ env_universal_common_remove( key );
- entry->exportv=exportv;
- entry->val = val;
- env_universal_common_remove( key );
-
env_universal_var[key] = entry;
- if( callback )
- {
- callback( exportv?SET_EXPORT:SET, key, val );
- }
+ if( callback )
+ {
+ callback( exportv?SET_EXPORT:SET, key, val );
+ }
}
@@ -593,90 +593,90 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor
Parse message msg
*/
static void parse_message( wchar_t *msg,
- connection_t *src )
+ connection_t *src )
{
-// debug( 3, L"parse_message( %ls );", msg );
-
- if( msg[0] == L'#' )
- return;
-
- if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR ))
- {
- wchar_t *name, *tmp;
- int exportv = match( msg, SET_EXPORT_STR );
-
- name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR));
- while( wcschr( L"\t ", *name ) )
- name++;
-
- tmp = wcschr( name, L':' );
- if( tmp )
- {
- wchar_t *key;
- wchar_t *val;
-
- key = (wchar_t *)malloc( sizeof( wchar_t)*(tmp-name+1));
- memcpy( key, name, sizeof( wchar_t)*(tmp-name));
- key[tmp-name]=0;
-
- val = tmp+1;
- val = unescape( val, 0 );
-
- if (key && val)
- env_universal_common_set( key, val, exportv );
-
- free( val );
- free( key );
- }
- else
- {
- debug( 1, PARSE_ERR, msg );
- }
- }
- else if( match( msg, ERASE_STR ) )
- {
- wchar_t *name, *tmp;
-
- name = msg+wcslen(ERASE_STR);
- while( wcschr( L"\t ", *name ) )
- name++;
-
- tmp = name;
- while( iswalnum( *tmp ) || *tmp == L'_')
- tmp++;
-
- *tmp = 0;
-
- if( !wcslen( name ) )
- {
- debug( 1, PARSE_ERR, msg );
- }
-
- env_universal_common_remove( name );
-
- if( callback )
- {
- callback( ERASE, name, 0 );
- }
- }
- else if( match( msg, BARRIER_STR) )
- {
- message_t *msg = create_message( BARRIER_REPLY, 0, 0 );
- msg->count = 1;
+// debug( 3, L"parse_message( %ls );", msg );
+
+ if( msg[0] == L'#' )
+ return;
+
+ if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR ))
+ {
+ wchar_t *name, *tmp;
+ int exportv = match( msg, SET_EXPORT_STR );
+
+ name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR));
+ while( wcschr( L"\t ", *name ) )
+ name++;
+
+ tmp = wcschr( name, L':' );
+ if( tmp )
+ {
+ wchar_t *key;
+ wchar_t *val;
+
+ key = (wchar_t *)malloc( sizeof( wchar_t)*(tmp-name+1));
+ memcpy( key, name, sizeof( wchar_t)*(tmp-name));
+ key[tmp-name]=0;
+
+ val = tmp+1;
+ val = unescape( val, 0 );
+
+ if (key && val)
+ env_universal_common_set( key, val, exportv );
+
+ free( val );
+ free( key );
+ }
+ else
+ {
+ debug( 1, PARSE_ERR, msg );
+ }
+ }
+ else if( match( msg, ERASE_STR ) )
+ {
+ wchar_t *name, *tmp;
+
+ name = msg+wcslen(ERASE_STR);
+ while( wcschr( L"\t ", *name ) )
+ name++;
+
+ tmp = name;
+ while( iswalnum( *tmp ) || *tmp == L'_')
+ tmp++;
+
+ *tmp = 0;
+
+ if( !wcslen( name ) )
+ {
+ debug( 1, PARSE_ERR, msg );
+ }
+
+ env_universal_common_remove( name );
+
+ if( callback )
+ {
+ callback( ERASE, name, 0 );
+ }
+ }
+ else if( match( msg, BARRIER_STR) )
+ {
+ message_t *msg = create_message( BARRIER_REPLY, 0, 0 );
+ msg->count = 1;
src->unsent->push(msg);
- try_send_all( src );
- }
- else if( match( msg, BARRIER_REPLY_STR ) )
- {
- if( callback )
- {
- callback( BARRIER_REPLY, 0, 0 );
- }
- }
- else
- {
- debug( 1, PARSE_ERR, msg );
- }
+ try_send_all( src );
+ }
+ else if( match( msg, BARRIER_REPLY_STR ) )
+ {
+ if( callback )
+ {
+ callback( BARRIER_REPLY, 0, 0 );
+ }
+ }
+ else
+ {
+ debug( 1, PARSE_ERR, msg );
+ }
}
/**
@@ -685,72 +685,72 @@ static void parse_message( wchar_t *msg,
\return 1 on sucess, 0 if the message could not be sent without blocking and -1 on error
*/
static int try_send( message_t *msg,
- int fd )
+ int fd )
{
- debug( 3,
- L"before write of %d chars to fd %d", msg->body.size(), fd );
-
- ssize_t res = write( fd, msg->body.c_str(), msg->body.size() );
-
- if( res != -1 )
- {
- debug( 4, L"Wrote message '%s'", msg->body.c_str() );
- }
- else
- {
- debug( 4, L"Failed to write message '%s'", msg->body.c_str() );
- }
-
- if( res == -1 )
- {
- switch( errno )
- {
- case EAGAIN:
- return 0;
-
- default:
- debug( 2,
- L"Error while sending universal variable message to fd %d. Closing connection",
- fd );
- if( debug_level > 2 )
- wperror( L"write" );
-
- return -1;
- }
- }
- msg->count--;
-
- if( !msg->count )
- {
- delete msg;
- }
- return 1;
+ debug( 3,
+ L"before write of %d chars to fd %d", msg->body.size(), fd );
+
+ ssize_t res = write( fd, msg->body.c_str(), msg->body.size() );
+
+ if( res != -1 )
+ {
+ debug( 4, L"Wrote message '%s'", msg->body.c_str() );
+ }
+ else
+ {
+ debug( 4, L"Failed to write message '%s'", msg->body.c_str() );
+ }
+
+ if( res == -1 )
+ {
+ switch( errno )
+ {
+ case EAGAIN:
+ return 0;
+
+ default:
+ debug( 2,
+ L"Error while sending universal variable message to fd %d. Closing connection",
+ fd );
+ if( debug_level > 2 )
+ wperror( L"write" );
+
+ return -1;
+ }
+ }
+ msg->count--;
+
+ if( !msg->count )
+ {
+ delete msg;
+ }
+ return 1;
}
void try_send_all( connection_t *c )
{
-/* debug( 3,
- L"Send all updates to connection on fd %d",
- c->fd );*/
- while( !c->unsent->empty() )
- {
- switch( try_send( c->unsent->front(), c->fd ) )
- {
- case 1:
- c->unsent->pop();
- break;
-
- case 0:
- debug( 4,
- L"Socket full, send rest later" );
- return;
-
- case -1:
- c->killme = 1;
- return;
- }
- }
+/* debug( 3,
+ L"Send all updates to connection on fd %d",
+ c->fd );*/
+ while( !c->unsent->empty() )
+ {
+ switch( try_send( c->unsent->front(), c->fd ) )
+ {
+ case 1:
+ c->unsent->pop();
+ break;
+
+ case 0:
+ debug( 4,
+ L"Socket full, send rest later" );
+ return;
+
+ case -1:
+ c->killme = 1;
+ return;
+ }
+ }
}
/* The universal variable format has some funny escaping requirements; here we try to be safe */
@@ -758,7 +758,7 @@ static bool is_universal_safe_to_encode_directly(wchar_t c)
{
if (c < 32 || c > 128)
return false;
-
+
return iswalnum(c) || wcschr(L"/", c);
}
@@ -767,28 +767,28 @@ static bool is_universal_safe_to_encode_directly(wchar_t c)
*/
static wcstring full_escape( const wchar_t *in )
{
- wcstring out;
- for( ; *in; in++ )
- {
+ wcstring out;
+ for( ; *in; in++ )
+ {
wchar_t c = *in;
if (is_universal_safe_to_encode_directly(c))
{
out.push_back(c);
}
- else if (c < 256)
- {
- append_format(out, L"\\x%.2x", c);
- }
- else if (c < 65536)
- {
- append_format(out, L"\\u%.4x", c);
- }
- else
- {
- append_format(out, L"\\U%.8x", c);
- }
- }
- return out;
+ else if (c < 256)
+ {
+ append_format(out, L"\\x%.2x", c);
+ }
+ else if (c < 65536)
+ {
+ append_format(out, L"\\u%.4x", c);
+ }
+ else
+ {
+ append_format(out, L"\\U%.8x", c);
+ }
+ }
+ return out;
}
/* Sets the body of a message to the null-terminated list of null terminated const char *. */
@@ -798,19 +798,19 @@ void set_body(message_t *msg, ...)
size_t body_len = 0;
const char *arg;
va_list arg_list;
- va_start(arg_list, msg);
- while ((arg = va_arg(arg_list, const char *)) != NULL)
- body_len += strlen(arg);
- va_end(arg_list);
-
+ va_start(arg_list, msg);
+ while ((arg = va_arg(arg_list, const char *)) != NULL)
+ body_len += strlen(arg);
+ va_end(arg_list);
+
/* Reserve that length in the string */
msg->body.reserve(body_len + 1); //+1 for trailing NULL? Do I need that?
-
+
/* Set the string contents */
- va_start(arg_list, msg);
- while ((arg = va_arg(arg_list, const char *)) != NULL)
- msg->body.append(arg);
- va_end(arg_list);
+ va_start(arg_list, msg);
+ while ((arg = va_arg(arg_list, const char *)) != NULL)
+ msg->body.append(arg);
+ va_end(arg_list);
}
/* Returns an instance of message_t allocated via new */
@@ -818,169 +818,169 @@ message_t *create_message( fish_message_type_t type,
const wchar_t *key_in,
const wchar_t *val_in )
{
- message_t *msg = new message_t;
+ message_t *msg = new message_t;
msg->count = 0;
-
- char *key=0;
-
- // debug( 4, L"Crete message of type %d", type );
-
- if( key_in )
- {
- if( wcsvarname( key_in ) )
- {
- debug( 0, L"Illegal variable name: '%ls'", key_in );
- return 0;
- }
-
- key = wcs2utf(key_in);
- if( !key )
- {
- debug( 0,
+
+ char *key=0;
+
+ // debug( 4, L"Crete message of type %d", type );
+
+ if( key_in )
+ {
+ if( wcsvarname( key_in ) )
+ {
+ debug( 0, L"Illegal variable name: '%ls'", key_in );
+ return 0;
+ }
+
+ key = wcs2utf(key_in);
+ if( !key )
+ {
+ debug( 0,
L"Could not convert %ls to narrow character string",
key_in );
- return 0;
- }
- }
-
-
- switch( type )
- {
- case SET:
- case SET_EXPORT:
- {
- if( !val_in )
- {
- val_in=L"";
- }
-
- wcstring esc = full_escape( val_in );
- char *val = wcs2utf(esc.c_str());
+ return 0;
+ }
+ }
+
+
+ switch( type )
+ {
+ case SET:
+ case SET_EXPORT:
+ {
+ if( !val_in )
+ {
+ val_in=L"";
+ }
+
+ wcstring esc = full_escape( val_in );
+ char *val = wcs2utf(esc.c_str());
set_body(msg, (type==SET?SET_MBS:SET_EXPORT_MBS), " ", key, ":", val, "\n", NULL);
- free( val );
-
- break;
- }
-
- case ERASE:
- {
+ free( val );
+
+ break;
+ }
+
+ case ERASE:
+ {
set_body(msg, ERASE_MBS, " ", key, "\n", NULL);
break;
- }
-
- case BARRIER:
- {
+ }
+
+ case BARRIER:
+ {
set_body(msg, BARRIER_MBS, "\n", NULL);
- break;
- }
-
- case BARRIER_REPLY:
- {
+ break;
+ }
+
+ case BARRIER_REPLY:
+ {
set_body(msg, BARRIER_REPLY_MBS, "\n", NULL);
- break;
- }
-
- default:
- {
- debug( 0, L"create_message: Unknown message type" );
- }
- }
-
- free( key );
-
- // debug( 4, L"Message body is '%s'", msg->body );
-
- return msg;
+ break;
+ }
+
+ default:
+ {
+ debug( 0, L"create_message: Unknown message type" );
+ }
+ }
+
+ free( key );
+
+ // debug( 4, L"Message body is '%s'", msg->body );
+
+ return msg;
}
/**
- Put exported or unexported variables in a string list
-*/
+ Put exported or unexported variables in a string list
+*/
void env_universal_common_get_names( wcstring_list_t &lst,
- int show_exported,
- int show_unexported )
+ int show_exported,
+ int show_unexported )
{
- env_var_table_t::const_iterator iter;
- for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
- {
- const wcstring& key = iter->first;
- const var_uni_entry_t *e = iter->second;
- if( ( e->exportv && show_exported) ||
- ( !e->exportv && show_unexported) )
- {
- lst.push_back(key);
- }
-
- }
+ env_var_table_t::const_iterator iter;
+ for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
+ {
+ const wcstring& key = iter->first;
+ const var_uni_entry_t *e = iter->second;
+ if( ( e->exportv && show_exported) ||
+ ( !e->exportv && show_unexported) )
+ {
+ lst.push_back(key);
+ }
+
+ }
}
wchar_t *env_universal_common_get( const wcstring &name )
{
- env_var_table_t::const_iterator result = env_universal_var.find(name);
+ env_var_table_t::const_iterator result = env_universal_var.find(name);
- if (result != env_universal_var.end() )
- {
- const var_uni_entry_t *e = result->second;
- if( e )
- return const_cast<wchar_t*>(e->val.c_str());
- }
+ if (result != env_universal_var.end() )
+ {
+ const var_uni_entry_t *e = result->second;
+ if( e )
+ return const_cast<wchar_t*>(e->val.c_str());
+ }
- return 0;
+ return 0;
}
int env_universal_common_get_export( const wcstring &name )
{
- env_var_table_t::const_iterator result = env_universal_var.find(name);
- if (result != env_universal_var.end() )
- {
- const var_uni_entry_t *e = result->second;
- if (e != NULL)
- return e->exportv;
- }
- return 0;
+ env_var_table_t::const_iterator result = env_universal_var.find(name);
+ if (result != env_universal_var.end() )
+ {
+ const var_uni_entry_t *e = result->second;
+ if (e != NULL)
+ return e->exportv;
+ }
+ return 0;
}
void enqueue_all( connection_t *c )
{
- env_var_table_t::const_iterator iter;
-
- for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
- {
- const wcstring &key = iter->first;
- const var_uni_entry_t *val = iter->second;
-
- message_t *msg = create_message( val->exportv?SET_EXPORT:SET, key.c_str(), val->val.c_str() );
- msg->count=1;
- c->unsent->push(msg);
- }
-
- try_send_all( c );
+ env_var_table_t::const_iterator iter;
+
+ for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
+ {
+ const wcstring &key = iter->first;
+ const var_uni_entry_t *val = iter->second;
+
+ message_t *msg = create_message( val->exportv?SET_EXPORT:SET, key.c_str(), val->val.c_str() );
+ msg->count=1;
+ c->unsent->push(msg);
+ }
+
+ try_send_all( c );
}
void connection_init( connection_t *c, int fd )
{
- memset (c, 0, sizeof (connection_t));
- c->fd = fd;
+ memset (c, 0, sizeof (connection_t));
+ c->fd = fd;
c->unsent = new std::queue<message_t *>;
- c->buffer_consumed = c->buffer_used = 0;
+ c->buffer_consumed = c->buffer_used = 0;
}
void connection_destroy( connection_t *c)
{
if (c->unsent) delete c->unsent;
- /*
- A connection need not always be open - we only try to close it
- if it is open.
- */
- if( c->fd >= 0 )
- {
- if( close( c->fd ) )
- {
- wperror( L"close" );
- }
- }
+ /*
+ A connection need not always be open - we only try to close it
+ if it is open.
+ */
+ if( c->fd >= 0 )
+ {
+ if( close( c->fd ) )
+ {
+ wperror( L"close" );
+ }
+ }
}
diff --git a/env_universal_common.h b/env_universal_common.h
index 7da8cd63..d783da54 100644
--- a/env_universal_common.h
+++ b/env_universal_common.h
@@ -42,11 +42,11 @@
*/
typedef enum
{
- SET,
- SET_EXPORT,
- ERASE,
- BARRIER,
- BARRIER_REPLY,
+ SET,
+ SET_EXPORT,
+ ERASE,
+ BARRIER,
+ BARRIER_REPLY,
} fish_message_type_t;
/**
@@ -57,18 +57,18 @@ typedef enum
/**
A struct representing a message to be sent between client and server
*/
-typedef struct
+typedef struct
{
- /**
- Number of queues that contain this message. Once this reaches zero, the message should be deleted
- */
- int count;
-
- /**
- Message body. The message must be allocated using enough memory to actually contain the message.
- */
- std::string body;
-
+ /**
+ Number of queues that contain this message. Once this reaches zero, the message should be deleted
+ */
+ int count;
+
+ /**
+ Message body. The message must be allocated using enough memory to actually contain the message.
+ */
+ std::string body;
+
} message_t;
typedef std::queue<message_t *> message_queue_t;
@@ -78,46 +78,46 @@ typedef std::queue<message_t *> message_queue_t;
*/
typedef struct connection
{
- /**
- The file descriptor this socket lives on
- */
- int fd;
- /**
- Queue of onsent messages
- */
+ /**
+ The file descriptor this socket lives on
+ */
+ int fd;
+ /**
+ Queue of onsent messages
+ */
message_queue_t *unsent;
- /**
- Set to one when this connection should be killed
- */
- int killme;
- /**
- The input string. Input from the socket goes here. When a
- newline is encountered, the buffer is parsed and cleared.
- */
- std::vector<char> input;
-
- /**
- The read buffer.
- */
- char buffer[ENV_UNIVERSAL_BUFFER_SIZE];
-
- /**
- Number of bytes that have already been consumed.
- */
- size_t buffer_consumed;
-
- /**
- Number of bytes that have been read into the buffer.
- */
- size_t buffer_used;
-
-
- /**
- Link to the next connection
- */
- struct connection *next;
+ /**
+ Set to one when this connection should be killed
+ */
+ int killme;
+ /**
+ The input string. Input from the socket goes here. When a
+ newline is encountered, the buffer is parsed and cleared.
+ */
+ std::vector<char> input;
+
+ /**
+ The read buffer.
+ */
+ char buffer[ENV_UNIVERSAL_BUFFER_SIZE];
+
+ /**
+ Number of bytes that have already been consumed.
+ */
+ size_t buffer_consumed;
+
+ /**
+ Number of bytes that have been read into the buffer.
+ */
+ size_t buffer_used;
+
+
+ /**
+ Link to the next connection
+ */
+ struct connection *next;
}
- connection_t;
+ connection_t;
/**
Read all available messages on this connection
@@ -151,8 +151,8 @@ void env_universal_common_destroy();
variables, it does not communicate with any other process.
*/
void env_universal_common_get_names( wcstring_list_t &lst,
- int show_exported,
- int show_unexported );
+ int show_exported,
+ int show_unexported );
/**
Perform the specified variable assignment.
@@ -166,7 +166,7 @@ void env_universal_common_get_names( wcstring_list_t &lst,
void env_universal_common_set( const wchar_t *key, const wchar_t *val, int exportv );
/**
- Remove the specified variable.
+ Remove the specified variable.
This function operate agains the local copy of all universal
variables, it does not communicate with any other process.
diff --git a/event.cpp b/event.cpp
index fc04ab13..371a3a34 100644
--- a/event.cpp
+++ b/event.cpp
@@ -1,6 +1,6 @@
/** \file event.c
- Functions for handling event triggers
+ Functions for handling event triggers
*/
#include "config.h"
@@ -36,20 +36,20 @@
*/
typedef struct
{
- /**
- Number of delivered signals
- */
- int count;
- /**
- Whether signals have been skipped
- */
- int overflow;
- /**
- Array of signal events
- */
- int signal[SIG_UNHANDLED_MAX];
+ /**
+ Number of delivered signals
+ */
+ int count;
+ /**
+ Whether signals have been skipped
+ */
+ int overflow;
+ /**
+ Array of signal events
+ */
+ int signal[SIG_UNHANDLED_MAX];
}
- signal_list_t;
+ signal_list_t;
/**
The signal event list. Actually two separate lists. One which is
@@ -63,7 +63,7 @@ static signal_list_t sig_list[]={{0,0},{0,0}};
*/
static int active_list=0;
-typedef std::vector<event_t *> event_list_t;
+typedef std::vector<event_t *> event_list_t;
/**
List of event handlers.
@@ -90,48 +90,48 @@ static int event_match( const event_t *classv, const event_t *instance )
{
/* If the function names are both non-empty and different, then it's not a match */
- if( ! classv->function_name.empty() &&
+ if( ! classv->function_name.empty() &&
! instance->function_name.empty() &&
classv->function_name != instance->function_name)
- {
+ {
return 0;
- }
-
- if( classv->type == EVENT_ANY )
- return 1;
-
- if( classv->type != instance->type )
- return 0;
-
-
- switch( classv->type )
- {
-
- case EVENT_SIGNAL:
- if( classv->param1.signal == EVENT_ANY_SIGNAL )
- return 1;
- return classv->param1.signal == instance->param1.signal;
-
- case EVENT_VARIABLE:
- return instance->str_param1 == classv->str_param1;
-
- case EVENT_EXIT:
- if( classv->param1.pid == EVENT_ANY_PID )
- return 1;
- return classv->param1.pid == instance->param1.pid;
-
- case EVENT_JOB_ID:
- return classv->param1.job_id == instance->param1.job_id;
-
- case EVENT_GENERIC:
- return instance->str_param1 == classv->str_param1;
-
- }
-
- /**
- This should never be reached
- */
- return 0;
+ }
+
+ if( classv->type == EVENT_ANY )
+ return 1;
+
+ if( classv->type != instance->type )
+ return 0;
+
+
+ switch( classv->type )
+ {
+
+ case EVENT_SIGNAL:
+ if( classv->param1.signal == EVENT_ANY_SIGNAL )
+ return 1;
+ return classv->param1.signal == instance->param1.signal;
+
+ case EVENT_VARIABLE:
+ return instance->str_param1 == classv->str_param1;
+
+ case EVENT_EXIT:
+ if( classv->param1.pid == EVENT_ANY_PID )
+ return 1;
+ return classv->param1.pid == instance->param1.pid;
+
+ case EVENT_JOB_ID:
+ return classv->param1.job_id == instance->param1.job_id;
+
+ case EVENT_GENERIC:
+ return instance->str_param1 == classv->str_param1;
+
+ }
+
+ /**
+ This should never be reached
+ */
+ return 0;
}
@@ -142,14 +142,14 @@ static int event_match( const event_t *classv, const event_t *instance )
static event_t *event_copy( const event_t *event, int copy_arguments )
{
event_t *e = new event_t(*event);
-
+
e->arguments.reset(new wcstring_list_t);
- if( copy_arguments && event->arguments.get() != NULL )
- {
- *(e->arguments) = *(event->arguments);
- }
-
- return e;
+ if( copy_arguments && event->arguments.get() != NULL )
+ {
+ *(e->arguments) = *(event->arguments);
+ }
+
+ return e;
}
/**
@@ -157,71 +157,71 @@ static event_t *event_copy( const event_t *event, int copy_arguments )
*/
static int event_is_blocked( event_t *e )
{
- block_t *block;
- parser_t &parser = parser_t::principal_parser();
- for( block = parser.current_block; block; block = block->outer )
- {
+ block_t *block;
+ parser_t &parser = parser_t::principal_parser();
+ for( block = parser.current_block; block; block = block->outer )
+ {
if (event_block_list_blocks_type(block->event_blocks, e->type))
return true;
- }
+ }
return event_block_list_blocks_type(parser.global_event_blocks, e->type);
}
wcstring event_get_desc( const event_t *e )
{
- CHECK( e, 0 );
+ CHECK( e, 0 );
+
+ wcstring result;
+ switch( e->type )
+ {
- wcstring result;
- switch( e->type )
- {
-
- case EVENT_SIGNAL:
+ case EVENT_SIGNAL:
result = format_string(_(L"signal handler for %ls (%ls)"), sig2wcs(e->param1.signal ), signal_get_desc( e->param1.signal ));
- break;
-
- case EVENT_VARIABLE:
- result = format_string(_(L"handler for variable '%ls'"), e->str_param1.c_str() );
- break;
-
- case EVENT_EXIT:
- if( e->param1.pid > 0 )
- {
- result = format_string(_(L"exit handler for process %d"), e->param1.pid );
- }
- else
- {
- job_t *j = job_get_from_pid( -e->param1.pid );
- if( j )
- result = format_string(_(L"exit handler for job %d, '%ls'"), j->job_id, j->command_wcstr() );
- else
- result = format_string(_(L"exit handler for job with process group %d"), -e->param1.pid );
- }
-
- break;
-
- case EVENT_JOB_ID:
- {
- job_t *j = job_get( e->param1.job_id );
- if( j )
- result = format_string(_(L"exit handler for job %d, '%ls'"), j->job_id, j->command_wcstr() );
- else
- result = format_string(_(L"exit handler for job with job id %d"), e->param1.job_id );
-
- break;
- }
-
- case EVENT_GENERIC:
- result = format_string(_(L"handler for generic event '%ls'"), e->str_param1.c_str() );
- break;
-
- default:
- result = format_string(_(L"Unknown event type") );
- break;
-
- }
-
- return result;
+ break;
+
+ case EVENT_VARIABLE:
+ result = format_string(_(L"handler for variable '%ls'"), e->str_param1.c_str() );
+ break;
+
+ case EVENT_EXIT:
+ if( e->param1.pid > 0 )
+ {
+ result = format_string(_(L"exit handler for process %d"), e->param1.pid );
+ }
+ else
+ {
+ job_t *j = job_get_from_pid( -e->param1.pid );
+ if( j )
+ result = format_string(_(L"exit handler for job %d, '%ls'"), j->job_id, j->command_wcstr() );
+ else
+ result = format_string(_(L"exit handler for job with process group %d"), -e->param1.pid );
+ }
+
+ break;
+
+ case EVENT_JOB_ID:
+ {
+ job_t *j = job_get( e->param1.job_id );
+ if( j )
+ result = format_string(_(L"exit handler for job %d, '%ls'"), j->job_id, j->command_wcstr() );
+ else
+ result = format_string(_(L"exit handler for job with job id %d"), e->param1.job_id );
+
+ break;
+ }
+
+ case EVENT_GENERIC:
+ result = format_string(_(L"handler for generic event '%ls'"), e->str_param1.c_str() );
+ break;
+
+ default:
+ result = format_string(_(L"Unknown event type") );
+ break;
+
+ }
+
+ return result;
}
#if 0
@@ -237,17 +237,17 @@ static void show_all_handlers(void) {
void event_add_handler( const event_t *event )
{
- event_t *e;
+ event_t *e;
- CHECK( event, );
-
- e = event_copy( event, 0 );
+ CHECK( event, );
+
+ e = event_copy( event, 0 );
+
+ if( e->type == EVENT_SIGNAL )
+ {
+ signal_handle( e->param1.signal, 1 );
+ }
- if( e->type == EVENT_SIGNAL )
- {
- signal_handle( e->param1.signal, 1 );
- }
-
// Block around updating the events vector
signal_block();
events.push_back(e);
@@ -257,75 +257,75 @@ void event_add_handler( const event_t *event )
void event_remove( event_t *criterion )
{
- size_t i;
- event_list_t new_list;
-
- CHECK( criterion, );
-
- /*
- Because of concurrency issues (env_remove could remove an event
- that is currently being executed), env_remove does not actually
- free any events - instead it simply moves all events that should
- be removed from the event list to the killme list, and the ones
- that shouldn't be killed to new_list, and then drops the empty
- events-list.
- */
-
- if( events.empty() )
- return;
-
- for( i=0; i<events.size(); i++ )
- {
- event_t *n = events.at(i);
- if( event_match( criterion, n ) )
- {
+ size_t i;
+ event_list_t new_list;
+
+ CHECK( criterion, );
+
+ /*
+ Because of concurrency issues (env_remove could remove an event
+ that is currently being executed), env_remove does not actually
+ free any events - instead it simply moves all events that should
+ be removed from the event list to the killme list, and the ones
+ that shouldn't be killed to new_list, and then drops the empty
+ events-list.
+ */
+
+ if( events.empty() )
+ return;
+
+ for( i=0; i<events.size(); i++ )
+ {
+ event_t *n = events.at(i);
+ if( event_match( criterion, n ) )
+ {
killme.push_back(n);
- /*
- If this event was a signal handler and no other handler handles
- the specified signal type, do not handle that type of signal any
- more.
- */
- if( n->type == EVENT_SIGNAL )
- {
+ /*
+ If this event was a signal handler and no other handler handles
+ the specified signal type, do not handle that type of signal any
+ more.
+ */
+ if( n->type == EVENT_SIGNAL )
+ {
event_t e = event_t::signal_event(n->param1.signal);
- if( event_get( &e, 0 ) == 1 )
- {
- signal_handle( e.param1.signal, 0 );
- }
- }
- }
- else
- {
+ if( event_get( &e, 0 ) == 1 )
+ {
+ signal_handle( e.param1.signal, 0 );
+ }
+ }
+ }
+ else
+ {
new_list.push_back(n);
- }
- }
+ }
+ }
signal_block();
- events.swap(new_list);
+ events.swap(new_list);
signal_unblock();
}
int event_get( event_t *criterion, std::vector<event_t *> *out )
{
- size_t i;
- int found = 0;
-
- if( events.empty() )
- return 0;
-
- CHECK( criterion, 0 );
-
- for( i=0; i<events.size(); i++ )
- {
- event_t *n = events.at(i);
- if( event_match(criterion, n ) )
- {
- found++;
- if( out )
+ size_t i;
+ int found = 0;
+
+ if( events.empty() )
+ return 0;
+
+ CHECK( criterion, 0 );
+
+ for( i=0; i<events.size(); i++ )
+ {
+ event_t *n = events.at(i);
+ if( event_match(criterion, n ) )
+ {
+ found++;
+ if( out )
out->push_back(n);
- }
- }
- return found;
+ }
+ }
+ return found;
}
bool event_is_signal_observed(int sig)
@@ -365,7 +365,7 @@ static void event_free_kills()
static int event_is_killed( event_t *e )
{
return std::find(killme.begin(), killme.end(), e) != killme.end();
-}
+}
/**
Perform the specified event. Since almost all event firings will
@@ -376,96 +376,96 @@ static int event_is_killed( event_t *e )
static void event_fire_internal( const event_t *event )
{
- size_t i, j;
- event_list_t fire;
-
- /*
- First we free all events that have been removed
- */
- event_free_kills();
-
- if( events.empty() )
- return;
-
- /*
- Then we iterate over all events, adding events that should be
- fired to a second list. We need to do this in a separate step
- since an event handler might call event_remove or
- event_add_handler, which will change the contents of the \c
- events list.
- */
- for( i=0; i<events.size(); i++ )
- {
- event_t *criterion = events.at(i);
-
- /*
- Check if this event is a match
- */
- if(event_match( criterion, event ) )
- {
+ size_t i, j;
+ event_list_t fire;
+
+ /*
+ First we free all events that have been removed
+ */
+ event_free_kills();
+
+ if( events.empty() )
+ return;
+
+ /*
+ Then we iterate over all events, adding events that should be
+ fired to a second list. We need to do this in a separate step
+ since an event handler might call event_remove or
+ event_add_handler, which will change the contents of the \c
+ events list.
+ */
+ for( i=0; i<events.size(); i++ )
+ {
+ event_t *criterion = events.at(i);
+
+ /*
+ Check if this event is a match
+ */
+ if(event_match( criterion, event ) )
+ {
fire.push_back(criterion);
- }
- }
-
- /*
- No matches. Time to return.
- */
- if( fire.empty() )
- return;
-
- /*
- Iterate over our list of matching events
- */
-
- for( i=0; i<fire.size(); i++ )
- {
- event_t *criterion = fire.at(i);
- int prev_status;
-
- /*
- Check if this event has been removed, if so, dont fire it
- */
- if( event_is_killed( criterion ) )
- continue;
-
- /*
- Fire event
- */
- wcstring buffer = criterion->function_name;
-
+ }
+ }
+
+ /*
+ No matches. Time to return.
+ */
+ if( fire.empty() )
+ return;
+
+ /*
+ Iterate over our list of matching events
+ */
+
+ for( i=0; i<fire.size(); i++ )
+ {
+ event_t *criterion = fire.at(i);
+ int prev_status;
+
+ /*
+ Check if this event has been removed, if so, dont fire it
+ */
+ if( event_is_killed( criterion ) )
+ continue;
+
+ /*
+ Fire event
+ */
+ wcstring buffer = criterion->function_name;
+
if (event->arguments.get())
{
for( j=0; j< event->arguments->size(); j++ )
{
- wcstring arg_esc = escape_string( event->arguments->at(j), 1 );
+ wcstring arg_esc = escape_string( event->arguments->at(j), 1 );
buffer += L" ";
buffer += arg_esc;
}
}
-// debug( 1, L"Event handler fires command '%ls'", buffer.c_str() );
-
- /*
- Event handlers are not part of the main flow of code, so
- they are marked as non-interactive
- */
- proc_push_interactive(0);
- prev_status = proc_get_last_status();
+// debug( 1, L"Event handler fires command '%ls'", buffer.c_str() );
+
+ /*
+ Event handlers are not part of the main flow of code, so
+ they are marked as non-interactive
+ */
+ proc_push_interactive(0);
+ prev_status = proc_get_last_status();
parser_t &parser = parser_t::principal_parser();
-
+
block_t *block = new event_block_t(event);
- parser.push_block(block);
- parser.eval( buffer, io_chain_t(), TOP );
- parser.pop_block();
- proc_pop_interactive();
- proc_set_last_status( prev_status );
- }
-
- /*
- Free killed events
- */
- event_free_kills();
-
+ parser.push_block(block);
+ parser.eval( buffer, io_chain_t(), TOP );
+ parser.pop_block();
+ proc_pop_interactive();
+ proc_set_last_status( prev_status );
+ }
+
+ /*
+ Free killed events
+ */
+ event_free_kills();
+
}
/**
@@ -474,78 +474,78 @@ static void event_fire_internal( const event_t *event )
static void event_fire_delayed()
{
- size_t i;
-
- /*
- If is_event is one, we are running the event-handler non-recursively.
-
- When the event handler has called a piece of code that triggers
- another event, we do not want to fire delayed events because of
- concurrency problems.
- */
- if( ! blocked.empty() && is_event==1)
- {
- event_list_t new_blocked;
-
- for( i=0; i<blocked.size(); i++ )
- {
- event_t *e = blocked.at(i);
- if( event_is_blocked( e ) )
- {
+ size_t i;
+
+ /*
+ If is_event is one, we are running the event-handler non-recursively.
+
+ When the event handler has called a piece of code that triggers
+ another event, we do not want to fire delayed events because of
+ concurrency problems.
+ */
+ if( ! blocked.empty() && is_event==1)
+ {
+ event_list_t new_blocked;
+
+ for( i=0; i<blocked.size(); i++ )
+ {
+ event_t *e = blocked.at(i);
+ if( event_is_blocked( e ) )
+ {
new_blocked.push_back(e);
- }
- else
- {
- event_fire_internal( e );
- event_free( e );
- }
- }
+ }
+ else
+ {
+ event_fire_internal( e );
+ event_free( e );
+ }
+ }
blocked.swap(new_blocked);
- }
-
- while( sig_list[active_list].count > 0 )
- {
- signal_list_t *lst;
-
- /*
- Switch signal lists
- */
- sig_list[1-active_list].count=0;
- sig_list[1-active_list].overflow=0;
- active_list=1-active_list;
-
- /*
- Set up
- */
+ }
+
+ while( sig_list[active_list].count > 0 )
+ {
+ signal_list_t *lst;
+
+ /*
+ Switch signal lists
+ */
+ sig_list[1-active_list].count=0;
+ sig_list[1-active_list].overflow=0;
+ active_list=1-active_list;
+
+ /*
+ Set up
+ */
event_t e = event_t::signal_event(0);
e.arguments.reset(new wcstring_list_t(1)); //one element
- lst = &sig_list[1-active_list];
-
- if( lst->overflow )
- {
- debug( 0, _( L"Signal list overflow. Signals have been ignored." ) );
- }
-
- /*
- Send all signals in our private list
- */
- for( int i=0; i < lst->count; i++ )
- {
- e.param1.signal = lst->signal[i];
+ lst = &sig_list[1-active_list];
+
+ if( lst->overflow )
+ {
+ debug( 0, _( L"Signal list overflow. Signals have been ignored." ) );
+ }
+
+ /*
+ Send all signals in our private list
+ */
+ for( int i=0; i < lst->count; i++ )
+ {
+ e.param1.signal = lst->signal[i];
e.arguments->at(0) = sig2wcs( e.param1.signal );
- if( event_is_blocked( &e ) )
- {
+ if( event_is_blocked( &e ) )
+ {
blocked.push_back(event_copy(&e, 1));
- }
- else
- {
- event_fire_internal( &e );
- }
- }
-
+ }
+ else
+ {
+ event_fire_internal( &e );
+ }
+ }
+
e.arguments.reset(NULL);
-
- }
+
+ }
}
void event_fire_signal(int signal)
@@ -565,33 +565,33 @@ void event_fire_signal(int signal)
void event_fire( event_t *event )
{
-
- if( event && (event->type == EVENT_SIGNAL) )
- {
+
+ if( event && (event->type == EVENT_SIGNAL) )
+ {
event_fire_signal(event->param1.signal);
- }
- else
- {
+ }
+ else
+ {
is_event++;
- /*
- Fire events triggered by signals
- */
- event_fire_delayed();
-
- if( event )
- {
- if( event_is_blocked( event ) )
- {
+ /*
+ Fire events triggered by signals
+ */
+ event_fire_delayed();
+
+ if( event )
+ {
+ if( event_is_blocked( event ) )
+ {
blocked.push_back(event_copy(event, 1));
- }
- else
- {
- event_fire_internal( event );
- }
- }
+ }
+ else
+ {
+ event_fire_internal( event );
+ }
+ }
is_event--;
- }
+ }
}
@@ -604,36 +604,36 @@ void event_destroy()
for_each(events.begin(), events.end(), event_free);
events.clear();
-
+
for_each(killme.begin(), killme.end(), event_free);
killme.clear();
}
void event_free( event_t *e )
{
- CHECK( e, );
+ CHECK( e, );
delete e;
}
void event_fire_generic_internal(const wchar_t *name, ...)
{
- va_list va;
- wchar_t *arg;
+ va_list va;
+ wchar_t *arg;
- CHECK( name, );
+ CHECK( name, );
- event_t ev(EVENT_GENERIC);
- ev.str_param1 = name;
+ event_t ev(EVENT_GENERIC);
+ ev.str_param1 = name;
ev.arguments.reset(new wcstring_list_t);
- va_start( va, name );
- while( (arg=va_arg(va, wchar_t *) )!= 0 )
- {
+ va_start( va, name );
+ while( (arg=va_arg(va, wchar_t *) )!= 0 )
+ {
ev.arguments->push_back(arg);
- }
- va_end( va );
-
- event_fire( &ev );
+ }
+ va_end( va );
+
+ event_fire( &ev );
ev.arguments.reset(NULL);
}
diff --git a/event.h b/event.h
index 1ba6d01d..7ed5efac 100644
--- a/event.h
+++ b/event.h
@@ -1,13 +1,13 @@
/** \file event.h
- Functions for handling event triggers
+ Functions for handling event triggers
+
+ Because most of these functions can be called by signal
+ handler, it is important to make it well defined when these
+ functions produce output or perform memory allocations, since
+ such functions may not be safely called by signal handlers.
- Because most of these functions can be called by signal
- handler, it is important to make it well defined when these
- functions produce output or perform memory allocations, since
- such functions may not be safely called by signal handlers.
-
*/
#ifndef FISH_EVENT_H
#define FISH_EVENT_H
@@ -31,14 +31,14 @@
*/
enum
{
- EVENT_ANY, /**< Matches any event type (Not always any event, as the function name may limit the choice as well */
- EVENT_SIGNAL, /**< An event triggered by a signal */
- EVENT_VARIABLE, /**< An event triggered by a variable update */
- EVENT_EXIT, /**< An event triggered by a job or process exit */
- EVENT_JOB_ID, /**< An event triggered by a job exit */
- EVENT_GENERIC, /**< A generic event */
+ EVENT_ANY, /**< Matches any event type (Not always any event, as the function name may limit the choice as well */
+ EVENT_SIGNAL, /**< An event triggered by a signal */
+ EVENT_VARIABLE, /**< An event triggered by a variable update */
+ EVENT_EXIT, /**< An event triggered by a job or process exit */
+ EVENT_JOB_ID, /**< An event triggered by a job exit */
+ EVENT_GENERIC, /**< A generic event */
}
- ;
+ ;
/**
The structure which represents an event. The event_t struct has
@@ -49,75 +49,75 @@ enum
*/
struct event_t
{
- /**
- Type of event
- */
- int type;
-
- /** The type-specific parameter. The int types are one of the following:
-
- signal: Signal number for signal-type events.Use EVENT_ANY_SIGNAL to match any signal
+ /**
+ Type of event
+ */
+ int type;
+
+ /** The type-specific parameter. The int types are one of the following:
+
+ signal: Signal number for signal-type events.Use EVENT_ANY_SIGNAL to match any signal
pid: Process id for process-type events. Use EVENT_ANY_PID to match any pid.
job_id: Job id for EVENT_JOB_ID type events
- */
+ */
union {
int signal;
int job_id;
pid_t pid;
} param1;
-
+
/** The string types are one of the following:
-
+
variable: Variable name for variable-type events.
param: The parameter describing this generic event.
*/
wcstring str_param1;
- /**
- The name of the event handler function
- */
- wcstring function_name;
+ /**
+ The name of the event handler function
+ */
+ wcstring function_name;
- /**
- The argument list. Only used when sending a new event using
- event_fire. In all other situations, the value of this variable
- is ignored.
- */
+ /**
+ The argument list. Only used when sending a new event using
+ event_fire. In all other situations, the value of this variable
+ is ignored.
+ */
std::auto_ptr<wcstring_list_t> arguments;
-
+
event_t(int t) : type(t), param1(), str_param1(), function_name(), arguments() { }
-
+
/** Copy constructor */
event_t(const event_t &x);
-
+
static event_t signal_event(int sig);
static event_t variable_event(const wcstring &str);
static event_t generic_event(const wcstring &str);
};
/**
- Add an event handler
+ Add an event handler
May not be called by a signal handler, since it may allocate new memory.
*/
void event_add_handler( const event_t *event );
/**
- Remove all events matching the specified criterion.
+ Remove all events matching the specified criterion.
May not be called by a signal handler, since it may free allocated memory.
*/
void event_remove( event_t *event );
/**
- Return all events which match the specified event class
+ Return all events which match the specified event class
This function is safe to call from a signal handler _ONLY_ if the
out parameter is null.
\param criterion Is the class of events to return. If the criterion has a non-null function_name, only events which trigger the specified function will return.
\param out the list to add events to. May be 0, in which case no events will be added, but the result count will still be valid
-
+
\return the number of found matches
*/
int event_get( event_t *criterion, std::vector<event_t *> *out );
diff --git a/exec.cpp b/exec.cpp
index a3400a98..92ce69cf 100644
--- a/exec.cpp
+++ b/exec.cpp
@@ -1,8 +1,8 @@
/** \file exec.c
- Functions for executing a program.
+ Functions for executing a program.
- Some of the code in this file is based on code from the Glibc
- manual, though I the changes performed have been massive.
+ Some of the code in this file is based on code from the Glibc
+ manual, though I the changes performed have been massive.
*/
#include "config.h"
@@ -76,7 +76,7 @@
List of all pipes used by internal pipes. These must be closed in
many situations in order to make sure that stray fds aren't lying
around.
-
+
Note this is used after fork, so we must not do anything that may allocate memory. Hopefully methods like open_fds.at() don't.
*/
static std::vector<bool> open_fds;
@@ -84,37 +84,37 @@ static std::vector<bool> open_fds;
// Called in a forked child
static void exec_write_and_exit( int fd, const char *buff, size_t count, int status )
{
- if( write_loop(fd, buff, count) == -1 )
- {
- debug( 0, WRITE_ERROR);
- wperror( L"write" );
- exit_without_destructors(status);
- }
- exit_without_destructors( status );
+ if( write_loop(fd, buff, count) == -1 )
+ {
+ debug( 0, WRITE_ERROR);
+ wperror( L"write" );
+ exit_without_destructors(status);
+ }
+ exit_without_destructors( status );
}
void exec_close( int fd )
{
ASSERT_IS_MAIN_THREAD();
-
+
/* This may be called in a child of fork(), so don't allocate memory */
- if( fd < 0 )
- {
- debug( 0, L"Called close on invalid file descriptor " );
- return;
- }
-
- while( close(fd) == -1 )
- {
- if( errno != EINTR )
- {
- debug( 1, FD_ERROR, fd );
- wperror( L"close" );
- break;
- }
- }
-
+ if( fd < 0 )
+ {
+ debug( 0, L"Called close on invalid file descriptor " );
+ return;
+ }
+
+ while( close(fd) == -1 )
+ {
+ if( errno != EINTR )
+ {
+ debug( 1, FD_ERROR, fd );
+ wperror( L"close" );
+ break;
+ }
+ }
+
/* Maybe remove this from our set of open fds */
if ((size_t)fd < open_fds.size()) {
open_fds[fd] = false;
@@ -123,27 +123,27 @@ void exec_close( int fd )
int exec_pipe( int fd[2])
{
- int res;
-
- while ((res=pipe(fd)))
- {
- if( errno != EINTR )
- {
- wperror(L"pipe");
- return res;
- }
- }
-
- debug( 4, L"Created pipe using fds %d and %d", fd[0], fd[1]);
-
+ int res;
+
+ while ((res=pipe(fd)))
+ {
+ if( errno != EINTR )
+ {
+ wperror(L"pipe");
+ return res;
+ }
+ }
+
+ debug( 4, L"Created pipe using fds %d and %d", fd[0], fd[1]);
+
int max_fd = std::max(fd[0], fd[1]);
if (max_fd >= 0 && open_fds.size() <= (size_t)max_fd) {
open_fds.resize(max_fd + 1, false);
}
open_fds.at(fd[0]) = true;
open_fds.at(fd[1]) = true;
-
- return res;
+
+ return res;
}
/**
@@ -159,7 +159,7 @@ static bool use_fd_in_pipe(int fd, const io_chain_t &io_chain )
for (size_t idx = 0; idx < io_chain.size(); idx++)
{
const io_data_t *io = io_chain.at(idx);
- if( ( io->io_mode == IO_BUFFER ) ||
+ if( ( io->io_mode == IO_BUFFER ) ||
( io->io_mode == IO_PIPE ) )
{
if( io->param1.pipe_fd[0] == fd ||
@@ -175,7 +175,7 @@ static bool use_fd_in_pipe(int fd, const io_chain_t &io_chain )
Close all fds in open_fds, except for those that are mentioned in
the redirection list io. This should make sure that there are no
stray opened file descriptors in the child.
-
+
\param io the list of io redirections for this job. Pipes mentioned
here should not be closed.
*/
@@ -215,24 +215,24 @@ void get_unused_internal_pipes(std::vector<int> &fds, const io_chain_t &io)
char *get_interpreter( const char *command, char *interpreter, size_t buff_size )
{
// OK to not use CLO_EXEC here because this is only called after fork
- int fd = open( command, O_RDONLY );
- if( fd >= 0 )
- {
+ int fd = open( command, O_RDONLY );
+ if( fd >= 0 )
+ {
size_t idx = 0;
- while( idx + 1 < buff_size )
- {
+ while( idx + 1 < buff_size )
+ {
char ch;
ssize_t amt = read(fd, &ch, sizeof ch);
- if( amt <= 0 )
- break;
- if( ch == '\n' )
- break;
+ if( amt <= 0 )
+ break;
+ if( ch == '\n' )
+ break;
interpreter[idx++] = ch;
- }
+ }
interpreter[idx++] = '\0';
close(fd);
- }
- if (strncmp(interpreter, "#! /", 4) == 0) {
+ }
+ if (strncmp(interpreter, "#! /", 4) == 0) {
return interpreter + 3;
} else if (strncmp(interpreter, "#!/", 3) == 0) {
return interpreter + 2;
@@ -250,30 +250,30 @@ char *get_interpreter( const char *command, char *interpreter, size_t buff_size
/* Called in a forked child! Do not allocate memory, etc. */
static void safe_launch_process( process_t *p, const char *actual_cmd, char **argv, char **envv )
{
- int err;
-
-// debug( 1, L"exec '%ls'", p->argv[0] );
+ int err;
+
+// debug( 1, L"exec '%ls'", p->argv[0] );
// Wow, this wcs2str call totally allocates memory
- execve ( actual_cmd, argv, envv );
-
- err = errno;
-
- /*
- Something went wrong with execve, check for a ":", and run
- /bin/sh if encountered. This is a weird predecessor to the shebang
- that is still sometimes used since it is supported on Windows.
- */
+ execve ( actual_cmd, argv, envv );
+
+ err = errno;
+
+ /*
+ Something went wrong with execve, check for a ":", and run
+ /bin/sh if encountered. This is a weird predecessor to the shebang
+ that is still sometimes used since it is supported on Windows.
+ */
/* OK to not use CLO_EXEC here because this is called after fork and the file is immediately closed */
- int fd = open(actual_cmd, O_RDONLY);
- if (fd >= 0)
- {
- char begin[1] = {0};
- ssize_t amt_read = read(fd, begin, 1);
- close(fd);
-
- if( (amt_read==1) && (begin[0] == ':') )
- {
+ int fd = open(actual_cmd, O_RDONLY);
+ if (fd >= 0)
+ {
+ char begin[1] = {0};
+ ssize_t amt_read = read(fd, begin, 1);
+ close(fd);
+
+ if( (amt_read==1) && (begin[0] == ':') )
+ {
// Relaunch it with /bin/sh. Don't allocate memory, so if you have more args than this, update your silly script! Maybe this should be changed to be based on ARG_MAX somehow.
char sh_command[] = "/bin/sh";
char *argv2[128];
@@ -283,14 +283,14 @@ static void safe_launch_process( process_t *p, const char *actual_cmd, char **ar
if (argv2[i] == NULL)
break;
}
-
- execve(sh_command, argv2, envv);
- }
- }
-
- errno = err;
+
+ execve(sh_command, argv2, envv);
+ }
+ }
+
+ errno = err;
safe_report_exec_error(errno, actual_cmd, argv, envv);
- exit_without_destructors(STATUS_EXEC_FAIL);
+ exit_without_destructors(STATUS_EXEC_FAIL);
}
/**
@@ -300,11 +300,11 @@ static void launch_process_nofork( process_t *p )
{
ASSERT_IS_MAIN_THREAD();
ASSERT_IS_NOT_FORKED_CHILD();
-
- char **argv = wcsv2strv(p->get_argv());
- char **envv = env_export_arr( false );
+
+ char **argv = wcsv2strv(p->get_argv());
+ char **envv = env_export_arr( false );
char *actual_cmd = wcs2str(p->actual_cmd.c_str());
-
+
/* Bounce to launch_process. This never returns. */
safe_launch_process(p, actual_cmd, argv, envv);
}
@@ -316,7 +316,7 @@ static void launch_process_nofork( process_t *p )
*/
static int has_fd( const io_chain_t &d, int fd )
{
- return io_chain_get( d, fd ) != NULL;
+ return io_chain_get( d, fd ) != NULL;
}
/**
@@ -329,7 +329,7 @@ static void io_cleanup_chains(io_chain_t &chains, const std::vector<int> &opened
for (size_t idx = 0; idx < opened_fds.size(); idx++) {
close(opened_fds.at(idx));
}
-
+
/* Then delete all of the redirections we made */
chains.destroy();
}
@@ -346,25 +346,25 @@ static void io_cleanup_chains(io_chain_t &chains, const std::vector<int> &opened
static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, std::vector<int> &out_opened_fds) {
ASSERT_IS_MAIN_THREAD();
assert(out_chain.empty());
-
+
/* Just to be clear what we do for an empty chain */
if (in_chain.empty()) {
return true;
}
-
+
bool success = true;
-
+
/* Make our chain of redirections */
io_chain_t result_chain;
-
+
/* In the event we can't finish transmorgrifying, we'll have to close all the files we opened. */
std::vector<int> opened_fds;
-
+
for (size_t idx = 0; idx < in_chain.size(); idx++)
{
io_data_t *in = in_chain.at(idx);
io_data_t *out = NULL; //gets allocated via new
-
+
switch( in->io_mode )
{
default:
@@ -372,7 +372,7 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s
fprintf(stderr, "Unknown io_mode %ld\n", (long)in->io_mode);
abort();
break;
-
+
/*
These redirections don't need transmogrification. They can be passed through.
*/
@@ -384,13 +384,13 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s
out = new io_data_t(*in);
break;
}
-
+
/*
Transmogrify file redirections
*/
case IO_FILE:
{
- out = new io_data_t();
+ out = new io_data_t();
out->fd = in->fd;
out->io_mode = IO_FD;
out->param2.close_old = 1;
@@ -398,31 +398,31 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s
int fd;
if ((fd=open(in->filename_cstr, in->param2.flags, OPEN_MASK))==-1)
{
- debug( 1,
+ debug( 1,
FILE_ERROR,
in->filename_cstr );
-
+
wperror( L"open" );
success = false;
break;
- }
+ }
opened_fds.push_back(fd);
out->param1.old_fd = fd;
-
+
break;
}
}
-
+
/* Record this IO redirection even if we failed (so we can free it) */
result_chain.push_back(out);
-
+
/* But don't go any further if we failed */
if (! success) {
break;
}
}
-
+
/* Now either return success, or clean up */
if (success) {
/* Yay */
@@ -446,68 +446,68 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t &out_chain, s
*/
static void internal_exec_helper( parser_t &parser,
- const wchar_t *def,
- enum block_type_t block_type,
- io_chain_t &ios )
+ const wchar_t *def,
+ enum block_type_t block_type,
+ io_chain_t &ios )
{
io_chain_t morphed_chain;
std::vector<int> opened_fds;
bool transmorgrified = io_transmogrify(ios, morphed_chain, opened_fds);
-
- int is_block_old=is_block;
- is_block=1;
-
- /*
- Did the transmogrification fail - if so, set error status and return
- */
- if( ! transmorgrified )
- {
- proc_set_last_status( STATUS_EXEC_FAIL );
- return;
- }
-
- signal_unblock();
-
- parser.eval( def, morphed_chain, block_type );
-
- signal_block();
-
- io_cleanup_chains(morphed_chain, opened_fds);
- job_reap( 0 );
- is_block=is_block_old;
+
+ int is_block_old=is_block;
+ is_block=1;
+
+ /*
+ Did the transmogrification fail - if so, set error status and return
+ */
+ if( ! transmorgrified )
+ {
+ proc_set_last_status( STATUS_EXEC_FAIL );
+ return;
+ }
+
+ signal_unblock();
+
+ parser.eval( def, morphed_chain, block_type );
+
+ signal_block();
+
+ io_cleanup_chains(morphed_chain, opened_fds);
+ job_reap( 0 );
+ is_block=is_block_old;
}
/** Perform output from builtins. Called from a forked child, so don't do anything that may allocate memory, etc.. */
static void do_builtin_io( const char *out, const char *err )
{
size_t len;
- if (out && (len = strlen(out)))
- {
-
- if (write_loop(STDOUT_FILENO, out, len) == -1)
- {
- debug( 0, L"Error while writing to stdout" );
- wperror( L"write_loop" );
- show_stackframe();
- }
- }
-
- if (err && (len = strlen(err)))
- {
- if (write_loop(STDERR_FILENO, err, len) == -1)
- {
- /*
- Can't really show any error message here, since stderr is
- dead.
- */
- }
- }
+ if (out && (len = strlen(out)))
+ {
+
+ if (write_loop(STDOUT_FILENO, out, len) == -1)
+ {
+ debug( 0, L"Error while writing to stdout" );
+ wperror( L"write_loop" );
+ show_stackframe();
+ }
+ }
+
+ if (err && (len = strlen(err)))
+ {
+ if (write_loop(STDERR_FILENO, err, len) == -1)
+ {
+ /*
+ Can't really show any error message here, since stderr is
+ dead.
+ */
+ }
+ }
}
/* Returns whether we can use posix spawn for a given process in a given job.
Per https://github.com/fish-shell/fish-shell/issues/364 , error handling for file redirections is too difficult with posix_spawn
So in that case we use fork/exec
-
+
Furthermore, to avoid the race between the caller calling tcsetpgrp() and the client checking the foreground process group, we don't use posix_spawn if we're going to foreground the process. (If we use fork(), we can call tcsetpgrp after the fork, before the exec, and avoid the racse).
*/
static bool can_use_posix_spawn_for_job(const job_t *job, const process_t *process)
@@ -543,621 +543,621 @@ static bool can_use_posix_spawn_for_job(const job_t *job, const process_t *proce
void exec( parser_t &parser, job_t *j )
{
- process_t *p;
- pid_t pid = 0;
- int mypipe[2];
- sigset_t chldset;
-
- io_data_t pipe_read, pipe_write;
-
- io_data_t *io_buffer =0;
-
- /*
- Set to true if something goes wrong while exec:ing the job, in
- which case the cleanup code will kick in.
- */
- bool exec_error = false;
-
- bool needs_keepalive = false;
- process_t keepalive;
-
-
- CHECK( j, );
- CHECK_BLOCK();
-
- if( no_exec )
- return;
-
- sigemptyset( &chldset );
- sigaddset( &chldset, SIGCHLD );
-
- debug( 4, L"Exec job '%ls' with id %d", j->command_wcstr(), j->job_id );
-
- if( ! parser.block_io.empty() )
- {
+ process_t *p;
+ pid_t pid = 0;
+ int mypipe[2];
+ sigset_t chldset;
+
+ io_data_t pipe_read, pipe_write;
+
+ io_data_t *io_buffer =0;
+
+ /*
+ Set to true if something goes wrong while exec:ing the job, in
+ which case the cleanup code will kick in.
+ */
+ bool exec_error = false;
+
+ bool needs_keepalive = false;
+ process_t keepalive;
+
+
+ CHECK( j, );
+ CHECK_BLOCK();
+
+ if( no_exec )
+ return;
+
+ sigemptyset( &chldset );
+ sigaddset( &chldset, SIGCHLD );
+
+ debug( 4, L"Exec job '%ls' with id %d", j->command_wcstr(), j->job_id );
+
+ if( ! parser.block_io.empty() )
+ {
io_duplicate_prepend(parser.block_io, j->io);
- }
+ }
- const io_data_t *input_redirect = NULL;
+ const io_data_t *input_redirect = NULL;
for (size_t idx = 0; idx < j->io.size(); idx++)
- {
+ {
input_redirect = j->io.at(idx);
-
- if( (input_redirect->io_mode == IO_BUFFER) &&
- input_redirect->is_input )
- {
- /*
- Input redirection - create a new gobetween process to take
- care of buffering
- */
- process_t *fake = new process_t();
+
+ if( (input_redirect->io_mode == IO_BUFFER) &&
+ input_redirect->is_input )
+ {
+ /*
+ Input redirection - create a new gobetween process to take
+ care of buffering
+ */
+ process_t *fake = new process_t();
fake->type = INTERNAL_BUFFER;
- fake->pipe_write_fd = 1;
- j->first_process->pipe_read_fd = input_redirect->fd;
- fake->next = j->first_process;
- j->first_process = fake;
- break;
- }
- }
-
- if( j->first_process->type==INTERNAL_EXEC )
- {
- /*
- Do a regular launch - but without forking first...
- */
- signal_block();
-
- /*
- setup_child_process makes sure signals are properly set
- up. It will also call signal_unblock
- */
- if( !setup_child_process( j, 0 ) )
- {
- /*
- launch_process _never_ returns
- */
- launch_process_nofork( j->first_process );
- }
- else
- {
- job_set_flag( j, JOB_CONSTRUCTED, 1 );
- j->first_process->completed=1;
- return;
- }
-
- }
-
- pipe_read.fd=0;
- pipe_write.fd=1;
- pipe_read.io_mode=IO_PIPE;
- pipe_read.param1.pipe_fd[0] = -1;
- pipe_read.param1.pipe_fd[1] = -1;
- pipe_read.is_input = 1;
-
- pipe_write.io_mode=IO_PIPE;
- pipe_write.is_input = 0;
- pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1;
-
+ fake->pipe_write_fd = 1;
+ j->first_process->pipe_read_fd = input_redirect->fd;
+ fake->next = j->first_process;
+ j->first_process = fake;
+ break;
+ }
+ }
+
+ if( j->first_process->type==INTERNAL_EXEC )
+ {
+ /*
+ Do a regular launch - but without forking first...
+ */
+ signal_block();
+
+ /*
+ setup_child_process makes sure signals are properly set
+ up. It will also call signal_unblock
+ */
+ if( !setup_child_process( j, 0 ) )
+ {
+ /*
+ launch_process _never_ returns
+ */
+ launch_process_nofork( j->first_process );
+ }
+ else
+ {
+ job_set_flag( j, JOB_CONSTRUCTED, 1 );
+ j->first_process->completed=1;
+ return;
+ }
+
+ }
+
+ pipe_read.fd=0;
+ pipe_write.fd=1;
+ pipe_read.io_mode=IO_PIPE;
+ pipe_read.param1.pipe_fd[0] = -1;
+ pipe_read.param1.pipe_fd[1] = -1;
+ pipe_read.is_input = 1;
+
+ pipe_write.io_mode=IO_PIPE;
+ pipe_write.is_input = 0;
+ pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1;
+
j->io.push_back(&pipe_write);
-
- signal_block();
-
- /*
- See if we need to create a group keepalive process. This is
- a process that we create to make sure that the process group
- doesn't die accidentally, and is often needed when a
- builtin/block/function is inside a pipeline, since that
- usually means we have to wait for one program to exit before
- continuing in the pipeline, causing the group leader to
- exit.
- */
-
- if( job_get_flag( j, JOB_CONTROL ) )
- {
- for( p=j->first_process; p; p = p->next )
- {
- if( p->type != EXTERNAL )
- {
- if( p->next )
- {
- needs_keepalive = true;
- break;
- }
- if( p != j->first_process )
- {
- needs_keepalive = true;
- break;
- }
-
- }
-
- }
- }
-
- if( needs_keepalive )
- {
+
+ signal_block();
+
+ /*
+ See if we need to create a group keepalive process. This is
+ a process that we create to make sure that the process group
+ doesn't die accidentally, and is often needed when a
+ builtin/block/function is inside a pipeline, since that
+ usually means we have to wait for one program to exit before
+ continuing in the pipeline, causing the group leader to
+ exit.
+ */
+
+ if( job_get_flag( j, JOB_CONTROL ) )
+ {
+ for( p=j->first_process; p; p = p->next )
+ {
+ if( p->type != EXTERNAL )
+ {
+ if( p->next )
+ {
+ needs_keepalive = true;
+ break;
+ }
+ if( p != j->first_process )
+ {
+ needs_keepalive = true;
+ break;
+ }
+
+ }
+
+ }
+ }
+
+ if( needs_keepalive )
+ {
/* Call fork. No need to wait for threads since our use is confined and simple. */
if (g_log_forks) {
printf("fork #%d: Executing keepalive fork for '%ls'\n", g_fork_count, j->command_wcstr());
}
- keepalive.pid = execute_fork(false);
- if( keepalive.pid == 0 )
- {
+ keepalive.pid = execute_fork(false);
+ if( keepalive.pid == 0 )
+ {
/* Child */
- keepalive.pid = getpid();
- set_child_group( j, &keepalive, 1 );
- pause();
- exit_without_destructors(0);
- }
- else
- {
+ keepalive.pid = getpid();
+ set_child_group( j, &keepalive, 1 );
+ pause();
+ exit_without_destructors(0);
+ }
+ else
+ {
/* Parent */
- set_child_group( j, &keepalive, 0 );
- }
- }
-
- /*
- This loop loops over every process_t in the job, starting it as
- appropriate. This turns out to be rather complex, since a
- process_t can be one of many rather different things.
-
- The loop also has to handle pipelining between the jobs.
- */
-
- for( p=j->first_process; p; p = p->next )
- {
- const bool p_wants_pipe = (p->next != NULL);
- mypipe[1]=-1;
-
- pipe_write.fd = p->pipe_write_fd;
- pipe_read.fd = p->pipe_read_fd;
-// debug( 0, L"Pipe created from fd %d to fd %d", pipe_write.fd, pipe_read.fd );
-
-
- /*
- This call is used so the global environment variable array
- is regenerated, if needed, before the fork. That way, we
- avoid a lot of duplicate work where EVERY child would need
- to generate it, since that result would not get written
- back to the parent. This call could be safely removed, but
- it would result in slightly lower performance - at least on
- uniprocessor systems.
- */
- if( p->type == EXTERNAL )
- env_export_arr( true );
-
-
- /*
- Set up fd:s that will be used in the pipe
- */
-
- if( p == j->first_process->next )
- {
+ set_child_group( j, &keepalive, 0 );
+ }
+ }
+
+ /*
+ This loop loops over every process_t in the job, starting it as
+ appropriate. This turns out to be rather complex, since a
+ process_t can be one of many rather different things.
+
+ The loop also has to handle pipelining between the jobs.
+ */
+
+ for( p=j->first_process; p; p = p->next )
+ {
+ const bool p_wants_pipe = (p->next != NULL);
+ mypipe[1]=-1;
+
+ pipe_write.fd = p->pipe_write_fd;
+ pipe_read.fd = p->pipe_read_fd;
+// debug( 0, L"Pipe created from fd %d to fd %d", pipe_write.fd, pipe_read.fd );
+
+
+ /*
+ This call is used so the global environment variable array
+ is regenerated, if needed, before the fork. That way, we
+ avoid a lot of duplicate work where EVERY child would need
+ to generate it, since that result would not get written
+ back to the parent. This call could be safely removed, but
+ it would result in slightly lower performance - at least on
+ uniprocessor systems.
+ */
+ if( p->type == EXTERNAL )
+ env_export_arr( true );
+
+
+ /*
+ Set up fd:s that will be used in the pipe
+ */
+
+ if( p == j->first_process->next )
+ {
j->io.push_back(&pipe_read);
- }
-
- if( p_wants_pipe )
- {
-// debug( 1, L"%ls|%ls" , p->argv[0], p->next->argv[0]);
-
- if( exec_pipe( mypipe ) == -1 )
- {
- debug( 1, PIPE_ERROR );
- wperror (L"pipe");
- exec_error = true;
- break;
- }
-
- memcpy( pipe_write.param1.pipe_fd, mypipe, sizeof(int)*2);
- }
- else
- {
- /*
- This is the last element of the pipeline.
- Remove the io redirection for pipe output.
- */
+ }
+
+ if( p_wants_pipe )
+ {
+// debug( 1, L"%ls|%ls" , p->argv[0], p->next->argv[0]);
+
+ if( exec_pipe( mypipe ) == -1 )
+ {
+ debug( 1, PIPE_ERROR );
+ wperror (L"pipe");
+ exec_error = true;
+ break;
+ }
+
+ memcpy( pipe_write.param1.pipe_fd, mypipe, sizeof(int)*2);
+ }
+ else
+ {
+ /*
+ This is the last element of the pipeline.
+ Remove the io redirection for pipe output.
+ */
io_chain_t::iterator where = std::find(j->io.begin(), j->io.end(), &pipe_write);
if (where != j->io.end())
j->io.erase(where);
- }
-
- switch( p->type )
- {
- case INTERNAL_FUNCTION:
- {
- wchar_t * def=0;
- int shadows;
-
-
- /*
- Calls to function_get_definition might need to
- source a file as a part of autoloading, hence there
- must be no blocks.
- */
-
- signal_unblock();
+ }
+
+ switch( p->type )
+ {
+ case INTERNAL_FUNCTION:
+ {
+ wchar_t * def=0;
+ int shadows;
+
+
+ /*
+ Calls to function_get_definition might need to
+ source a file as a part of autoloading, hence there
+ must be no blocks.
+ */
+
+ signal_unblock();
wcstring orig_def;
function_get_definition( p->argv0(), &orig_def );
-
+
// function_get_named_arguments may trigger autoload, which deallocates the orig_def.
// We should make function_get_definition return a wcstring (but how to handle NULL...)
if (! orig_def.empty())
def = wcsdup(orig_def.c_str());
-
- wcstring_list_t named_arguments = function_get_named_arguments( p->argv0() );
- shadows = function_get_shadows( p->argv0() );
-
- signal_block();
-
- if( def == NULL )
- {
- debug( 0, _( L"Unknown function '%ls'" ), p->argv0() );
- break;
- }
+
+ wcstring_list_t named_arguments = function_get_named_arguments( p->argv0() );
+ shadows = function_get_shadows( p->argv0() );
+
+ signal_block();
+
+ if( def == NULL )
+ {
+ debug( 0, _( L"Unknown function '%ls'" ), p->argv0() );
+ break;
+ }
function_block_t *newv = new function_block_t(p, p->argv0(), shadows);
- parser.push_block( newv );
-
-
- /*
- set_argv might trigger an event
- handler, hence we need to unblock
- signals.
- */
- signal_unblock();
- parse_util_set_argv( p->get_argv()+1, named_arguments );
- signal_block();
-
- parser.forbid_function( p->argv0() );
-
- if( p->next )
- {
- io_buffer = io_buffer_create( 0 );
+ parser.push_block( newv );
+
+
+ /*
+ set_argv might trigger an event
+ handler, hence we need to unblock
+ signals.
+ */
+ signal_unblock();
+ parse_util_set_argv( p->get_argv()+1, named_arguments );
+ signal_block();
+
+ parser.forbid_function( p->argv0() );
+
+ if( p->next )
+ {
+ io_buffer = io_buffer_create( 0 );
j->io.push_back(io_buffer);
- }
-
- internal_exec_helper( parser, def, TOP, j->io );
-
- parser.allow_function();
- parser.pop_block();
+ }
+
+ internal_exec_helper( parser, def, TOP, j->io );
+
+ parser.allow_function();
+ parser.pop_block();
free(def);
-
- break;
- }
-
- case INTERNAL_BLOCK:
- {
- if( p->next )
- {
- io_buffer = io_buffer_create( 0 );
+
+ break;
+ }
+
+ case INTERNAL_BLOCK:
+ {
+ if( p->next )
+ {
+ io_buffer = io_buffer_create( 0 );
j->io.push_back(io_buffer);
- }
-
- internal_exec_helper( parser, p->argv0(), TOP, j->io );
- break;
-
- }
-
- case INTERNAL_BUILTIN:
- {
- int builtin_stdin=0;
- int fg;
- int close_stdin=0;
-
- /*
- If this is the first process, check the io
- redirections and see where we should be reading
- from.
- */
- if( p == j->first_process )
- {
- const io_data_t *in = io_chain_get( j->io, 0 );
-
- if( in )
- {
- switch( in->io_mode )
- {
-
- case IO_FD:
- {
- builtin_stdin = in->param1.old_fd;
- break;
- }
- case IO_PIPE:
- {
- builtin_stdin = in->param1.pipe_fd[0];
- break;
- }
-
- case IO_FILE:
- {
+ }
+
+ internal_exec_helper( parser, p->argv0(), TOP, j->io );
+ break;
+
+ }
+
+ case INTERNAL_BUILTIN:
+ {
+ int builtin_stdin=0;
+ int fg;
+ int close_stdin=0;
+
+ /*
+ If this is the first process, check the io
+ redirections and see where we should be reading
+ from.
+ */
+ if( p == j->first_process )
+ {
+ const io_data_t *in = io_chain_get( j->io, 0 );
+
+ if( in )
+ {
+ switch( in->io_mode )
+ {
+
+ case IO_FD:
+ {
+ builtin_stdin = in->param1.old_fd;
+ break;
+ }
+ case IO_PIPE:
+ {
+ builtin_stdin = in->param1.pipe_fd[0];
+ break;
+ }
+
+ case IO_FILE:
+ {
/* Do not set CLO_EXEC because child needs access */
- builtin_stdin=open( in->filename_cstr,
+ builtin_stdin=open( in->filename_cstr,
in->param2.flags, OPEN_MASK );
- if( builtin_stdin == -1 )
- {
- debug( 1,
- FILE_ERROR,
- in->filename_cstr );
- wperror( L"open" );
- }
- else
- {
- close_stdin = 1;
- }
-
- break;
- }
-
- case IO_CLOSE:
- {
- /*
- FIXME:
-
- When
- requesting
- that
- stdin
- be
- closed,
- we
- really
- don't
- do
- anything. How
- should
- this
- be
- handled?
- */
- builtin_stdin = -1;
-
- break;
- }
-
- default:
- {
- builtin_stdin=-1;
- debug( 1,
- _( L"Unknown input redirection type %d" ),
- in->io_mode);
- break;
- }
-
- }
- }
- }
- else
- {
- builtin_stdin = pipe_read.param1.pipe_fd[0];
- }
-
- if( builtin_stdin == -1 )
- {
- exec_error = true;
- break;
- }
- else
- {
- int old_out = builtin_out_redirect;
- int old_err = builtin_err_redirect;
-
- /*
- Since this may be the foreground job, and since
- a builtin may execute another foreground job,
- we need to pretend to suspend this job while
- running the builtin, in order to avoid a
- situation where two jobs are running at once.
-
- The reason this is done here, and not by the
- relevant builtins, is that this way, the
- builtin does not need to know what job it is
- part of. It could probably figure that out by
- walking the job list, but it seems more robust
- to make exec handle things.
- */
-
- builtin_push_io( parser, builtin_stdin );
-
- builtin_out_redirect = has_fd( j->io, 1 );
- builtin_err_redirect = has_fd( j->io, 2 );
-
- fg = job_get_flag( j, JOB_FOREGROUND );
- job_set_flag( j, JOB_FOREGROUND, 0 );
-
- signal_unblock();
-
- p->status = builtin_run( parser, p->get_argv(), j->io );
-
- builtin_out_redirect=old_out;
- builtin_err_redirect=old_err;
-
- signal_block();
-
- /*
- Restore the fg flag, which is temporarily set to
- false during builtin execution so as not to confuse
- some job-handling builtins.
- */
- job_set_flag( j, JOB_FOREGROUND, fg );
- }
-
- /*
- If stdin has been redirected, close the redirection
- stream.
- */
- if( close_stdin )
- {
- exec_close( builtin_stdin );
- }
- break;
- }
- }
-
- if( exec_error )
- {
- break;
- }
-
- switch( p->type )
- {
-
- case INTERNAL_BLOCK:
- case INTERNAL_FUNCTION:
- {
- int status = proc_get_last_status();
-
- /*
- Handle output from a block or function. This usually
- means do nothing, but in the case of pipes, we have
- to buffer such io, since otherwise the internal pipe
- buffer might overflow.
- */
- if( !io_buffer )
- {
- /*
- No buffer, so we exit directly. This means we
- have to manually set the exit status.
- */
- if( p->next == 0 )
- {
- proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
- }
- p->completed = 1;
- break;
- }
-
- io_remove( j->io, io_buffer );
-
- io_buffer_read( io_buffer );
-
+ if( builtin_stdin == -1 )
+ {
+ debug( 1,
+ FILE_ERROR,
+ in->filename_cstr );
+ wperror( L"open" );
+ }
+ else
+ {
+ close_stdin = 1;
+ }
+
+ break;
+ }
+
+ case IO_CLOSE:
+ {
+ /*
+ FIXME:
+
+ When
+ requesting
+ that
+ stdin
+ be
+ closed,
+ we
+ really
+ don't
+ do
+ anything. How
+ should
+ this
+ be
+ handled?
+ */
+ builtin_stdin = -1;
+
+ break;
+ }
+
+ default:
+ {
+ builtin_stdin=-1;
+ debug( 1,
+ _( L"Unknown input redirection type %d" ),
+ in->io_mode);
+ break;
+ }
+
+ }
+ }
+ }
+ else
+ {
+ builtin_stdin = pipe_read.param1.pipe_fd[0];
+ }
+
+ if( builtin_stdin == -1 )
+ {
+ exec_error = true;
+ break;
+ }
+ else
+ {
+ int old_out = builtin_out_redirect;
+ int old_err = builtin_err_redirect;
+
+ /*
+ Since this may be the foreground job, and since
+ a builtin may execute another foreground job,
+ we need to pretend to suspend this job while
+ running the builtin, in order to avoid a
+ situation where two jobs are running at once.
+
+ The reason this is done here, and not by the
+ relevant builtins, is that this way, the
+ builtin does not need to know what job it is
+ part of. It could probably figure that out by
+ walking the job list, but it seems more robust
+ to make exec handle things.
+ */
+
+ builtin_push_io( parser, builtin_stdin );
+
+ builtin_out_redirect = has_fd( j->io, 1 );
+ builtin_err_redirect = has_fd( j->io, 2 );
+
+ fg = job_get_flag( j, JOB_FOREGROUND );
+ job_set_flag( j, JOB_FOREGROUND, 0 );
+
+ signal_unblock();
+
+ p->status = builtin_run( parser, p->get_argv(), j->io );
+
+ builtin_out_redirect=old_out;
+ builtin_err_redirect=old_err;
+
+ signal_block();
+
+ /*
+ Restore the fg flag, which is temporarily set to
+ false during builtin execution so as not to confuse
+ some job-handling builtins.
+ */
+ job_set_flag( j, JOB_FOREGROUND, fg );
+ }
+
+ /*
+ If stdin has been redirected, close the redirection
+ stream.
+ */
+ if( close_stdin )
+ {
+ exec_close( builtin_stdin );
+ }
+ break;
+ }
+ }
+
+ if( exec_error )
+ {
+ break;
+ }
+
+ switch( p->type )
+ {
+
+ case INTERNAL_BLOCK:
+ case INTERNAL_FUNCTION:
+ {
+ int status = proc_get_last_status();
+
+ /*
+ Handle output from a block or function. This usually
+ means do nothing, but in the case of pipes, we have
+ to buffer such io, since otherwise the internal pipe
+ buffer might overflow.
+ */
+ if( !io_buffer )
+ {
+ /*
+ No buffer, so we exit directly. This means we
+ have to manually set the exit status.
+ */
+ if( p->next == 0 )
+ {
+ proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
+ }
+ p->completed = 1;
+ break;
+ }
+
+ io_remove( j->io, io_buffer );
+
+ io_buffer_read( io_buffer );
+
const char *buffer = io_buffer->out_buffer_ptr();
size_t count = io_buffer->out_buffer_size();
-
- if( io_buffer->out_buffer_size() > 0 )
- {
+
+ if( io_buffer->out_buffer_size() > 0 )
+ {
/* We don't have to drain threads here because our child process is simple */
if (g_log_forks) {
printf("Executing fork for internal block or function for '%ls'\n", p->argv0());
}
- pid = execute_fork(false);
- if( pid == 0 )
- {
-
- /*
- This is the child process. Write out the contents of the pipeline.
- */
- p->pid = getpid();
- setup_child_process( j, p );
-
- exec_write_and_exit(io_buffer->fd, buffer, count, status);
- }
- else
- {
- /*
- This is the parent process. Store away
- information on the child, and possibly give
- it control over the terminal.
- */
- p->pid = pid;
- set_child_group( j, p, 0 );
-
- }
-
- }
- else
- {
- if( p->next == 0 )
- {
- proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
- }
- p->completed = 1;
- }
-
- io_buffer_destroy( io_buffer );
-
- io_buffer=0;
- break;
-
- }
-
-
- case INTERNAL_BUFFER:
- {
-
- const char *buffer = input_redirect->out_buffer_ptr();
- size_t count = input_redirect->out_buffer_size();
-
+ pid = execute_fork(false);
+ if( pid == 0 )
+ {
+
+ /*
+ This is the child process. Write out the contents of the pipeline.
+ */
+ p->pid = getpid();
+ setup_child_process( j, p );
+
+ exec_write_and_exit(io_buffer->fd, buffer, count, status);
+ }
+ else
+ {
+ /*
+ This is the parent process. Store away
+ information on the child, and possibly give
+ it control over the terminal.
+ */
+ p->pid = pid;
+ set_child_group( j, p, 0 );
+
+ }
+
+ }
+ else
+ {
+ if( p->next == 0 )
+ {
+ proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
+ }
+ p->completed = 1;
+ }
+
+ io_buffer_destroy( io_buffer );
+
+ io_buffer=0;
+ break;
+
+ }
+
+
+ case INTERNAL_BUFFER:
+ {
+
+ const char *buffer = input_redirect->out_buffer_ptr();
+ size_t count = input_redirect->out_buffer_size();
+
/* We don't have to drain threads here because our child process is simple */
if (g_log_forks) {
printf("fork #%d: Executing fork for internal buffer for '%ls'\n", g_fork_count, p->argv0() ? p->argv0() : L"(null)");
}
- pid = execute_fork(false);
- if( pid == 0 )
- {
- /*
- This is the child process. Write out the
- contents of the pipeline.
- */
- p->pid = getpid();
- setup_child_process( j, p );
-
- exec_write_and_exit( 1, buffer, count, 0);
- }
- else
- {
- /*
- This is the parent process. Store away
- information on the child, and possibly give
- it control over the terminal.
- */
- p->pid = pid;
- set_child_group( j, p, 0 );
- }
-
- break;
- }
-
- case INTERNAL_BUILTIN:
- {
- int skip_fork;
-
- /*
- Handle output from builtin commands. In the general
- case, this means forking of a worker process, that
- will write out the contents of the stdout and stderr
- buffers to the correct file descriptor. Since
- forking is expensive, fish tries to avoid it wehn
- possible.
- */
-
- /*
- If a builtin didn't produce any output, and it is
- not inside a pipeline, there is no need to fork
- */
- skip_fork =
+ pid = execute_fork(false);
+ if( pid == 0 )
+ {
+ /*
+ This is the child process. Write out the
+ contents of the pipeline.
+ */
+ p->pid = getpid();
+ setup_child_process( j, p );
+
+ exec_write_and_exit( 1, buffer, count, 0);
+ }
+ else
+ {
+ /*
+ This is the parent process. Store away
+ information on the child, and possibly give
+ it control over the terminal.
+ */
+ p->pid = pid;
+ set_child_group( j, p, 0 );
+ }
+
+ break;
+ }
+
+ case INTERNAL_BUILTIN:
+ {
+ int skip_fork;
+
+ /*
+ Handle output from builtin commands. In the general
+ case, this means forking of a worker process, that
+ will write out the contents of the stdout and stderr
+ buffers to the correct file descriptor. Since
+ forking is expensive, fish tries to avoid it wehn
+ possible.
+ */
+
+ /*
+ If a builtin didn't produce any output, and it is
+ not inside a pipeline, there is no need to fork
+ */
+ skip_fork =
get_stdout_buffer().empty() &&
get_stderr_buffer().empty() &&
- !p->next;
-
- /*
- If the output of a builtin is to be sent to an internal
- buffer, there is no need to fork. This helps out the
- performance quite a bit in complex completion code.
- */
-
- io_data_t *io = io_chain_get( j->io, 1 );
- bool buffer_stdout = io && io->io_mode == IO_BUFFER;
-
- if( ( get_stderr_buffer().empty() ) &&
- ( !p->next ) &&
- ( ! get_stdout_buffer().empty() ) &&
- ( buffer_stdout ) )
- {
- const std::string res = wcs2string( get_stdout_buffer() );
- io->out_buffer_append( res.c_str(), res.size() );
- skip_fork = 1;
- }
-
+ !p->next;
+
+ /*
+ If the output of a builtin is to be sent to an internal
+ buffer, there is no need to fork. This helps out the
+ performance quite a bit in complex completion code.
+ */
+
+ io_data_t *io = io_chain_get( j->io, 1 );
+ bool buffer_stdout = io && io->io_mode == IO_BUFFER;
+
+ if( ( get_stderr_buffer().empty() ) &&
+ ( !p->next ) &&
+ ( ! get_stdout_buffer().empty() ) &&
+ ( buffer_stdout ) )
+ {
+ const std::string res = wcs2string( get_stdout_buffer() );
+ io->out_buffer_append( res.c_str(), res.size() );
+ skip_fork = 1;
+ }
+
if (! skip_fork && j->io.empty()) {
/* PCA for some reason, fish forks a lot, even for basic builtins like echo just to write out their buffers. I'm certain a lot of this is unnecessary, but I am not sure exactly when. If j->io is NULL, then it means there's no pipes or anything, so we can certainly just write out our data. Beyond that, we may be able to do the same if io_get returns 0 for STDOUT_FILENO and STDERR_FILENO. */
if (g_log_forks) {
@@ -1172,100 +1172,100 @@ void exec( parser_t &parser, job_t *j )
}
for( io_chain_t::iterator iter = j->io.begin(); iter != j->io.end(); iter++ )
- {
+ {
io_data_t *tmp_io = *iter;
- if( tmp_io->io_mode == IO_FILE && strcmp(tmp_io->filename_cstr, "/dev/null") != 0)
- {
- skip_fork = 0;
+ if( tmp_io->io_mode == IO_FILE && strcmp(tmp_io->filename_cstr, "/dev/null") != 0)
+ {
+ skip_fork = 0;
break;
- }
- }
-
-
- if( skip_fork )
- {
- p->completed=1;
- if( p->next == 0 )
- {
- debug( 3, L"Set status of %ls to %d using short circut", j->command_wcstr(), p->status );
-
- int status = p->status;
- proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status );
- }
- break;
- }
-
-
- /* Ok, unfortunatly, we have to do a real fork. Bummer. We work hard to make sure we don't have to wait for all our threads to exit, by arranging things so that we don't have to allocate memory or do anything except system calls in the child. */
-
+ }
+ }
+
+
+ if( skip_fork )
+ {
+ p->completed=1;
+ if( p->next == 0 )
+ {
+ debug( 3, L"Set status of %ls to %d using short circut", j->command_wcstr(), p->status );
+
+ int status = p->status;
+ proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status );
+ }
+ break;
+ }
+
+
+ /* Ok, unfortunatly, we have to do a real fork. Bummer. We work hard to make sure we don't have to wait for all our threads to exit, by arranging things so that we don't have to allocate memory or do anything except system calls in the child. */
+
/* Get the strings we'll write before we fork (since they call malloc) */
const wcstring &out = get_stdout_buffer(), &err = get_stderr_buffer();
char *outbuff = wcs2str(out.c_str()), *errbuff = wcs2str(err.c_str());
-
+
fflush(stdout);
fflush(stderr);
if (g_log_forks) {
printf("fork #%d: Executing fork for internal builtin for '%ls'\n", g_fork_count, p->argv0());
io_print(io_chain_t(io));
}
- pid = execute_fork(false);
- if( pid == 0 )
- {
- /*
- This is the child process. Setup redirections,
- print correct output to stdout and stderr, and
- then exit.
- */
- p->pid = getpid();
- setup_child_process( j, p );
- do_builtin_io(outbuff, errbuff);
- exit_without_destructors( p->status );
-
- }
- else
- {
+ pid = execute_fork(false);
+ if( pid == 0 )
+ {
+ /*
+ This is the child process. Setup redirections,
+ print correct output to stdout and stderr, and
+ then exit.
+ */
+ p->pid = getpid();
+ setup_child_process( j, p );
+ do_builtin_io(outbuff, errbuff);
+ exit_without_destructors( p->status );
+
+ }
+ else
+ {
/* Free the strings in the parent */
free(outbuff);
free(errbuff);
-
- /*
- This is the parent process. Store away
- information on the child, and possibly give
- it control over the terminal.
- */
- p->pid = pid;
-
- set_child_group( j, p, 0 );
-
- }
-
- break;
- }
-
- case EXTERNAL:
- {
+
+ /*
+ This is the parent process. Store away
+ information on the child, and possibly give
+ it control over the terminal.
+ */
+ p->pid = pid;
+
+ set_child_group( j, p, 0 );
+
+ }
+
+ break;
+ }
+
+ case EXTERNAL:
+ {
/* Get argv and envv before we fork */
null_terminated_array_t<char> argv_array = convert_wide_array_to_narrow(p->get_argv_array());
-
+
null_terminated_array_t<char> envv_array;
env_export_arr(false, envv_array);
-
+
char **envv = envv_array.get();
char **argv = argv_array.get();
-
+
std::string actual_cmd_str = wcs2string(p->actual_cmd);
const char *actual_cmd = actual_cmd_str.c_str();
-
+
const wchar_t *reader_current_filename();
if (g_log_forks) {
const wchar_t *file = reader_current_filename();
const wchar_t *func = parser_t::principal_parser().is_function();
printf("fork #%d: forking for '%s' in '%ls:%ls'\n", g_fork_count, actual_cmd, file ? file : L"", func ? func : L"?");
-
+
fprintf(stderr, "IO chain for %s:\n", actual_cmd);
io_print(j->io);
}
-
+
#if FISH_USE_POSIX_SPAWN
/* Prefer to use posix_spawn, since it's faster on some systems like OS X */
bool use_posix_spawn = g_use_posix_spawn && can_use_posix_spawn_for_job(j, p);
@@ -1279,22 +1279,22 @@ void exec( parser_t &parser, job_t *j )
{
/* We successfully made the attributes and actions; actually call posix_spawn */
int spawn_ret = posix_spawn(&pid, actual_cmd, &actions, &attr, argv, envv);
-
+
/* This usleep can be used to test for various race conditions (https://github.com/fish-shell/fish-shell/issues/360) */
//usleep(10000);
-
+
if (spawn_ret != 0)
{
safe_report_exec_error(spawn_ret, actual_cmd, argv, envv);
/* Make sure our pid isn't set */
pid = 0;
}
-
+
/* Clean up our actions */
posix_spawn_file_actions_destroy(&actions);
posix_spawnattr_destroy(&attr);
}
-
+
/* A 0 pid means we failed to posix_spawn. Since we have no pid, we'll never get told when it's exited, so we have to mark the process as failed. */
if (pid == 0)
{
@@ -1312,7 +1312,7 @@ void exec( parser_t &parser, job_t *j )
p->pid = getpid();
setup_child_process( j, p );
safe_launch_process( p, actual_cmd, argv, envv );
-
+
/*
safe_launch_process _never_ returns...
*/
@@ -1320,7 +1320,7 @@ void exec( parser_t &parser, job_t *j )
}
- /*
+ /*
This is the parent process. Store away
information on the child, and possibly fice
it control over the terminal.
@@ -1329,174 +1329,174 @@ void exec( parser_t &parser, job_t *j )
set_child_group( j, p, 0 );
- break;
- }
-
- }
-
- if( p->type == INTERNAL_BUILTIN )
- builtin_pop_io(parser);
-
- /*
- Close the pipe the current process uses to read from the
- previous process_t
- */
- if( pipe_read.param1.pipe_fd[0] >= 0 )
- exec_close( pipe_read.param1.pipe_fd[0] );
- /*
- Set up the pipe the next process uses to read from the
- current process_t
- */
- if( p_wants_pipe )
- pipe_read.param1.pipe_fd[0] = mypipe[0];
-
- /*
- If there is a next process in the pipeline, close the
- output end of the current pipe (the surrent child
- subprocess already has a copy of the pipe - this makes sure
- we don't leak file descriptors either in the shell or in
- the children).
- */
- if( p->next )
- {
- exec_close(mypipe[1]);
- }
- }
-
- /*
- The keepalive process is no longer needed, so we terminate it
- with extreme prejudice
- */
- if( needs_keepalive )
- {
- kill( keepalive.pid, SIGKILL );
- }
-
- signal_unblock();
-
- debug( 3, L"Job is constructed" );
-
- io_remove( j->io, &pipe_read );
-
+ break;
+ }
+
+ }
+
+ if( p->type == INTERNAL_BUILTIN )
+ builtin_pop_io(parser);
+
+ /*
+ Close the pipe the current process uses to read from the
+ previous process_t
+ */
+ if( pipe_read.param1.pipe_fd[0] >= 0 )
+ exec_close( pipe_read.param1.pipe_fd[0] );
+ /*
+ Set up the pipe the next process uses to read from the
+ current process_t
+ */
+ if( p_wants_pipe )
+ pipe_read.param1.pipe_fd[0] = mypipe[0];
+
+ /*
+ If there is a next process in the pipeline, close the
+ output end of the current pipe (the surrent child
+ subprocess already has a copy of the pipe - this makes sure
+ we don't leak file descriptors either in the shell or in
+ the children).
+ */
+ if( p->next )
+ {
+ exec_close(mypipe[1]);
+ }
+ }
+
+ /*
+ The keepalive process is no longer needed, so we terminate it
+ with extreme prejudice
+ */
+ if( needs_keepalive )
+ {
+ kill( keepalive.pid, SIGKILL );
+ }
+
+ signal_unblock();
+
+ debug( 3, L"Job is constructed" );
+
+ io_remove( j->io, &pipe_read );
+
for (io_chain_t::const_iterator iter = parser.block_io.begin(); iter != parser.block_io.end(); iter++)
{
io_remove( j->io, *iter );
}
-
- job_set_flag( j, JOB_CONSTRUCTED, 1 );
-
- if( !job_get_flag( j, JOB_FOREGROUND ) )
- {
- proc_last_bg_pid = j->pgid;
- }
-
- if( !exec_error )
- {
- job_continue (j, 0);
- }
-
+
+ job_set_flag( j, JOB_CONSTRUCTED, 1 );
+
+ if( !job_get_flag( j, JOB_FOREGROUND ) )
+ {
+ proc_last_bg_pid = j->pgid;
+ }
+
+ if( !exec_error )
+ {
+ job_continue (j, 0);
+ }
+
}
static int exec_subshell_internal( const wcstring &cmd, wcstring_list_t *lst )
{
ASSERT_IS_MAIN_THREAD();
- char *begin, *end;
- char z=0;
- int prev_subshell = is_subshell;
- int status, prev_status;
- io_data_t *io_buffer;
- char sep=0;
-
- const env_var_t ifs = env_get_string(L"IFS");
-
- if( ! ifs.missing_or_empty() )
- {
- if( ifs.at(0) < 128 )
- {
- sep = '\n';//ifs[0];
- }
- else
- {
- sep = 0;
- debug( 0, L"Warning - invalid command substitution separator '%lc'. Please change the firsta character of IFS", ifs[0] );
- }
-
- }
-
- is_subshell=1;
- io_buffer= io_buffer_create( 0 );
-
- prev_status = proc_get_last_status();
-
+ char *begin, *end;
+ char z=0;
+ int prev_subshell = is_subshell;
+ int status, prev_status;
+ io_data_t *io_buffer;
+ char sep=0;
+
+ const env_var_t ifs = env_get_string(L"IFS");
+
+ if( ! ifs.missing_or_empty() )
+ {
+ if( ifs.at(0) < 128 )
+ {
+ sep = '\n';//ifs[0];
+ }
+ else
+ {
+ sep = 0;
+ debug( 0, L"Warning - invalid command substitution separator '%lc'. Please change the firsta character of IFS", ifs[0] );
+ }
+
+ }
+
+ is_subshell=1;
+ io_buffer= io_buffer_create( 0 );
+
+ prev_status = proc_get_last_status();
+
parser_t &parser = parser_t::principal_parser();
- if( parser.eval( cmd, io_chain_t(io_buffer), SUBST ) )
- {
- status = -1;
- }
- else
- {
- status = proc_get_last_status();
- }
-
- io_buffer_read( io_buffer );
-
- proc_set_last_status( prev_status );
-
- is_subshell = prev_subshell;
-
- io_buffer->out_buffer_append( &z, 1 );
-
- begin=end=io_buffer->out_buffer_ptr();
-
- if( lst )
- {
- while( 1 )
- {
- if( *end == 0 )
- {
- if( begin != end )
- {
- wchar_t *el = str2wcs( begin );
- if( el )
- {
- lst->push_back(el);
-
- free(el);
- }
- else
- {
- debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
- }
- }
- io_buffer_destroy( io_buffer );
-
- return status;
- }
- else if( *end == sep )
- {
- wchar_t *el;
- *end=0;
- el = str2wcs( begin );
- if( el )
- {
+ if( parser.eval( cmd, io_chain_t(io_buffer), SUBST ) )
+ {
+ status = -1;
+ }
+ else
+ {
+ status = proc_get_last_status();
+ }
+
+ io_buffer_read( io_buffer );
+
+ proc_set_last_status( prev_status );
+
+ is_subshell = prev_subshell;
+
+ io_buffer->out_buffer_append( &z, 1 );
+
+ begin=end=io_buffer->out_buffer_ptr();
+
+ if( lst )
+ {
+ while( 1 )
+ {
+ if( *end == 0 )
+ {
+ if( begin != end )
+ {
+ wchar_t *el = str2wcs( begin );
+ if( el )
+ {
+ lst->push_back(el);
+
+ free(el);
+ }
+ else
+ {
+ debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
+ }
+ }
+ io_buffer_destroy( io_buffer );
+
+ return status;
+ }
+ else if( *end == sep )
+ {
+ wchar_t *el;
+ *end=0;
+ el = str2wcs( begin );
+ if( el )
+ {
lst->push_back(el);
- free(el);
- }
- else
- {
- debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
- }
- begin = end+1;
- }
- end++;
- }
- }
-
- io_buffer_destroy( io_buffer );
-
- return status;
+ free(el);
+ }
+ else
+ {
+ debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
+ }
+ begin = end+1;
+ }
+ end++;
+ }
+ }
+
+ io_buffer_destroy( io_buffer );
+
+ return status;
}
int exec_subshell( const wcstring &cmd, std::vector<wcstring> &outputs )
diff --git a/exec.h b/exec.h
index 97342f11..9ca30839 100644
--- a/exec.h
+++ b/exec.h
@@ -1,5 +1,5 @@
/** \file exec.h
- Prototypes for functions for executing a program
+ Prototypes for functions for executing a program
*/
#ifndef FISH_EXEC_H
@@ -21,7 +21,7 @@
#define PIPE_ERROR _(L"An error occurred while setting up pipe")
/**
- Execute the processes specified by j.
+ Execute the processes specified by j.
I've put a fair bit of work into making builtins behave like other
programs as far as pipes are concerned. Unlike i.e. bash, builtins
diff --git a/expand.cpp b/expand.cpp
index 98dfc460..b6806c81 100644
--- a/expand.cpp
+++ b/expand.cpp
@@ -1,7 +1,7 @@
/**\file expand.c
String expansion functions. These functions perform several kinds of
-parameter expansion.
+parameter expansion.
*/
@@ -128,27 +128,27 @@ static void remove_internal_separator( wcstring &s, bool conv );
int expand_is_clean( const wchar_t *in )
{
- const wchar_t * str = in;
+ const wchar_t * str = in;
- CHECK( in, 1 );
+ CHECK( in, 1 );
- /*
- Test characters that have a special meaning in the first character position
- */
- if( wcschr( UNCLEAN_FIRST, *str ) )
- return 0;
+ /*
+ Test characters that have a special meaning in the first character position
+ */
+ if( wcschr( UNCLEAN_FIRST, *str ) )
+ return 0;
- /*
- Test characters that have a special meaning in any character position
- */
- while( *str )
- {
- if( wcschr( UNCLEAN, *str ) )
- return 0;
- str++;
- }
+ /*
+ Test characters that have a special meaning in any character position
+ */
+ while( *str )
+ {
+ if( wcschr( UNCLEAN, *str ) )
+ return 0;
+ str++;
+ }
- return 1;
+ return 1;
}
/**
@@ -156,9 +156,9 @@ int expand_is_clean( const wchar_t *in )
*/
static env_var_t expand_var(const wchar_t *in)
{
- if( !in )
- return env_var_t::missing_var();
- return env_get_string( in );
+ if( !in )
+ return env_var_t::missing_var();
+ return env_get_string( in );
}
/**
@@ -167,22 +167,22 @@ static env_var_t expand_var(const wchar_t *in)
*/
static int is_quotable( const wchar_t *str )
{
- switch( *str )
- {
- case 0:
- return 1;
-
- case L'\n':
- case L'\t':
- case L'\r':
- case L'\b':
- case L'\x1b':
- return 0;
-
- default:
- return is_quotable(str+1);
- }
- return 0;
+ switch( *str )
+ {
+ case 0:
+ return 1;
+
+ case L'\n':
+ case L'\t':
+ case L'\r':
+ case L'\b':
+ case L'\x1b':
+ return 0;
+
+ default:
+ return is_quotable(str+1);
+ }
+ return 0;
}
@@ -193,55 +193,55 @@ static int is_quotable(const wcstring &str) {
wcstring expand_escape_variable( const wcstring &in )
{
- wcstring_list_t lst;
- wcstring buff;
+ wcstring_list_t lst;
+ wcstring buff;
- tokenize_variable_array( in, lst );
+ tokenize_variable_array( in, lst );
- switch( lst.size() )
- {
- case 0:
- buff.append(L"''");
- break;
-
- case 1:
- {
+ switch( lst.size() )
+ {
+ case 0:
+ buff.append(L"''");
+ break;
+
+ case 1:
+ {
const wcstring &el = lst.at(0);
- if( el.find(L' ') != wcstring::npos && is_quotable( el ) )
- {
+ if( el.find(L' ') != wcstring::npos && is_quotable( el ) )
+ {
buff.append(L"'");
buff.append(el);
buff.append(L"'");
- }
- else
- {
+ }
+ else
+ {
buff.append(escape_string(el, 1));
- }
- break;
- }
- default:
- {
- for( size_t j=0; j<lst.size(); j++ )
- {
- const wcstring &el = lst.at(j);
- if( j )
- buff.append(L" " );
-
- if( is_quotable( el ) )
- {
+ }
+ break;
+ }
+ default:
+ {
+ for( size_t j=0; j<lst.size(); j++ )
+ {
+ const wcstring &el = lst.at(j);
+ if( j )
+ buff.append(L" " );
+
+ if( is_quotable( el ) )
+ {
buff.append(L"'");
buff.append(el);
buff.append(L"'");
- }
- else
- {
+ }
+ else
+ {
buff.append(escape_string(el, 1));
- }
- }
- }
- }
- return buff;
+ }
+ }
+ }
+ }
+ return buff;
}
/**
@@ -249,14 +249,14 @@ wcstring expand_escape_variable( const wcstring &in )
*/
static int iswnumeric( const wchar_t *n )
{
- for( ; *n; n++ )
- {
- if( *n < L'0' || *n > L'9' )
- {
- return 0;
- }
- }
- return 1;
+ for( ; *n; n++ )
+ {
+ if( *n < L'0' || *n > L'9' )
+ {
+ return 0;
+ }
+ }
+ return 1;
}
/**
@@ -264,21 +264,21 @@ static int iswnumeric( const wchar_t *n )
cmd
*/
static bool match_pid( const wcstring &cmd,
- const wchar_t *proc,
- int flags,
- size_t *offset)
+ const wchar_t *proc,
+ int flags,
+ size_t *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.c_str(), proc, wcslen( proc ) ) == 0 )
- {
- if( offset )
- *offset = 0;
- return true;
- }
-
+ /* 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.c_str(), proc, wcslen( proc ) ) == 0 )
+ {
+ if( offset )
+ *offset = 0;
+ return true;
+ }
+
/* Get the command to match against. We're only interested in the last path component. */
const wcstring base_cmd = wbasename(cmd);
-
+
bool result = string_prefixes_string(proc, base_cmd);
if (result)
{
@@ -297,9 +297,9 @@ static bool match_pid( const wcstring &cmd,
class process_iterator_t {
std::vector<pid_t> pids;
size_t idx;
-
+
wcstring name_for_pid(pid_t pid);
-
+
public:
process_iterator_t();
bool next_process(wcstring *str, pid_t *pid);
@@ -311,30 +311,30 @@ wcstring process_iterator_t::name_for_pid(pid_t pid)
int mib[4], maxarg = 0, numArgs = 0;
size_t size = 0;
char *args = NULL, *stringPtr = NULL;
-
+
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
-
+
size = sizeof(maxarg);
if (sysctl(mib, 2, &maxarg, &size, NULL, 0) == -1) {
return result;
}
-
+
args = (char *)malloc( maxarg );
if ( args == NULL ) {
return result;
}
-
+
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = pid;
-
+
size = (size_t)maxarg;
if ( sysctl(mib, 3, args, &size, NULL, 0) == -1 ) {
free( args );
return result;;
}
-
+
memcpy( &numArgs, args, sizeof(numArgs) );
stringPtr = args + sizeof(numArgs);
result = str2wcstring(stringPtr);
@@ -374,8 +374,8 @@ process_iterator_t::process_iterator_t() : idx(0)
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
size_t length;
-
-
+
+
// We start by calling sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
@@ -385,14 +385,14 @@ process_iterator_t::process_iterator_t() : idx(0)
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.
-
+
result = NULL;
done = false;
do {
assert(result == NULL);
-
+
// Call sysctl with a NULL buffer.
-
+
length = 0;
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
@@ -400,20 +400,20 @@ process_iterator_t::process_iterator_t() : idx(0)
if (err == -1) {
err = errno;
}
-
+
// Allocate an appropriately sized buffer based on the results
// from the previous call.
-
+
if (err == 0) {
result = (struct kinfo_proc *)malloc(length);
if (result == NULL) {
err = ENOMEM;
}
}
-
+
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
-
+
if (err == 0) {
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
@@ -431,16 +431,16 @@ process_iterator_t::process_iterator_t() : idx(0)
}
}
} while (err == 0 && ! done);
-
+
// Clean up and establish post conditions.
if (err == 0 && result != NULL)
{
for (size_t idx = 0; idx < length / sizeof(struct kinfo_proc); idx++)
pids.push_back(result[idx].kp_proc.p_pid);
}
-
+
if (result)
- free(result);
+ free(result);
}
#else
@@ -448,11 +448,11 @@ process_iterator_t::process_iterator_t() : idx(0)
/* /proc style process completions */
class process_iterator_t {
DIR *dir;
-
+
public:
process_iterator_t();
~process_iterator_t();
-
+
bool next_process(wcstring *out_str, pid_t *out_pid);
};
@@ -476,30 +476,30 @@ bool process_iterator_t::next_process(wcstring *out_str, pid_t *out_pid)
wcstring name;
if (! dir || ! wreaddir(dir, name))
break;
-
- if (!iswnumeric(name.c_str()))
- continue;
-
+
+ if (!iswnumeric(name.c_str()))
+ continue;
+
wcstring path = wcstring(L"/proc/") + name;
struct stat buf;
- if (wstat(path, &buf))
- continue;
+ if (wstat(path, &buf))
+ continue;
+
+ if( buf.st_uid != getuid() )
+ continue;
- if( buf.st_uid != getuid() )
- continue;
-
/* remember the pid */
pid = fish_wcstoi(name.c_str(), NULL, 10);
-
+
/* the 'cmdline' file exists, it should contain the commandline */
FILE *cmdfile;
if ((cmdfile=wfopen(path + L"/cmdline", "r")))
{
wcstring full_command_line;
- signal_block();
- fgetws2(&full_command_line, cmdfile);
- signal_unblock();
-
+ signal_block();
+ fgetws2(&full_command_line, cmdfile);
+ signal_unblock();
+
/* The command line needs to be escaped */
wchar_t *first_arg = tok_first( full_command_line.c_str() );
if (first_arg)
@@ -522,7 +522,7 @@ bool process_iterator_t::next_process(wcstring *out_str, pid_t *out_pid)
if (cmdfile)
fclose(cmdfile);
}
-
+
bool result = ! cmd.empty();
if (result)
{
@@ -562,11 +562,11 @@ std::vector<wcstring> expand_get_all_process_names(void)
*/
static int find_process( const wchar_t *proc,
- expand_flags_t flags,
- std::vector<completion_t> &out )
+ expand_flags_t flags,
+ std::vector<completion_t> &out )
{
- int found = 0;
-
+ int found = 0;
+
if (! (flags & EXPAND_SKIP_JOBS))
{
ASSERT_IS_MAIN_THREAD();
@@ -592,7 +592,7 @@ static int find_process( const wchar_t *proc,
if( wcsncmp( proc, jid, wcslen(proc ) )==0 )
{
wcstring desc_buff = format_string(COMPLETE_JOB_DESC_VAL, j->command_wcstr());
- append_completion( out,
+ append_completion( out,
jid+wcslen(proc),
desc_buff,
0 );
@@ -605,7 +605,7 @@ static int find_process( const wchar_t *proc,
int jid;
wchar_t *end;
-
+
errno = 0;
jid = fish_wcstoi( proc, &end, 10 );
if( jid > 0 && !errno && !*end )
@@ -627,16 +627,16 @@ static int find_process( const wchar_t *proc,
job_iterator_t jobs;
while ((j = jobs.next()))
{
-
+
if( j->command_is_empty() )
continue;
-
+
size_t offset;
if( match_pid( j->command(), proc, flags, &offset ) )
{
if( flags & ACCEPT_INCOMPLETE )
{
- append_completion( out,
+ append_completion( out,
j->command_wcstr() + offset + wcslen(proc),
COMPLETE_JOB_DESC,
0 );
@@ -664,13 +664,13 @@ static int find_process( const wchar_t *proc,
{
if( p->actual_cmd.empty() )
continue;
-
+
size_t offset;
if( match_pid( p->actual_cmd, proc, flags, &offset ) )
{
if( flags & ACCEPT_INCOMPLETE )
{
- append_completion( out,
+ append_completion( out,
wcstring(p->actual_cmd, offset + wcslen(proc)),
COMPLETE_CHILD_PROCESS_DESC,
0 );
@@ -704,7 +704,7 @@ static int find_process( const wchar_t *proc,
{
if( flags & ACCEPT_INCOMPLETE )
{
- append_completion( out,
+ append_completion( out,
process_name.c_str() + offset + wcslen(proc),
COMPLETE_PROCESS_DESC,
0 );
@@ -716,162 +716,162 @@ static int find_process( const wchar_t *proc,
}
}
- return 1;
+ return 1;
}
/**
Process id expansion
*/
static int expand_pid( const wcstring &instr_with_sep,
- expand_flags_t flags,
- std::vector<completion_t> &out )
+ expand_flags_t flags,
+ std::vector<completion_t> &out )
{
-
+
/* expand_string calls us with internal separators in instr...sigh */
wcstring instr = instr_with_sep;
remove_internal_separator(instr, false);
-
- if( instr.empty() || instr.at(0) != PROCESS_EXPAND )
- {
+
+ if( instr.empty() || instr.at(0) != PROCESS_EXPAND )
+ {
append_completion(out, instr);
- return 1;
- }
-
+ return 1;
+ }
+
const wchar_t * const in = instr.c_str();
- if( flags & ACCEPT_INCOMPLETE )
- {
- if( wcsncmp( in+1, SELF_STR, wcslen(in+1) )==0 )
- {
- append_completion( out,
- SELF_STR+wcslen(in+1),
- COMPLETE_SELF_DESC,
- 0 );
- }
- else if( wcsncmp( in+1, LAST_STR, wcslen(in+1) )==0 )
- {
- append_completion( out,
- LAST_STR+wcslen(in+1),
- COMPLETE_LAST_DESC,
- 0 );
- }
- }
- else
- {
- if( wcscmp( (in+1), SELF_STR )==0 )
- {
+ if( flags & ACCEPT_INCOMPLETE )
+ {
+ if( wcsncmp( in+1, SELF_STR, wcslen(in+1) )==0 )
+ {
+ append_completion( out,
+ SELF_STR+wcslen(in+1),
+ COMPLETE_SELF_DESC,
+ 0 );
+ }
+ else if( wcsncmp( in+1, LAST_STR, wcslen(in+1) )==0 )
+ {
+ append_completion( out,
+ LAST_STR+wcslen(in+1),
+ COMPLETE_LAST_DESC,
+ 0 );
+ }
+ }
+ else
+ {
+ if( wcscmp( (in+1), SELF_STR )==0 )
+ {
append_completion(out, to_string<long>(getpid()));
- return 1;
- }
- if( wcscmp( (in+1), LAST_STR )==0 )
- {
- if( proc_last_bg_pid > 0 )
- {
+ return 1;
+ }
+ if( wcscmp( (in+1), LAST_STR )==0 )
+ {
+ if( proc_last_bg_pid > 0 )
+ {
append_completion(out, to_string<long>(proc_last_bg_pid));
- }
+ }
- return 1;
- }
- }
+ return 1;
+ }
+ }
- size_t prev = out.size();
- if( !find_process( in+1, flags, out ) )
- return 0;
+ size_t prev = out.size();
+ if( !find_process( in+1, flags, out ) )
+ return 0;
- if( prev == out.size() )
- {
- if( ! (flags & ACCEPT_INCOMPLETE) )
- {
- return 0;
- }
- }
+ if( prev == out.size() )
+ {
+ if( ! (flags & ACCEPT_INCOMPLETE) )
+ {
+ return 0;
+ }
+ }
- return 1;
+ return 1;
}
void expand_variable_error( parser_t &parser, const wchar_t *token, size_t token_pos, int error_pos )
{
- size_t stop_pos = token_pos+1;
-
- switch( token[stop_pos] )
- {
- case BRACKET_BEGIN:
- {
- wchar_t *cpy = wcsdup( token );
- *(cpy+token_pos)=0;
- wchar_t *name = &cpy[stop_pos+1];
- wchar_t *end = wcschr( name, BRACKET_END );
- wchar_t *post;
- int is_var=0;
- if( end )
- {
- post = end+1;
- *end = 0;
-
- if( !wcsvarname( name ) )
- {
- is_var = 1;
- }
- }
-
- if( is_var )
- {
- parser.error( SYNTAX_ERROR,
- error_pos,
- COMPLETE_VAR_BRACKET_DESC,
- cpy,
- name,
- post );
- }
- else
- {
- parser.error( SYNTAX_ERROR,
- error_pos,
- COMPLETE_VAR_BRACKET_DESC,
- L"",
- L"VARIABLE",
- L"" );
- }
- free( cpy );
-
- break;
- }
-
- case INTERNAL_SEPARATOR:
- {
- parser.error( SYNTAX_ERROR,
- error_pos,
- COMPLETE_VAR_PARAN_DESC );
- break;
- }
-
- case 0:
- {
- parser.error( SYNTAX_ERROR,
- error_pos,
- COMPLETE_VAR_NULL_DESC );
- break;
- }
-
- default:
- {
+ size_t stop_pos = token_pos+1;
+
+ switch( token[stop_pos] )
+ {
+ case BRACKET_BEGIN:
+ {
+ wchar_t *cpy = wcsdup( token );
+ *(cpy+token_pos)=0;
+ wchar_t *name = &cpy[stop_pos+1];
+ wchar_t *end = wcschr( name, BRACKET_END );
+ wchar_t *post;
+ int is_var=0;
+ if( end )
+ {
+ post = end+1;
+ *end = 0;
+
+ if( !wcsvarname( name ) )
+ {
+ is_var = 1;
+ }
+ }
+
+ if( is_var )
+ {
+ parser.error( SYNTAX_ERROR,
+ error_pos,
+ COMPLETE_VAR_BRACKET_DESC,
+ cpy,
+ name,
+ post );
+ }
+ else
+ {
+ parser.error( SYNTAX_ERROR,
+ error_pos,
+ COMPLETE_VAR_BRACKET_DESC,
+ L"",
+ L"VARIABLE",
+ L"" );
+ }
+ free( cpy );
+
+ break;
+ }
+
+ case INTERNAL_SEPARATOR:
+ {
+ parser.error( SYNTAX_ERROR,
+ error_pos,
+ COMPLETE_VAR_PARAN_DESC );
+ break;
+ }
+
+ case 0:
+ {
+ parser.error( SYNTAX_ERROR,
+ error_pos,
+ COMPLETE_VAR_NULL_DESC );
+ break;
+ }
+
+ default:
+ {
wchar_t token_stop_char = token[stop_pos];
// Unescape (see http://github.com/fish-shell/fish-shell/issues/50)
if (token_stop_char == ANY_CHAR)
token_stop_char = L'?';
else if (token_stop_char == ANY_STRING || token_stop_char == ANY_STRING_RECURSIVE)
token_stop_char = L'*';
-
- parser.error( SYNTAX_ERROR,
- error_pos,
- (token_stop_char == L'?' ? COMPLETE_YOU_WANT_STATUS : COMPLETE_VAR_DESC),
- token_stop_char );
- break;
- }
- }
+
+ parser.error( SYNTAX_ERROR,
+ error_pos,
+ (token_stop_char == L'?' ? COMPLETE_YOU_WANT_STATUS : COMPLETE_VAR_DESC),
+ token_stop_char );
+ break;
+ }
+ }
}
/**
@@ -879,73 +879,73 @@ void expand_variable_error( parser_t &parser, const wchar_t *token, size_t token
*/
static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, size_t array_size )
{
- wchar_t *end;
-
+ wchar_t *end;
+
const long size = (long)array_size;
- size_t pos = 1; //skip past the opening square bracket
-
- // debug( 0, L"parse_slice on '%ls'", in );
-
- while( 1 )
- {
- long tmp;
-
- while( iswspace(in[pos]) || (in[pos]==INTERNAL_SEPARATOR))
- pos++;
-
- if( in[pos] == L']' )
- {
- pos++;
- break;
- }
-
- errno=0;
- tmp = wcstol( &in[pos], &end, 10 );
- if( ( errno ) || ( end == &in[pos] ) )
- {
- return 1;
- }
- // debug( 0, L"Push idx %d", tmp );
-
- long i1 = tmp>-1 ? tmp : (long)array_size+tmp+1;
- pos = end-in;
- while( in[pos]==INTERNAL_SEPARATOR )
- pos++;
- if ( in[pos]==L'.' && in[pos+1]==L'.' ){
- pos+=2;
- while( in[pos]==INTERNAL_SEPARATOR )
- pos++;
- long tmp1 = wcstol( &in[pos], &end, 10 );
- if( ( errno ) || ( end == &in[pos] ) )
- {
- return 1;
- }
- pos = end-in;
-
- // debug( 0, L"Push range %d %d", tmp, tmp1 );
- long i2 = tmp1>-1 ? tmp1 : size+tmp1+1;
- // debug( 0, L"Push range idx %d %d", i1, i2 );
- short direction = i2<i1 ? -1 : 1 ;
- for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) {
- // debug(0, L"Expand range [subst]: %i\n", jjj);
- idx.push_back( jjj );
- }
- continue;
- }
-
- // debug( 0, L"Push idx %d", tmp );
- idx.push_back( i1 );
- }
-
- if( end_ptr )
- {
- // debug( 0, L"Remainder is '%ls', slice def was %d characters long", in+pos, pos );
-
- *end_ptr = (wchar_t *)(in+pos);
- }
- // debug( 0, L"ok, done" );
-
- return 0;
+ size_t pos = 1; //skip past the opening square bracket
+
+ // debug( 0, L"parse_slice on '%ls'", in );
+
+ while( 1 )
+ {
+ long tmp;
+
+ while( iswspace(in[pos]) || (in[pos]==INTERNAL_SEPARATOR))
+ pos++;
+
+ if( in[pos] == L']' )
+ {
+ pos++;
+ break;
+ }
+
+ errno=0;
+ tmp = wcstol( &in[pos], &end, 10 );
+ if( ( errno ) || ( end == &in[pos] ) )
+ {
+ return 1;
+ }
+ // debug( 0, L"Push idx %d", tmp );
+
+ long i1 = tmp>-1 ? tmp : (long)array_size+tmp+1;
+ pos = end-in;
+ while( in[pos]==INTERNAL_SEPARATOR )
+ pos++;
+ if ( in[pos]==L'.' && in[pos+1]==L'.' ){
+ pos+=2;
+ while( in[pos]==INTERNAL_SEPARATOR )
+ pos++;
+ long tmp1 = wcstol( &in[pos], &end, 10 );
+ if( ( errno ) || ( end == &in[pos] ) )
+ {
+ return 1;
+ }
+ pos = end-in;
+
+ // debug( 0, L"Push range %d %d", tmp, tmp1 );
+ long i2 = tmp1>-1 ? tmp1 : size+tmp1+1;
+ // debug( 0, L"Push range idx %d %d", i1, i2 );
+ short direction = i2<i1 ? -1 : 1 ;
+ for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) {
+ // debug(0, L"Expand range [subst]: %i\n", jjj);
+ idx.push_back( jjj );
+ }
+ continue;
+ }
+
+ // debug( 0, L"Push idx %d", tmp );
+ idx.push_back( i1 );
+ }
+
+ if( end_ptr )
+ {
+ // debug( 0, L"Remainder is '%ls', slice def was %d characters long", in+pos, pos );
+
+ *end_ptr = (wchar_t *)(in+pos);
+ }
+ // debug( 0, L"ok, done" );
+
+ return 0;
}
@@ -975,206 +975,206 @@ static int expand_variables2( parser_t &parser, const wcstring &instr, std::vect
static int expand_variables_internal( parser_t &parser, wchar_t * const in, std::vector<completion_t> &out, long last_idx )
{
- int is_ok= 1;
- int empty=0;
-
+ int is_ok= 1;
+ int empty=0;
+
wcstring var_tmp;
std::vector<long> var_idx_list;
-
- // CHECK( out, 0 );
-
- for( long i=last_idx; (i>=0) && is_ok && !empty; i-- )
- {
- const wchar_t c = in[i];
- if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
- {
- long start_pos = i+1;
- long stop_pos;
- long var_len;
- int is_single = (c==VARIABLE_EXPAND_SINGLE);
-
- stop_pos = start_pos;
-
- while( 1 )
- {
- if( !(in[stop_pos ]) )
- break;
- if( !( iswalnum( in[stop_pos] ) ||
+
+ // CHECK( out, 0 );
+
+ for( long i=last_idx; (i>=0) && is_ok && !empty; i-- )
+ {
+ const wchar_t c = in[i];
+ if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
+ {
+ long start_pos = i+1;
+ long stop_pos;
+ long var_len;
+ int is_single = (c==VARIABLE_EXPAND_SINGLE);
+
+ stop_pos = start_pos;
+
+ while( 1 )
+ {
+ if( !(in[stop_pos ]) )
+ break;
+ if( !( iswalnum( in[stop_pos] ) ||
(wcschr(L"_", in[stop_pos])!= 0) ) )
- break;
-
- stop_pos++;
- }
-
- /* printf( "Stop for '%c'\n", in[stop_pos]);*/
-
- var_len = stop_pos - start_pos;
-
- if( var_len == 0 )
- {
- expand_variable_error( parser, in, stop_pos-1, -1 );
-
- is_ok = 0;
- break;
- }
-
+ break;
+
+ stop_pos++;
+ }
+
+ /* printf( "Stop for '%c'\n", in[stop_pos]);*/
+
+ var_len = stop_pos - start_pos;
+
+ if( var_len == 0 )
+ {
+ expand_variable_error( parser, in, stop_pos-1, -1 );
+
+ is_ok = 0;
+ break;
+ }
+
var_tmp.append(in + start_pos, var_len);
- env_var_t var_val = expand_var(var_tmp.c_str() );
-
- if( ! var_val.missing() )
- {
- int all_vars=1;
+ env_var_t var_val = expand_var(var_tmp.c_str() );
+
+ if( ! var_val.missing() )
+ {
+ int all_vars=1;
wcstring_list_t var_item_list;
-
- if( is_ok )
- {
- tokenize_variable_array( var_val.c_str(), var_item_list );
-
- if( in[stop_pos] == L'[' )
- {
- wchar_t *slice_end;
- all_vars=0;
-
- if( parse_slice( in + stop_pos, &slice_end, var_idx_list, var_item_list.size() ) )
- {
- parser.error( SYNTAX_ERROR,
+
+ if( is_ok )
+ {
+ tokenize_variable_array( var_val.c_str(), var_item_list );
+
+ if( in[stop_pos] == L'[' )
+ {
+ wchar_t *slice_end;
+ all_vars=0;
+
+ if( parse_slice( in + stop_pos, &slice_end, var_idx_list, var_item_list.size() ) )
+ {
+ parser.error( SYNTAX_ERROR,
-1,
- L"Invalid index value" );
- is_ok = 0;
- break;
- }
- stop_pos = (slice_end-in);
- }
-
- if( !all_vars )
- {
+ L"Invalid index value" );
+ is_ok = 0;
+ break;
+ }
+ stop_pos = (slice_end-in);
+ }
+
+ if( !all_vars )
+ {
wcstring_list_t string_values(var_idx_list.size());
-
- for( size_t j=0; j<var_idx_list.size(); j++)
- {
- long tmp = var_idx_list.at(j);
- /*
+
+ for( size_t j=0; j<var_idx_list.size(); j++)
+ {
+ long tmp = var_idx_list.at(j);
+ /*
Check that we are within array
bounds. If not, truncate the list to
exit.
*/
- if( tmp < 1 || (size_t)tmp > var_item_list.size() )
- {
- parser.error( SYNTAX_ERROR,
+ if( tmp < 1 || (size_t)tmp > var_item_list.size() )
+ {
+ parser.error( SYNTAX_ERROR,
-1,
ARRAY_BOUNDS_ERR );
- is_ok=0;
- var_idx_list.resize(j);
- break;
- }
- else
- {
- /* Replace each index in var_idx_list inplace with the string value at the specified index */
- //al_set( var_idx_list, j, wcsdup((const wchar_t *)al_get( &var_item_list, tmp-1 ) ) );
+ is_ok=0;
+ var_idx_list.resize(j);
+ break;
+ }
+ else
+ {
+ /* Replace each index in var_idx_list inplace with the string value at the specified index */
+ //al_set( var_idx_list, j, wcsdup((const wchar_t *)al_get( &var_item_list, tmp-1 ) ) );
string_values.at(j) = var_item_list.at(tmp-1);
- }
- }
-
+ }
+ }
+
// string_values is the new var_item_list
var_item_list.swap(string_values);
- }
- }
-
- if( is_ok )
- {
-
- if( is_single )
- {
+ }
+ }
+
+ if( is_ok )
+ {
+
+ if( is_single )
+ {
in[i]=0;
wcstring res = in;
res.push_back(INTERNAL_SEPARATOR);
-
- for( size_t j=0; j<var_item_list.size(); j++ )
- {
- const wcstring &next = var_item_list.at(j);
- if( is_ok )
- {
- if( j != 0 )
- res.append(L" ");
- res.append(next);
- }
- }
+
+ for( size_t j=0; j<var_item_list.size(); j++ )
+ {
+ const wcstring &next = var_item_list.at(j);
+ if( is_ok )
+ {
+ if( j != 0 )
+ res.append(L" ");
+ res.append(next);
+ }
+ }
res.append(in + stop_pos);
- is_ok &= expand_variables2( parser, res, out, i );
- }
- else
- {
- for( size_t j=0; j<var_item_list.size(); j++ )
- {
- const wcstring &next = var_item_list.at(j);
- if( is_ok && (i == 0) && (!in[stop_pos]) )
- {
+ is_ok &= expand_variables2( parser, res, out, i );
+ }
+ else
+ {
+ for( size_t j=0; j<var_item_list.size(); j++ )
+ {
+ const wcstring &next = var_item_list.at(j);
+ if( is_ok && (i == 0) && (!in[stop_pos]) )
+ {
append_completion(out, next);
- }
- else
- {
-
- if( is_ok )
- {
+ }
+ else
+ {
+
+ if( is_ok )
+ {
wcstring new_in;
-
+
if (start_pos > 0)
new_in.append(in, start_pos - 1);
-
+
// at this point new_in.size() is start_pos - 1
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
{
new_in.push_back(INTERNAL_SEPARATOR);
- }
+ }
new_in.append(next);
- new_in.append(in + stop_pos);
+ new_in.append(in + stop_pos);
is_ok &= expand_variables2( parser, new_in, out, i );
- }
- }
-
- }
- }
- }
-
- return is_ok;
- }
- else
- {
- /*
+ }
+ }
+
+ }
+ }
+ }
+
+ return is_ok;
+ }
+ else
+ {
+ /*
Expand a non-existing variable
*/
- if( c == VARIABLE_EXPAND )
- {
- /*
+ if( c == VARIABLE_EXPAND )
+ {
+ /*
Regular expansion, i.e. expand this argument to nothing
*/
- empty = 1;
- }
- else
- {
- /*
+ empty = 1;
+ }
+ else
+ {
+ /*
Expansion to single argument.
*/
- wcstring res;
+ wcstring res;
in[i] = 0;
res.append(in);
res.append(in + stop_pos);
-
- is_ok &= expand_variables2( parser, res, out, i );
- return is_ok;
- }
- }
-
-
- }
- }
-
- if( !empty )
- {
+
+ is_ok &= expand_variables2( parser, res, out, i );
+ return is_ok;
+ }
+ }
+
+
+ }
+ }
+
+ if( !empty )
+ {
append_completion(out, in);
- }
-
- return is_ok;
+ }
+
+ return is_ok;
}
/**
@@ -1182,130 +1182,130 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
*/
static int expand_brackets(parser_t &parser, const wcstring &instr, int flags, std::vector<completion_t> &out )
{
- const wchar_t *pos;
- bool syntax_error = false;
- int bracket_count=0;
+ const wchar_t *pos;
+ bool syntax_error = false;
+ int bracket_count=0;
+
+ const wchar_t *bracket_begin=0, *bracket_end=0;
+ const wchar_t *last_sep=0;
- const wchar_t *bracket_begin=0, *bracket_end=0;
- const wchar_t *last_sep=0;
+ const wchar_t *item_begin;
+ size_t len1, len2, tot_len;
- const wchar_t *item_begin;
- size_t len1, len2, tot_len;
-
const wchar_t * const in = instr.c_str();
-
- for( pos=in;
- (*pos) && !syntax_error;
- pos++ )
- {
- switch( *pos )
- {
- case BRACKET_BEGIN:
- {
- bracket_begin = pos;
-
- bracket_count++;
- break;
-
- }
- case BRACKET_END:
- {
- bracket_count--;
- if( bracket_end < bracket_begin )
- {
- bracket_end = pos;
- }
-
- if( bracket_count < 0 )
- {
- syntax_error = true;
- }
- break;
- }
- case BRACKET_SEP:
- {
- if( bracket_count == 1 )
- last_sep = pos;
- }
- }
- }
-
- if( bracket_count > 0 )
- {
- if( !(flags & ACCEPT_INCOMPLETE) )
- {
- syntax_error = true;
- }
- else
- {
+
+ for( pos=in;
+ (*pos) && !syntax_error;
+ pos++ )
+ {
+ switch( *pos )
+ {
+ case BRACKET_BEGIN:
+ {
+ bracket_begin = pos;
+
+ bracket_count++;
+ break;
+
+ }
+ case BRACKET_END:
+ {
+ bracket_count--;
+ if( bracket_end < bracket_begin )
+ {
+ bracket_end = pos;
+ }
+
+ if( bracket_count < 0 )
+ {
+ syntax_error = true;
+ }
+ break;
+ }
+ case BRACKET_SEP:
+ {
+ if( bracket_count == 1 )
+ last_sep = pos;
+ }
+ }
+ }
+
+ if( bracket_count > 0 )
+ {
+ if( !(flags & ACCEPT_INCOMPLETE) )
+ {
+ syntax_error = true;
+ }
+ else
+ {
wcstring mod;
- if( last_sep )
- {
- mod.append( in, bracket_begin-in+1 );
- mod.append( last_sep+1 );
- mod.push_back( BRACKET_END );
- }
- else
- {
+ if( last_sep )
+ {
+ mod.append( in, bracket_begin-in+1 );
+ mod.append( last_sep+1 );
+ mod.push_back( BRACKET_END );
+ }
+ else
+ {
mod.append(in);
mod.push_back(BRACKET_END);
- }
-
- return expand_brackets( parser, mod, 1, out );
- }
- }
-
- if( syntax_error )
- {
- parser.error( SYNTAX_ERROR,
- -1,
- _(L"Mismatched brackets") );
- return 0;
- }
-
- if( bracket_begin == 0 )
- {
- append_completion(out, in);
- return 1;
- }
-
- len1 = (bracket_begin-in);
- len2 = wcslen(bracket_end)-1;
- tot_len = len1+len2;
- item_begin = bracket_begin+1;
- for( pos=(bracket_begin+1); 1; pos++ )
- {
- if( bracket_count == 0 )
- {
- if( (*pos == BRACKET_SEP) || (pos==bracket_end) )
- {
+ }
+
+ return expand_brackets( parser, mod, 1, out );
+ }
+ }
+
+ if( syntax_error )
+ {
+ parser.error( SYNTAX_ERROR,
+ -1,
+ _(L"Mismatched brackets") );
+ return 0;
+ }
+
+ if( bracket_begin == 0 )
+ {
+ append_completion(out, in);
+ return 1;
+ }
+
+ len1 = (bracket_begin-in);
+ len2 = wcslen(bracket_end)-1;
+ tot_len = len1+len2;
+ item_begin = bracket_begin+1;
+ for( pos=(bracket_begin+1); 1; pos++ )
+ {
+ if( bracket_count == 0 )
+ {
+ if( (*pos == BRACKET_SEP) || (pos==bracket_end) )
+ {
assert(pos >= item_begin);
- size_t item_len = pos-item_begin;
-
+ size_t item_len = pos-item_begin;
+
wcstring whole_item;
whole_item.reserve(tot_len + item_len + 2);
whole_item.append(in, len1);
whole_item.append(item_begin, item_len);
whole_item.append(bracket_end + 1);
expand_brackets( parser, whole_item, flags, out );
-
- item_begin = pos+1;
- if( pos == bracket_end )
- break;
- }
- }
-
- if( *pos == BRACKET_BEGIN )
- {
- bracket_count++;
- }
-
- if( *pos == BRACKET_END )
- {
- bracket_count--;
- }
- }
- return 1;
+
+ item_begin = pos+1;
+ if( pos == bracket_end )
+ break;
+ }
+ }
+
+ if( *pos == BRACKET_BEGIN )
+ {
+ bracket_count++;
+ }
+
+ if( *pos == BRACKET_END )
+ {
+ bracket_count--;
+ }
+ }
+ return 1;
}
/**
@@ -1313,85 +1313,85 @@ static int expand_brackets(parser_t &parser, const wcstring &instr, int flags, s
*/
static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector<completion_t> &outList )
{
- wchar_t *paran_begin=0, *paran_end=0;
+ wchar_t *paran_begin=0, *paran_end=0;
std::vector<wcstring> sub_res;
- size_t i, j;
- wchar_t *tail_begin = 0;
-
+ size_t i, j;
+ wchar_t *tail_begin = 0;
+
const wchar_t * const in = input.c_str();
-
- int parse_ret;
- switch( parse_ret = parse_util_locate_cmdsubst(in,
+
+ int parse_ret;
+ switch( parse_ret = parse_util_locate_cmdsubst(in,
&paran_begin,
&paran_end,
0 ) )
- {
- case -1:
- parser.error( SYNTAX_ERROR,
+ {
+ case -1:
+ parser.error( SYNTAX_ERROR,
-1,
L"Mismatched parenthesis" );
- return 0;
- case 0:
+ return 0;
+ case 0:
outList.push_back(completion_t(input));
- return 1;
- case 1:
-
- break;
- }
-
+ return 1;
+ case 1:
+
+ break;
+ }
+
const wcstring subcmd(paran_begin + 1, paran_end-paran_begin - 1);
-
- if( exec_subshell( subcmd, sub_res) == -1 )
- {
- parser.error( CMDSUBST_ERROR, -1, L"Unknown error while evaulating command substitution" );
- return 0;
- }
-
- tail_begin = paran_end + 1;
- if( *tail_begin == L'[' )
- {
+
+ if( exec_subshell( subcmd, sub_res) == -1 )
+ {
+ parser.error( CMDSUBST_ERROR, -1, L"Unknown error while evaulating command substitution" );
+ return 0;
+ }
+
+ tail_begin = paran_end + 1;
+ if( *tail_begin == L'[' )
+ {
std::vector<long> slice_idx;
- wchar_t *slice_end;
-
- if( parse_slice( tail_begin, &slice_end, slice_idx, sub_res.size() ) )
- {
- parser.error( SYNTAX_ERROR, -1, L"Invalid index value" );
- return 0;
- }
- else
- {
+ wchar_t *slice_end;
+
+ if( parse_slice( tail_begin, &slice_end, slice_idx, sub_res.size() ) )
+ {
+ parser.error( SYNTAX_ERROR, -1, L"Invalid index value" );
+ return 0;
+ }
+ else
+ {
std::vector<wcstring> sub_res2;
- tail_begin = slice_end;
- for( i=0; i < slice_idx.size(); i++ )
- {
- long idx = slice_idx.at(i);
- if( idx < 1 || (size_t)idx > sub_res.size() )
- {
- parser.error( SYNTAX_ERROR,
- -1,
- ARRAY_BOUNDS_ERR );
- return 0;
- }
- idx = idx-1;
-
+ tail_begin = slice_end;
+ for( i=0; i < slice_idx.size(); i++ )
+ {
+ long idx = slice_idx.at(i);
+ if( idx < 1 || (size_t)idx > sub_res.size() )
+ {
+ parser.error( SYNTAX_ERROR,
+ -1,
+ ARRAY_BOUNDS_ERR );
+ return 0;
+ }
+ idx = idx-1;
+
sub_res2.push_back(sub_res.at(idx));
- // debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx );
- //sub_res[idx] = 0; // ??
- }
- sub_res = sub_res2;
- }
- }
-
-
- /*
+ // debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx );
+ //sub_res[idx] = 0; // ??
+ }
+ sub_res = sub_res2;
+ }
+ }
+
+
+ /*
Recursively call ourselves to expand any remaining command
substitutions. The result of this recursive call using the tail
of the string is inserted into the tail_expand array list
*/
std::vector<completion_t> tail_expand;
- expand_cmdsubst( parser, tail_begin, tail_expand );
-
- /*
+ expand_cmdsubst( parser, tail_begin, tail_expand );
+
+ /*
Combine the result of the current command substitution with the
result of the recursive tail expansion
*/
@@ -1399,35 +1399,35 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
{
wcstring sub_item = sub_res.at(i);
wcstring sub_item2 = escape_string(sub_item, 1);
-
+
for( j=0; j < tail_expand.size(); j++ )
{
-
+
wcstring whole_item;
-
+
wcstring tail_item = tail_expand.at(j).completion;
-
+
//sb_append_substring( &whole_item, in, len1 );
whole_item.append(in, paran_begin-in);
-
+
//sb_append_char( &whole_item, INTERNAL_SEPARATOR );
whole_item.push_back(INTERNAL_SEPARATOR);
-
+
//sb_append_substring( &whole_item, sub_item2, item_len );
- whole_item.append(sub_item2);
-
+ whole_item.append(sub_item2);
+
//sb_append_char( &whole_item, INTERNAL_SEPARATOR );
whole_item.push_back(INTERNAL_SEPARATOR);
-
+
//sb_append( &whole_item, tail_item );
whole_item.append(tail_item);
-
- //al_push( out, whole_item.buff );
+
+ //al_push( out, whole_item.buff );
outList.push_back(completion_t(whole_item));
}
}
-
- return 1;
+
+ return 1;
}
/**
@@ -1436,10 +1436,10 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
__attribute__((unused))
static wchar_t *expand_unescape( parser_t &parser, const wchar_t * in, int escape_special )
{
- wchar_t *res = unescape( in, escape_special );
- if( !res )
- parser.error( SYNTAX_ERROR, -1, L"Unexpected end of string" );
- return res;
+ wchar_t *res = unescape( in, escape_special );
+ if( !res )
+ parser.error( SYNTAX_ERROR, -1, L"Unexpected end of string" );
+ return res;
}
static wcstring expand_unescape_string( const wcstring &in, int escape_special )
@@ -1447,7 +1447,7 @@ static wcstring expand_unescape_string( const wcstring &in, int escape_special )
wcstring tmp = in;
unescape_string(tmp, escape_special);
/* Need to detect error here */
- return tmp;
+ return tmp;
}
/**
@@ -1455,24 +1455,24 @@ static wcstring expand_unescape_string( const wcstring &in, int escape_special )
*/
static void expand_home_directory( wcstring &input )
{
- const wchar_t * const in = input.c_str();
- if( in[0] == HOME_DIRECTORY )
- {
- int tilde_error = 0;
+ const wchar_t * const in = input.c_str();
+ if( in[0] == HOME_DIRECTORY )
+ {
+ int tilde_error = 0;
size_t tail_idx;
wcstring home;
- if( in[1] == '/' || in[1] == '\0' )
- {
- /* Current users home directory */
+ if( in[1] == '/' || in[1] == '\0' )
+ {
+ /* Current users home directory */
- home = env_get_string( L"HOME" );
+ home = env_get_string( L"HOME" );
tail_idx = 1;
- }
- else
- {
- /* Some other users home directory */
- const wchar_t *name_end = wcschr( in, L'/' );
+ }
+ else
+ {
+ /* Some other users home directory */
+ const wchar_t *name_end = wcschr( in, L'/' );
if (name_end)
{
tail_idx = name_end - in;
@@ -1483,33 +1483,33 @@ static void expand_home_directory( wcstring &input )
}
wcstring name_str = input.substr(1, tail_idx - 1);
std::string name_cstr = wcs2string(name_str);
- struct passwd *userinfo = getpwnam( name_cstr.c_str() );
+ struct passwd *userinfo = getpwnam( name_cstr.c_str() );
- if( userinfo == NULL )
- {
- tilde_error = 1;
+ if( userinfo == NULL )
+ {
+ tilde_error = 1;
input[0] = L'~';
- }
- else
- {
- home = str2wcstring(userinfo->pw_dir);
- }
- }
+ }
+ else
+ {
+ home = str2wcstring(userinfo->pw_dir);
+ }
+ }
if (! tilde_error)
{
input.replace(input.begin(), input.begin() + tail_idx, home);
}
- }
+ }
}
void expand_tilde(wcstring &input)
{
- if( ! input.empty() && input.at(0) == L'~' )
- {
- input.at(0) = HOME_DIRECTORY;
- expand_home_directory( input );
- }
+ if( ! input.empty() && input.at(0) == L'~' )
+ {
+ input.at(0) = HOME_DIRECTORY;
+ expand_home_directory( input );
+ }
}
/**
@@ -1520,7 +1520,7 @@ static void remove_internal_separator( wcstring &str, bool conv )
{
/* Remove all instances of INTERNAL_SEPARATOR */
str.erase(std::remove(str.begin(), str.end(), (wchar_t)INTERNAL_SEPARATOR), str.end());
-
+
/* If conv is true, replace all instances of ANY_CHAR with '?', ANY_STRING with '*', ANY_STRING_RECURSIVE with '*' */
if (conv)
{
@@ -1543,43 +1543,43 @@ static void remove_internal_separator( wcstring &str, bool conv )
int expand_string( const wcstring &input, std::vector<completion_t> &output, expand_flags_t flags )
{
- parser_t parser(PARSER_TYPE_ERRORS_ONLY, true /* show errors */);
- std::vector<completion_t> list1, list2;
- std::vector<completion_t> *in, *out;
-
- size_t i;
- int res = EXPAND_OK;
-
- if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( input.c_str() ) )
- {
- output.push_back(completion_t(input));
- return EXPAND_OK;
- }
-
- if( EXPAND_SKIP_CMDSUBST & flags )
- {
- wchar_t *begin, *end;
-
- if( parse_util_locate_cmdsubst( input.c_str(),
+ parser_t parser(PARSER_TYPE_ERRORS_ONLY, true /* show errors */);
+ std::vector<completion_t> list1, list2;
+ std::vector<completion_t> *in, *out;
+
+ size_t i;
+ int res = EXPAND_OK;
+
+ if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( input.c_str() ) )
+ {
+ output.push_back(completion_t(input));
+ return EXPAND_OK;
+ }
+
+ if( EXPAND_SKIP_CMDSUBST & flags )
+ {
+ wchar_t *begin, *end;
+
+ if( parse_util_locate_cmdsubst( input.c_str(),
&begin,
&end,
1 ) != 0 )
- {
- parser.error( CMDSUBST_ERROR, -1, L"Command substitutions not allowed" );
- return EXPAND_ERROR;
- }
- list1.push_back(completion_t(input));
- }
- else
- {
+ {
+ parser.error( CMDSUBST_ERROR, -1, L"Command substitutions not allowed" );
+ return EXPAND_ERROR;
+ }
+ list1.push_back(completion_t(input));
+ }
+ else
+ {
int cmdsubst_ok = expand_cmdsubst(parser, input, list1);
if (! cmdsubst_ok)
return EXPAND_ERROR;
- }
+ }
in = &list1;
out = &list2;
-
+
for( i=0; i < in->size(); i++ )
{
/*
@@ -1587,9 +1587,9 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
expand_string to expand incomplete strings from the
commandline.
*/
- int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE;
+ int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE;
wcstring next = expand_unescape_string( in->at(i).completion, unescape_flags );
-
+
if( EXPAND_SKIP_VARIABLES & flags )
{
for (size_t i=0; i < next.size(); i++) {
@@ -1607,33 +1607,33 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
}
}
}
-
+
in->clear();
-
+
in = &list2;
out = &list1;
-
+
for( i=0; i < in->size(); i++ )
{
wcstring next = in->at(i).completion;
-
+
if( !expand_brackets( parser, next, flags, *out ))
{
return EXPAND_ERROR;
}
}
in->clear();
-
+
in = &list1;
out = &list2;
-
+
for( i=0; i < in->size(); i++ )
{
wcstring next = in->at(i).completion;
-
+
expand_home_directory(next);
-
-
+
+
if( flags & ACCEPT_INCOMPLETE )
{
if( next[0] == PROCESS_EXPAND )
@@ -1660,26 +1660,26 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
}
}
}
-
+
in->clear();
-
+
in = &list2;
out = &list1;
-
+
for( i=0; i < in->size(); i++ )
{
wcstring next_str = in->at(i).completion;
int wc_res;
-
- remove_internal_separator( next_str, (EXPAND_SKIP_WILDCARDS & flags) ? true : false );
+
+ remove_internal_separator( next_str, (EXPAND_SKIP_WILDCARDS & flags) ? true : false );
const wchar_t *next = next_str.c_str();
-
+
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
wildcard_has( next, 1 ) )
{
const wchar_t *start, *rest;
std::vector<completion_t> *list = out;
-
+
if( next[0] == '/' )
{
start = L"/";
@@ -1690,17 +1690,17 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
start = L"";
rest = next;
}
-
+
if( flags & ACCEPT_INCOMPLETE )
{
list = &output;
}
-
+
wc_res = wildcard_expand_string(rest, start, flags, *list);
-
+
if( !(flags & ACCEPT_INCOMPLETE) )
{
-
+
switch( wc_res )
{
case 0:
@@ -1712,13 +1712,13 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
break;
}
}
-
+
case 1:
{
size_t j;
res = EXPAND_WILDCARD_MATCH;
sort_completions( *out );
-
+
for( j=0; j< out->size(); j++ )
{
output.push_back( out->at(j) );
@@ -1726,15 +1726,15 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
out->clear();
break;
}
-
+
case -1:
{
return EXPAND_ERROR;
}
-
+
}
}
-
+
}
else
{
@@ -1746,26 +1746,26 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, exp
output.push_back(completion_t(next));
}
}
-
+
}
-
- return res;
+
+ return res;
}
bool expand_one(wcstring &string, expand_flags_t flags) {
- std::vector<completion_t> completions;
- bool result = false;
-
- if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string.c_str() ) )
- {
+ std::vector<completion_t> completions;
+ bool result = false;
+
+ if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string.c_str() ) )
+ {
return true;
- }
-
+ }
+
if (expand_string(string, completions, flags)) {
if (completions.size() == 1) {
string = completions.at(0).completion;
result = true;
}
}
- return result;
+ return result;
}
diff --git a/expand.h b/expand.h
index 1f8c08e8..79942575 100644
--- a/expand.h
+++ b/expand.h
@@ -6,7 +6,7 @@
benefit from using a more clever memory allocation scheme, perhaps
an evil combination of talloc, string buffers and reference
counting.
-
+
*/
#ifndef FISH_EXPAND_H
@@ -24,10 +24,10 @@
enum {
/** Flag specifying that cmdsubst expansion should be skipped */
EXPAND_SKIP_CMDSUBST = 1 << 0,
-
+
/** Flag specifying that variable expansion should be skipped */
EXPAND_SKIP_VARIABLES = 1 << 1,
-
+
/** Flag specifying that wildcard expansion should be skipped */
EXPAND_SKIP_WILDCARDS = 1 << 2,
@@ -36,21 +36,21 @@ enum {
completion). An incomplete match is a wildcard that matches a
prefix of the filename. If accept_incomplete is true, only the
remainder of the string is returned.
- */
+ */
ACCEPT_INCOMPLETE = 1 << 3,
/** Only match files that are executable by the current user. Only applicable together with ACCEPT_INCOMPLETE. */
EXECUTABLES_ONLY = 1 << 4,
-
+
/** Only match directories. Only applicable together with ACCEPT_INCOMPLETE. */
DIRECTORIES_ONLY = 1 << 5,
-
+
/** Don't generate descriptions */
EXPAND_NO_DESCRIPTIONS = 1 << 6,
-
+
/** Don't do process expansion */
EXPAND_SKIP_PROCESS = 1 << 7,
-
+
/** Don't expand jobs (but you can still expand processes). This is because job expansion is not thread safe. */
EXPAND_SKIP_JOBS = 1 << 8
};
@@ -69,33 +69,33 @@ class completion_t;
enum
{
- /** Character represeting a home directory */
- HOME_DIRECTORY = EXPAND_RESERVED,
+ /** Character represeting a home directory */
+ HOME_DIRECTORY = EXPAND_RESERVED,
+
+ /** Character represeting process expansion */
+ PROCESS_EXPAND,
- /** Character represeting process expansion */
- PROCESS_EXPAND,
-
- /** Character representing variable expansion */
- VARIABLE_EXPAND,
+ /** Character representing variable expansion */
+ VARIABLE_EXPAND,
- /** Character rpresenting variable expansion into a single element*/
- VARIABLE_EXPAND_SINGLE,
+ /** Character rpresenting variable expansion into a single element*/
+ VARIABLE_EXPAND_SINGLE,
- /** Character representing the start of a bracket expansion */
- BRACKET_BEGIN,
+ /** Character representing the start of a bracket expansion */
+ BRACKET_BEGIN,
- /** Character representing the end of a bracket expansion */
- BRACKET_END,
+ /** Character representing the end of a bracket expansion */
+ BRACKET_END,
- /** Character representing separation between two bracket elements */
- BRACKET_SEP,
- /**
- Separate subtokens in a token with this character.
- */
- INTERNAL_SEPARATOR,
+ /** Character representing separation between two bracket elements */
+ BRACKET_SEP,
+ /**
+ Separate subtokens in a token with this character.
+ */
+ INTERNAL_SEPARATOR,
}
- ;
+ ;
/**
@@ -103,14 +103,14 @@ enum
*/
enum
{
- /** Error */
- EXPAND_ERROR,
- /** Ok */
- EXPAND_OK,
- /** Ok, a wildcard in the string matched no files */
- EXPAND_WILDCARD_NO_MATCH,
- /* Ok, a wildcard in the string matched a file */
- EXPAND_WILDCARD_MATCH
+ /** Error */
+ EXPAND_ERROR,
+ /** Ok */
+ EXPAND_OK,
+ /** Ok, a wildcard in the string matched no files */
+ EXPAND_WILDCARD_NO_MATCH,
+ /* Ok, a wildcard in the string matched a file */
+ EXPAND_WILDCARD_MATCH
};
/** Character for separating two array elements. We use 30, i.e. the ascii record separator since that seems logical. */
@@ -132,7 +132,7 @@ class parser_t;
(\$VAR_NAME becomes the value of the environment variable VAR_NAME),
cmdsubst expansion and wildcard expansion. The results are inserted
into the list out.
-
+
If the parameter does not need expansion, it is copied into the list
out.
@@ -148,7 +148,7 @@ __warn_unused int expand_string( const wcstring &input, std::vector<completion_t
expand_one is identical to expand_string, except it will fail if in
expands to more than one string. This is used for expanding command
names.
-
+
\param inout_str The parameter to expand in-place
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\return Whether expansion succeded
diff --git a/fallback.cpp b/fallback.cpp
index 1dd96406..59096685 100644
--- a/fallback.cpp
+++ b/fallback.cpp
@@ -57,10 +57,10 @@ char **__environ = 0;
int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
{
- while( *str )
- {
- fish_putc( *str++ );
- }
+ while( *str )
+ {
+ fish_putc( *str++ );
+ }
}
#endif
@@ -74,48 +74,48 @@ int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
*/
char *tparm_solaris_kludge( char *str, ... )
{
- long int param[9] = { };
+ long int param[9] = { };
- va_list ap;
- va_start( ap, str );
+ va_list ap;
+ va_start( ap, str );
- if( ( set_a_foreground && ! strcmp( str, set_a_foreground ) )
+ if( ( set_a_foreground && ! strcmp( str, set_a_foreground ) )
|| ( set_a_background && ! strcmp( str, set_a_background ) )
- || ( set_foreground && ! strcmp( str, set_foreground ) )
+ || ( set_foreground && ! strcmp( str, set_foreground ) )
|| ( set_background && ! strcmp( str, set_background ) )
- || ( enter_underline_mode && ! strcmp( str, enter_underline_mode ) )
- || ( exit_underline_mode && ! strcmp( str, exit_underline_mode ) )
- || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
- || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
- || ( flash_screen && ! strcmp( str, flash_screen ) )
- || ( enter_subscript_mode && ! strcmp( str, enter_subscript_mode ) )
- || ( exit_subscript_mode && ! strcmp( str, exit_subscript_mode ) )
- || ( enter_superscript_mode && ! strcmp( str, enter_superscript_mode ) )
- || ( exit_superscript_mode && ! strcmp( str, exit_superscript_mode ) )
- || ( enter_blink_mode && ! strcmp( str, enter_blink_mode ) )
- || ( enter_italics_mode && ! strcmp( str, enter_italics_mode ) )
- || ( exit_italics_mode && ! strcmp( str, exit_italics_mode ) )
- || ( enter_reverse_mode && ! strcmp( str, enter_reverse_mode ) )
- || ( enter_shadow_mode && ! strcmp( str, enter_shadow_mode ) )
- || ( exit_shadow_mode && ! strcmp( str, exit_shadow_mode ) )
- || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
- || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
- || ( enter_secure_mode && ! strcmp( str, enter_secure_mode ) )
- || ( enter_bold_mode && ! strcmp ( str, enter_bold_mode ) ) )
- {
- param[0] = va_arg( ap, long int );
- }
- else if( cursor_address && ! strcmp( str, cursor_address ) )
- {
- param[0] = va_arg( ap, long int );
- param[1] = va_arg( ap, long int );
- }
-
- va_end( ap );
-
-
- return tparm( str, param[0], param[1], param[2], param[3],
- param[4], param[5], param[6], param[7], param[8] );
+ || ( enter_underline_mode && ! strcmp( str, enter_underline_mode ) )
+ || ( exit_underline_mode && ! strcmp( str, exit_underline_mode ) )
+ || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
+ || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
+ || ( flash_screen && ! strcmp( str, flash_screen ) )
+ || ( enter_subscript_mode && ! strcmp( str, enter_subscript_mode ) )
+ || ( exit_subscript_mode && ! strcmp( str, exit_subscript_mode ) )
+ || ( enter_superscript_mode && ! strcmp( str, enter_superscript_mode ) )
+ || ( exit_superscript_mode && ! strcmp( str, exit_superscript_mode ) )
+ || ( enter_blink_mode && ! strcmp( str, enter_blink_mode ) )
+ || ( enter_italics_mode && ! strcmp( str, enter_italics_mode ) )
+ || ( exit_italics_mode && ! strcmp( str, exit_italics_mode ) )
+ || ( enter_reverse_mode && ! strcmp( str, enter_reverse_mode ) )
+ || ( enter_shadow_mode && ! strcmp( str, enter_shadow_mode ) )
+ || ( exit_shadow_mode && ! strcmp( str, exit_shadow_mode ) )
+ || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
+ || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
+ || ( enter_secure_mode && ! strcmp( str, enter_secure_mode ) )
+ || ( enter_bold_mode && ! strcmp ( str, enter_bold_mode ) ) )
+ {
+ param[0] = va_arg( ap, long int );
+ }
+ else if( cursor_address && ! strcmp( str, cursor_address ) )
+ {
+ param[0] = va_arg( ap, long int );
+ param[1] = va_arg( ap, long int );
+ }
+
+ va_end( ap );
+
+
+ return tparm( str, param[0], param[1], param[2], param[3],
+ param[4], param[5], param[6], param[7], param[8] );
}
// Re-defining just to make sure nothing breaks further down in this file.
@@ -140,15 +140,15 @@ char *tparm_solaris_kludge( char *str, ... )
*/
static void pad( void (*writer)(wchar_t), int count)
{
-
- int i;
- if( count < 0 )
- return;
-
- for( i=0; i<count; i++ )
- {
- writer( L' ' );
- }
+
+ int i;
+ if( count < 0 )
+ return;
+
+ for( i=0; i<count; i++ )
+ {
+ writer( L' ' );
+ }
}
/**
@@ -171,380 +171,380 @@ static void pad( void (*writer)(wchar_t), int count)
For a full description on the usage of *printf, see use 'man 3 printf'.
*/
-static int vgwprintf( void (*writer)(wchar_t),
- const wchar_t *filter,
- va_list va )
+static int vgwprintf( void (*writer)(wchar_t),
+ const wchar_t *filter,
+ va_list va )
{
- const wchar_t *filter_org=filter;
- int count=0;
-
- for( ;*filter; filter++)
- {
- if(*filter == L'%')
- {
- int is_long=0;
- int width = -1;
- filter++;
- int loop=1;
- int precision=-1;
- int pad_left = 1;
-
- if( iswdigit( *filter ) )
- {
- width=0;
- while( (*filter >= L'0') && (*filter <= L'9'))
- {
- width=10*width+(*filter++ - L'0');
- }
- }
-
- while( loop )
- {
-
- switch(*filter)
- {
- case L'l':
- /* Long variable */
- is_long++;
- filter++;
- break;
-
- case L'*':
- /* Set minimum field width */
- width = va_arg( va, int );
- filter++;
- break;
-
- case L'-':
- filter++;
- pad_left=0;
- break;
-
- case L'.':
- /*
- Set precision.
- */
- filter++;
- if( *filter == L'*' )
- {
- precision = va_arg( va, int );
- }
- else
- {
- precision=0;
- while( (*filter >= L'0') && (*filter <= L'9'))
- {
- precision=10*precision+(*filter++ - L'0');
- }
- }
- break;
-
- default:
- loop=0;
- break;
- }
- }
-
- switch( *filter )
- {
- case L'c':
- {
- wchar_t c;
-
- if( (width >= 0) && pad_left )
- {
- pad( writer, width-1 );
- count += maxi( width-1, 0 );
- }
-
- c = is_long?va_arg(va, wint_t):btowc(va_arg(va, int));
- if( precision != 0 )
- writer( c );
-
-
- if( (width >= 0) && !pad_left )
- {
- pad( writer, width-1 );
- count += maxi( width-1, 0 );
- }
-
- count++;
-
- break;
- }
- case L's':
- {
-
- wchar_t *ss=0;
- if( is_long )
- {
- ss = va_arg(va, wchar_t *);
- }
- else
- {
- char *ns = va_arg(va, char*);
-
- if( ns )
- {
- ss = str2wcs( ns );
- }
- }
-
- if( !ss )
- {
- return -1;
- }
-
- if( (width >= 0) && pad_left )
- {
- pad( writer, width-wcslen(ss) );
- count += maxi(width-wcslen(ss), 0);
- }
-
- wchar_t *s=ss;
- int precount = count;
-
- while( *s )
- {
- if( (precision > 0) && (precision <= (count-precount) ) )
- break;
-
- writer( *(s++) );
- count++;
- }
-
- if( (width >= 0) && !pad_left )
- {
- pad( writer, width-wcslen(ss) );
- count += maxi( width-wcslen(ss), 0 );
- }
-
- if( !is_long )
- free( ss );
-
- break;
- }
-
- case L'd':
- case L'i':
- case L'o':
- case L'u':
- case L'x':
- case L'X':
- {
- char str[33];
- char *pos;
- char format[16];
- int len;
-
- format[0]=0;
- strcat( format, "%");
- if( precision >= 0 )
- strcat( format, ".*" );
- switch( is_long )
- {
- case 2:
- strcat( format, "ll" );
- break;
- case 1:
- strcat( format, "l" );
- break;
- }
-
- len = strlen(format);
- format[len++]=(char)*filter;
- format[len]=0;
-
- switch( *filter )
- {
- case L'd':
- case L'i':
- {
-
- switch( is_long )
- {
- case 0:
- {
- int d = va_arg( va, int );
- if( precision >= 0 )
- snprintf( str, 32, format, precision, d );
- else
- snprintf( str, 32, format, d );
-
- break;
- }
-
- case 1:
- {
- long d = va_arg( va, long );
- if( precision >= 0 )
- snprintf( str, 32, format, precision, d );
- else
- snprintf( str, 32, format, d );
- break;
- }
-
- case 2:
- {
- long long d = va_arg( va, long long );
- if( precision >= 0 )
- snprintf( str, 32, format, precision, d );
- else
- snprintf( str, 32, format, d );
- break;
- }
-
- default:
- debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
- return -1;
- }
- break;
-
- }
-
- case L'u':
- case L'o':
- case L'x':
- case L'X':
- {
-
- switch( is_long )
- {
- case 0:
- {
- unsigned d = va_arg( va, unsigned );
- if( precision >= 0 )
- snprintf( str, 32, format, precision, d );
- else
- snprintf( str, 32, format, d );
- break;
- }
-
- case 1:
- {
- unsigned long d = va_arg( va, unsigned long );
- if( precision >= 0 )
- snprintf( str, 32, format, precision, d );
- else
- snprintf( str, 32, format, d );
- break;
- }
-
- case 2:
- {
- unsigned long long d = va_arg( va, unsigned long long );
- if( precision >= 0 )
- snprintf( str, 32, format, precision, d );
- else
- snprintf( str, 32, format, d );
- break;
- }
-
- default:
- debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
- return -1;
- }
- break;
-
- }
-
- default:
- debug( 0, L"Invalid filter %ls in string %ls\n", *filter, filter_org );
- return -1;
-
- }
-
- if( (width >= 0) && pad_left )
- {
- int l = maxi(width-strlen(str), 0 );
- pad( writer, l );
- count += l;
- }
-
- pos = str;
-
- while( *pos )
- {
- writer( *(pos++) );
- count++;
- }
-
- if( (width >= 0) && !pad_left )
- {
- int l = maxi(width-strlen(str), 0 );
- pad( writer, l );
- count += l;
- }
-
- break;
- }
-
- case L'f':
- {
- char str[32];
- char *pos;
- double val = va_arg( va, double );
-
- if( precision>= 0 )
- {
- if( width>= 0 )
- {
- snprintf( str, 32, "%*.*f", width, precision, val );
- }
- else
- {
- snprintf( str, 32, "%.*f", precision, val );
- }
- }
- else
- {
- if( width>= 0 )
- {
- snprintf( str, 32, "%*f", width, val );
- }
- else
- {
- snprintf( str, 32, "%f", val );
- }
- }
-
- pos = str;
-
- while( *pos )
- {
- writer( *(pos++) );
- count++;
- }
-
- break;
- }
-
- case L'n':
- {
- int *n = va_arg( va, int *);
-
- *n = count;
- break;
- }
- case L'%':
- {
- writer('%');
- count++;
- break;
- }
- default:
- debug( 0, L"Unknown switch %lc in string %ls\n", *filter, filter_org );
- return -1;
- }
- }
- else
- {
- writer( *filter );
- count++;
- }
- }
-
- return count;
+ const wchar_t *filter_org=filter;
+ int count=0;
+
+ for( ;*filter; filter++)
+ {
+ if(*filter == L'%')
+ {
+ int is_long=0;
+ int width = -1;
+ filter++;
+ int loop=1;
+ int precision=-1;
+ int pad_left = 1;
+
+ if( iswdigit( *filter ) )
+ {
+ width=0;
+ while( (*filter >= L'0') && (*filter <= L'9'))
+ {
+ width=10*width+(*filter++ - L'0');
+ }
+ }
+
+ while( loop )
+ {
+
+ switch(*filter)
+ {
+ case L'l':
+ /* Long variable */
+ is_long++;
+ filter++;
+ break;
+
+ case L'*':
+ /* Set minimum field width */
+ width = va_arg( va, int );
+ filter++;
+ break;
+
+ case L'-':
+ filter++;
+ pad_left=0;
+ break;
+
+ case L'.':
+ /*
+ Set precision.
+ */
+ filter++;
+ if( *filter == L'*' )
+ {
+ precision = va_arg( va, int );
+ }
+ else
+ {
+ precision=0;
+ while( (*filter >= L'0') && (*filter <= L'9'))
+ {
+ precision=10*precision+(*filter++ - L'0');
+ }
+ }
+ break;
+
+ default:
+ loop=0;
+ break;
+ }
+ }
+
+ switch( *filter )
+ {
+ case L'c':
+ {
+ wchar_t c;
+
+ if( (width >= 0) && pad_left )
+ {
+ pad( writer, width-1 );
+ count += maxi( width-1, 0 );
+ }
+
+ c = is_long?va_arg(va, wint_t):btowc(va_arg(va, int));
+ if( precision != 0 )
+ writer( c );
+
+
+ if( (width >= 0) && !pad_left )
+ {
+ pad( writer, width-1 );
+ count += maxi( width-1, 0 );
+ }
+
+ count++;
+
+ break;
+ }
+ case L's':
+ {
+
+ wchar_t *ss=0;
+ if( is_long )
+ {
+ ss = va_arg(va, wchar_t *);
+ }
+ else
+ {
+ char *ns = va_arg(va, char*);
+
+ if( ns )
+ {
+ ss = str2wcs( ns );
+ }
+ }
+
+ if( !ss )
+ {
+ return -1;
+ }
+
+ if( (width >= 0) && pad_left )
+ {
+ pad( writer, width-wcslen(ss) );
+ count += maxi(width-wcslen(ss), 0);
+ }
+
+ wchar_t *s=ss;
+ int precount = count;
+
+ while( *s )
+ {
+ if( (precision > 0) && (precision <= (count-precount) ) )
+ break;
+
+ writer( *(s++) );
+ count++;
+ }
+
+ if( (width >= 0) && !pad_left )
+ {
+ pad( writer, width-wcslen(ss) );
+ count += maxi( width-wcslen(ss), 0 );
+ }
+
+ if( !is_long )
+ free( ss );
+
+ break;
+ }
+
+ case L'd':
+ case L'i':
+ case L'o':
+ case L'u':
+ case L'x':
+ case L'X':
+ {
+ char str[33];
+ char *pos;
+ char format[16];
+ int len;
+
+ format[0]=0;
+ strcat( format, "%");
+ if( precision >= 0 )
+ strcat( format, ".*" );
+ switch( is_long )
+ {
+ case 2:
+ strcat( format, "ll" );
+ break;
+ case 1:
+ strcat( format, "l" );
+ break;
+ }
+
+ len = strlen(format);
+ format[len++]=(char)*filter;
+ format[len]=0;
+
+ switch( *filter )
+ {
+ case L'd':
+ case L'i':
+ {
+
+ switch( is_long )
+ {
+ case 0:
+ {
+ int d = va_arg( va, int );
+ if( precision >= 0 )
+ snprintf( str, 32, format, precision, d );
+ else
+ snprintf( str, 32, format, d );
+
+ break;
+ }
+
+ case 1:
+ {
+ long d = va_arg( va, long );
+ if( precision >= 0 )
+ snprintf( str, 32, format, precision, d );
+ else
+ snprintf( str, 32, format, d );
+ break;
+ }
+
+ case 2:
+ {
+ long long d = va_arg( va, long long );
+ if( precision >= 0 )
+ snprintf( str, 32, format, precision, d );
+ else
+ snprintf( str, 32, format, d );
+ break;
+ }
+
+ default:
+ debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
+ return -1;
+ }
+ break;
+
+ }
+
+ case L'u':
+ case L'o':
+ case L'x':
+ case L'X':
+ {
+
+ switch( is_long )
+ {
+ case 0:
+ {
+ unsigned d = va_arg( va, unsigned );
+ if( precision >= 0 )
+ snprintf( str, 32, format, precision, d );
+ else
+ snprintf( str, 32, format, d );
+ break;
+ }
+
+ case 1:
+ {
+ unsigned long d = va_arg( va, unsigned long );
+ if( precision >= 0 )
+ snprintf( str, 32, format, precision, d );
+ else
+ snprintf( str, 32, format, d );
+ break;
+ }
+
+ case 2:
+ {
+ unsigned long long d = va_arg( va, unsigned long long );
+ if( precision >= 0 )
+ snprintf( str, 32, format, precision, d );
+ else
+ snprintf( str, 32, format, d );
+ break;
+ }
+
+ default:
+ debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
+ return -1;
+ }
+ break;
+
+ }
+
+ default:
+ debug( 0, L"Invalid filter %ls in string %ls\n", *filter, filter_org );
+ return -1;
+
+ }
+
+ if( (width >= 0) && pad_left )
+ {
+ int l = maxi(width-strlen(str), 0 );
+ pad( writer, l );
+ count += l;
+ }
+
+ pos = str;
+
+ while( *pos )
+ {
+ writer( *(pos++) );
+ count++;
+ }
+
+ if( (width >= 0) && !pad_left )
+ {
+ int l = maxi(width-strlen(str), 0 );
+ pad( writer, l );
+ count += l;
+ }
+
+ break;
+ }
+
+ case L'f':
+ {
+ char str[32];
+ char *pos;
+ double val = va_arg( va, double );
+
+ if( precision>= 0 )
+ {
+ if( width>= 0 )
+ {
+ snprintf( str, 32, "%*.*f", width, precision, val );
+ }
+ else
+ {
+ snprintf( str, 32, "%.*f", precision, val );
+ }
+ }
+ else
+ {
+ if( width>= 0 )
+ {
+ snprintf( str, 32, "%*f", width, val );
+ }
+ else
+ {
+ snprintf( str, 32, "%f", val );
+ }
+ }
+
+ pos = str;
+
+ while( *pos )
+ {
+ writer( *(pos++) );
+ count++;
+ }
+
+ break;
+ }
+
+ case L'n':
+ {
+ int *n = va_arg( va, int *);
+
+ *n = count;
+ break;
+ }
+ case L'%':
+ {
+ writer('%');
+ count++;
+ break;
+ }
+ default:
+ debug( 0, L"Unknown switch %lc in string %ls\n", *filter, filter_org );
+ return -1;
+ }
+ }
+ else
+ {
+ writer( *filter );
+ count++;
+ }
+ }
+
+ return count;
}
/**
@@ -552,9 +552,9 @@ static int vgwprintf( void (*writer)(wchar_t),
*/
static struct
{
- int count;
- int max;
- wchar_t *pos;
+ int count;
+ int max;
+ wchar_t *pos;
}
sw_data;
@@ -563,42 +563,42 @@ sw_data;
*/
static void sw_writer( wchar_t c )
{
- if( sw_data.count < sw_data.max )
- *(sw_data.pos++)=c;
- sw_data.count++;
+ if( sw_data.count < sw_data.max )
+ *(sw_data.pos++)=c;
+ sw_data.count++;
}
int vswprintf( wchar_t *out, size_t n, const wchar_t *filter, va_list va )
{
- int written;
-
- sw_data.pos=out;
- sw_data.max=n;
- sw_data.count=0;
- written=vgwprintf( &sw_writer,
- filter,
- va );
- if( written < n )
- {
- *sw_data.pos = 0;
- }
- else
- {
- written=-1;
- }
-
- return written;
+ int written;
+
+ sw_data.pos=out;
+ sw_data.max=n;
+ sw_data.count=0;
+ written=vgwprintf( &sw_writer,
+ filter,
+ va );
+ if( written < n )
+ {
+ *sw_data.pos = 0;
+ }
+ else
+ {
+ written=-1;
+ }
+
+ return written;
}
int swprintf( wchar_t *out, size_t n, const wchar_t *filter, ... )
{
- va_list va;
- int written;
-
- va_start( va, filter );
- written = vswprintf( out, n, filter, va );
- va_end( va );
- return written;
+ va_list va;
+ int written;
+
+ va_start( va, filter );
+ written = vswprintf( out, n, filter, va );
+ va_end( va );
+ return written;
}
/**
@@ -608,7 +608,7 @@ static FILE *fw_data;
static void fw_writer( wchar_t c )
{
- putwc( c, fw_data );
+ putwc( c, fw_data );
}
/*
@@ -616,35 +616,35 @@ static void fw_writer( wchar_t c )
*/
int vfwprintf( FILE *f, const wchar_t *filter, va_list va )
{
- fw_data = f;
- return vgwprintf( &fw_writer, filter, va );
+ fw_data = f;
+ return vgwprintf( &fw_writer, filter, va );
}
int fwprintf( FILE *f, const wchar_t *filter, ... )
{
- va_list va;
- int written;
-
- va_start( va, filter );
- written = vfwprintf( f, filter, va );
- va_end( va );
- return written;
+ va_list va;
+ int written;
+
+ va_start( va, filter );
+ written = vfwprintf( f, filter, va );
+ va_end( va );
+ return written;
}
int vwprintf( const wchar_t *filter, va_list va )
{
- return vfwprintf( stdout, filter, va );
+ return vfwprintf( stdout, filter, va );
}
int wprintf( const wchar_t *filter, ... )
{
- va_list va;
- int written;
-
- va_start( va, filter );
- written=vwprintf( filter, va );
- va_end( va );
- return written;
+ va_list va;
+ int written;
+
+ va_start( va, filter );
+ written=vwprintf( filter, va );
+ va_end( va );
+ return written;
}
#endif
@@ -653,45 +653,45 @@ int wprintf( const wchar_t *filter, ... )
wint_t fgetwc(FILE *stream)
{
- wchar_t res=0;
- mbstate_t state;
- memset (&state, '\0', sizeof (state));
-
- while(1)
- {
- int b = fgetc( stream );
- char bb;
-
- int sz;
-
- if( b == EOF )
- return WEOF;
-
- bb=b;
-
- sz = mbrtowc( &res, &bb, 1, &state );
-
- switch( sz )
- {
- case -1:
- memset (&state, '\0', sizeof (state));
- return WEOF;
-
- case -2:
- break;
- case 0:
- return 0;
- default:
- return res;
- }
- }
+ wchar_t res=0;
+ mbstate_t state;
+ memset (&state, '\0', sizeof (state));
+
+ while(1)
+ {
+ int b = fgetc( stream );
+ char bb;
+
+ int sz;
+
+ if( b == EOF )
+ return WEOF;
+
+ bb=b;
+
+ sz = mbrtowc( &res, &bb, 1, &state );
+
+ switch( sz )
+ {
+ case -1:
+ memset (&state, '\0', sizeof (state));
+ return WEOF;
+
+ case -2:
+ break;
+ case 0:
+ return 0;
+ default:
+ return res;
+ }
+ }
}
wint_t getwc(FILE *stream)
{
- return fgetwc( stream );
+ return fgetwc( stream );
}
@@ -701,17 +701,17 @@ wint_t getwc(FILE *stream)
wint_t fputwc(wchar_t wc, FILE *stream)
{
- int res;
- char s[MB_CUR_MAX+1];
- memset( s, 0, MB_CUR_MAX+1 );
- wctomb( s, wc );
- res = fputs( s, stream );
- return res==EOF?WEOF:wc;
+ int res;
+ char s[MB_CUR_MAX+1];
+ memset( s, 0, MB_CUR_MAX+1 );
+ wctomb( s, wc );
+ res = fputs( s, stream );
+ return res==EOF?WEOF:wc;
}
wint_t putwc(wchar_t wc, FILE *stream)
{
- return fputwc( wc, stream );
+ return fputwc( wc, stream );
}
#endif
@@ -722,24 +722,24 @@ wint_t putwc(wchar_t wc, FILE *stream)
Used by fallback wcstok. Borrowed from glibc
*/
static size_t fish_wcsspn (const wchar_t *wcs,
- const wchar_t *accept )
+ const wchar_t *accept )
{
- register const wchar_t *p;
- register const wchar_t *a;
- register size_t count = 0;
+ register const wchar_t *p;
+ register const wchar_t *a;
+ register size_t count = 0;
- for (p = wcs; *p != L'\0'; ++p)
+ for (p = wcs; *p != L'\0'; ++p)
{
- for (a = accept; *a != L'\0'; ++a)
- if (*p == *a)
- break;
-
- if (*a == L'\0')
- return count;
- else
- ++count;
+ for (a = accept; *a != L'\0'; ++a)
+ if (*p == *a)
+ break;
+
+ if (*a == L'\0')
+ return count;
+ else
+ ++count;
}
- return count;
+ return count;
}
/*
@@ -747,12 +747,12 @@ static size_t fish_wcsspn (const wchar_t *wcs,
*/
static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept)
{
- while (*wcs != L'\0')
- if (wcschr (accept, *wcs) == NULL)
- ++wcs;
- else
- return (wchar_t *) wcs;
- return NULL;
+ while (*wcs != L'\0')
+ if (wcschr (accept, *wcs) == NULL)
+ ++wcs;
+ else
+ return (wchar_t *) wcs;
+ return NULL;
}
/*
@@ -760,45 +760,45 @@ static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept)
*/
wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr)
{
- wchar_t *result;
+ wchar_t *result;
- if (wcs == NULL)
+ if (wcs == NULL)
{
- if (*save_ptr == NULL)
+ if (*save_ptr == NULL)
{
- errno = EINVAL;
- return NULL;
+ errno = EINVAL;
+ return NULL;
}
- else
- wcs = *save_ptr;
+ else
+ wcs = *save_ptr;
}
- /* Scan leading delimiters. */
- wcs += fish_wcsspn (wcs, delim);
-
- if (*wcs == L'\0')
+ /* Scan leading delimiters. */
+ wcs += fish_wcsspn (wcs, delim);
+
+ if (*wcs == L'\0')
{
- *save_ptr = NULL;
- return NULL;
+ *save_ptr = NULL;
+ return NULL;
}
- /* Find the end of the token. */
- result = wcs;
-
- wcs = fish_wcspbrk (result, delim);
-
- if (wcs == NULL)
- {
- /* This token finishes the string. */
- *save_ptr = NULL;
- }
- else
+ /* Find the end of the token. */
+ result = wcs;
+
+ wcs = fish_wcspbrk (result, delim);
+
+ if (wcs == NULL)
+ {
+ /* This token finishes the string. */
+ *save_ptr = NULL;
+ }
+ else
{
- /* Terminate the token and make *SAVE_PTR point past it. */
- *wcs = L'\0';
- *save_ptr = wcs + 1;
+ /* Terminate the token and make *SAVE_PTR point past it. */
+ *wcs = L'\0';
+ *save_ptr = wcs + 1;
}
- return result;
+ return result;
}
#endif
@@ -807,32 +807,32 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr)
*/
static wchar_t *wcsdup_fallback(const wchar_t *in)
{
- size_t len=wcslen(in);
- wchar_t *out = (wchar_t *)malloc( sizeof( wchar_t)*(len+1));
- if( out == 0 )
- {
- return 0;
- }
-
- memcpy( out, in, sizeof( wchar_t)*(len+1));
- return out;
+ size_t len=wcslen(in);
+ wchar_t *out = (wchar_t *)malloc( sizeof( wchar_t)*(len+1));
+ if( out == 0 )
+ {
+ return 0;
+ }
+
+ memcpy( out, in, sizeof( wchar_t)*(len+1));
+ return out;
}
int wcscasecmp_fallback( const wchar_t *a, const wchar_t *b )
{
- if( *a == 0 )
- {
- return (*b==0)?0:-1;
- }
- else if( *b == 0 )
- {
- return 1;
- }
- int diff = towlower(*a)-towlower(*b);
- if( diff != 0 )
- return diff;
- else
- return wcscasecmp_fallback( a+1,b+1);
+ if( *a == 0 )
+ {
+ return (*b==0)?0:-1;
+ }
+ else if( *b == 0 )
+ {
+ return 1;
+ }
+ int diff = towlower(*a)-towlower(*b);
+ if( diff != 0 )
+ return diff;
+ else
+ return wcscasecmp_fallback( a+1,b+1);
}
@@ -851,14 +851,14 @@ int wcscasecmp_use_weak(const wchar_t *a, const wchar_t *b)
return (wcscasecmp)(a, b);
return wcscasecmp_fallback(a, b);
}
-
+
#else //__APPLE__
#ifndef HAVE_WCSDUP
wchar_t *wcsdup( const wchar_t *in )
{
- return wcsdup_fallback(in);
-
+ return wcsdup_fallback(in);
+
}
#endif
@@ -866,7 +866,7 @@ wchar_t *wcsdup( const wchar_t *in )
#ifndef HAVE_WCSCASECMP
int wcscasecmp( const wchar_t *a, const wchar_t *b )
{
- return wcscasecmp_fallback(a, b);
+ return wcscasecmp_fallback(a, b);
}
#endif
#endif //__APPLE__
@@ -874,122 +874,122 @@ int wcscasecmp( const wchar_t *a, const wchar_t *b )
#ifndef HAVE_WCSLEN
size_t wcslen(const wchar_t *in)
{
- const wchar_t *end=in;
- while( *end )
- end++;
- return end-in;
+ const wchar_t *end=in;
+ while( *end )
+ end++;
+ return end-in;
}
#endif
#ifndef HAVE_WCSNCASECMP
int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count )
{
- if( count == 0 )
- return 0;
-
- if( *a == 0 )
- {
- return (*b==0)?0:-1;
- }
- else if( *b == 0 )
- {
- return 1;
- }
- int diff = towlower(*a)-towlower(*b);
- if( diff != 0 )
- return diff;
- else
- return wcsncasecmp( a+1,b+1, count-1);
+ if( count == 0 )
+ return 0;
+
+ if( *a == 0 )
+ {
+ return (*b==0)?0:-1;
+ }
+ else if( *b == 0 )
+ {
+ return 1;
+ }
+ int diff = towlower(*a)-towlower(*b);
+ if( diff != 0 )
+ return diff;
+ else
+ return wcsncasecmp( a+1,b+1, count-1);
}
#endif
#ifndef HAVE_WCWIDTH
int wcwidth( wchar_t c )
{
- if( c < 32 )
- return 0;
- if ( c == 127 )
- return 0;
- return 1;
+ if( c < 32 )
+ return 0;
+ if ( c == 127 )
+ return 0;
+ return 1;
}
#endif
#ifndef HAVE_WCSNDUP
wchar_t *wcsndup( const wchar_t *in, size_t c )
{
- wchar_t *res = (wchar_t *)malloc( sizeof(wchar_t)*(c+1) );
- if( res == 0 )
- {
- return 0;
- }
- wcslcpy( res, in, c+1 );
- return res;
+ wchar_t *res = (wchar_t *)malloc( sizeof(wchar_t)*(c+1) );
+ if( res == 0 )
+ {
+ return 0;
+ }
+ wcslcpy( res, in, c+1 );
+ return res;
}
#endif
long convert_digit( wchar_t d, int base )
{
- long res=-1;
- if( (d <= L'9') && (d >= L'0') )
- {
- res = d - L'0';
- }
- else if( (d <= L'z') && (d >= L'a') )
- {
- res = d + 10 - L'a';
- }
- else if( (d <= L'Z') && (d >= L'A') )
- {
- res = d + 10 - L'A';
- }
- if( res >= base )
- {
- res = -1;
- }
-
- return res;
+ long res=-1;
+ if( (d <= L'9') && (d >= L'0') )
+ {
+ res = d - L'0';
+ }
+ else if( (d <= L'z') && (d >= L'a') )
+ {
+ res = d + 10 - L'a';
+ }
+ else if( (d <= L'Z') && (d >= L'A') )
+ {
+ res = d + 10 - L'A';
+ }
+ if( res >= base )
+ {
+ res = -1;
+ }
+
+ return res;
}
#ifndef HAVE_WCSTOL
-long wcstol(const wchar_t *nptr,
- wchar_t **endptr,
- int base)
+long wcstol(const wchar_t *nptr,
+ wchar_t **endptr,
+ int base)
{
- long long res=0;
- int is_set=0;
- if( base > 36 )
- {
- errno = EINVAL;
- return 0;
- }
-
- while( 1 )
- {
- long nxt = convert_digit( *nptr, base );
- if( endptr != 0 )
- *endptr = (wchar_t *)nptr;
- if( nxt < 0 )
- {
- if( !is_set )
- {
- errno = EINVAL;
- }
- return res;
- }
- res = (res*base)+nxt;
- is_set = 1;
- if( res > LONG_MAX )
- {
- errno = ERANGE;
- return LONG_MAX;
- }
- if( res < LONG_MIN )
- {
- errno = ERANGE;
- return LONG_MIN;
- }
- nptr++;
- }
+ long long res=0;
+ int is_set=0;
+ if( base > 36 )
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+ while( 1 )
+ {
+ long nxt = convert_digit( *nptr, base );
+ if( endptr != 0 )
+ *endptr = (wchar_t *)nptr;
+ if( nxt < 0 )
+ {
+ if( !is_set )
+ {
+ errno = EINVAL;
+ }
+ return res;
+ }
+ res = (res*base)+nxt;
+ is_set = 1;
+ if( res > LONG_MAX )
+ {
+ errno = ERANGE;
+ return LONG_MAX;
+ }
+ if( res < LONG_MIN )
+ {
+ errno = ERANGE;
+ return LONG_MIN;
+ }
+ nptr++;
+ }
}
#endif
@@ -1016,35 +1016,35 @@ long wcstol(const wchar_t *nptr,
size_t
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
{
-
- register wchar_t *d = dst;
- register const wchar_t *s = src;
- register size_t n = siz;
- size_t dlen;
-
- /* Find the end of dst and adjust bytes left but don't go past end */
- while (n-- != 0 && *d != '\0')
- d++;
-
- dlen = d - dst;
- n = siz - dlen;
-
- if (n == 0)
- return(dlen + wcslen(s));
-
- while (*s != '\0')
- {
- if (n != 1)
- {
- *d++ = *s;
- n--;
- }
- s++;
- }
- *d = '\0';
-
- return(dlen + (s - src));
- /* count does not include NUL */
+
+ register wchar_t *d = dst;
+ register const wchar_t *s = src;
+ register size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + wcslen(s));
+
+ while (*s != '\0')
+ {
+ if (n != 1)
+ {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src));
+ /* count does not include NUL */
}
#endif
@@ -1071,32 +1071,32 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
size_t
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
{
- register wchar_t *d = dst;
- register const wchar_t *s = src;
- register size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0)
- {
- do
- {
- if ((*d++ = *s++) == 0)
- break;
- }
- while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0)
- {
- if (siz != 0)
- *d = '\0';
- /* NUL-terminate dst */
- while (*s++)
- ;
- }
- return(s - src - 1);
- /* count does not include NUL */
+ register wchar_t *d = dst;
+ register const wchar_t *s = src;
+ register size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0)
+ {
+ do
+ {
+ if ((*d++ = *s++) == 0)
+ break;
+ }
+ while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0)
+ {
+ if (siz != 0)
+ *d = '\0';
+ /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+ return(s - src - 1);
+ /* count does not include NUL */
}
#endif
@@ -1105,14 +1105,14 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
int lrand48_r(struct drand48_data *buffer, long int *result)
{
- *result = rand_r( &buffer->seed );
- return 0;
+ *result = rand_r( &buffer->seed );
+ return 0;
}
int srand48_r(long int seedval, struct drand48_data *buffer)
{
- buffer->seed = (unsigned int)seedval;
- return 0;
+ buffer->seed = (unsigned int)seedval;
+ return 0;
}
#endif
@@ -1121,8 +1121,8 @@ int srand48_r(long int seedval, struct drand48_data *buffer)
int futimes(int fd, const struct timeval *times)
{
- errno = ENOSYS;
- return -1;
+ errno = ENOSYS;
+ return -1;
}
#endif
@@ -1131,17 +1131,17 @@ int futimes(int fd, const struct timeval *times)
char * gettext (const char * msgid)
{
- return (char *)msgid;
+ return (char *)msgid;
}
char * bindtextdomain (const char * domainname, const char * dirname)
{
- return 0;
+ return 0;
}
char * textdomain (const char * domainname)
{
- return 0;
+ return 0;
}
#endif
@@ -1149,10 +1149,10 @@ char * textdomain (const char * domainname)
#ifndef HAVE_DCGETTEXT
char * dcgettext ( const char * domainname,
- const char * msgid,
- int category)
+ const char * msgid,
+ int category)
{
- return (char *)msgid;
+ return (char *)msgid;
}
@@ -1167,20 +1167,20 @@ int _nl_msg_cat_cntr=0;
#ifndef HAVE_KILLPG
int killpg( int pgr, int sig )
{
- assert( pgr > 1 );
- return kill( -pgr, sig );
+ assert( pgr > 1 );
+ return kill( -pgr, sig );
}
#endif
#ifndef HAVE_WORKING_GETOPT_LONG
-int getopt_long( int argc,
- char * const argv[],
- const char *optstring,
- const struct option *longopts,
- int *longindex )
+int getopt_long( int argc,
+ char * const argv[],
+ const char *optstring,
+ const struct option *longopts,
+ int *longindex )
{
- return getopt( argc, argv, optstring );
+ return getopt( argc, argv, optstring );
}
@@ -1189,14 +1189,14 @@ int getopt_long( int argc,
#ifndef HAVE_BACKTRACE
int backtrace (void **buffer, int size)
{
- return 0;
+ return 0;
}
#endif
#ifndef HAVE_BACKTRACE_SYMBOLS
char ** backtrace_symbols (void *const *buffer, int size)
{
- return 0;
+ return 0;
}
#endif
@@ -1204,22 +1204,22 @@ char ** backtrace_symbols (void *const *buffer, int size)
long sysconf(int name)
{
- if( name == _SC_ARG_MAX )
- {
+ if( name == _SC_ARG_MAX )
+ {
#ifdef ARG_MAX
- return ARG_MAX;
+ return ARG_MAX;
#endif
- }
+ }
+
+ return -1;
- return -1;
-
}
#endif
#ifndef HAVE_NAN
double nan(char *tagp)
{
- return 0.0/0.0;
+ return 0.0/0.0;
}
#endif
@@ -1443,12 +1443,12 @@ static int mk_wcwidth(wchar_t ucs)
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining,
- sizeof(combining) / sizeof(struct interval) - 1))
+ sizeof(combining) / sizeof(struct interval) - 1))
return 0;
/* if we arrive here, ucs is not a combining or C0/C1 control character */
- return 1 +
+ return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
ucs == 0x2329 || ucs == 0x232a ||
diff --git a/fallback.h b/fallback.h
index 2c091be0..3b852b30 100644
--- a/fallback.h
+++ b/fallback.h
@@ -61,16 +61,16 @@ typedef char tputs_arg_t;
/**
Structure used to get the size of a terminal window
*/
-struct winsize
+struct winsize
{
- /**
- Number of rows
- */
- unsigned short ws_row;
- /**
- Number of columns
- */
- unsigned short ws_col;
+ /**
+ Number of rows
+ */
+ unsigned short ws_row;
+ /**
+ Number of columns
+ */
+ unsigned short ws_col;
}
;
@@ -197,7 +197,7 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr);
/**
Return the number of columns used by a character. This is a libc
function, but the prototype for this function is missing in some libc
- implementations.
+ implementations.
Fish has a fallback implementation in case the implementation is
missing altogether. In locales without a native wcwidth, Unicode
@@ -219,7 +219,7 @@ int wcwidth( wchar_t c );
int wcscasecmp_use_weak(const wchar_t *, const wchar_t *);
#define wcsdup(a) wcsdup_use_weak((a))
#define wcscasecmp(a, b) wcscasecmp_use_weak((a), (b))
-
+
#else
#ifndef HAVE_WCSDUP
@@ -312,8 +312,8 @@ long convert_digit( wchar_t d, int base );
supported.
*/
long wcstol(const wchar_t *nptr,
- wchar_t **endptr,
- int base);
+ wchar_t **endptr,
+ int base);
#endif
#ifndef HAVE_WCSLCAT
@@ -340,7 +340,7 @@ size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
wcslen(src); if retval >= siz, truncation occurred.
This is the OpenBSD strlcpy function, modified for wide characters,
- and renamed to reflect this change.
+ and renamed to reflect this change.
*/
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
@@ -361,10 +361,10 @@ size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
*/
struct drand48_data
{
- /**
- Seed value
- */
- unsigned int seed;
+ /**
+ Seed value
+ */
+ unsigned int seed;
}
;
@@ -410,9 +410,9 @@ char * textdomain( const char * domainname );
/**
Fallback implementation of dcgettext. Just returns the original string.
*/
-char * dcgettext ( const char * domainname,
- const char * msgid,
- int category );
+char * dcgettext ( const char * domainname,
+ const char * msgid,
+ int category );
#endif
@@ -441,44 +441,44 @@ int killpg( int pgr, int sig );
/**
Struct describing a long getopt option
*/
-struct option
+struct option
{
- /**
- Name of option
- */
- const char *name;
- /**
- Flag
- */
- int has_arg;
- /**
- Flag
- */
- int *flag;
- /**
- Return value
- */
- int val;
+ /**
+ Name of option
+ */
+ const char *name;
+ /**
+ Flag
+ */
+ int has_arg;
+ /**
+ Flag
+ */
+ int *flag;
+ /**
+ Return value
+ */
+ int val;
}
;
#ifndef no_argument
-#define no_argument 0
+#define no_argument 0
#endif
#ifndef required_argument
-#define required_argument 1
+#define required_argument 1
#endif
#ifndef optional_argument
-#define optional_argument 2
+#define optional_argument 2
#endif
-int getopt_long(int argc,
- char * const argv[],
- const char *optstring,
- const struct option *longopts,
- int *longindex);
+int getopt_long(int argc,
+ char * const argv[],
+ const char *optstring,
+ const struct option *longopts,
+ int *longindex);
#endif
diff --git a/fish.cpp b/fish.cpp
index d1699d58..78723bd0 100644
--- a/fish.cpp
+++ b/fish.cpp
@@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file fish.c
- The main loop of <tt>fish</tt>.
+ The main loop of <tt>fish</tt>.
*/
#include "config.h"
@@ -104,12 +104,12 @@ static std::string get_executable_path(const char *argv0)
uint32_t buffSize = sizeof buff;
if (0 == _NSGetExecutablePath(buff, &buffSize))
return std::string(buff);
-
+
/* Loop until we're big enough */
char *mbuff = (char *)malloc(buffSize);
while (0 > _NSGetExecutablePath(mbuff, &buffSize))
mbuff = (char *)realloc(mbuff, buffSize);
-
+
/* Return the string */
std::string result = mbuff;
free(mbuff);
@@ -125,7 +125,7 @@ static std::string get_executable_path(const char *argv0)
return std::string(buff);
}
}
-
+
/* Just return argv0, which probably won't work (i.e. it's not an absolute path or a path relative to the working directory, but instead something the caller found via $PATH). We'll eventually fall back to the compile time paths. */
return std::string(argv0 ? argv0 : "");
}
@@ -137,9 +137,9 @@ static struct config_paths_t determine_config_directory_paths(const char *argv0)
bool done = false;
std::string exec_path = get_executable_path(argv0);
if (get_realpath(exec_path))
- {
+ {
#if __APPLE__
-
+
/* On OS X, maybe we're an app bundle, and should use the bundle's files. Since we don't link CF, use this lame approach to test it: see if the resolved path ends with /Contents/MacOS/fish, case insensitive since HFS+ usually is.
*/
if (! done)
@@ -152,28 +152,28 @@ static struct config_paths_t determine_config_directory_paths(const char *argv0)
wcstring wide_resolved_path = str2wcstring(exec_path);
wide_resolved_path.resize(exec_path.size() - suffixlen);
wide_resolved_path.append(L"/Contents/Resources/");
-
+
/* Append share, etc, doc */
paths.data = wide_resolved_path + L"share/fish";
paths.sysconf = wide_resolved_path + L"etc/fish";
paths.doc = wide_resolved_path + L"doc/fish";
-
+
/* But the bin_dir is the resolved_path, minus fish (aka the MacOS directory) */
paths.bin = str2wcstring(exec_path);
paths.bin.resize(paths.bin.size() - strlen("/fish"));
-
+
done = true;
}
}
#endif
-
+
if (! done)
{
/* The next check is that we are in a reloctable directory tree like this:
bin/fish
etc/fish
share/fish
-
+
Check it!
*/
const char *suffix = "/bin/fish";
@@ -181,12 +181,12 @@ static struct config_paths_t determine_config_directory_paths(const char *argv0)
{
wcstring base_path = str2wcstring(exec_path);
base_path.resize(base_path.size() - strlen(suffix));
-
+
paths.data = base_path + L"/share/fish";
paths.sysconf = base_path + L"/etc/fish";
paths.doc = base_path + L"/share/doc/fish";
paths.bin = base_path + L"/bin";
-
+
struct stat buf;
if (0 == wstat(paths.data, &buf) && 0 == wstat(paths.sysconf, &buf))
{
@@ -195,7 +195,7 @@ static struct config_paths_t determine_config_directory_paths(const char *argv0)
}
}
}
-
+
if (! done)
{
/* Fall back to what got compiled in. */
@@ -203,10 +203,10 @@ static struct config_paths_t determine_config_directory_paths(const char *argv0)
paths.sysconf = L"" SYSCONFDIR "/fish";
paths.doc = L"" DATADIR "/doc/fish";
paths.bin = L"" PREFIX "/bin";
-
+
done = true;
}
-
+
return paths;
}
@@ -217,27 +217,27 @@ static int read_init(const struct config_paths_t &paths)
{
parser_t &parser = parser_t::principal_parser();
const io_chain_t empty_ios;
- parser.eval( L"builtin . " + paths.data + L"/config.fish 2>/dev/null", empty_ios, TOP );
- parser.eval( L"builtin . " + paths.sysconf + L"/config.fish 2>/dev/null", empty_ios, TOP );
-
-
- /*
- We need to get the configuration directory before we can source the user configuration file
- */
- wcstring config_dir;
-
- /*
- If path_get_config returns false then we have no configuration directory
- and no custom config to load.
- */
+ parser.eval( L"builtin . " + paths.data + L"/config.fish 2>/dev/null", empty_ios, TOP );
+ parser.eval( L"builtin . " + paths.sysconf + L"/config.fish 2>/dev/null", empty_ios, TOP );
+
+
+ /*
+ We need to get the configuration directory before we can source the user configuration file
+ */
+ wcstring config_dir;
+
+ /*
+ If path_get_config returns false then we have no configuration directory
+ and no custom config to load.
+ */
if (path_get_config(config_dir))
- {
- wcstring config_dir_escaped = escape_string( config_dir, 1 );
+ {
+ wcstring config_dir_escaped = escape_string( config_dir, 1 );
wcstring eval_buff = format_string(L"builtin . %ls/config.fish 2>/dev/null", config_dir_escaped.c_str());
- parser.eval( eval_buff, empty_ios, TOP );
- }
-
- return 1;
+ parser.eval( eval_buff, empty_ios, TOP );
+ }
+
+ return 1;
}
@@ -247,162 +247,162 @@ static int read_init(const struct config_paths_t &paths)
*/
static int fish_parse_opt( int argc, char **argv, const char **cmd_ptr )
{
- int my_optind;
- int force_interactive=0;
-
- while( 1 )
- {
- static struct option
- long_options[] =
- {
- {
- "command", required_argument, 0, 'c'
- }
- ,
- {
- "debug-level", required_argument, 0, 'd'
- }
- ,
- {
- "interactive", no_argument, 0, 'i'
- }
- ,
- {
- "login", no_argument, 0, 'l'
- }
- ,
- {
- "no-execute", no_argument, 0, 'n'
- }
- ,
- {
- "profile", required_argument, 0, 'p'
- }
- ,
- {
- "help", no_argument, 0, 'h'
- }
- ,
- {
- "version", no_argument, 0, 'v'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = getopt_long( argc,
- argv,
- GETOPT_STRING,
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- {
- break;
- }
-
- case 'c':
- {
- *cmd_ptr = optarg;
- is_interactive_session = 0;
- break;
- }
-
- case 'd':
- {
- char *end;
- long tmp;
-
- errno = 0;
- tmp = strtol(optarg, &end, 10);
-
- if( tmp >= 0 && tmp <=10 && !*end && !errno )
- {
- debug_level = (int)tmp;
- }
- else
- {
- debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
- exit_without_destructors(1);
- }
- break;
- }
-
- case 'h':
- {
- *cmd_ptr = "__fish_print_help fish";
- break;
- }
-
- case 'i':
- {
- force_interactive = 1;
- break;
- }
-
- case 'l':
- {
- is_login=1;
- break;
- }
-
- case 'n':
- {
- no_exec=1;
- break;
- }
-
- case 'p':
- {
- profile = optarg;
- break;
- }
-
- case 'v':
- {
- fwprintf( stderr,
- _(L"%s, version %s\n"),
- PACKAGE_NAME,
- PACKAGE_VERSION );
- exit_without_destructors( 0 );
- }
-
- case '?':
- {
- exit_without_destructors( 1 );
- }
-
- }
- }
-
- my_optind = optind;
-
- is_login |= (strcmp( argv[0], "-fish") == 0);
-
- /*
- We are an interactive session if we have not been given an
- explicit command to execute, _and_ stdin is a tty.
- */
- is_interactive_session &= (*cmd_ptr == 0);
- is_interactive_session &= (my_optind == argc);
- is_interactive_session &= isatty(STDIN_FILENO);
-
- /*
- We are also an interactive session if we have are forced-
- */
- is_interactive_session |= force_interactive;
-
- return my_optind;
+ int my_optind;
+ int force_interactive=0;
+
+ while( 1 )
+ {
+ static struct option
+ long_options[] =
+ {
+ {
+ "command", required_argument, 0, 'c'
+ }
+ ,
+ {
+ "debug-level", required_argument, 0, 'd'
+ }
+ ,
+ {
+ "interactive", no_argument, 0, 'i'
+ }
+ ,
+ {
+ "login", no_argument, 0, 'l'
+ }
+ ,
+ {
+ "no-execute", no_argument, 0, 'n'
+ }
+ ,
+ {
+ "profile", required_argument, 0, 'p'
+ }
+ ,
+ {
+ "help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ "version", no_argument, 0, 'v'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = getopt_long( argc,
+ argv,
+ GETOPT_STRING,
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ {
+ break;
+ }
+
+ case 'c':
+ {
+ *cmd_ptr = optarg;
+ is_interactive_session = 0;
+ break;
+ }
+
+ case 'd':
+ {
+ char *end;
+ long tmp;
+
+ errno = 0;
+ tmp = strtol(optarg, &end, 10);
+
+ if( tmp >= 0 && tmp <=10 && !*end && !errno )
+ {
+ debug_level = (int)tmp;
+ }
+ else
+ {
+ debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
+ exit_without_destructors(1);
+ }
+ break;
+ }
+
+ case 'h':
+ {
+ *cmd_ptr = "__fish_print_help fish";
+ break;
+ }
+
+ case 'i':
+ {
+ force_interactive = 1;
+ break;
+ }
+
+ case 'l':
+ {
+ is_login=1;
+ break;
+ }
+
+ case 'n':
+ {
+ no_exec=1;
+ break;
+ }
+
+ case 'p':
+ {
+ profile = optarg;
+ break;
+ }
+
+ case 'v':
+ {
+ fwprintf( stderr,
+ _(L"%s, version %s\n"),
+ PACKAGE_NAME,
+ PACKAGE_VERSION );
+ exit_without_destructors( 0 );
+ }
+
+ case '?':
+ {
+ exit_without_destructors( 1 );
+ }
+
+ }
+ }
+
+ my_optind = optind;
+
+ is_login |= (strcmp( argv[0], "-fish") == 0);
+
+ /*
+ We are an interactive session if we have not been given an
+ explicit command to execute, _and_ stdin is a tty.
+ */
+ is_interactive_session &= (*cmd_ptr == 0);
+ is_interactive_session &= (my_optind == argc);
+ is_interactive_session &= isatty(STDIN_FILENO);
+
+ /*
+ We are also an interactive session if we have are forced-
+ */
+ is_interactive_session |= force_interactive;
+
+ return my_optind;
}
/**
@@ -412,68 +412,68 @@ static int fish_parse_opt( int argc, char **argv, const char **cmd_ptr )
static wcstring full_escape( const wchar_t *in )
{
- wcstring out;
- for( ; *in; in++ )
- {
- if( *in < 32 )
- {
- append_format( out, L"\\x%.2x", *in );
- }
- else if( *in < 128 )
- {
- out.push_back(*in);
- }
- else if( *in < 65536 )
- {
- append_format( out, L"\\u%.4x", *in );
- }
- else
- {
- append_format( out, L"\\U%.8x", *in );
- }
- }
- return out;
+ wcstring out;
+ for( ; *in; in++ )
+ {
+ if( *in < 32 )
+ {
+ append_format( out, L"\\x%.2x", *in );
+ }
+ else if( *in < 128 )
+ {
+ out.push_back(*in);
+ }
+ else if( *in < 65536 )
+ {
+ append_format( out, L"\\u%.4x", *in );
+ }
+ else
+ {
+ append_format( out, L"\\U%.8x", *in );
+ }
+ }
+ return out;
}
extern int g_fork_count;
int main( int argc, char **argv )
-{
- int res=1;
- const char *cmd=0;
- int my_optind=0;
+{
+ int res=1;
+ const char *cmd=0;
+ int my_optind=0;
- set_main_thread();
+ set_main_thread();
setup_fork_guards();
-
- wsetlocale( LC_ALL, L"" );
- is_interactive_session=1;
- program_name=L"fish";
+
+ wsetlocale( LC_ALL, L"" );
+ is_interactive_session=1;
+ program_name=L"fish";
//struct stat tmp;
//stat("----------FISH_HIT_MAIN----------", &tmp);
- my_optind = fish_parse_opt( argc, argv, &cmd );
-
- /*
- No-exec is prohibited when in interactive mode
- */
- if( is_interactive_session && no_exec)
- {
- debug( 1, _(L"Can not use the no-execute mode when running an interactive session") );
- no_exec = 0;
- }
-
- const struct config_paths_t paths = determine_config_directory_paths(argv[0]);
-
- proc_init();
- event_init();
- wutil_init();
- //parser_init();
- builtin_init();
- function_init();
- env_init(&paths);
- reader_init();
- history_init();
+ my_optind = fish_parse_opt( argc, argv, &cmd );
+
+ /*
+ No-exec is prohibited when in interactive mode
+ */
+ if( is_interactive_session && no_exec)
+ {
+ debug( 1, _(L"Can not use the no-execute mode when running an interactive session") );
+ no_exec = 0;
+ }
+
+ const struct config_paths_t paths = determine_config_directory_paths(argv[0]);
+
+ proc_init();
+ event_init();
+ wutil_init();
+ //parser_init();
+ builtin_init();
+ function_init();
+ env_init(&paths);
+ reader_init();
+ history_init();
parser_t &parser = parser_t::principal_parser();
@@ -481,91 +481,91 @@ int main( int argc, char **argv )
printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count);
const io_chain_t empty_ios;
- if( read_init(paths) )
- {
- if( cmd != 0 )
- {
- wchar_t *cmd_wcs = str2wcs( cmd );
- res = parser.eval( cmd_wcs, empty_ios, TOP );
- free(cmd_wcs);
- reader_exit(0, 0);
- }
- else
- {
- if( my_optind == argc )
- {
- res = reader_read( STDIN_FILENO, empty_ios );
- }
- else
- {
- char **ptr;
- char *file = *(argv+(my_optind++));
- int i;
- int fd;
- wchar_t *rel_filename, *abs_filename;
-
-
- if( ( fd = open(file, O_RDONLY) ) == -1 )
- {
- wperror( L"open" );
- return 1;
- }
-
+ if( read_init(paths) )
+ {
+ if( cmd != 0 )
+ {
+ wchar_t *cmd_wcs = str2wcs( cmd );
+ res = parser.eval( cmd_wcs, empty_ios, TOP );
+ free(cmd_wcs);
+ reader_exit(0, 0);
+ }
+ else
+ {
+ if( my_optind == argc )
+ {
+ res = reader_read( STDIN_FILENO, empty_ios );
+ }
+ else
+ {
+ char **ptr;
+ char *file = *(argv+(my_optind++));
+ int i;
+ int fd;
+ wchar_t *rel_filename, *abs_filename;
+
+
+ if( ( fd = open(file, O_RDONLY) ) == -1 )
+ {
+ wperror( L"open" );
+ return 1;
+ }
+
// OK to not do this atomically since we cannot have gone multithreaded yet
set_cloexec(fd);
-
- if( *(argv+my_optind))
- {
+
+ if( *(argv+my_optind))
+ {
wcstring sb;
- for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ )
- {
- if( i != 1 )
+ for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ )
+ {
+ if( i != 1 )
sb.append( ARRAY_SEP_STR );
sb.append( str2wcstring( *ptr ));
- }
-
- env_set( L"argv", sb.c_str(), 0 );
- }
-
- rel_filename = str2wcs( file );
- abs_filename = wrealpath( rel_filename, 0 );
-
- if( !abs_filename )
- {
- abs_filename = wcsdup(rel_filename);
- }
-
- reader_push_current_filename( intern( abs_filename ) );
- free( rel_filename );
- free( abs_filename );
-
- res = reader_read( fd, empty_ios );
-
- if( res )
- {
- debug( 1,
- _(L"Error while reading file %ls\n"),
- reader_current_filename()?reader_current_filename(): _(L"Standard input") );
- }
- reader_pop_current_filename();
- }
- }
- }
-
- proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
-
- history_destroy();
- proc_destroy();
- builtin_destroy();
- reader_destroy();
- parser.destroy();
- wutil_destroy();
- event_destroy();
-
- env_destroy();
-
+ }
+
+ env_set( L"argv", sb.c_str(), 0 );
+ }
+
+ rel_filename = str2wcs( file );
+ abs_filename = wrealpath( rel_filename, 0 );
+
+ if( !abs_filename )
+ {
+ abs_filename = wcsdup(rel_filename);
+ }
+
+ reader_push_current_filename( intern( abs_filename ) );
+ free( rel_filename );
+ free( abs_filename );
+
+ res = reader_read( fd, empty_ios );
+
+ if( res )
+ {
+ debug( 1,
+ _(L"Error while reading file %ls\n"),
+ reader_current_filename()?reader_current_filename(): _(L"Standard input") );
+ }
+ reader_pop_current_filename();
+ }
+ }
+ }
+
+ proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
+
+ history_destroy();
+ proc_destroy();
+ builtin_destroy();
+ reader_destroy();
+ parser.destroy();
+ wutil_destroy();
+ event_destroy();
+
+ env_destroy();
+
if (g_log_forks)
printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count);
-
- return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status();
+
+ return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status();
}
diff --git a/fish_indent.cpp b/fish_indent.cpp
index 298d52e8..c04e6ded 100644
--- a/fish_indent.cpp
+++ b/fish_indent.cpp
@@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file fish_indent.cpp
- The fish_indent proegram.
+ The fish_indent proegram.
*/
#include "config.h"
@@ -51,22 +51,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
static void read_file( FILE *f, wcstring &b )
{
- while( 1 )
- {
- errno=0;
- wint_t c = fgetwc( f );
- if( c == WEOF )
- {
- if( errno )
- {
- wperror(L"fgetwc");
- exit(1);
- }
-
- break;
- }
- b.push_back((wchar_t)c);
- }
+ while( 1 )
+ {
+ errno=0;
+ wint_t c = fgetwc( f );
+ if( c == WEOF )
+ {
+ if( errno )
+ {
+ wperror(L"fgetwc");
+ exit(1);
+ }
+
+ break;
+ }
+ b.push_back((wchar_t)c);
+ }
}
/**
@@ -76,7 +76,7 @@ static void insert_tabs( wcstring &out, int indent )
{
if (indent > 0)
out.append((size_t)indent, L'\t');
-
+
}
/**
@@ -84,175 +84,175 @@ static void insert_tabs( wcstring &out, int indent )
*/
static int indent( wcstring &out, const wcstring &in, int flags )
{
- tokenizer tok;
- int res=0;
- int is_command = 1;
- int indent = 0;
- int do_indent = 1;
- int prev_type = 0;
- int prev_prev_type = 0;
-
- tok_init( &tok, in.c_str(), TOK_SHOW_COMMENTS );
-
- for( ; tok_has_next( &tok ); tok_next( &tok ) )
- {
- int type = tok_last_type( &tok );
- wchar_t *last = tok_last( &tok );
-
- switch( type )
- {
- case TOK_STRING:
- {
- if( is_command )
- {
- int next_indent = indent;
- is_command = 0;
-
+ tokenizer tok;
+ int res=0;
+ int is_command = 1;
+ int indent = 0;
+ int do_indent = 1;
+ int prev_type = 0;
+ int prev_prev_type = 0;
+
+ tok_init( &tok, in.c_str(), TOK_SHOW_COMMENTS );
+
+ for( ; tok_has_next( &tok ); tok_next( &tok ) )
+ {
+ int type = tok_last_type( &tok );
+ wchar_t *last = tok_last( &tok );
+
+ switch( type )
+ {
+ case TOK_STRING:
+ {
+ if( is_command )
+ {
+ int next_indent = indent;
+ is_command = 0;
+
wcstring unesc = last;
unescape_string(unesc, UNESCAPE_SPECIAL);
-
- if( parser_keywords_is_block(unesc))
- {
- next_indent++;
- }
- else if (unesc == L"else")
- {
- indent--;
- }
- /* case should have the same indent level as switch*/
- else if (unesc == L"case")
- {
- indent--;
- }
- else if (unesc == L"end")
- {
- indent--;
- next_indent--;
- }
-
-
- if( do_indent && flags && prev_type != TOK_PIPE )
- {
- insert_tabs( out, indent );
- }
-
+
+ if( parser_keywords_is_block(unesc))
+ {
+ next_indent++;
+ }
+ else if (unesc == L"else")
+ {
+ indent--;
+ }
+ /* case should have the same indent level as switch*/
+ else if (unesc == L"case")
+ {
+ indent--;
+ }
+ else if (unesc == L"end")
+ {
+ indent--;
+ next_indent--;
+ }
+
+
+ if( do_indent && flags && prev_type != TOK_PIPE )
+ {
+ insert_tabs( out, indent );
+ }
+
append_format(out, L"%ls", last );
-
- indent = next_indent;
-
- }
- else
- {
- if ( prev_type != TOK_REDIRECT_FD )
- out.append( L" " );
- out.append( last );
- }
-
- break;
- }
-
- case TOK_END:
- {
- if( prev_type != TOK_END || prev_prev_type != TOK_END )
- out.append( L"\n" );
- do_indent = 1;
- is_command = 1;
- break;
- }
-
- case TOK_PIPE:
- {
- out.append( L" " );
- if ( last[0] == '2' && !last[1] ) {
- out.append( L"^" );
- } else if ( last[0] != '1' || last[1] ) {
- out.append( last);
+
+ indent = next_indent;
+
+ }
+ else
+ {
+ if ( prev_type != TOK_REDIRECT_FD )
+ out.append( L" " );
+ out.append( last );
+ }
+
+ break;
+ }
+
+ case TOK_END:
+ {
+ if( prev_type != TOK_END || prev_prev_type != TOK_END )
+ out.append( L"\n" );
+ do_indent = 1;
+ is_command = 1;
+ break;
+ }
+
+ case TOK_PIPE:
+ {
+ out.append( L" " );
+ if ( last[0] == '2' && !last[1] ) {
+ out.append( L"^" );
+ } else if ( last[0] != '1' || last[1] ) {
+ out.append( last);
out.append( L">" );
- }
- out.append( L" | " );
- is_command = 1;
- break;
- }
-
- case TOK_REDIRECT_OUT:
- {
- out.append( L" " );
- if ( wcscmp( last, L"2" ) == 0 ) {
- out.append( L"^" );
- } else {
- if ( wcscmp( last, L"1" ) != 0 )
- out.append( last );
- out.append( L"> " );
- }
- break;
- }
-
- case TOK_REDIRECT_APPEND:
- {
- out.append( L" " );
- if ( wcscmp( last, L"2" ) == 0 ) {
- out.append( L"^^" );
- } else {
- if ( wcscmp( last, L"1" ) != 0 )
- out.append( last );
- out.append( L">> " );
- }
- break;
- }
-
- case TOK_REDIRECT_IN:
- {
- out.append( L" " );
- if ( wcscmp( last, L"0" ) != 0 )
- out.append( last );
- out.append( L"< " );
- break;
- }
-
- case TOK_REDIRECT_FD:
- {
- out.append( L" " );
- if ( wcscmp( last, L"1" ) != 0 )
- out.append( last );
- out.append( L">& " );
- break;
- }
-
- case TOK_BACKGROUND:
- {
- out.append( L"&\n" );
- do_indent = 1;
- is_command = 1;
- break;
- }
-
- case TOK_COMMENT:
- {
- if( do_indent && flags)
- {
- insert_tabs( out, indent );
- }
-
- append_format( out, L"%ls", last );
- do_indent = 1;
- break;
- }
-
- default:
- {
- debug( 0, L"Unknown token '%ls'", last );
- exit(1);
- }
- }
-
- prev_prev_type = prev_type;
- prev_type = type;
-
- }
-
- tok_destroy( &tok );
-
- return res;
+ }
+ out.append( L" | " );
+ is_command = 1;
+ break;
+ }
+
+ case TOK_REDIRECT_OUT:
+ {
+ out.append( L" " );
+ if ( wcscmp( last, L"2" ) == 0 ) {
+ out.append( L"^" );
+ } else {
+ if ( wcscmp( last, L"1" ) != 0 )
+ out.append( last );
+ out.append( L"> " );
+ }
+ break;
+ }
+
+ case TOK_REDIRECT_APPEND:
+ {
+ out.append( L" " );
+ if ( wcscmp( last, L"2" ) == 0 ) {
+ out.append( L"^^" );
+ } else {
+ if ( wcscmp( last, L"1" ) != 0 )
+ out.append( last );
+ out.append( L">> " );
+ }
+ break;
+ }
+
+ case TOK_REDIRECT_IN:
+ {
+ out.append( L" " );
+ if ( wcscmp( last, L"0" ) != 0 )
+ out.append( last );
+ out.append( L"< " );
+ break;
+ }
+
+ case TOK_REDIRECT_FD:
+ {
+ out.append( L" " );
+ if ( wcscmp( last, L"1" ) != 0 )
+ out.append( last );
+ out.append( L">& " );
+ break;
+ }
+
+ case TOK_BACKGROUND:
+ {
+ out.append( L"&\n" );
+ do_indent = 1;
+ is_command = 1;
+ break;
+ }
+
+ case TOK_COMMENT:
+ {
+ if( do_indent && flags)
+ {
+ insert_tabs( out, indent );
+ }
+
+ append_format( out, L"%ls", last );
+ do_indent = 1;
+ break;
+ }
+
+ default:
+ {
+ debug( 0, L"Unknown token '%ls'", last );
+ exit(1);
+ }
+ }
+
+ prev_prev_type = prev_type;
+ prev_type = type;
+
+ }
+
+ tok_destroy( &tok );
+
+ return res;
}
/**
@@ -267,7 +267,7 @@ static void trim( wcstring &str )
size_t pos = str.find_first_not_of(L" \n");
if (pos > 0)
str.erase(0, pos);
-
+
pos = str.find_last_not_of(L" \n");
if (pos != wcstring::npos && pos + 1 < str.length())
str.erase(pos + 1);
@@ -278,106 +278,106 @@ static void trim( wcstring &str )
The main mathod. Run the program.
*/
int main( int argc, char **argv )
-{
- int do_indent=1;
- set_main_thread();
+{
+ int do_indent=1;
+ set_main_thread();
setup_fork_guards();
-
- wsetlocale( LC_ALL, L"" );
- program_name=L"fish_indent";
-
- while( 1 )
- {
- static struct option
- long_options[] =
- {
- {
- "no-indent", no_argument, 0, 'i'
- }
- ,
- {
- "help", no_argument, 0, 'h'
- }
- ,
- {
- "version", no_argument, 0, 'v'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = getopt_long( argc,
- argv,
- GETOPT_STRING,
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- {
- break;
- }
-
- case 'h':
- {
- print_help( "fish_indent", 1 );
- exit( 0 );
- break;
- }
-
- case 'v':
- {
- fwprintf( stderr,
- _(L"%ls, version %s\n"),
- program_name,
- PACKAGE_VERSION );
- exit( 0 );
- }
-
- case 'i':
- {
- do_indent = 0;
- break;
- }
-
-
- case '?':
- {
- exit( 1 );
- }
-
- }
- }
+
+ wsetlocale( LC_ALL, L"" );
+ program_name=L"fish_indent";
+
+ while( 1 )
+ {
+ static struct option
+ long_options[] =
+ {
+ {
+ "no-indent", no_argument, 0, 'i'
+ }
+ ,
+ {
+ "help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ "version", no_argument, 0, 'v'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = getopt_long( argc,
+ argv,
+ GETOPT_STRING,
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ {
+ break;
+ }
+
+ case 'h':
+ {
+ print_help( "fish_indent", 1 );
+ exit( 0 );
+ break;
+ }
+
+ case 'v':
+ {
+ fwprintf( stderr,
+ _(L"%ls, version %s\n"),
+ program_name,
+ PACKAGE_VERSION );
+ exit( 0 );
+ }
+
+ case 'i':
+ {
+ do_indent = 0;
+ break;
+ }
+
+
+ case '?':
+ {
+ exit( 1 );
+ }
+
+ }
+ }
wcstring sb_in, sb_out;
- read_file( stdin, sb_in );
-
- wutil_init();
+ read_file( stdin, sb_in );
+
+ wutil_init();
- if( !indent( sb_out, sb_in, do_indent ) )
- {
+ if( !indent( sb_out, sb_in, do_indent ) )
+ {
trim(sb_out);
- fwprintf( stdout, L"%ls", sb_out.c_str() );
- }
- else
- {
- /*
- Indenting failed - print original input
- */
- fwprintf( stdout, L"%ls", sb_in.c_str() );
- }
-
-
- wutil_destroy();
-
- return 0;
+ fwprintf( stdout, L"%ls", sb_out.c_str() );
+ }
+ else
+ {
+ /*
+ Indenting failed - print original input
+ */
+ fwprintf( stdout, L"%ls", sb_in.c_str() );
+ }
+
+
+ wutil_destroy();
+
+ return 0;
}
diff --git a/fish_pager.cpp b/fish_pager.cpp
index 4fc0a44c..88ef8d3b 100644
--- a/fish_pager.cpp
+++ b/fish_pager.cpp
@@ -62,42 +62,42 @@
#include "env_universal.h"
#include "print_help.h"
-enum
+enum
{
- LINE_UP = R_NULL+1,
- LINE_DOWN,
- PAGE_UP,
- PAGE_DOWN
+ LINE_UP = R_NULL+1,
+ LINE_DOWN,
+ PAGE_UP,
+ PAGE_DOWN
}
- ;
+ ;
enum
{
- HIGHLIGHT_PAGER_PREFIX,
- HIGHLIGHT_PAGER_COMPLETION,
- HIGHLIGHT_PAGER_DESCRIPTION,
- HIGHLIGHT_PAGER_PROGRESS,
- HIGHLIGHT_PAGER_SECONDARY
+ HIGHLIGHT_PAGER_PREFIX,
+ HIGHLIGHT_PAGER_COMPLETION,
+ HIGHLIGHT_PAGER_DESCRIPTION,
+ HIGHLIGHT_PAGER_PROGRESS,
+ HIGHLIGHT_PAGER_SECONDARY
}
- ;
+ ;
enum
{
- /*
- Returnd by the pager if no more displaying is needed
- */
- PAGER_DONE,
- /*
- Returned by the pager if the completions would not fit in the specified number of columns
- */
- PAGER_RETRY,
- /*
- Returned by the pager if the terminal changes size
- */
- PAGER_RESIZE
+ /*
+ Returnd by the pager if no more displaying is needed
+ */
+ PAGER_DONE,
+ /*
+ Returned by the pager if the completions would not fit in the specified number of columns
+ */
+ PAGER_RETRY,
+ /*
+ Returned by the pager if the terminal changes size
+ */
+ PAGER_RESIZE
}
- ;
+ ;
/**
The minimum width (in characters) the terminal may have for fish_pager to not refuse showing the completions
@@ -148,15 +148,15 @@ static std::vector<char> pager_buffer;
The environment variables used to specify the color of different
tokens.
*/
-static const wchar_t *hightlight_var[] =
+static const wchar_t *hightlight_var[] =
{
- L"fish_pager_color_prefix",
- L"fish_pager_color_completion",
- L"fish_pager_color_description",
- L"fish_pager_color_progress",
- L"fish_pager_color_secondary"
+ L"fish_pager_color_prefix",
+ L"fish_pager_color_completion",
+ L"fish_pager_color_description",
+ L"fish_pager_color_progress",
+ L"fish_pager_color_secondary"
}
- ;
+ ;
/**
This string contains the text that should be sent back to the calling program
@@ -172,30 +172,30 @@ static FILE *out_file;
*/
struct comp_t
{
- /**
- The list of all completin strings this entry applies to
- */
- wcstring_list_t comp;
- /**
- The description
- */
- wcstring desc;
- /**
- On-screen width of the completion string
- */
- int comp_width;
- /**
- On-screen width of the description information
- */
- int desc_width;
- /**
- Preffered total width
- */
- int pref_width;
- /**
- Minimum acceptable width
- */
- int min_width;
+ /**
+ The list of all completin strings this entry applies to
+ */
+ wcstring_list_t comp;
+ /**
+ The description
+ */
+ wcstring desc;
+ /**
+ On-screen width of the completion string
+ */
+ int comp_width;
+ /**
+ On-screen width of the description information
+ */
+ int desc_width;
+ /**
+ Preffered total width
+ */
+ int pref_width;
+ /**
+ Minimum acceptable width
+ */
+ int min_width;
};
/**
@@ -204,26 +204,26 @@ struct comp_t
*/
static rgb_color_t get_color( int highlight )
{
- const wchar_t *val;
-
- if( highlight < 0 )
- return rgb_color_t::normal();
- if( highlight >= (5) )
- return rgb_color_t::normal();
-
- val = wgetenv( hightlight_var[highlight]);
-
- if( !val )
- {
- val = env_universal_get( hightlight_var[highlight]);
- }
-
- if( !val )
- {
- return rgb_color_t::normal();
- }
-
- return parse_color( val, false );
+ const wchar_t *val;
+
+ if( highlight < 0 )
+ return rgb_color_t::normal();
+ if( highlight >= (5) )
+ return rgb_color_t::normal();
+
+ val = wgetenv( hightlight_var[highlight]);
+
+ if( !val )
+ {
+ val = env_universal_get( hightlight_var[highlight]);
+ }
+
+ if( !val )
+ {
+ return rgb_color_t::normal();
+ }
+
+ return parse_color( val, false );
}
/**
@@ -234,14 +234,14 @@ static rgb_color_t get_color( int highlight )
*/
static void recalc_width( std::vector<comp_t *> &lst, const wchar_t *prefix )
{
- for( size_t i=0; i<lst.size(); i++ )
- {
- comp_t *c = lst.at(i);
-
- c->min_width = mini( c->desc_width, maxi(0,termsize.ws_col/3 - 2)) +
- mini( c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4;
- }
-
+ for( size_t i=0; i<lst.size(); i++ )
+ {
+ comp_t *c = lst.at(i);
+
+ c->min_width = mini( c->desc_width, maxi(0,termsize.ws_col/3 - 2)) +
+ mini( c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4;
+ }
+
}
/**
@@ -250,25 +250,25 @@ static void recalc_width( std::vector<comp_t *> &lst, const wchar_t *prefix )
*/
static int try_sequence( const char *seq )
{
- int j, k;
- wint_t c=0;
-
- for( j=0;
- seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 ));
- j++ )
- ;
-
- if( seq[j] == '\0' )
- {
- return 1;
- }
- else
- {
- input_common_unreadch(c);
- for(k=j-1; k>=0; k--)
- input_common_unreadch(seq[k]);
- }
- return 0;
+ int j, k;
+ wint_t c=0;
+
+ for( j=0;
+ seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 ));
+ j++ )
+ ;
+
+ if( seq[j] == '\0' )
+ {
+ return 1;
+ }
+ else
+ {
+ input_common_unreadch(c);
+ for(k=j-1; k>=0; k--)
+ input_common_unreadch(seq[k]);
+ }
+ return 0;
}
/**
@@ -276,66 +276,66 @@ static int try_sequence( const char *seq )
*/
static wint_t readch()
{
- struct mapping
- {
- const char *seq;
- wint_t bnd;
- }
- ;
-
- struct mapping m[]=
- {
- {
- "\x1b[A", LINE_UP
- }
- ,
- {
- key_up, LINE_UP
- }
- ,
- {
- "\x1b[B", LINE_DOWN
- }
- ,
- {
- key_down, LINE_DOWN
- }
- ,
- {
- key_ppage, PAGE_UP
- }
- ,
- {
- key_npage, PAGE_DOWN
- }
- ,
- {
- " ", PAGE_DOWN
- }
- ,
- {
- "\t", PAGE_DOWN
- }
- ,
- {
- 0, 0
- }
-
- }
- ;
- int i;
-
- for( i=0; m[i].bnd; i++ )
- {
- if( !m[i].seq )
- {
- continue;
- }
-
- if( try_sequence(m[i].seq ) )
- return m[i].bnd;
- }
- return input_common_readch(0);
+ struct mapping
+ {
+ const char *seq;
+ wint_t bnd;
+ }
+ ;
+
+ struct mapping m[]=
+ {
+ {
+ "\x1b[A", LINE_UP
+ }
+ ,
+ {
+ key_up, LINE_UP
+ }
+ ,
+ {
+ "\x1b[B", LINE_DOWN
+ }
+ ,
+ {
+ key_down, LINE_DOWN
+ }
+ ,
+ {
+ key_ppage, PAGE_UP
+ }
+ ,
+ {
+ key_npage, PAGE_DOWN
+ }
+ ,
+ {
+ " ", PAGE_DOWN
+ }
+ ,
+ {
+ "\t", PAGE_DOWN
+ }
+ ,
+ {
+ 0, 0
+ }
+
+ }
+ ;
+ int i;
+
+ for( i=0; m[i].bnd; i++ )
+ {
+ if( !m[i].seq )
+ {
+ continue;
+ }
+
+ if( try_sequence(m[i].seq ) )
+ return m[i].bnd;
+ }
+ return input_common_readch(0);
}
/**
@@ -343,8 +343,8 @@ static wint_t readch()
*/
static int pager_buffered_writer( char c)
{
- pager_buffer.push_back(c);
- return 0;
+ pager_buffer.push_back(c);
+ return 0;
}
/**
@@ -368,24 +368,24 @@ static void pager_flush()
*/
static int print_max( const wchar_t *str, int max, int has_more )
{
- int i;
- int written = 0;
- for( i=0; str[i]; i++ )
- {
-
- if( written + wcwidth(str[i]) > max )
- break;
- if( ( written + wcwidth(str[i]) == max) && (has_more || str[i+1]) )
- {
- writech( ellipsis_char );
- written += wcwidth(ellipsis_char );
- break;
- }
-
- writech( str[i] );
- written+= wcwidth( str[i] );
- }
- return written;
+ int i;
+ int written = 0;
+ for( i=0; str[i]; i++ )
+ {
+
+ if( written + wcwidth(str[i]) > max )
+ break;
+ if( ( written + wcwidth(str[i]) == max) && (has_more || str[i+1]) )
+ {
+ writech( ellipsis_char );
+ written += wcwidth(ellipsis_char );
+ break;
+ }
+
+ writech( str[i] );
+ written+= wcwidth( str[i] );
+ }
+ return written;
}
/**
@@ -393,72 +393,72 @@ static int print_max( const wchar_t *str, int max, int has_more )
*/
static void completion_print_item( const wchar_t *prefix, comp_t *c, int width, bool secondary )
{
- int comp_width=0, desc_width=0;
- int written=0;
-
- if( c->pref_width <= width )
- {
- /*
- The entry fits, we give it as much space as it wants
- */
- comp_width = c->comp_width;
- desc_width = c->desc_width;
- }
- else
- {
- /*
- The completion and description won't fit on the
- allocated space. Give a maximum of 2/3 of the
- space to the completion, and whatever is left to
- the description.
- */
- int desc_all = c->desc_width?c->desc_width+4:0;
-
- comp_width = maxi( mini( c->comp_width,
- 2*(width-4)/3 ),
- width - desc_all );
- if( c->desc_width )
- desc_width = width-comp_width-4;
- else
- c->desc_width=0;
-
- }
-
+ int comp_width=0, desc_width=0;
+ int written=0;
+
+ if( c->pref_width <= width )
+ {
+ /*
+ The entry fits, we give it as much space as it wants
+ */
+ comp_width = c->comp_width;
+ desc_width = c->desc_width;
+ }
+ else
+ {
+ /*
+ The completion and description won't fit on the
+ allocated space. Give a maximum of 2/3 of the
+ space to the completion, and whatever is left to
+ the description.
+ */
+ int desc_all = c->desc_width?c->desc_width+4:0;
+
+ comp_width = maxi( mini( c->comp_width,
+ 2*(width-4)/3 ),
+ width - desc_all );
+ if( c->desc_width )
+ desc_width = width-comp_width-4;
+ else
+ c->desc_width=0;
+
+ }
+
rgb_color_t bg = secondary ? get_color(HIGHLIGHT_PAGER_SECONDARY) : rgb_color_t::normal();
- for( size_t i=0; i<c->comp.size(); i++ )
- {
+ for( size_t i=0; i<c->comp.size(); i++ )
+ {
const wcstring &comp = c->comp.at(i);
- if( i != 0 )
- written += print_max( L" ", comp_width - written, 2 );
- set_color( get_color(HIGHLIGHT_PAGER_PREFIX), bg );
- written += print_max( prefix, comp_width - written, comp.empty()?0:1 );
- set_color( get_color(HIGHLIGHT_PAGER_COMPLETION), bg);
- written += print_max( comp.c_str(), comp_width - written, i!=(c->comp.size()-1) );
- }
-
-
- if( desc_width )
- {
- while( written < (width-desc_width-2))
- {
- written++;
- writech( L' ');
- }
- set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ), bg);
- written += print_max( L"(", 1, 0 );
- written += print_max( c->desc.c_str(), desc_width, 0 );
- written += print_max( L")", 1, 0 );
- }
- else
- {
- while( written < width )
- {
- written++;
- writech( L' ');
- }
- }
- if ( secondary )
- set_color( rgb_color_t::normal(), rgb_color_t::normal() );
+ if( i != 0 )
+ written += print_max( L" ", comp_width - written, 2 );
+ set_color( get_color(HIGHLIGHT_PAGER_PREFIX), bg );
+ written += print_max( prefix, comp_width - written, comp.empty()?0:1 );
+ set_color( get_color(HIGHLIGHT_PAGER_COMPLETION), bg);
+ written += print_max( comp.c_str(), comp_width - written, i!=(c->comp.size()-1) );
+ }
+
+
+ if( desc_width )
+ {
+ while( written < (width-desc_width-2))
+ {
+ written++;
+ writech( L' ');
+ }
+ set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ), bg);
+ written += print_max( L"(", 1, 0 );
+ written += print_max( c->desc.c_str(), desc_width, 0 );
+ written += print_max( L")", 1, 0 );
+ }
+ else
+ {
+ while( written < width )
+ {
+ written++;
+ writech( L' ');
+ }
+ }
+ if ( secondary )
+ set_color( rgb_color_t::normal(), rgb_color_t::normal() );
}
/**
@@ -475,37 +475,37 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width,
*/
static void completion_print( int cols,
- int *width,
- int row_start,
- int row_stop,
- wchar_t *prefix,
- int is_quoted,
- const std::vector<comp_t *> &lst )
+ int *width,
+ int row_start,
+ int row_stop,
+ wchar_t *prefix,
+ int is_quoted,
+ const std::vector<comp_t *> &lst )
{
- size_t rows = (lst.size()-1)/cols+1;
- size_t i, j;
-
- for( i = row_start; i<row_stop; i++ )
- {
- for( j = 0; j < cols; j++ )
- {
- comp_t *el;
-
- int is_last = (j==(cols-1));
-
- if( lst.size() <= j*rows + i )
- continue;
-
- el = lst.at(j*rows + i );
-
- completion_print_item( prefix, el, width[j] - (is_last?0:2), i%2 );
-
- if( !is_last)
- writestr( L" " );
- }
- writech( L'\n' );
- }
+ size_t rows = (lst.size()-1)/cols+1;
+ size_t i, j;
+
+ for( i = row_start; i<row_stop; i++ )
+ {
+ for( j = 0; j < cols; j++ )
+ {
+ comp_t *el;
+
+ int is_last = (j==(cols-1));
+
+ if( lst.size() <= j*rows + i )
+ continue;
+
+ el = lst.at(j*rows + i );
+
+ completion_print_item( prefix, el, width[j] - (is_last?0:2), i%2 );
+
+ if( !is_last)
+ writestr( L" " );
+ }
+ writech( L'\n' );
+ }
}
@@ -528,301 +528,301 @@ static void completion_print( int cols,
*/
static int completion_try_print( int cols,
- wchar_t *prefix,
- int is_quoted,
- std::vector<comp_t *> &lst )
+ wchar_t *prefix,
+ int is_quoted,
+ std::vector<comp_t *> &lst )
{
- /*
- The calculated preferred width of each column
- */
- int pref_width[PAGER_MAX_COLS];
- /*
- The calculated minimum width of each column
- */
- int min_width[PAGER_MAX_COLS];
- /*
- If the list can be printed with this width, width will contain the width of each column
- */
- int *width=pref_width;
- /*
- Set to one if the list should be printed at this width
- */
- int print=0;
-
- long i, j;
-
- int rows = (int)((lst.size()-1)/cols+1);
-
- int pref_tot_width=0;
- int min_tot_width = 0;
- int res=PAGER_RETRY;
- /*
- Skip completions on tiny terminals
- */
-
- if( termsize.ws_col < PAGER_MIN_WIDTH )
- return PAGER_DONE;
-
- memset( pref_width, 0, sizeof(pref_width) );
- memset( min_width, 0, sizeof(min_width) );
-
- /* Calculate how wide the list would be */
- for( j = 0; j < cols; j++ )
- {
- for( i = 0; i<rows; i++ )
- {
- int pref,min;
- comp_t *c;
- if( lst.size() <= j*rows + i )
- continue;
-
- c = lst.at(j*rows + i );
- pref = c->pref_width;
- min = c->min_width;
-
- if( j != cols-1 )
- {
- pref += 2;
- min += 2;
- }
- min_width[j] = maxi( min_width[j],
- min );
- pref_width[j] = maxi( pref_width[j],
- pref );
- }
- min_tot_width += min_width[j];
- pref_tot_width += pref_width[j];
- }
- /*
- Force fit if one column
- */
- if( cols == 1)
- {
- if( pref_tot_width > termsize.ws_col )
- {
- pref_width[0] = termsize.ws_col;
- }
- width = pref_width;
- print=1;
- }
- else if( pref_tot_width <= termsize.ws_col )
- {
- /* Terminal is wide enough. Print the list! */
- width = pref_width;
- print=1;
- }
- else
- {
- long next_rows = (lst.size()-1)/(cols-1)+1;
-/* fwprintf( stderr,
+ /*
+ The calculated preferred width of each column
+ */
+ int pref_width[PAGER_MAX_COLS];
+ /*
+ The calculated minimum width of each column
+ */
+ int min_width[PAGER_MAX_COLS];
+ /*
+ If the list can be printed with this width, width will contain the width of each column
+ */
+ int *width=pref_width;
+ /*
+ Set to one if the list should be printed at this width
+ */
+ int print=0;
+
+ long i, j;
+
+ int rows = (int)((lst.size()-1)/cols+1);
+
+ int pref_tot_width=0;
+ int min_tot_width = 0;
+ int res=PAGER_RETRY;
+ /*
+ Skip completions on tiny terminals
+ */
+
+ if( termsize.ws_col < PAGER_MIN_WIDTH )
+ return PAGER_DONE;
+
+ memset( pref_width, 0, sizeof(pref_width) );
+ memset( min_width, 0, sizeof(min_width) );
+
+ /* Calculate how wide the list would be */
+ for( j = 0; j < cols; j++ )
+ {
+ for( i = 0; i<rows; i++ )
+ {
+ int pref,min;
+ comp_t *c;
+ if( lst.size() <= j*rows + i )
+ continue;
+
+ c = lst.at(j*rows + i );
+ pref = c->pref_width;
+ min = c->min_width;
+
+ if( j != cols-1 )
+ {
+ pref += 2;
+ min += 2;
+ }
+ min_width[j] = maxi( min_width[j],
+ min );
+ pref_width[j] = maxi( pref_width[j],
+ pref );
+ }
+ min_tot_width += min_width[j];
+ pref_tot_width += pref_width[j];
+ }
+ /*
+ Force fit if one column
+ */
+ if( cols == 1)
+ {
+ if( pref_tot_width > termsize.ws_col )
+ {
+ pref_width[0] = termsize.ws_col;
+ }
+ width = pref_width;
+ print=1;
+ }
+ else if( pref_tot_width <= termsize.ws_col )
+ {
+ /* Terminal is wide enough. Print the list! */
+ width = pref_width;
+ print=1;
+ }
+ else
+ {
+ long next_rows = (lst.size()-1)/(cols-1)+1;
+/* fwprintf( stderr,
L"cols %d, min_tot %d, term %d, rows=%d, nextrows %d, termrows %d, diff %d\n",
cols,
min_tot_width, termsize.ws_col,
rows, next_rows, termsize.ws_row,
pref_tot_width-termsize.ws_col );
*/
- if( min_tot_width < termsize.ws_col &&
- ( ( (rows < termsize.ws_row) && (next_rows >= termsize.ws_row ) ) ||
- ( pref_tot_width-termsize.ws_col< 4 && cols < 3 ) ) )
- {
- /*
- Terminal almost wide enough, or squeezing makes the
- whole list fit on-screen.
-
- This part of the code is really important. People hate
- having to scroll through the completion list. In cases
- where there are a huge number of completions, it can't
- be helped, but it is not uncommon for the completions to
- _almost_ fit on one screen. In those cases, it is almost
- always desirable to 'squeeze' the completions into a
- single page.
-
- If we are using N columns and can get everything to
- fit using squeezing, but everything would also fit
- using N-1 columns, don't try.
- */
-
- int tot_width = min_tot_width;
- width = min_width;
-
- while( tot_width < termsize.ws_col )
- {
- for( i=0; (i<cols) && ( tot_width < termsize.ws_col ); i++ )
- {
- if( width[i] < pref_width[i] )
- {
- width[i]++;
- tot_width++;
- }
- }
- }
- print=1;
- }
- }
-
- if( print )
- {
- res=PAGER_DONE;
- if( rows < termsize.ws_row )
- {
- /* List fits on screen. Print it and leave */
- if( is_ca_mode )
- {
- is_ca_mode = 0;
- writembs(exit_ca_mode);
- }
-
- completion_print( cols, width, 0, rows, prefix, is_quoted, lst);
- pager_flush();
- }
- else
- {
- int npos, pos = 0;
- int do_loop = 1;
-
- /*
- Enter ca_mode, which means that the terminal
- content will be restored to the current
- state on exit.
- */
- if( enter_ca_mode && exit_ca_mode )
- {
- is_ca_mode=1;
- writembs(enter_ca_mode);
- }
-
-
- completion_print( cols,
- width,
- 0,
- termsize.ws_row-1,
- prefix,
- is_quoted,
- lst);
- /*
- List does not fit on screen. Print one screenfull and
- leave a scrollable interface
- */
- while(do_loop)
- {
- set_color( rgb_color_t::black(), get_color(HIGHLIGHT_PAGER_PROGRESS) );
+ if( min_tot_width < termsize.ws_col &&
+ ( ( (rows < termsize.ws_row) && (next_rows >= termsize.ws_row ) ) ||
+ ( pref_tot_width-termsize.ws_col< 4 && cols < 3 ) ) )
+ {
+ /*
+ Terminal almost wide enough, or squeezing makes the
+ whole list fit on-screen.
+
+ This part of the code is really important. People hate
+ having to scroll through the completion list. In cases
+ where there are a huge number of completions, it can't
+ be helped, but it is not uncommon for the completions to
+ _almost_ fit on one screen. In those cases, it is almost
+ always desirable to 'squeeze' the completions into a
+ single page.
+
+ If we are using N columns and can get everything to
+ fit using squeezing, but everything would also fit
+ using N-1 columns, don't try.
+ */
+
+ int tot_width = min_tot_width;
+ width = min_width;
+
+ while( tot_width < termsize.ws_col )
+ {
+ for( i=0; (i<cols) && ( tot_width < termsize.ws_col ); i++ )
+ {
+ if( width[i] < pref_width[i] )
+ {
+ width[i]++;
+ tot_width++;
+ }
+ }
+ }
+ print=1;
+ }
+ }
+
+ if( print )
+ {
+ res=PAGER_DONE;
+ if( rows < termsize.ws_row )
+ {
+ /* List fits on screen. Print it and leave */
+ if( is_ca_mode )
+ {
+ is_ca_mode = 0;
+ writembs(exit_ca_mode);
+ }
+
+ completion_print( cols, width, 0, rows, prefix, is_quoted, lst);
+ pager_flush();
+ }
+ else
+ {
+ int npos, pos = 0;
+ int do_loop = 1;
+
+ /*
+ Enter ca_mode, which means that the terminal
+ content will be restored to the current
+ state on exit.
+ */
+ if( enter_ca_mode && exit_ca_mode )
+ {
+ is_ca_mode=1;
+ writembs(enter_ca_mode);
+ }
+
+
+ completion_print( cols,
+ width,
+ 0,
+ termsize.ws_row-1,
+ prefix,
+ is_quoted,
+ lst);
+ /*
+ List does not fit on screen. Print one screenfull and
+ leave a scrollable interface
+ */
+ while(do_loop)
+ {
+ set_color( rgb_color_t::black(), get_color(HIGHLIGHT_PAGER_PROGRESS) );
wcstring msg = format_string(_(L" %d to %d of %d"), pos, pos+termsize.ws_row-1, rows );
- msg.append(L" \r" );
-
- writestr(msg.c_str());
- set_color( rgb_color_t::normal(), rgb_color_t::normal() );
- pager_flush();
- int c = readch();
-
- switch( c )
- {
- case LINE_UP:
- {
- if( pos > 0 )
- {
- pos--;
- writembs(tparm( cursor_address, 0, 0));
- writembs(scroll_reverse);
- completion_print( cols,
- width,
- pos,
- pos+1,
- prefix,
- is_quoted,
- lst );
- writembs( tparm( cursor_address,
- termsize.ws_row-1, 0) );
- writembs(clr_eol );
-
- }
-
- break;
- }
-
- case LINE_DOWN:
- {
- if( pos <= (rows - termsize.ws_row ) )
- {
- pos++;
- completion_print( cols,
- width,
- pos+termsize.ws_row-2,
- pos+termsize.ws_row-1,
- prefix,
- is_quoted,
- lst );
- }
- break;
- }
-
- case PAGE_DOWN:
- {
-
- npos = mini( (int)(rows - termsize.ws_row+1), (int)(pos + termsize.ws_row-1) );
- if( npos != pos )
- {
- pos = npos;
- completion_print( cols,
- width,
- pos,
- pos+termsize.ws_row-1,
- prefix,
- is_quoted,
- lst );
- }
- else
- {
- if( flash_screen )
- writembs( flash_screen );
- }
-
- break;
- }
-
- case PAGE_UP:
- {
- npos = maxi( 0,
- pos - termsize.ws_row+1 );
-
- if( npos != pos )
- {
- pos = npos;
- completion_print( cols,
- width,
- pos,
- pos+termsize.ws_row-1,
- prefix,
- is_quoted,
- lst );
- }
- else
- {
- if( flash_screen )
- writembs( flash_screen );
- }
- break;
- }
-
- case R_NULL:
- {
- do_loop=0;
- res=PAGER_RESIZE;
- break;
-
- }
-
- default:
- {
- out_buff.push_back( c );
- do_loop = 0;
- break;
- }
- }
- }
- writembs(clr_eol);
- }
- }
- return res;
+ msg.append(L" \r" );
+
+ writestr(msg.c_str());
+ set_color( rgb_color_t::normal(), rgb_color_t::normal() );
+ pager_flush();
+ int c = readch();
+
+ switch( c )
+ {
+ case LINE_UP:
+ {
+ if( pos > 0 )
+ {
+ pos--;
+ writembs(tparm( cursor_address, 0, 0));
+ writembs(scroll_reverse);
+ completion_print( cols,
+ width,
+ pos,
+ pos+1,
+ prefix,
+ is_quoted,
+ lst );
+ writembs( tparm( cursor_address,
+ termsize.ws_row-1, 0) );
+ writembs(clr_eol );
+
+ }
+
+ break;
+ }
+
+ case LINE_DOWN:
+ {
+ if( pos <= (rows - termsize.ws_row ) )
+ {
+ pos++;
+ completion_print( cols,
+ width,
+ pos+termsize.ws_row-2,
+ pos+termsize.ws_row-1,
+ prefix,
+ is_quoted,
+ lst );
+ }
+ break;
+ }
+
+ case PAGE_DOWN:
+ {
+
+ npos = mini( (int)(rows - termsize.ws_row+1), (int)(pos + termsize.ws_row-1) );
+ if( npos != pos )
+ {
+ pos = npos;
+ completion_print( cols,
+ width,
+ pos,
+ pos+termsize.ws_row-1,
+ prefix,
+ is_quoted,
+ lst );
+ }
+ else
+ {
+ if( flash_screen )
+ writembs( flash_screen );
+ }
+
+ break;
+ }
+
+ case PAGE_UP:
+ {
+ npos = maxi( 0,
+ pos - termsize.ws_row+1 );
+
+ if( npos != pos )
+ {
+ pos = npos;
+ completion_print( cols,
+ width,
+ pos,
+ pos+termsize.ws_row-1,
+ prefix,
+ is_quoted,
+ lst );
+ }
+ else
+ {
+ if( flash_screen )
+ writembs( flash_screen );
+ }
+ break;
+ }
+
+ case R_NULL:
+ {
+ do_loop=0;
+ res=PAGER_RESIZE;
+ break;
+
+ }
+
+ default:
+ {
+ out_buff.push_back( c );
+ do_loop = 0;
+ break;
+ }
+ }
+ }
+ writembs(clr_eol);
+ }
+ }
+ return res;
}
/**
@@ -832,39 +832,39 @@ static int completion_try_print( int cols,
*/
static void mangle_descriptions( wcstring_list_t &lst )
{
- int skip;
- for( size_t i=0; i<lst.size(); i++ )
- {
+ int skip;
+ for( size_t i=0; i<lst.size(); i++ )
+ {
wcstring &next = lst.at(i);
- size_t in, out;
- skip=1;
-
+ size_t in, out;
+ skip=1;
+
size_t next_idx = 0;
- while( next_idx < next.size() && next[next_idx] != COMPLETE_SEP )
- next_idx++;
-
- if( next_idx == next.size() )
- continue;
-
- in=out=next_idx + 1;
-
- while( in < next.size() )
- {
- if( next[in] == L' ' || next[in]==L'\t' || next[in]<32 )
- {
- if( !skip )
- next[out++]=L' ';
- skip=1;
- }
- else
- {
- next[out++] = next[in];
- skip=0;
- }
- in++;
- }
+ while( next_idx < next.size() && next[next_idx] != COMPLETE_SEP )
+ next_idx++;
+
+ if( next_idx == next.size() )
+ continue;
+
+ in=out=next_idx + 1;
+
+ while( in < next.size() )
+ {
+ if( next[in] == L' ' || next[in]==L'\t' || next[in]<32 )
+ {
+ if( !skip )
+ next[out++]=L' ';
+ skip=1;
+ }
+ else
+ {
+ next[out++] = next[in];
+ skip=0;
+ }
+ in++;
+ }
next.resize(out);
- }
+ }
}
/**
@@ -874,40 +874,40 @@ static void join_completions( wcstring_list_t lst )
{
std::map<wcstring, long> desc_table;
- for( size_t i=0; i<lst.size(); i++ )
- {
- const wchar_t *item = lst.at(i).c_str();
- const wchar_t *desc = wcschr( item, COMPLETE_SEP );
- long prev_idx;
-
- if( !desc )
- continue;
- desc++;
+ for( size_t i=0; i<lst.size(); i++ )
+ {
+ const wchar_t *item = lst.at(i).c_str();
+ const wchar_t *desc = wcschr( item, COMPLETE_SEP );
+ long prev_idx;
+
+ if( !desc )
+ continue;
+ desc++;
prev_idx = desc_table[desc] - 1;
- if( prev_idx == -1 )
- {
+ if( prev_idx == -1 )
+ {
desc_table[desc] = (long)(i+1);
- }
- else
- {
- const wchar_t *old = lst.at(i).c_str();
- const wchar_t *old_end = wcschr( old, COMPLETE_SEP );
-
- if( old_end )
- {
-
+ }
+ else
+ {
+ const wchar_t *old = lst.at(i).c_str();
+ const wchar_t *old_end = wcschr( old, COMPLETE_SEP );
+
+ if( old_end )
+ {
+
wcstring foo;
foo.append(old, old_end - old);
foo.push_back(COMPLETE_ITEM_SEP);
foo.append(item);
-
+
lst.at(prev_idx) = foo;
lst.at(i).clear();
- }
-
- }
-
- }
+ }
+
+ }
+
+ }
/* Remove empty strings */
lst.erase(remove(lst.begin(), lst.end(), wcstring()), lst.end());
@@ -919,47 +919,47 @@ static void join_completions( wcstring_list_t lst )
static std::vector<comp_t *> mangle_completions( wcstring_list_t &lst, const wchar_t *prefix )
{
std::vector<comp_t *> result;
- for( size_t i=0; i<lst.size(); i++ )
- {
+ for( size_t i=0; i<lst.size(); i++ )
+ {
wcstring &next = lst.at(i);
- size_t start, end;
-
+ size_t start, end;
+
comp_t zerod = {};
- comp_t *comp = new comp_t(zerod);
-
- for( start=end=0; 1; end++ )
- {
- wchar_t c = next.c_str()[end];
-
- if( (c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c)
- {
+ comp_t *comp = new comp_t(zerod);
+
+ for( start=end=0; 1; end++ )
+ {
+ wchar_t c = next.c_str()[end];
+
+ if( (c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c)
+ {
wcstring start2 = wcstring(next, start, end - start);
wcstring str = escape_string(start2, ESCAPE_ALL | ESCAPE_NO_QUOTED);
- comp->comp_width += my_wcswidth( str.c_str() );
- comp->comp.push_back(str);
- start = end+1;
- }
-
- if( c == COMPLETE_SEP )
- {
- comp->desc = next.c_str() + start;
- break;
- }
-
- if( !c )
- break;
-
- }
-
- comp->comp_width += (int)(my_wcswidth(prefix)*comp->comp.size() + 2*(comp->comp.size()-1));
- comp->desc_width = comp->desc.empty()?0:my_wcswidth( comp->desc.c_str() );
-
- comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0);
-
+ comp->comp_width += my_wcswidth( str.c_str() );
+ comp->comp.push_back(str);
+ start = end+1;
+ }
+
+ if( c == COMPLETE_SEP )
+ {
+ comp->desc = next.c_str() + start;
+ break;
+ }
+
+ if( !c )
+ break;
+
+ }
+
+ comp->comp_width += (int)(my_wcswidth(prefix)*comp->comp.size() + 2*(comp->comp.size()-1));
+ comp->desc_width = comp->desc.empty()?0:my_wcswidth( comp->desc.c_str() );
+
+ comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0);
+
result.push_back(comp);
- }
-
- recalc_width( result, prefix );
+ }
+
+ recalc_width( result, prefix );
return result;
}
@@ -970,10 +970,10 @@ static std::vector<comp_t *> mangle_completions( wcstring_list_t &lst, const wch
*/
static void handle_winch( int sig )
{
- if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
- {
- return;
- }
+ if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
+ {
+ return;
+ }
}
/**
@@ -983,7 +983,7 @@ static void handle_winch( int sig )
*/
static int interrupt_handler()
{
- return R_NULL;
+ return R_NULL;
}
/**
@@ -993,103 +993,103 @@ static int interrupt_handler()
*/
static void init( int mangle_descriptors, int out )
{
- struct sigaction act;
-
- static struct termios pager_modes;
- char *term;
-
- if( mangle_descriptors )
- {
-
- /*
- Make fd 1 output to screen, and use some other fd for writing
- the resulting output back to the caller
- */
- int in;
- out = dup( 1 );
- close(1);
- close(0);
+ struct sigaction act;
+
+ static struct termios pager_modes;
+ char *term;
+
+ if( mangle_descriptors )
+ {
+
+ /*
+ Make fd 1 output to screen, and use some other fd for writing
+ the resulting output back to the caller
+ */
+ int in;
+ out = dup( 1 );
+ close(1);
+ close(0);
/* OK to not use CLO_EXEC here because fish_pager is single threaded */
- if( (in = open( ttyname(2), O_RDWR )) != -1 )
- {
- if( dup2( 2, 1 ) == -1 )
- {
- debug( 0, _(L"Could not set up output file descriptors for pager") );
- exit( 1 );
- }
-
- if( dup2( in, 0 ) == -1 )
- {
- debug( 0, _(L"Could not set up input file descriptors for pager") );
- exit( 1 );
- }
- }
- else
- {
- debug( 0, _(L"Could not open tty for pager") );
- exit( 1 );
- }
- }
-
- if( !(out_file = fdopen( out, "w" )) )
- {
- debug( 0, _(L"Could not initialize result pipe" ) );
- exit( 1 );
- }
-
-
- env_universal_init( 0, 0, 0, 0);
- input_common_init( &interrupt_handler );
- output_set_writer( &pager_buffered_writer );
-
- sigemptyset( & act.sa_mask );
- act.sa_flags=0;
- act.sa_handler=SIG_DFL;
- act.sa_flags = 0;
- act.sa_handler= &handle_winch;
- if( sigaction( SIGWINCH, &act, 0 ) )
- {
- wperror( L"sigaction" );
- exit(1);
- }
-
- handle_winch( 0 ); /* Set handler for window change events */
-
- tcgetattr(0,&pager_modes); /* get the current terminal modes */
- memcpy( &saved_modes,
- &pager_modes,
- sizeof(saved_modes)); /* save a copy so we can reset the terminal later */
-
- pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */
- pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */
- pager_modes.c_cc[VMIN]=1;
- pager_modes.c_cc[VTIME]=0;
-
- /*
-
- */
- if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */
- {
- wperror(L"tcsetattr");
- exit(1);
- }
-
-
- if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
- {
- debug( 0, _(L"Could not set up terminal") );
- exit(1);
- }
-
- term = getenv("TERM");
- if( term )
- {
- wchar_t *wterm = str2wcs(term);
- output_set_term( wterm );
- free( wterm );
- }
-
+ if( (in = open( ttyname(2), O_RDWR )) != -1 )
+ {
+ if( dup2( 2, 1 ) == -1 )
+ {
+ debug( 0, _(L"Could not set up output file descriptors for pager") );
+ exit( 1 );
+ }
+
+ if( dup2( in, 0 ) == -1 )
+ {
+ debug( 0, _(L"Could not set up input file descriptors for pager") );
+ exit( 1 );
+ }
+ }
+ else
+ {
+ debug( 0, _(L"Could not open tty for pager") );
+ exit( 1 );
+ }
+ }
+
+ if( !(out_file = fdopen( out, "w" )) )
+ {
+ debug( 0, _(L"Could not initialize result pipe" ) );
+ exit( 1 );
+ }
+
+
+ env_universal_init( 0, 0, 0, 0);
+ input_common_init( &interrupt_handler );
+ output_set_writer( &pager_buffered_writer );
+
+ sigemptyset( & act.sa_mask );
+ act.sa_flags=0;
+ act.sa_handler=SIG_DFL;
+ act.sa_flags = 0;
+ act.sa_handler= &handle_winch;
+ if( sigaction( SIGWINCH, &act, 0 ) )
+ {
+ wperror( L"sigaction" );
+ exit(1);
+ }
+
+ handle_winch( 0 ); /* Set handler for window change events */
+
+ tcgetattr(0,&pager_modes); /* get the current terminal modes */
+ memcpy( &saved_modes,
+ &pager_modes,
+ sizeof(saved_modes)); /* save a copy so we can reset the terminal later */
+
+ pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */
+ pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */
+ pager_modes.c_cc[VMIN]=1;
+ pager_modes.c_cc[VTIME]=0;
+
+ /*
+
+ */
+ if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */
+ {
+ wperror(L"tcsetattr");
+ exit(1);
+ }
+
+
+ if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
+ {
+ debug( 0, _(L"Could not set up terminal") );
+ exit(1);
+ }
+
+ term = getenv("TERM");
+ if( term )
+ {
+ wchar_t *wterm = str2wcs(term);
+ output_set_term( wterm );
+ free( wterm );
+ }
+
/* Infer term256 support */
char *fish_term256 = getenv("fish_term256");
bool support_term256;
@@ -1098,7 +1098,7 @@ static void init( int mangle_descriptors, int out )
} else {
support_term256 = term && strstr(term, "256color");
}
- output_set_supports_term256(support_term256);
+ output_set_supports_term256(support_term256);
}
/**
@@ -1106,15 +1106,15 @@ static void init( int mangle_descriptors, int out )
*/
static void destroy()
{
- env_universal_destroy();
- input_common_destroy();
- wutil_destroy();
- if( del_curterm( cur_term ) == ERR )
- {
- debug( 0, _(L"Error while closing terminfo") );
- }
-
- fclose( out_file );
+ env_universal_destroy();
+ input_common_destroy();
+ wutil_destroy();
+ if( del_curterm( cur_term ) == ERR )
+ {
+ debug( 0, _(L"Error while closing terminfo") );
+ }
+
+ fclose( out_file );
}
/**
@@ -1123,319 +1123,319 @@ static void destroy()
*/
static void read_array( FILE* file, wcstring_list_t &comp )
{
- std::vector<char> buffer;
- int c;
- wchar_t *wcs;
-
- while( !feof( file ) )
- {
- buffer.clear();
-
- while( 1 )
- {
- c = getc( file );
- if( c == EOF )
- {
- break;
- }
-
- if( c == '\n' )
- {
- break;
- }
+ std::vector<char> buffer;
+ int c;
+ wchar_t *wcs;
+
+ while( !feof( file ) )
+ {
+ buffer.clear();
+
+ while( 1 )
+ {
+ c = getc( file );
+ if( c == EOF )
+ {
+ break;
+ }
+
+ if( c == '\n' )
+ {
+ break;
+ }
buffer.push_back(static_cast<char>(c));
- }
+ }
- if( ! buffer.empty() )
- {
+ if( ! buffer.empty() )
+ {
buffer.push_back(0);
-
- wcs = str2wcs( &buffer.at(0) );
- if( wcs )
- {
+
+ wcs = str2wcs( &buffer.at(0) );
+ if( wcs )
+ {
wcstring tmp = wcs;
if (unescape_string(tmp, 0))
{
comp.push_back(tmp);
- }
- free( wcs );
- }
- }
- }
+ }
+ free( wcs );
+ }
+ }
+ }
}
static int get_fd( const char *str )
{
- char *end;
- long fd;
-
- errno = 0;
- fd = strtol( str, &end, 10 );
- if( fd < 0 || *end || errno )
- {
- debug( 0, ERR_NOT_FD, program_name, optarg );
- exit( 1 );
- }
- return (int)fd;
+ char *end;
+ long fd;
+
+ errno = 0;
+ fd = strtol( str, &end, 10 );
+ if( fd < 0 || *end || errno )
+ {
+ debug( 0, ERR_NOT_FD, program_name, optarg );
+ exit( 1 );
+ }
+ return (int)fd;
}
int main( int argc, char **argv )
{
- int i;
- int is_quoted=0;
- wcstring_list_t comp;
- wchar_t *prefix = 0;
-
- int mangle_descriptors = 0;
- int result_fd = -1;
- set_main_thread();
+ int i;
+ int is_quoted=0;
+ wcstring_list_t comp;
+ wchar_t *prefix = 0;
+
+ int mangle_descriptors = 0;
+ int result_fd = -1;
+ set_main_thread();
setup_fork_guards();
-
- /*
- This initialization is made early, so that the other init code
- can use global_context for memory managment
- */
- program_name = L"fish_pager";
-
-
- wsetlocale( LC_ALL, L"" );
-
- /*
- The call signature for fish_pager is a mess. Because we want
- to be able to upgrade fish without breaking running
- instances, we need to support all previous
- modes. Unfortunatly, the two previous ones are a mess. The
- third one is designed to be extensible, so hopefully it will
- be the last.
- */
-
- if( argc > 1 && argv[1][0] == '-' )
- {
- /*
- Third mode
- */
-
- int completion_fd = -1;
- FILE *completion_file;
-
- while( 1 )
- {
- static struct option
- long_options[] =
- {
- {
- "result-fd", required_argument, 0, 'r'
- }
- ,
- {
- "completion-fd", required_argument, 0, 'c'
- }
- ,
- {
- "prefix", required_argument, 0, 'p'
- }
- ,
- {
- "is-quoted", no_argument, 0, 'q'
- }
- ,
- {
- "help", no_argument, 0, 'h'
- }
- ,
- {
- "version", no_argument, 0, 'v'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = getopt_long( argc,
- argv,
- GETOPT_STRING,
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- {
- break;
- }
-
- case 'r':
- {
- result_fd = get_fd( optarg );
- break;
- }
-
- case 'c':
- {
- completion_fd = get_fd( optarg );
- break;
- }
-
- case 'p':
- {
- prefix = str2wcs(optarg);
- break;
- }
-
- case 'h':
- {
- print_help( argv[0], 1 );
- exit(0);
- }
-
- case 'v':
- {
- debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
- exit( 0 );
- }
-
- case 'q':
- {
- is_quoted = 1;
- }
-
- }
- }
-
- if( completion_fd == -1 || result_fd == -1 )
- {
- debug( 0, _(L"Unspecified file descriptors") );
- exit( 1 );
- }
-
-
- if( (completion_file = fdopen( completion_fd, "r" ) ) )
- {
- read_array( completion_file, comp );
- fclose( completion_file );
- }
- else
- {
- debug( 0, _(L"Could not read completions") );
- wperror( L"fdopen" );
- exit( 1 );
- }
-
- if( !prefix )
- {
- prefix = wcsdup( L"" );
- }
-
-
- }
- else
- {
- /*
- Second or first mode. These suck, but we need to support
- them for backwards compatibility. At least for some
- time.
-
- Third mode was implemented in January 2007, and previous
- modes should be considered deprecated from that point
- forward. A reasonable time frame for removal of the code
- below has yet to be determined.
- */
-
- if( argc < 3 )
- {
- print_help( argv[0], 1 );
- exit( 0 );
- }
- else
- {
- mangle_descriptors = 1;
-
- prefix = str2wcs( argv[2] );
- is_quoted = strcmp( "1", argv[1] )==0;
-
- if( argc > 3 )
- {
- /*
- First mode
- */
- for( i=3; i<argc; i++ )
- {
- wcstring wcs = str2wcstring( argv[i] );
+
+ /*
+ This initialization is made early, so that the other init code
+ can use global_context for memory managment
+ */
+ program_name = L"fish_pager";
+
+
+ wsetlocale( LC_ALL, L"" );
+
+ /*
+ The call signature for fish_pager is a mess. Because we want
+ to be able to upgrade fish without breaking running
+ instances, we need to support all previous
+ modes. Unfortunatly, the two previous ones are a mess. The
+ third one is designed to be extensible, so hopefully it will
+ be the last.
+ */
+
+ if( argc > 1 && argv[1][0] == '-' )
+ {
+ /*
+ Third mode
+ */
+
+ int completion_fd = -1;
+ FILE *completion_file;
+
+ while( 1 )
+ {
+ static struct option
+ long_options[] =
+ {
+ {
+ "result-fd", required_argument, 0, 'r'
+ }
+ ,
+ {
+ "completion-fd", required_argument, 0, 'c'
+ }
+ ,
+ {
+ "prefix", required_argument, 0, 'p'
+ }
+ ,
+ {
+ "is-quoted", no_argument, 0, 'q'
+ }
+ ,
+ {
+ "help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ "version", no_argument, 0, 'v'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = getopt_long( argc,
+ argv,
+ GETOPT_STRING,
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ {
+ break;
+ }
+
+ case 'r':
+ {
+ result_fd = get_fd( optarg );
+ break;
+ }
+
+ case 'c':
+ {
+ completion_fd = get_fd( optarg );
+ break;
+ }
+
+ case 'p':
+ {
+ prefix = str2wcs(optarg);
+ break;
+ }
+
+ case 'h':
+ {
+ print_help( argv[0], 1 );
+ exit(0);
+ }
+
+ case 'v':
+ {
+ debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
+ exit( 0 );
+ }
+
+ case 'q':
+ {
+ is_quoted = 1;
+ }
+
+ }
+ }
+
+ if( completion_fd == -1 || result_fd == -1 )
+ {
+ debug( 0, _(L"Unspecified file descriptors") );
+ exit( 1 );
+ }
+
+
+ if( (completion_file = fdopen( completion_fd, "r" ) ) )
+ {
+ read_array( completion_file, comp );
+ fclose( completion_file );
+ }
+ else
+ {
+ debug( 0, _(L"Could not read completions") );
+ wperror( L"fdopen" );
+ exit( 1 );
+ }
+
+ if( !prefix )
+ {
+ prefix = wcsdup( L"" );
+ }
+
+
+ }
+ else
+ {
+ /*
+ Second or first mode. These suck, but we need to support
+ them for backwards compatibility. At least for some
+ time.
+
+ Third mode was implemented in January 2007, and previous
+ modes should be considered deprecated from that point
+ forward. A reasonable time frame for removal of the code
+ below has yet to be determined.
+ */
+
+ if( argc < 3 )
+ {
+ print_help( argv[0], 1 );
+ exit( 0 );
+ }
+ else
+ {
+ mangle_descriptors = 1;
+
+ prefix = str2wcs( argv[2] );
+ is_quoted = strcmp( "1", argv[1] )==0;
+
+ if( argc > 3 )
+ {
+ /*
+ First mode
+ */
+ for( i=3; i<argc; i++ )
+ {
+ wcstring wcs = str2wcstring( argv[i] );
comp.push_back(wcs);
- }
- }
- else
- {
- /*
- Second mode
- */
- read_array( stdin, comp );
- }
- }
-
- }
-
-// debug( 3, L"prefix is '%ls'", prefix );
-
- init( mangle_descriptors, result_fd );
-
- mangle_descriptions( comp );
-
- if( wcscmp( prefix, L"-" ) == 0 )
- join_completions( comp );
-
- std::vector<comp_t *> completions = mangle_completions( comp, prefix );
-
- /**
- Try to print the completions. Start by trying to print the
- list in PAGER_MAX_COLS columns, if the completions won't
- fit, reduce the number of columns by one. Printing a single
- column never fails.
- */
- for( i = PAGER_MAX_COLS; i>0; i-- )
- {
- switch( completion_try_print( i, prefix, is_quoted, completions ) )
- {
-
- case PAGER_RETRY:
- break;
-
- case PAGER_DONE:
- i=0;
- break;
-
- case PAGER_RESIZE:
- /*
- This means we got a resize event, so we start
- over from the beginning. Since it the screen got
- bigger, we might be able to fit all completions
- on-screen.
- */
- i=PAGER_MAX_COLS+1;
- break;
-
- }
- }
-
- free(prefix );
-
- fwprintf( out_file, L"%ls", out_buff.c_str() );
- if( is_ca_mode )
- {
- writembs(exit_ca_mode);
- pager_flush();
- }
- destroy();
+ }
+ }
+ else
+ {
+ /*
+ Second mode
+ */
+ read_array( stdin, comp );
+ }
+ }
+
+ }
+
+// debug( 3, L"prefix is '%ls'", prefix );
+
+ init( mangle_descriptors, result_fd );
+
+ mangle_descriptions( comp );
+
+ if( wcscmp( prefix, L"-" ) == 0 )
+ join_completions( comp );
+
+ std::vector<comp_t *> completions = mangle_completions( comp, prefix );
+
+ /**
+ Try to print the completions. Start by trying to print the
+ list in PAGER_MAX_COLS columns, if the completions won't
+ fit, reduce the number of columns by one. Printing a single
+ column never fails.
+ */
+ for( i = PAGER_MAX_COLS; i>0; i-- )
+ {
+ switch( completion_try_print( i, prefix, is_quoted, completions ) )
+ {
+
+ case PAGER_RETRY:
+ break;
+
+ case PAGER_DONE:
+ i=0;
+ break;
+
+ case PAGER_RESIZE:
+ /*
+ This means we got a resize event, so we start
+ over from the beginning. Since it the screen got
+ bigger, we might be able to fit all completions
+ on-screen.
+ */
+ i=PAGER_MAX_COLS+1;
+ break;
+
+ }
+ }
+
+ free(prefix );
+
+ fwprintf( out_file, L"%ls", out_buff.c_str() );
+ if( is_ca_mode )
+ {
+ writembs(exit_ca_mode);
+ pager_flush();
+ }
+ destroy();
}
diff --git a/fish_tests.cpp b/fish_tests.cpp
index 07e51f21..42f220bf 100644
--- a/fish_tests.cpp
+++ b/fish_tests.cpp
@@ -1,5 +1,5 @@
/** \file fish_tests.c
- Various bug and feature tests. Compiled and run by make test.
+ Various bug and feature tests. Compiled and run by make test.
*/
#include "config.h"
@@ -95,11 +95,11 @@ static int err_count=0;
*/
static void say( const wchar_t *blah, ... )
{
- va_list va;
- va_start( va, blah );
- vwprintf( blah, va );
- va_end( va );
- wprintf( L"\n" );
+ va_list va;
+ va_start( va, blah );
+ vwprintf( blah, va );
+ va_end( va );
+ wprintf( L"\n" );
}
/**
@@ -107,14 +107,14 @@ static void say( const wchar_t *blah, ... )
*/
static void err( const wchar_t *blah, ... )
{
- va_list va;
- va_start( va, blah );
- err_count++;
-
- wprintf( L"Error: " );
- vwprintf( blah, va );
- va_end( va );
- wprintf( L"\n" );
+ va_list va;
+ va_start( va, blah );
+ err_count++;
+
+ wprintf( L"Error: " );
+ vwprintf( blah, va );
+ va_end( va );
+ wprintf( L"\n" );
}
/**
@@ -123,40 +123,40 @@ static void err( const wchar_t *blah, ... )
*/
static void test_escape()
{
- int i;
- wcstring sb;
-
- say( L"Testing escaping and unescaping" );
-
- for( i=0; i<ESCAPE_TEST_COUNT; i++ )
- {
- const wchar_t *o, *e, *u;
-
- sb.clear();
- while( rand() % ESCAPE_TEST_LENGTH )
- {
- sb.push_back((rand() %ESCAPE_TEST_CHAR) +1 );
- }
- o = (const wchar_t *)sb.c_str();
- e = escape(o, 1);
- u = unescape( e, 0 );
- if( !o || !e || !u )
- {
- err( L"Escaping cycle of string %ls produced null pointer on %ls", o, e?L"unescaping":L"escaping" );
-
- }
-
-
- if( wcscmp(o, u) )
- {
- err( L"Escaping cycle of string %ls produced different string %ls", o, u );
-
-
- }
- free( (void *)e );
- free( (void *)u );
-
- }
+ int i;
+ wcstring sb;
+
+ say( L"Testing escaping and unescaping" );
+
+ for( i=0; i<ESCAPE_TEST_COUNT; i++ )
+ {
+ const wchar_t *o, *e, *u;
+
+ sb.clear();
+ while( rand() % ESCAPE_TEST_LENGTH )
+ {
+ sb.push_back((rand() %ESCAPE_TEST_CHAR) +1 );
+ }
+ o = (const wchar_t *)sb.c_str();
+ e = escape(o, 1);
+ u = unescape( e, 0 );
+ if( !o || !e || !u )
+ {
+ err( L"Escaping cycle of string %ls produced null pointer on %ls", o, e?L"unescaping":L"escaping" );
+
+ }
+
+
+ if( wcscmp(o, u) )
+ {
+ err( L"Escaping cycle of string %ls produced different string %ls", o, u );
+
+
+ }
+ free( (void *)e );
+ free( (void *)u );
+
+ }
}
static void test_format(void) {
@@ -175,20 +175,20 @@ static void test_format(void) {
format_size_safe(buff, tests[i].val);
assert( ! strcmp(buff, tests[i].expected));
}
-
+
for (int j=-129; j <= 129; j++) {
char buff1[128], buff2[128];
format_long_safe(buff1, j);
sprintf(buff2, "%d", j);
assert( ! strcmp(buff1, buff2));
}
-
+
long q = LONG_MIN;
char buff1[128], buff2[128];
format_long_safe(buff1, q);
sprintf(buff2, "%ld", q);
assert( ! strcmp(buff1, buff2));
-
+
}
/**
@@ -198,81 +198,81 @@ static void test_format(void) {
*/
static void test_convert()
{
-/* char o[] =
- {
- -17, -128, -121, -68, 0
- }
- ;
-
- wchar_t *w = str2wcs(o);
- char *n = wcs2str(w);
-
- int i;
-
- for( i=0; o[i]; i++ )
- {
- bitprint(o[i]);;
- //wprintf(L"%d ", o[i]);
- }
- wprintf(L"\n");
-
- for( i=0; w[i]; i++ )
- {
- wbitprint(w[i]);;
- //wprintf(L"%d ", w[i]);
- }
- wprintf(L"\n");
-
- for( i=0; n[i]; i++ )
- {
- bitprint(n[i]);;
- //wprintf(L"%d ", n[i]);
- }
- wprintf(L"\n");
-
- return;
+/* char o[] =
+ {
+ -17, -128, -121, -68, 0
+ }
+ ;
+
+ wchar_t *w = str2wcs(o);
+ char *n = wcs2str(w);
+
+ int i;
+
+ for( i=0; o[i]; i++ )
+ {
+ bitprint(o[i]);;
+ //wprintf(L"%d ", o[i]);
+ }
+ wprintf(L"\n");
+
+ for( i=0; w[i]; i++ )
+ {
+ wbitprint(w[i]);;
+ //wprintf(L"%d ", w[i]);
+ }
+ wprintf(L"\n");
+
+ for( i=0; n[i]; i++ )
+ {
+ bitprint(n[i]);;
+ //wprintf(L"%d ", n[i]);
+ }
+ wprintf(L"\n");
+
+ return;
*/
- int i;
- std::vector<char> sb;
-
- say( L"Testing wide/narrow string conversion" );
-
- for( i=0; i<ESCAPE_TEST_COUNT; i++ )
- {
- wchar_t *w;
- const char *o, *n;
-
- char c;
-
- sb.clear();
-
- while( rand() % ESCAPE_TEST_LENGTH )
- {
- c = rand ();
+ int i;
+ std::vector<char> sb;
+
+ say( L"Testing wide/narrow string conversion" );
+
+ for( i=0; i<ESCAPE_TEST_COUNT; i++ )
+ {
+ wchar_t *w;
+ const char *o, *n;
+
+ char c;
+
+ sb.clear();
+
+ while( rand() % ESCAPE_TEST_LENGTH )
+ {
+ c = rand ();
sb.push_back(c);
- }
- c = 0;
+ }
+ c = 0;
sb.push_back(c);
-
- o = &sb.at(0);
- w = str2wcs(o);
- n = wcs2str(w);
-
- if( !o || !w || !n )
- {
- err( L"Line %d - Conversion cycle of string %s produced null pointer on %s", __LINE__, o, w?L"str2wcs":L"wcs2str" );
- }
-
- if( strcmp(o, n) )
- {
- err( L"Line %d - %d: Conversion cycle of string %s produced different string %s", __LINE__, i, o, n );
- }
- free( w );
- free( (void *)n );
-
- }
+
+ o = &sb.at(0);
+ w = str2wcs(o);
+ n = wcs2str(w);
+
+ if( !o || !w || !n )
+ {
+ err( L"Line %d - Conversion cycle of string %s produced null pointer on %s", __LINE__, o, w?L"str2wcs":L"wcs2str" );
+ }
+
+ if( strcmp(o, n) )
+ {
+ err( L"Line %d - %d: Conversion cycle of string %s produced different string %s", __LINE__, i, o, n );
+ }
+ free( w );
+ free( (void *)n );
+
+ }
}
@@ -281,63 +281,63 @@ static void test_convert()
*/
static void test_tok()
{
- tokenizer t;
-
- say( L"Testing tokenizer" );
-
-
- say( L"Testing invalid input" );
- tok_init( &t, 0, 0 );
-
- if( tok_last_type( &t ) != TOK_ERROR )
- {
- err(L"Invalid input to tokenizer was undetected" );
- }
-
- say( L"Testing use of broken tokenizer" );
- if( !tok_has_next( &t ) )
- {
- err( L"tok_has_next() should return 1 once on broken tokenizer" );
- }
-
- tok_next( &t );
- if( tok_last_type( &t ) != TOK_ERROR )
- {
- err(L"Invalid input to tokenizer was undetected" );
- }
-
- /*
- This should crash if there is a bug. No reliable way to detect otherwise.
- */
- say( L"Test destruction of broken tokenizer" );
- tok_destroy( &t );
-
- {
-
- const wchar_t *str = L"string <redirection 2>&1 'nested \"quoted\" '(string containing subshells ){and,brackets}$as[$well (as variable arrays)] not_a_redirect^ ^ ^^is_a_redirect";
- const int types[] =
- {
- TOK_STRING, TOK_REDIRECT_IN, TOK_STRING, TOK_REDIRECT_FD, TOK_STRING, TOK_STRING, TOK_STRING, TOK_REDIRECT_OUT, TOK_REDIRECT_APPEND, TOK_STRING, TOK_END
- }
- ;
- size_t i;
-
- say( L"Test correct tokenization" );
-
- for( i=0, tok_init( &t, str, 0 ); i<(sizeof(types)/sizeof(int)); i++,tok_next( &t ) )
- {
- if( types[i] != tok_last_type( &t ) )
- {
- err( L"Tokenization error:");
- wprintf( L"Token number %d of string \n'%ls'\n, expected token type %ls, got token '%ls' of type %ls\n",
- i+1,
- str,
- tok_get_desc(types[i]),
- tok_last(&t),
- tok_get_desc(tok_last_type( &t )) );
- }
- }
- }
+ tokenizer t;
+
+ say( L"Testing tokenizer" );
+
+
+ say( L"Testing invalid input" );
+ tok_init( &t, 0, 0 );
+
+ if( tok_last_type( &t ) != TOK_ERROR )
+ {
+ err(L"Invalid input to tokenizer was undetected" );
+ }
+
+ say( L"Testing use of broken tokenizer" );
+ if( !tok_has_next( &t ) )
+ {
+ err( L"tok_has_next() should return 1 once on broken tokenizer" );
+ }
+
+ tok_next( &t );
+ if( tok_last_type( &t ) != TOK_ERROR )
+ {
+ err(L"Invalid input to tokenizer was undetected" );
+ }
+
+ /*
+ This should crash if there is a bug. No reliable way to detect otherwise.
+ */
+ say( L"Test destruction of broken tokenizer" );
+ tok_destroy( &t );
+
+ {
+
+ const wchar_t *str = L"string <redirection 2>&1 'nested \"quoted\" '(string containing subshells ){and,brackets}$as[$well (as variable arrays)] not_a_redirect^ ^ ^^is_a_redirect";
+ const int types[] =
+ {
+ TOK_STRING, TOK_REDIRECT_IN, TOK_STRING, TOK_REDIRECT_FD, TOK_STRING, TOK_STRING, TOK_STRING, TOK_REDIRECT_OUT, TOK_REDIRECT_APPEND, TOK_STRING, TOK_END
+ }
+ ;
+ size_t i;
+
+ say( L"Test correct tokenization" );
+
+ for( i=0, tok_init( &t, str, 0 ); i<(sizeof(types)/sizeof(int)); i++,tok_next( &t ) )
+ {
+ if( types[i] != tok_last_type( &t ) )
+ {
+ err( L"Tokenization error:");
+ wprintf( L"Token number %d of string \n'%ls'\n, expected token type %ls, got token '%ls' of type %ls\n",
+ i+1,
+ str,
+ tok_get_desc(types[i]),
+ tok_last(&t),
+ tok_get_desc(tok_last_type( &t )) );
+ }
+ }
+ }
}
static int test_fork_helper(void *unused) {
@@ -375,7 +375,7 @@ static void test_fork(void) {
exit_without_destructors(0);
} else {
perror("fork");
- }
+ }
}
for (size_t i=0; i < FORK_COUNT; i++) {
int status = 0;
@@ -397,73 +397,73 @@ static void test_fork(void) {
*/
static void test_parser()
{
- say( L"Testing parser" );
-
- parser_t parser(PARSER_TYPE_GENERAL, true);
-
- say( L"Testing null input to parser" );
- if( !parser.test( 0, 0, 0, 0 ) )
- {
- err( L"Null input to parser.test undetected" );
- }
-
- say( L"Testing block nesting" );
- if( !parser.test( L"if; end", 0, 0, 0 ) )
- {
- err( L"Incomplete if statement undetected" );
- }
- if( !parser.test( L"if test; echo", 0, 0, 0 ) )
- {
- err( L"Missing end undetected" );
- }
- if( !parser.test( L"if test; end; end", 0, 0, 0 ) )
- {
- err( L"Unbalanced end undetected" );
- }
-
- say( L"Testing detection of invalid use of builtin commands" );
- if( !parser.test( L"case foo", 0, 0, 0 ) )
- {
- err( L"'case' command outside of block context undetected" );
- }
- if( !parser.test( L"switch ggg; if true; case foo;end;end", 0, 0, 0 ) )
- {
- err( L"'case' command outside of switch block context undetected" );
- }
- if( !parser.test( L"else", 0, 0, 0 ) )
- {
- err( L"'else' command outside of conditional block context undetected" );
- }
- if( !parser.test( L"else if", 0, 0, 0 ) )
- {
- err( L"'else if' command outside of conditional block context undetected" );
- }
- if( !parser.test( L"if false; else if; end", 0, 0, 0 ) )
- {
- err( L"'else if' missing command undetected" );
- }
-
- if( !parser.test( L"break", 0, 0, 0 ) )
- {
- err( L"'break' command outside of loop block context undetected" );
- }
- if( !parser.test( L"exec ls|less", 0, 0, 0 ) || !parser.test( L"echo|return", 0, 0, 0 ))
- {
- err( L"Invalid pipe command undetected" );
- }
-
- say( L"Testing basic evaluation" );
+ say( L"Testing parser" );
+
+ parser_t parser(PARSER_TYPE_GENERAL, true);
+
+ say( L"Testing null input to parser" );
+ if( !parser.test( 0, 0, 0, 0 ) )
+ {
+ err( L"Null input to parser.test undetected" );
+ }
+
+ say( L"Testing block nesting" );
+ if( !parser.test( L"if; end", 0, 0, 0 ) )
+ {
+ err( L"Incomplete if statement undetected" );
+ }
+ if( !parser.test( L"if test; echo", 0, 0, 0 ) )
+ {
+ err( L"Missing end undetected" );
+ }
+ if( !parser.test( L"if test; end; end", 0, 0, 0 ) )
+ {
+ err( L"Unbalanced end undetected" );
+ }
+
+ say( L"Testing detection of invalid use of builtin commands" );
+ if( !parser.test( L"case foo", 0, 0, 0 ) )
+ {
+ err( L"'case' command outside of block context undetected" );
+ }
+ if( !parser.test( L"switch ggg; if true; case foo;end;end", 0, 0, 0 ) )
+ {
+ err( L"'case' command outside of switch block context undetected" );
+ }
+ if( !parser.test( L"else", 0, 0, 0 ) )
+ {
+ err( L"'else' command outside of conditional block context undetected" );
+ }
+ if( !parser.test( L"else if", 0, 0, 0 ) )
+ {
+ err( L"'else if' command outside of conditional block context undetected" );
+ }
+ if( !parser.test( L"if false; else if; end", 0, 0, 0 ) )
+ {
+ err( L"'else if' missing command undetected" );
+ }
+
+ if( !parser.test( L"break", 0, 0, 0 ) )
+ {
+ err( L"'break' command outside of loop block context undetected" );
+ }
+ if( !parser.test( L"exec ls|less", 0, 0, 0 ) || !parser.test( L"echo|return", 0, 0, 0 ))
+ {
+ err( L"Invalid pipe command undetected" );
+ }
+
+ say( L"Testing basic evaluation" );
#if 0
/* This fails now since the parser takes a wcstring&, and NULL converts to wchar_t * converts to wcstring which crashes (thanks C++) */
- if( !parser.eval( 0, 0, TOP ) )
- {
- err( L"Null input when evaluating undetected" );
- }
+ if( !parser.eval( 0, 0, TOP ) )
+ {
+ err( L"Null input when evaluating undetected" );
+ }
#endif
- if( !parser.eval( L"ls", io_chain_t(), WHILE ) )
- {
- err( L"Invalid block mode when evaluating undetected" );
- }
+ if( !parser.eval( L"ls", io_chain_t(), WHILE ) )
+ {
+ err( L"Invalid block mode when evaluating undetected" );
+ }
}
class lru_node_test_t : public lru_node_t {
@@ -474,9 +474,9 @@ class lru_node_test_t : public lru_node_t {
class test_lru_t : public lru_cache_t<lru_node_test_t> {
public:
test_lru_t() : lru_cache_t<lru_node_test_t>(16) { }
-
+
std::vector<lru_node_test_t *> evicted_nodes;
-
+
virtual void node_was_evicted(lru_node_test_t *node) {
assert(find(evicted_nodes.begin(), evicted_nodes.end(), node) == evicted_nodes.end());
evicted_nodes.push_back(node);
@@ -485,7 +485,7 @@ class test_lru_t : public lru_cache_t<lru_node_test_t> {
static void test_lru(void) {
say( L"Testing LRU cache" );
-
+
test_lru_t cache;
std::vector<lru_node_test_t *> expected_evicted;
size_t total_nodes = 20;
@@ -506,7 +506,7 @@ static void test_lru(void) {
delete node;
}
}
-
+
/**
Perform parameter expansion and test if the output equals the zero-terminated parameter list supplied.
@@ -516,46 +516,46 @@ static void test_lru(void) {
static int expand_test( const wchar_t *in, int flags, ... )
{
- std::vector<completion_t> output;
- va_list va;
- size_t i=0;
- int res=1;
- wchar_t *arg;
-
- if( expand_string( in, output, flags) )
- {
-
- }
-
+ std::vector<completion_t> output;
+ va_list va;
+ size_t i=0;
+ int res=1;
+ wchar_t *arg;
+
+ if( expand_string( in, output, flags) )
+ {
+
+ }
+
#if 0
for (size_t idx=0; idx < output.size(); idx++)
{
printf("%ls\n", output.at(idx).completion.c_str());
}
#endif
-
- va_start( va, flags );
-
- while( (arg=va_arg(va, wchar_t *) )!= 0 )
- {
- if( output.size() == i )
- {
- res=0;
- break;
- }
-
+
+ va_start( va, flags );
+
+ while( (arg=va_arg(va, wchar_t *) )!= 0 )
+ {
+ if( output.size() == i )
+ {
+ res=0;
+ break;
+ }
+
if (output.at(i).completion != arg)
- {
- res=0;
- break;
- }
-
- i++;
- }
- va_end( va );
-
- return res;
-
+ {
+ res=0;
+ break;
+ }
+
+ i++;
+ }
+ va_end( va );
+
+ return res;
+
}
/**
@@ -563,36 +563,36 @@ static int expand_test( const wchar_t *in, int flags, ... )
*/
static void test_expand()
{
- say( L"Testing parameter expansion" );
-
- if( !expand_test( L"foo", 0, L"foo", 0 ))
- {
- err( L"Strings do not expand to themselves" );
- }
-
- if( !expand_test( L"a{b,c,d}e", 0, L"abe", L"ace", L"ade", 0 ) )
- {
- err( L"Bracket expansion is broken" );
- }
-
- if( !expand_test( L"a*", EXPAND_SKIP_WILDCARDS, L"a*", 0 ) )
- {
- err( L"Cannot skip wildcard expansion" );
- }
-
+ say( L"Testing parameter expansion" );
+
+ if( !expand_test( L"foo", 0, L"foo", 0 ))
+ {
+ err( L"Strings do not expand to themselves" );
+ }
+
+ if( !expand_test( L"a{b,c,d}e", 0, L"abe", L"ace", L"ade", 0 ) )
+ {
+ err( L"Bracket expansion is broken" );
+ }
+
+ if( !expand_test( L"a*", EXPAND_SKIP_WILDCARDS, L"a*", 0 ) )
+ {
+ err( L"Cannot skip wildcard expansion" );
+ }
+
if (system("mkdir -p /tmp/fish_expand_test/")) err(L"mkdir failed");
if (system("touch /tmp/fish_expand_test/.foo")) err(L"touch failed");
if (system("touch /tmp/fish_expand_test/bar")) err(L"touch failed");
-
+
// This is checking that .* does NOT match . and .. (https://github.com/fish-shell/fish-shell/issues/270). But it does have to match literal components (e.g. "./*" has to match the same as "*"
- if (! expand_test( L"/tmp/fish_expand_test/.*", 0, L"/tmp/fish_expand_test/.foo", 0 ))
- {
- err( L"Expansion not correctly handling dotfiles" );
- }
- if (! expand_test( L"/tmp/fish_expand_test/./.*", 0, L"/tmp/fish_expand_test/./.foo", 0 ))
- {
- err( L"Expansion not correctly handling literal path components in dotfiles" );
- }
+ if (! expand_test( L"/tmp/fish_expand_test/.*", 0, L"/tmp/fish_expand_test/.foo", 0 ))
+ {
+ err( L"Expansion not correctly handling dotfiles" );
+ }
+ if (! expand_test( L"/tmp/fish_expand_test/./.*", 0, L"/tmp/fish_expand_test/./.foo", 0 ))
+ {
+ err( L"Expansion not correctly handling literal path components in dotfiles" );
+ }
//system("rm -Rf /tmp/fish_expand_test");
}
@@ -600,21 +600,21 @@ static void test_expand()
/** Test path functions */
static void test_path()
{
- say( L"Testing path functions" );
+ say( L"Testing path functions" );
wcstring path = L"//foo//////bar/";
wcstring canon = path;
path_make_canonical(canon);
- if( canon != L"/foo/bar" )
- {
- err( L"Bug in canonical PATH code" );
- }
-
+ if( canon != L"/foo/bar" )
+ {
+ err( L"Bug in canonical PATH code" );
+ }
+
path = L"/";
path_make_canonical(path);
if (path != L"/")
{
- err( L"Bug in canonical PATH code" );
+ err( L"Bug in canonical PATH code" );
}
}
@@ -625,36 +625,36 @@ static void test_is_potential_path()
if (system("rm -Rf /tmp/is_potential_path_test/")) {
err(L"Failed to remove /tmp/is_potential_path_test/");
}
-
+
/* Directories */
if (system("mkdir -p /tmp/is_potential_path_test/alpha/")) err(L"mkdir failed");
if (system("mkdir -p /tmp/is_potential_path_test/beta/")) err(L"mkdir failed");
-
+
/* Files */
if (system("touch /tmp/is_potential_path_test/aardvark")) err(L"touch failed");
if (system("touch /tmp/is_potential_path_test/gamma")) err(L"touch failed");
-
+
const wcstring wd = L"/tmp/is_potential_path_test/";
const wcstring_list_t wds(1, wd);
-
+
wcstring tmp;
assert(is_potential_path(L"al", wds, PATH_REQUIRE_DIR, &tmp) && tmp == L"alpha/");
assert(is_potential_path(L"alpha/", wds, PATH_REQUIRE_DIR, &tmp) && tmp == L"alpha/");
assert(is_potential_path(L"aard", wds, 0, &tmp) && tmp == L"aardvark");
-
+
assert(! is_potential_path(L"balpha/", wds, PATH_REQUIRE_DIR, &tmp));
assert(! is_potential_path(L"aard", wds, PATH_REQUIRE_DIR, &tmp));
assert(! is_potential_path(L"aarde", wds, PATH_REQUIRE_DIR, &tmp));
assert(! is_potential_path(L"aarde", wds, 0, &tmp));
-
+
assert(is_potential_path(L"/tmp/is_potential_path_test/aardvark", wds, 0, &tmp) && tmp == L"/tmp/is_potential_path_test/aardvark");
assert(is_potential_path(L"/tmp/is_potential_path_test/al", wds, PATH_REQUIRE_DIR, &tmp) && tmp == L"/tmp/is_potential_path_test/alpha/");
assert(is_potential_path(L"/tmp/is_potential_path_test/aardv", wds, 0, &tmp) && tmp == L"/tmp/is_potential_path_test/aardvark");
-
+
assert(! is_potential_path(L"/tmp/is_potential_path_test/aardvark", wds, PATH_REQUIRE_DIR, &tmp));
assert(! is_potential_path(L"/tmp/is_potential_path_test/al/", wds, 0, &tmp));
assert(! is_potential_path(L"/tmp/is_potential_path_test/ar", wds, 0, &tmp));
-
+
assert(is_potential_path(L"/usr", wds, PATH_REQUIRE_DIR, &tmp) && tmp == L"/usr/");
}
@@ -711,7 +711,7 @@ static void test_test() {
assert(run_test_test(0, L"0 -ne 1 -a -n 5"));
assert(run_test_test(0, L"-n 5 -a 10 -gt 5"));
assert(run_test_test(0, L"-n 3 -a -n 5"));
-
+
/* test precedence:
'0 == 0 || 0 == 1 && 0 == 2'
should be evaluated as:
@@ -722,8 +722,8 @@ static void test_test() {
assert(run_test_test(0, L"0 = 0 -o 0 = 1 -a 0 = 2"));
assert(run_test_test(0, L"-n 5 -o 0 = 1 -a 0 = 2"));
assert(run_test_test(1, L"( 0 = 0 -o 0 = 1 ) -a 0 = 2"));
- assert(run_test_test(0, L"0 = 0 -o ( 0 = 1 -a 0 = 2 )"));
-
+ assert(run_test_test(0, L"0 = 0 -o ( 0 = 1 -a 0 = 2 )"));
+
/* A few lame tests for permissions; these need to be a lot more complete. */
assert(run_test_test(0, L"-e /bin/ls"));
assert(run_test_test(1, L"-e /bin/ls_not_a_path"));
@@ -731,12 +731,12 @@ static void test_test() {
assert(run_test_test(1, L"-x /bin/ls_not_a_path"));
assert(run_test_test(0, L"-d /bin/"));
assert(run_test_test(1, L"-d /bin/ls"));
-
+
/* This failed at one point */
assert(run_test_test(1, L"-d /bin -a 5 -eq 3"));
assert(run_test_test(0, L"-d /bin -o 5 -eq 3"));
assert(run_test_test(0, L"-d /bin -a ! 5 -eq 3"));
-
+
/* We didn't properly handle multiple "just strings" either */
assert(run_test_test(0, L"foo"));
assert(run_test_test(0, L"foo -a bar"));
@@ -773,7 +773,7 @@ static void perform_one_autosuggestion_test(const wcstring &command, const wcstr
printf("line %ld: autosuggest_suggest_special() returned the wrong expected string for command %ls\n", line, command.c_str());
printf(" actual: %ls\n", suggestion.c_str());
printf("expected: %ls\n", expected.c_str());
- assert(suggestion == expected);
+ assert(suggestion == expected);
}
}
@@ -786,7 +786,7 @@ static void test_autosuggest_suggest_special() {
if (system("mkdir -p /tmp/autosuggest_test/4foo\\'bar")) err(L"mkdir failed"); //a path with a single quote
if (system("mkdir -p /tmp/autosuggest_test/5foo\\\"bar")) err(L"mkdir failed"); //a path with a double quote
if (system("mkdir -p ~/test_autosuggest_suggest_special/")) err(L"mkdir failed"); //make sure tilde is handled
-
+
const wcstring wd = L"/tmp/autosuggest_test/";
perform_one_autosuggestion_test(L"cd /tmp/autosuggest_test/0", wd, L"cd /tmp/autosuggest_test/0foobar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"/tmp/autosuggest_test/0", wd, L"cd \"/tmp/autosuggest_test/0foobar/\"", __LINE__);
@@ -794,47 +794,47 @@ static void test_autosuggest_suggest_special() {
perform_one_autosuggestion_test(L"cd 0", wd, L"cd 0foobar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"0", wd, L"cd \"0foobar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '0", wd, L"cd '0foobar/'", __LINE__);
-
+
perform_one_autosuggestion_test(L"cd /tmp/autosuggest_test/1", wd, L"cd /tmp/autosuggest_test/1foo\\ bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"/tmp/autosuggest_test/1", wd, L"cd \"/tmp/autosuggest_test/1foo bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '/tmp/autosuggest_test/1", wd, L"cd '/tmp/autosuggest_test/1foo bar/'", __LINE__);
perform_one_autosuggestion_test(L"cd 1", wd, L"cd 1foo\\ bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"1", wd, L"cd \"1foo bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '1", wd, L"cd '1foo bar/'", __LINE__);
-
+
perform_one_autosuggestion_test(L"cd /tmp/autosuggest_test/2", wd, L"cd /tmp/autosuggest_test/2foo\\ \\ bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"/tmp/autosuggest_test/2", wd, L"cd \"/tmp/autosuggest_test/2foo bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '/tmp/autosuggest_test/2", wd, L"cd '/tmp/autosuggest_test/2foo bar/'", __LINE__);
perform_one_autosuggestion_test(L"cd 2", wd, L"cd 2foo\\ \\ bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"2", wd, L"cd \"2foo bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '2", wd, L"cd '2foo bar/'", __LINE__);
-
+
perform_one_autosuggestion_test(L"cd /tmp/autosuggest_test/3", wd, L"cd /tmp/autosuggest_test/3foo\\\\bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"/tmp/autosuggest_test/3", wd, L"cd \"/tmp/autosuggest_test/3foo\\bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '/tmp/autosuggest_test/3", wd, L"cd '/tmp/autosuggest_test/3foo\\bar/'", __LINE__);
perform_one_autosuggestion_test(L"cd 3", wd, L"cd 3foo\\\\bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"3", wd, L"cd \"3foo\\bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '3", wd, L"cd '3foo\\bar/'", __LINE__);
-
+
perform_one_autosuggestion_test(L"cd /tmp/autosuggest_test/4", wd, L"cd /tmp/autosuggest_test/4foo\\'bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"/tmp/autosuggest_test/4", wd, L"cd \"/tmp/autosuggest_test/4foo'bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '/tmp/autosuggest_test/4", wd, L"cd '/tmp/autosuggest_test/4foo\\'bar/'", __LINE__);
perform_one_autosuggestion_test(L"cd 4", wd, L"cd 4foo\\'bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"4", wd, L"cd \"4foo'bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '4", wd, L"cd '4foo\\'bar/'", __LINE__);
-
+
perform_one_autosuggestion_test(L"cd /tmp/autosuggest_test/5", wd, L"cd /tmp/autosuggest_test/5foo\\\"bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"/tmp/autosuggest_test/5", wd, L"cd \"/tmp/autosuggest_test/5foo\\\"bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '/tmp/autosuggest_test/5", wd, L"cd '/tmp/autosuggest_test/5foo\"bar/'", __LINE__);
perform_one_autosuggestion_test(L"cd 5", wd, L"cd 5foo\\\"bar/", __LINE__);
perform_one_autosuggestion_test(L"cd \"5", wd, L"cd \"5foo\\\"bar/\"", __LINE__);
perform_one_autosuggestion_test(L"cd '5", wd, L"cd '5foo\"bar/'", __LINE__);
-
+
perform_one_autosuggestion_test(L"cd ~/test_autosuggest_suggest_specia", wd, L"cd ~/test_autosuggest_suggest_special/", __LINE__);
-
+
// A single quote should defeat tilde expansion
perform_one_autosuggestion_test(L"cd '~/test_autosuggest_suggest_specia'", wd, L"", __LINE__);
-
+
system("rm -Rf '/tmp/autosuggest_test/'");
system("rm -Rf ~/test_autosuggest_suggest_special/");
}
@@ -845,65 +845,65 @@ static void test_autosuggest_suggest_special() {
*/
void perf_complete()
{
- wchar_t c;
- std::vector<completion_t> out;
- long long t1, t2;
- int matches=0;
- double t;
- wchar_t str[3]=
- {
- 0, 0, 0
- }
- ;
- int i;
-
-
- say( L"Testing completion performance" );
-
- reader_push(L"");
- say( L"Here we go" );
-
- t1 = get_time();
-
-
- for( c=L'a'; c<=L'z'; c++ )
- {
- str[0]=c;
- reader_set_buffer( str, 0 );
-
- complete( str, out, COMPLETE_DEFAULT, NULL );
-
- matches += out.size();
+ wchar_t c;
+ std::vector<completion_t> out;
+ long long t1, t2;
+ int matches=0;
+ double t;
+ wchar_t str[3]=
+ {
+ 0, 0, 0
+ }
+ ;
+ int i;
+
+
+ say( L"Testing completion performance" );
+
+ reader_push(L"");
+ say( L"Here we go" );
+
+ t1 = get_time();
+
+
+ for( c=L'a'; c<=L'z'; c++ )
+ {
+ str[0]=c;
+ reader_set_buffer( str, 0 );
+
+ complete( str, out, COMPLETE_DEFAULT, NULL );
+
+ matches += out.size();
out.clear();
- }
- t2=get_time();
-
- t = (double)(t2-t1)/(1000000*26);
-
- say( L"One letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
-
- matches=0;
- t1 = get_time();
- for( i=0; i<LAPS; i++ )
- {
- str[0]='a'+(rand()%26);
- str[1]='a'+(rand()%26);
-
- reader_set_buffer( str, 0 );
-
- complete( str, out, COMPLETE_DEFAULT, NULL );
-
- matches += out.size();
+ }
+ t2=get_time();
+
+ t = (double)(t2-t1)/(1000000*26);
+
+ say( L"One letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
+
+ matches=0;
+ t1 = get_time();
+ for( i=0; i<LAPS; i++ )
+ {
+ str[0]='a'+(rand()%26);
+ str[1]='a'+(rand()%26);
+
+ reader_set_buffer( str, 0 );
+
+ complete( str, out, COMPLETE_DEFAULT, NULL );
+
+ matches += out.size();
out.clear();
- }
- t2=get_time();
-
- t = (double)(t2-t1)/(1000000*LAPS);
-
- say( L"Two letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
-
- reader_pop();
-
+ }
+ t2=get_time();
+
+ t = (double)(t2-t1)/(1000000*LAPS);
+
+ say( L"Two letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
+
+ reader_pop();
+
}
static void test_history_matches(history_search_t &search, size_t matches) {
@@ -913,7 +913,7 @@ static void test_history_matches(history_search_t &search, size_t matches) {
wcstring item = search.current_string();
}
assert(! search.go_backwards());
-
+
for (i=1; i < matches; i++) {
assert(search.go_forwards());
}
@@ -927,7 +927,7 @@ static bool history_contains(history_t *history, const wcstring &txt) {
history_item_t item = history->item_at_index(i);
if (item.empty())
break;
-
+
if (item.str() == txt) {
result = true;
break;
@@ -955,18 +955,18 @@ static wcstring random_string(void) {
void history_tests_t::test_history(void) {
say( L"Testing history");
-
+
history_t &history = history_t::history_with_name(L"test_history");
history.clear();
history.add(L"Gamma");
history.add(L"Beta");
history.add(L"Alpha");
-
+
/* All three items match "a" */
history_search_t search1(history, L"a");
test_history_matches(search1, 3);
assert(search1.current_string() == L"Alpha");
-
+
/* One item matches "et" */
history_search_t search2(history, L"et");
test_history_matches(search2, 1);
@@ -976,34 +976,34 @@ void history_tests_t::test_history(void) {
history.remove(L"Alpha");
history_search_t search3(history, L"Alpha");
test_history_matches(search3, 0);
-
+
/* Test history escaping and unescaping, yaml, etc. */
std::vector<history_item_t> before, after;
history.clear();
size_t i, max = 100;
for (i=1; i <= max; i++) {
-
+
/* Generate a value */
wcstring value = wcstring(L"test item ") + to_string(i);
-
+
/* Maybe add some backslashes */
if (i % 3 == 0)
value.append(L"(slashies \\\\\\ slashies)");
/* Generate some paths */
- path_list_t paths;
+ path_list_t paths;
size_t count = rand() % 6;
while (count--) {
paths.push_back(random_string());
}
-
+
/* Record this item */
history_item_t item(value, time(NULL), paths);
before.push_back(item);
history.add(item);
}
history.save();
-
+
/* Read items back in reverse order and ensure they're the same */
for (i=100; i >= 1; i--) {
history_item_t item = history.item_at_index(i);
@@ -1017,7 +1017,7 @@ void history_tests_t::test_history(void) {
assert(bef.creation_timestamp == aft.creation_timestamp);
assert(bef.required_paths == aft.required_paths);
}
-
+
/* Clean up after our tests */
history.clear();
}
@@ -1040,25 +1040,25 @@ void history_tests_t::test_history_merge(void) {
const wcstring name = L"merge_test";
history_t *hists[count] = {new history_t(name), new history_t(name), new history_t(name)};
wcstring texts[count] = {L"History 1", L"History 2", L"History 3"};
-
+
/* Make sure history is clear */
for (size_t i=0; i < count; i++) {
hists[i]->clear();
}
-
+
/* Make sure we don't add an item in the same second as we created the history */
time_barrier();
-
+
/* Add a different item to each */
for (size_t i=0; i < count; i++) {
hists[i]->add(texts[i]);
}
-
+
/* Save them */
for (size_t i=0; i < count; i++) {
hists[i]->save();
}
-
+
/* Make sure each history contains what it ought to, but they have not leaked into each other */
for (size_t i = 0; i < count; i++) {
for (size_t j=0; j < count; j++) {
@@ -1067,7 +1067,7 @@ void history_tests_t::test_history_merge(void) {
assert(should_contain == does_contain);
}
}
-
+
/* Make a new history. It should contain everything. The time_barrier() is so that the timestamp is newer, since we only pick up items whose timestamp is before the birth stamp. */
time_barrier();
history_t *everything = new history_t(name);
@@ -1085,7 +1085,7 @@ void history_tests_t::test_history_merge(void) {
static bool install_sample_history(const wchar_t *name) {
char command[512];
- snprintf(command, sizeof command, "cp tests/%ls ~/.config/fish/%ls_history", name, name);
+ snprintf(command, sizeof command, "cp tests/%ls ~/.config/fish/%ls_history", name, name);
if (system(command)) {
err(L"Failed to copy sample history");
return false;
@@ -1100,7 +1100,7 @@ static bool history_equals(history_t &hist, const wchar_t * const *strings) {
while (strings[expected_count]) {
expected_count++;
}
-
+
/* Ensure the contents are the same */
size_t history_idx = 1;
size_t array_idx = 0;
@@ -1120,13 +1120,13 @@ static bool history_equals(history_t &hist, const wchar_t * const *strings) {
history_idx++;
array_idx++;
}
-
+
return true;
}
void history_tests_t::test_history_formats(void) {
const wchar_t *name;
-
+
// Test inferring and reading legacy and bash history formats
name = L"history_sample_fish_1_x";
say(L"Testing %ls", name);
@@ -1138,25 +1138,25 @@ void history_tests_t::test_history_formats(void) {
L"#def",
L"echo #abc",
-
+
L"function yay\n"
"echo hi\n"
"end",
-
+
L"cd foobar",
-
+
L"ls /",
-
+
NULL
};
-
+
history_t &test_history = history_t::history_with_name(name);
if (! history_equals(test_history, expected)) {
err(L"test_history_formats failed for %ls\n", name);
}
test_history.clear();
}
-
+
name = L"history_sample_fish_2_0";
say(L"Testing %ls", name);
if (! install_sample_history(name)) {
@@ -1164,23 +1164,23 @@ void history_tests_t::test_history_formats(void) {
} else {
const wchar_t * const expected[] = {
L"echo this has\\\nbackslashes",
-
+
L"function foo\n"
"echo bar\n"
"end",
-
+
L"echo alpha",
-
+
NULL
};
-
+
history_t &test_history = history_t::history_with_name(name);
if (! history_equals(test_history, expected)) {
err(L"test_history_formats failed for %ls\n", name);
}
test_history.clear();
}
-
+
say(L"Testing bash import");
FILE *f = fopen("tests/history_sample_bash", "r");
if (! f) {
@@ -1189,11 +1189,11 @@ void history_tests_t::test_history_formats(void) {
// It should skip over the export command since that's a bash-ism
const wchar_t *expected[] = {
L"echo supsup",
-
+
L"history --help",
-
+
L"echo foo",
-
+
NULL
};
history_t &test_history = history_t::history_with_name(L"bash_import");
@@ -1208,57 +1208,57 @@ void history_tests_t::test_history_formats(void) {
/**
- Main test
+ Main test
*/
int main( int argc, char **argv )
{
- setlocale( LC_ALL, "" );
- srand( time( 0 ) );
+ setlocale( LC_ALL, "" );
+ srand( time( 0 ) );
configure_thread_assertions_for_testing();
- program_name=L"(ignore)";
-
- say( L"Testing low-level functionality");
- say( L"Lines beginning with '(ignore):' are not errors, they are warning messages\ngenerated by the fish parser library when given broken input, and can be\nignored. All actual errors begin with 'Error:'." );
- set_main_thread();
+ program_name=L"(ignore)";
+
+ say( L"Testing low-level functionality");
+ say( L"Lines beginning with '(ignore):' are not errors, they are warning messages\ngenerated by the fish parser library when given broken input, and can be\nignored. All actual errors begin with 'Error:'." );
+ set_main_thread();
setup_fork_guards();
- proc_init();
- event_init();
- function_init();
- builtin_init();
- reader_init();
- env_init();
-
+ proc_init();
+ event_init();
+ function_init();
+ builtin_init();
+ reader_init();
+ env_init();
+
test_format();
- test_escape();
- test_convert();
- test_tok();
+ test_escape();
+ test_convert();
+ test_tok();
test_fork();
- test_parser();
- test_lru();
- test_expand();
+ test_parser();
+ test_lru();
+ test_expand();
test_test();
- test_path();
+ test_path();
test_is_potential_path();
test_colors();
test_autosuggest_suggest_special();
history_tests_t::test_history();
history_tests_t::test_history_merge();
history_tests_t::test_history_formats();
-
- say( L"Encountered %d errors in low-level tests", err_count );
-
- /*
- Skip performance tests for now, since they seem to hang when running from inside make (?)
- */
-// say( L"Testing performance" );
-// perf_complete();
-
- env_destroy();
- reader_destroy();
- builtin_destroy();
- wutil_destroy();
- event_destroy();
- proc_destroy();
-
+
+ say( L"Encountered %d errors in low-level tests", err_count );
+
+ /*
+ Skip performance tests for now, since they seem to hang when running from inside make (?)
+ */
+// say( L"Testing performance" );
+// perf_complete();
+
+ env_destroy();
+ reader_destroy();
+ builtin_destroy();
+ wutil_destroy();
+ event_destroy();
+ proc_destroy();
+
}
diff --git a/fishd.cpp b/fishd.cpp
index 86c17373..acfecae1 100644
--- a/fishd.cpp
+++ b/fishd.cpp
@@ -85,7 +85,7 @@ time the original barrier request was sent have been received.
/**
Maximum length of socket filename
*/
-#ifndef UNIX_PATH_MAX
+#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 100
#endif
@@ -153,47 +153,47 @@ static int quit=0;
*/
static char *get_socket_filename()
{
- char *name;
- const char *dir = getenv( "FISHD_SOCKET_DIR" );
- char *uname = getenv( "USER" );
-
- if( dir == NULL )
- {
- dir = "/tmp";
- }
-
- if( uname == NULL )
- {
- struct passwd *pw;
- pw = getpwuid( getuid() );
- uname = strdup( pw->pw_name );
- }
-
- name = (char *)malloc( strlen(dir)+ strlen(uname)+ strlen(SOCK_FILENAME) + 2 );
- if( name == NULL )
- {
- wperror( L"get_socket_filename" );
- exit( EXIT_FAILURE );
- }
- strcpy( name, dir );
- strcat( name, "/" );
- strcat( name, SOCK_FILENAME );
- strcat( name, uname );
-
- if( strlen( name ) >= UNIX_PATH_MAX )
- {
- debug( 1, L"Filename too long: '%s'", name );
- exit( EXIT_FAILURE );
- }
- return name;
+ char *name;
+ const char *dir = getenv( "FISHD_SOCKET_DIR" );
+ char *uname = getenv( "USER" );
+
+ if( dir == NULL )
+ {
+ dir = "/tmp";
+ }
+
+ if( uname == NULL )
+ {
+ struct passwd *pw;
+ pw = getpwuid( getuid() );
+ uname = strdup( pw->pw_name );
+ }
+
+ name = (char *)malloc( strlen(dir)+ strlen(uname)+ strlen(SOCK_FILENAME) + 2 );
+ if( name == NULL )
+ {
+ wperror( L"get_socket_filename" );
+ exit( EXIT_FAILURE );
+ }
+ strcpy( name, dir );
+ strcat( name, "/" );
+ strcat( name, SOCK_FILENAME );
+ strcat( name, uname );
+
+ if( strlen( name ) >= UNIX_PATH_MAX )
+ {
+ debug( 1, L"Filename too long: '%s'", name );
+ exit( EXIT_FAILURE );
+ }
+ return name;
}
/**
- Signal handler for the term signal.
+ Signal handler for the term signal.
*/
static void handle_term( int signal )
{
- quit=1;
+ quit=1;
}
@@ -214,24 +214,24 @@ static void handle_term( int signal )
*/
static void sprint_rand_digits( char *str, int maxlen )
{
- int i, max;
- struct timeval tv;
-
- /*
+ int i, max;
+ struct timeval tv;
+
+ /*
Seed the pseudo-random generator based on time - this assumes
that consecutive calls to gettimeofday will return different values
and ignores errors returned by gettimeofday.
Cast to unsigned so that wrapping occurs on overflow as per ANSI C.
*/
- (void)gettimeofday( &tv, NULL );
+ (void)gettimeofday( &tv, NULL );
unsigned long long seed = tv.tv_sec + tv.tv_usec * 1000000ULL;
- srand( (unsigned int)seed );
- max = (int)(1 + (maxlen - 1) * (rand() / (RAND_MAX + 1.0)));
- for( i = 0; i < max; i++ )
- {
- str[i] = '0' + 10 * (rand() / (RAND_MAX + 1.0));
- }
- str[i] = 0;
+ srand( (unsigned int)seed );
+ max = (int)(1 + (maxlen - 1) * (rand() / (RAND_MAX + 1.0)));
+ for( i = 0; i < max; i++ )
+ {
+ str[i] = '0' + 10 * (rand() / (RAND_MAX + 1.0));
+ }
+ str[i] = 0;
}
@@ -239,174 +239,174 @@ static void sprint_rand_digits( char *str, int maxlen )
Generate a filename unique in an NFS namespace by creating a copy of str and
appending .{hostname}.{pid} to it. If gethostname() fails then a pseudo-
random string is substituted for {hostname} - the randomness of the string
- should be strong enough across different machines. The main assumption
+ should be strong enough across different machines. The main assumption
though is that gethostname will not fail and this is just a "safe enough"
fallback.
The memory returned should be freed using free().
*/
static std::string gen_unique_nfs_filename( const char *filename )
{
- char hostname[HOST_NAME_MAX + 1];
+ char hostname[HOST_NAME_MAX + 1];
char pid_str[256];
snprintf(pid_str, sizeof pid_str, "%ld", (long)getpid());
-
- if ( gethostname( hostname, sizeof hostname ) != 0 )
+
+ if ( gethostname( hostname, sizeof hostname ) != 0 )
{
- sprint_rand_digits( hostname, HOST_NAME_MAX );
- }
-
+ sprint_rand_digits( hostname, HOST_NAME_MAX );
+ }
+
std::string newname(filename);
- newname.push_back('.');
+ newname.push_back('.');
newname.append(hostname);
newname.push_back('.');
- newname.append(pid_str);
- return newname;
+ newname.append(pid_str);
+ return newname;
}
/**
- The number of milliseconds to wait between polls when attempting to acquire
+ The number of milliseconds to wait between polls when attempting to acquire
a lockfile
*/
#define LOCKPOLLINTERVAL 10
/**
- Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
- milliseconds between polls and timing out after timeout seconds,
+ Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
+ milliseconds between polls and timing out after timeout seconds,
thereafter forcibly attempting to obtain the lock if force is non-zero.
Returns 1 on success, 0 on failure.
To release the lock the lockfile must be unlinked.
- A unique temporary file named by appending characters to the lockfile name
+ A unique temporary file named by appending characters to the lockfile name
is used; any pre-existing file of the same name is subject to deletion.
*/
static int acquire_lock_file( const char *lockfile, const int timeout, int force )
{
- int fd, timed_out = 0;
- int ret = 0; /* early exit returns failure */
- struct timespec pollint;
- struct timeval start, end;
- double elapsed;
- struct stat statbuf;
-
- /*
+ int fd, timed_out = 0;
+ int ret = 0; /* early exit returns failure */
+ struct timespec pollint;
+ struct timeval start, end;
+ double elapsed;
+ struct stat statbuf;
+
+ /*
(Re)create a unique file and check that it has one only link.
*/
- const std::string linkfile_str = gen_unique_nfs_filename( lockfile );
+ const std::string linkfile_str = gen_unique_nfs_filename( lockfile );
const char * const linkfile = linkfile_str.c_str();
- (void)unlink( linkfile );
+ (void)unlink( linkfile );
/* OK to not use CLO_EXEC here because fishd is single threaded */
- if( ( fd = open( linkfile, O_CREAT|O_RDONLY, 0600 ) ) == -1 )
- {
- debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) );
- goto done;
- }
- /*
+ if( ( fd = open( linkfile, O_CREAT|O_RDONLY, 0600 ) ) == -1 )
+ {
+ debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) );
+ goto done;
+ }
+ /*
Don't need to check exit status of close on read-only file descriptors
*/
- close( fd );
- if( stat( linkfile, &statbuf ) != 0 )
- {
- debug( 1, L"acquire_lock_file: stat: %s", strerror( errno ) );
- goto done;
- }
- if ( statbuf.st_nlink != 1 )
- {
- debug( 1, L"acquire_lock_file: number of hardlinks on unique "
+ close( fd );
+ if( stat( linkfile, &statbuf ) != 0 )
+ {
+ debug( 1, L"acquire_lock_file: stat: %s", strerror( errno ) );
+ goto done;
+ }
+ if ( statbuf.st_nlink != 1 )
+ {
+ debug( 1, L"acquire_lock_file: number of hardlinks on unique "
L"tmpfile is %d instead of 1.", (int)statbuf.st_nlink );
- goto done;
- }
- if( gettimeofday( &start, NULL ) != 0 )
- {
- debug( 1, L"acquire_lock_file: gettimeofday: %s", strerror( errno ) );
- goto done;
- }
- end = start;
- pollint.tv_sec = 0;
- pollint.tv_nsec = LOCKPOLLINTERVAL * 1000000;
- do
- {
- /*
- Try to create a hard link to the unique file from the
- lockfile. This will only succeed if the lockfile does not
- already exist. It is guaranteed to provide race-free
- semantics over NFS which the alternative of calling
- open(O_EXCL|O_CREAT) on the lockfile is not. The lock
- succeeds if the call to link returns 0 or the link count on
+ goto done;
+ }
+ if( gettimeofday( &start, NULL ) != 0 )
+ {
+ debug( 1, L"acquire_lock_file: gettimeofday: %s", strerror( errno ) );
+ goto done;
+ }
+ end = start;
+ pollint.tv_sec = 0;
+ pollint.tv_nsec = LOCKPOLLINTERVAL * 1000000;
+ do
+ {
+ /*
+ Try to create a hard link to the unique file from the
+ lockfile. This will only succeed if the lockfile does not
+ already exist. It is guaranteed to provide race-free
+ semantics over NFS which the alternative of calling
+ open(O_EXCL|O_CREAT) on the lockfile is not. The lock
+ succeeds if the call to link returns 0 or the link count on
the unique file increases to 2.
*/
- if( link( linkfile, lockfile ) == 0 ||
- ( stat( linkfile, &statbuf ) == 0 &&
+ if( link( linkfile, lockfile ) == 0 ||
+ ( stat( linkfile, &statbuf ) == 0 &&
statbuf.st_nlink == 2 ) )
- {
- /* Successful lock */
- ret = 1;
- break;
- }
- elapsed = end.tv_sec + end.tv_usec/1000000.0 -
+ {
+ /* Successful lock */
+ ret = 1;
+ break;
+ }
+ elapsed = end.tv_sec + end.tv_usec/1000000.0 -
( start.tv_sec + start.tv_usec/1000000.0 );
- /*
- The check for elapsed < 0 is to deal with the unlikely event
+ /*
+ The check for elapsed < 0 is to deal with the unlikely event
that after the loop is entered the system time is set forward
- past the loop's end time. This would otherwise result in a
+ past the loop's end time. This would otherwise result in a
(practically) infinite loop.
*/
- if( timed_out || elapsed >= timeout || elapsed < 0 )
- {
- if ( timed_out == 0 && force )
- {
- /*
+ if( timed_out || elapsed >= timeout || elapsed < 0 )
+ {
+ if ( timed_out == 0 && force )
+ {
+ /*
Timed out and force was specified - attempt to
remove stale lock and try a final time
*/
- (void)unlink( lockfile );
- timed_out = 1;
- continue;
- }
- else
- {
- /*
- Timed out and final try was unsuccessful or
+ (void)unlink( lockfile );
+ timed_out = 1;
+ continue;
+ }
+ else
+ {
+ /*
+ Timed out and final try was unsuccessful or
force was not specified
*/
- debug( 1, L"acquire_lock_file: timed out "
+ debug( 1, L"acquire_lock_file: timed out "
L"trying to obtain lockfile %s using "
L"linkfile %s", lockfile, linkfile );
- break;
- }
- }
- nanosleep( &pollint, NULL );
- } while( gettimeofday( &end, NULL ) == 0 );
+ break;
+ }
+ }
+ nanosleep( &pollint, NULL );
+ } while( gettimeofday( &end, NULL ) == 0 );
done:
- /* The linkfile is not needed once the lockfile has been created */
- (void)unlink( linkfile );
- return ret;
+ /* The linkfile is not needed once the lockfile has been created */
+ (void)unlink( linkfile );
+ return ret;
}
/**
Acquire the lock for the socket
- Returns the name of the lock file if successful or
+ Returns the name of the lock file if successful or
NULL if unable to obtain lock.
- The returned string must be free()d after unlink()ing the file to release
+ The returned string must be free()d after unlink()ing the file to release
the lock
*/
static char *acquire_socket_lock( const char *sock_name )
{
- size_t len = strlen( sock_name );
- char *lockfile = (char *)malloc( len + strlen( LOCKPOSTFIX ) + 1 );
-
- if( lockfile == NULL )
- {
- wperror( L"acquire_socket_lock" );
- exit( EXIT_FAILURE );
- }
- strcpy( lockfile, sock_name );
- strcpy( lockfile + len, LOCKPOSTFIX );
- if ( !acquire_lock_file( lockfile, LOCKTIMEOUT, 1 ) )
- {
- free( lockfile );
- lockfile = NULL;
- }
- return lockfile;
+ size_t len = strlen( sock_name );
+ char *lockfile = (char *)malloc( len + strlen( LOCKPOSTFIX ) + 1 );
+
+ if( lockfile == NULL )
+ {
+ wperror( L"acquire_socket_lock" );
+ exit( EXIT_FAILURE );
+ }
+ strcpy( lockfile, sock_name );
+ strcpy( lockfile + len, LOCKPOSTFIX );
+ if ( !acquire_lock_file( lockfile, LOCKTIMEOUT, 1 ) )
+ {
+ free( lockfile );
+ lockfile = NULL;
+ }
+ return lockfile;
}
/**
@@ -414,83 +414,83 @@ static char *acquire_socket_lock( const char *sock_name )
*/
static int get_socket()
{
- int s, len, doexit = 0;
- int exitcode = EXIT_FAILURE;
- struct sockaddr_un local;
- char *sock_name = get_socket_filename();
-
- /*
- Start critical section protected by lock
- */
- char *lockfile = acquire_socket_lock( sock_name );
- if( lockfile == NULL )
- {
- debug( 0, L"Unable to obtain lock on socket, exiting" );
- exit( EXIT_FAILURE );
- }
- debug( 4, L"Acquired lockfile: %s", lockfile );
-
- local.sun_family = AF_UNIX;
- strcpy( local.sun_path, sock_name );
- len = sizeof(local);
-
- debug(1, L"Connect to socket at %s", sock_name);
-
- if( ( s = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 )
- {
- wperror( L"socket" );
- doexit = 1;
- goto unlock;
- }
-
- /*
- First check whether the socket has been opened by another fishd;
- if so, exit with success status
- */
- if( connect( s, (struct sockaddr *)&local, len ) == 0 )
- {
- debug( 1, L"Socket already exists, exiting" );
- doexit = 1;
- exitcode = 0;
- goto unlock;
- }
-
- unlink( local.sun_path );
- if( bind( s, (struct sockaddr *)&local, len ) == -1 )
- {
- wperror( L"bind" );
- doexit = 1;
- goto unlock;
- }
-
- if( fcntl( s, F_SETFL, O_NONBLOCK ) != 0 )
- {
- wperror( L"fcntl" );
- close( s );
- doexit = 1;
- } else if( listen( s, 64 ) == -1 )
- {
- wperror( L"listen" );
- doexit = 1;
- }
+ int s, len, doexit = 0;
+ int exitcode = EXIT_FAILURE;
+ struct sockaddr_un local;
+ char *sock_name = get_socket_filename();
+
+ /*
+ Start critical section protected by lock
+ */
+ char *lockfile = acquire_socket_lock( sock_name );
+ if( lockfile == NULL )
+ {
+ debug( 0, L"Unable to obtain lock on socket, exiting" );
+ exit( EXIT_FAILURE );
+ }
+ debug( 4, L"Acquired lockfile: %s", lockfile );
+
+ local.sun_family = AF_UNIX;
+ strcpy( local.sun_path, sock_name );
+ len = sizeof(local);
+
+ debug(1, L"Connect to socket at %s", sock_name);
+
+ if( ( s = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 )
+ {
+ wperror( L"socket" );
+ doexit = 1;
+ goto unlock;
+ }
+
+ /*
+ First check whether the socket has been opened by another fishd;
+ if so, exit with success status
+ */
+ if( connect( s, (struct sockaddr *)&local, len ) == 0 )
+ {
+ debug( 1, L"Socket already exists, exiting" );
+ doexit = 1;
+ exitcode = 0;
+ goto unlock;
+ }
+
+ unlink( local.sun_path );
+ if( bind( s, (struct sockaddr *)&local, len ) == -1 )
+ {
+ wperror( L"bind" );
+ doexit = 1;
+ goto unlock;
+ }
+
+ if( fcntl( s, F_SETFL, O_NONBLOCK ) != 0 )
+ {
+ wperror( L"fcntl" );
+ close( s );
+ doexit = 1;
+ } else if( listen( s, 64 ) == -1 )
+ {
+ wperror( L"listen" );
+ doexit = 1;
+ }
unlock:
- (void)unlink( lockfile );
- debug( 4, L"Released lockfile: %s", lockfile );
- /*
- End critical section protected by lock
- */
-
- free( lockfile );
-
- free( sock_name );
-
- if( doexit )
- {
- exit( exitcode );
- }
-
- return s;
+ (void)unlink( lockfile );
+ debug( 4, L"Released lockfile: %s", lockfile );
+ /*
+ End critical section protected by lock
+ */
+
+ free( lockfile );
+
+ free( sock_name );
+
+ if( doexit )
+ {
+ exit( exitcode );
+ }
+
+ return s;
}
/**
@@ -498,29 +498,29 @@ unlock:
*/
static void broadcast( fish_message_type_t type, const wchar_t *key, const wchar_t *val )
{
- connection_t *c;
- message_t *msg;
-
- if( !conn )
- return;
-
- msg = create_message( type, key, val );
-
- /*
- Don't merge these loops, or try_send_all can free the message
- prematurely
- */
-
- for( c = conn; c; c=c->next )
- {
- msg->count++;
+ connection_t *c;
+ message_t *msg;
+
+ if( !conn )
+ return;
+
+ msg = create_message( type, key, val );
+
+ /*
+ Don't merge these loops, or try_send_all can free the message
+ prematurely
+ */
+
+ for( c = conn; c; c=c->next )
+ {
+ msg->count++;
c->unsent->push(msg);
- }
-
- for( c = conn; c; c=c->next )
- {
- try_send_all( c );
- }
+ }
+
+ for( c = conn; c; c=c->next )
+ {
+ try_send_all( c );
+ }
}
/**
@@ -528,58 +528,58 @@ static void broadcast( fish_message_type_t type, const wchar_t *key, const wchar
*/
static void daemonize()
{
- /*
- Fork, and let parent exit
- */
- switch( fork() )
- {
- case -1:
- debug( 0, L"Could not put fishd in background. Quitting" );
- wperror( L"fork" );
- exit(1);
-
- case 0:
- {
- /* Ordinarily there's very limited things we will do after fork, due to multithreading. But fishd is safe because it's single threaded. So don't die in is_forked_child. */
- setup_fork_guards();
-
- /*
- Make fishd ignore the HUP signal.
- */
- struct sigaction act;
- sigemptyset( & act.sa_mask );
- act.sa_flags=0;
- act.sa_handler=SIG_IGN;
- sigaction( SIGHUP, &act, 0);
-
- /*
- Make fishd save and exit on the TERM signal.
- */
- sigfillset( & act.sa_mask );
- act.sa_flags=0;
- act.sa_handler=&handle_term;
- sigaction( SIGTERM, &act, 0);
- break;
-
- }
-
- default:
- {
- debug( 0, L"Parent process exiting (This is normal)" );
- exit(0);
- }
- }
-
- /*
- Put ourself in out own processing group
- */
- setsid();
-
- /*
- Close stdin and stdout. We only use stderr, anyway.
- */
- close( 0 );
- close( 1 );
+ /*
+ Fork, and let parent exit
+ */
+ switch( fork() )
+ {
+ case -1:
+ debug( 0, L"Could not put fishd in background. Quitting" );
+ wperror( L"fork" );
+ exit(1);
+
+ case 0:
+ {
+ /* Ordinarily there's very limited things we will do after fork, due to multithreading. But fishd is safe because it's single threaded. So don't die in is_forked_child. */
+ setup_fork_guards();
+
+ /*
+ Make fishd ignore the HUP signal.
+ */
+ struct sigaction act;
+ sigemptyset( & act.sa_mask );
+ act.sa_flags=0;
+ act.sa_handler=SIG_IGN;
+ sigaction( SIGHUP, &act, 0);
+
+ /*
+ Make fishd save and exit on the TERM signal.
+ */
+ sigfillset( & act.sa_mask );
+ act.sa_flags=0;
+ act.sa_handler=&handle_term;
+ sigaction( SIGTERM, &act, 0);
+ break;
+
+ }
+
+ default:
+ {
+ debug( 0, L"Parent process exiting (This is normal)" );
+ exit(0);
+ }
+ }
+
+ /*
+ Put ourself in out own processing group
+ */
+ setsid();
+
+ /*
+ Close stdin and stdout. We only use stderr, anyway.
+ */
+ close( 0 );
+ close( 1 );
}
@@ -588,23 +588,23 @@ static void daemonize()
*/
static wchar_t *fishd_env_get( const wchar_t *key )
{
- char *nres, *nkey;
- wchar_t *res;
-
- nkey = wcs2str( key );
- nres = getenv( nkey );
- free( nkey );
- if( nres )
- {
- return str2wcs( nres );
- }
- else
- {
- res = env_universal_common_get( key );
- if( res )
- res = wcsdup( res );
- return res;
- }
+ char *nres, *nkey;
+ wchar_t *res;
+
+ nkey = wcs2str( key );
+ nres = getenv( nkey );
+ free( nkey );
+ if( nres )
+ {
+ return str2wcs( nres );
+ }
+ else
+ {
+ res = env_universal_common_get( key );
+ if( res )
+ res = wcsdup( res );
+ return res;
+ }
}
/**
@@ -615,42 +615,42 @@ static wchar_t *fishd_env_get( const wchar_t *key )
*/
static wcstring fishd_get_config()
{
- wchar_t *xdg_dir, *home;
- bool done = false;
- wcstring result;
-
- xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
- if (xdg_dir)
- {
+ wchar_t *xdg_dir, *home;
+ bool done = false;
+ wcstring result;
+
+ xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
+ if (xdg_dir)
+ {
result = xdg_dir;
append_path_component(result, L"/fish");
- if (!create_directory(result))
- {
- done = true;
- }
- free(xdg_dir);
- }
- else
- {
- home = fishd_env_get( L"HOME" );
- if( home )
- {
+ if (!create_directory(result))
+ {
+ done = true;
+ }
+ free(xdg_dir);
+ }
+ else
+ {
+ home = fishd_env_get( L"HOME" );
+ if( home )
+ {
result = home;
append_path_component(result, L"/.config/fish");
- if (!create_directory(result))
- {
- done = 1;
- }
- free( home );
- }
- }
-
+ if (!create_directory(result))
+ {
+ done = 1;
+ }
+ free( home );
+ }
+ }
+
if (! done) {
/* Bad juju */
- debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
- result.clear();
+ debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
+ result.clear();
}
-
+
return result;
}
@@ -659,51 +659,51 @@ static wcstring fishd_get_config()
*/
static void load_or_save( int save)
{
- const wcstring wdir = fishd_get_config();
- char hostname[HOSTNAME_LEN];
- connection_t c;
- int fd;
-
- if (wdir.empty())
- return;
-
- std::string dir = wcs2string( wdir );
-
- gethostname( hostname, HOSTNAME_LEN );
-
+ const wcstring wdir = fishd_get_config();
+ char hostname[HOSTNAME_LEN];
+ connection_t c;
+ int fd;
+
+ if (wdir.empty())
+ return;
+
+ std::string dir = wcs2string( wdir );
+
+ gethostname( hostname, HOSTNAME_LEN );
+
std::string name;
name.append(dir);
name.append("/");
name.append(FILE);
name.append(hostname);
-
- debug( 4, L"Open file for %s: '%s'",
- save?"saving":"loading",
- name.c_str() );
-
+
+ debug( 4, L"Open file for %s: '%s'",
+ save?"saving":"loading",
+ name.c_str() );
+
/* OK to not use CLO_EXEC here because fishd is single threaded */
- fd = open(name.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
-
- if( fd == -1 )
- {
- debug( 1, L"Could not open load/save file. No previous saves?" );
- wperror( L"open" );
- return;
- }
- debug( 4, L"File open on fd %d", c.fd );
-
- connection_init( &c, fd );
-
- if( save )
- {
-
- write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
- enqueue_all( &c );
- }
- else
- read_message( &c );
-
- connection_destroy( &c );
+ fd = open(name.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
+
+ if( fd == -1 )
+ {
+ debug( 1, L"Could not open load/save file. No previous saves?" );
+ wperror( L"open" );
+ return;
+ }
+ debug( 4, L"File open on fd %d", c.fd );
+
+ connection_init( &c, fd );
+
+ if( save )
+ {
+
+ write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
+ enqueue_all( &c );
+ }
+ else
+ read_message( &c );
+
+ connection_destroy( &c );
}
/**
@@ -711,7 +711,7 @@ static void load_or_save( int save)
*/
static void load()
{
- load_or_save(0);
+ load_or_save(0);
}
/**
@@ -719,7 +719,7 @@ static void load()
*/
static void save()
{
- load_or_save(1);
+ load_or_save(1);
}
/**
@@ -728,11 +728,11 @@ static void save()
static void init()
{
- sock = get_socket();
- daemonize();
- env_universal_common_init( &broadcast );
-
- load();
+ sock = get_socket();
+ daemonize();
+ env_universal_common_init( &broadcast );
+
+ load();
}
/**
@@ -740,220 +740,220 @@ static void init()
*/
int main( int argc, char ** argv )
{
- int child_socket;
- struct sockaddr_un remote;
- socklen_t t;
- int max_fd;
- int update_count=0;
-
- fd_set read_fd, write_fd;
-
- set_main_thread();
+ int child_socket;
+ struct sockaddr_un remote;
+ socklen_t t;
+ int max_fd;
+ int update_count=0;
+
+ fd_set read_fd, write_fd;
+
+ set_main_thread();
setup_fork_guards();
-
- program_name=L"fishd";
- wsetlocale( LC_ALL, L"" );
-
- /*
- Parse options
- */
- while( 1 )
- {
- static struct option
- long_options[] =
- {
- {
- "help", no_argument, 0, 'h'
- }
- ,
- {
- "version", no_argument, 0, 'v'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = getopt_long( argc,
- argv,
- GETOPT_STRING,
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- break;
-
- case 'h':
- print_help( argv[0], 1 );
- exit(0);
-
- case 'v':
- debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
- exit( 0 );
-
- case '?':
- return 1;
-
- }
- }
-
- init();
- while(1)
- {
- connection_t *c;
- int res;
-
- t = sizeof( remote );
-
- FD_ZERO( &read_fd );
- FD_ZERO( &write_fd );
- FD_SET( sock, &read_fd );
- max_fd = sock+1;
- for( c=conn; c; c=c->next )
- {
- FD_SET( c->fd, &read_fd );
- max_fd = maxi( max_fd, c->fd+1);
-
- if( ! c->unsent->empty() )
- {
- FD_SET( c->fd, &write_fd );
- }
- }
-
- while( 1 )
- {
- res=select( max_fd, &read_fd, &write_fd, 0, 0 );
-
- if( quit )
- {
- save();
- exit(0);
- }
-
- if( res != -1 )
- break;
-
- if( errno != EINTR )
- {
- wperror( L"select" );
- exit(1);
- }
- }
-
- if( FD_ISSET( sock, &read_fd ) )
- {
- if( (child_socket =
- accept( sock,
- (struct sockaddr *)&remote,
- &t) ) == -1) {
- wperror( L"accept" );
- exit(1);
- }
- else
- {
- debug( 4, L"Connected with new child on fd %d", child_socket );
-
- if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
- {
- wperror( L"fcntl" );
- close( child_socket );
- }
- else
- {
- connection_t *newc = (connection_t *)malloc( sizeof(connection_t));
- connection_init( newc, child_socket );
- newc->next = conn;
- send( newc->fd, GREETING, strlen(GREETING), MSG_DONTWAIT );
- enqueue_all( newc );
- conn=newc;
- }
- }
- }
-
- for( c=conn; c; c=c->next )
- {
- if( FD_ISSET( c->fd, &write_fd ) )
- {
- try_send_all( c );
- }
- }
-
- for( c=conn; c; c=c->next )
- {
- if( FD_ISSET( c->fd, &read_fd ) )
- {
- read_message( c );
-
- /*
- Occasionally we save during normal use, so that we
- won't lose everything on a system crash
- */
- update_count++;
- if( update_count >= 64 )
- {
- save();
- update_count = 0;
- }
- }
- }
-
- connection_t *prev=0;
- c=conn;
-
- while( c )
- {
- if( c->killme )
- {
- debug( 4, L"Close connection %d", c->fd );
-
- while( ! c->unsent->empty() )
- {
- message_t *msg = c->unsent->front();
+
+ program_name=L"fishd";
+ wsetlocale( LC_ALL, L"" );
+
+ /*
+ Parse options
+ */
+ while( 1 )
+ {
+ static struct option
+ long_options[] =
+ {
+ {
+ "help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ "version", no_argument, 0, 'v'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = getopt_long( argc,
+ argv,
+ GETOPT_STRING,
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ break;
+
+ case 'h':
+ print_help( argv[0], 1 );
+ exit(0);
+
+ case 'v':
+ debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
+ exit( 0 );
+
+ case '?':
+ return 1;
+
+ }
+ }
+
+ init();
+ while(1)
+ {
+ connection_t *c;
+ int res;
+
+ t = sizeof( remote );
+
+ FD_ZERO( &read_fd );
+ FD_ZERO( &write_fd );
+ FD_SET( sock, &read_fd );
+ max_fd = sock+1;
+ for( c=conn; c; c=c->next )
+ {
+ FD_SET( c->fd, &read_fd );
+ max_fd = maxi( max_fd, c->fd+1);
+
+ if( ! c->unsent->empty() )
+ {
+ FD_SET( c->fd, &write_fd );
+ }
+ }
+
+ while( 1 )
+ {
+ res=select( max_fd, &read_fd, &write_fd, 0, 0 );
+
+ if( quit )
+ {
+ save();
+ exit(0);
+ }
+
+ if( res != -1 )
+ break;
+
+ if( errno != EINTR )
+ {
+ wperror( L"select" );
+ exit(1);
+ }
+ }
+
+ if( FD_ISSET( sock, &read_fd ) )
+ {
+ if( (child_socket =
+ accept( sock,
+ (struct sockaddr *)&remote,
+ &t) ) == -1) {
+ wperror( L"accept" );
+ exit(1);
+ }
+ else
+ {
+ debug( 4, L"Connected with new child on fd %d", child_socket );
+
+ if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
+ {
+ wperror( L"fcntl" );
+ close( child_socket );
+ }
+ else
+ {
+ connection_t *newc = (connection_t *)malloc( sizeof(connection_t));
+ connection_init( newc, child_socket );
+ newc->next = conn;
+ send( newc->fd, GREETING, strlen(GREETING), MSG_DONTWAIT );
+ enqueue_all( newc );
+ conn=newc;
+ }
+ }
+ }
+
+ for( c=conn; c; c=c->next )
+ {
+ if( FD_ISSET( c->fd, &write_fd ) )
+ {
+ try_send_all( c );
+ }
+ }
+
+ for( c=conn; c; c=c->next )
+ {
+ if( FD_ISSET( c->fd, &read_fd ) )
+ {
+ read_message( c );
+
+ /*
+ Occasionally we save during normal use, so that we
+ won't lose everything on a system crash
+ */
+ update_count++;
+ if( update_count >= 64 )
+ {
+ save();
+ update_count = 0;
+ }
+ }
+ }
+
+ connection_t *prev=0;
+ c=conn;
+
+ while( c )
+ {
+ if( c->killme )
+ {
+ debug( 4, L"Close connection %d", c->fd );
+
+ while( ! c->unsent->empty() )
+ {
+ message_t *msg = c->unsent->front();
c->unsent->pop();
- msg->count--;
- if( !msg->count )
- free( msg );
- }
-
- connection_destroy( c );
- if( prev )
- {
- prev->next=c->next;
- }
- else
- {
- conn=c->next;
- }
-
- free(c);
-
- c=(prev?prev->next:conn);
-
- }
- else
- {
- prev=c;
- c=c->next;
- }
- }
-
- if( !conn )
- {
- debug( 0, L"No more clients. Quitting" );
- save();
- env_universal_common_destroy();
- break;
- }
-
- }
+ msg->count--;
+ if( !msg->count )
+ free( msg );
+ }
+
+ connection_destroy( c );
+ if( prev )
+ {
+ prev->next=c->next;
+ }
+ else
+ {
+ conn=c->next;
+ }
+
+ free(c);
+
+ c=(prev?prev->next:conn);
+
+ }
+ else
+ {
+ prev=c;
+ c=c->next;
+ }
+ }
+
+ if( !conn )
+ {
+ debug( 0, L"No more clients. Quitting" );
+ save();
+ env_universal_common_destroy();
+ break;
+ }
+
+ }
}
diff --git a/function.cpp b/function.cpp
index 551959d5..b1cdcdb2 100644
--- a/function.cpp
+++ b/function.cpp
@@ -1,10 +1,10 @@
/** \file function.c
Prototypes for functions for storing and retrieving function
- information. These functions also take care of autoloading
- functions in the $fish_function_path. Actual function evaluation
- is taken care of by the parser and to some degree the builtin
- handling library.
+ information. These functions also take care of autoloading
+ functions in the $fish_function_path. Actual function evaluation
+ is taken care of by the parser and to some degree the builtin
+ handling library.
*/
#include "config.h"
@@ -89,18 +89,18 @@ static int load( const wcstring &name )
{
ASSERT_IS_MAIN_THREAD();
scoped_lock lock(functions_lock);
- bool was_autoload = is_autoload;
- int res;
+ bool was_autoload = is_autoload;
+ int res;
function_map_t::iterator iter = loaded_functions.find(name);
- if( iter != loaded_functions.end() && !iter->second.is_autoload ) {
+ if( iter != loaded_functions.end() && !iter->second.is_autoload ) {
/* We have a non-autoload version already */
- return 0;
+ return 0;
}
-
- is_autoload = true;
- res = function_autoloader.load( name, true );
- is_autoload = was_autoload;
- return res;
+
+ is_autoload = true;
+ res = function_autoloader.load( name, true );
+ is_autoload = was_autoload;
+ return res;
}
/**
@@ -109,41 +109,41 @@ static int load( const wcstring &name )
*/
static void autoload_names( std::set<wcstring> &names, int get_hidden )
{
- size_t i;
-
- const env_var_t path_var_wstr = env_get_string( L"fish_function_path" );
+ size_t i;
+
+ const env_var_t path_var_wstr = env_get_string( L"fish_function_path" );
if (path_var_wstr.missing())
return;
- const wchar_t *path_var = path_var_wstr.c_str();
-
+ const wchar_t *path_var = path_var_wstr.c_str();
+
wcstring_list_t path_list;
- tokenize_variable_array( path_var, path_list );
- for( i=0; i<path_list.size(); i++ )
- {
+ tokenize_variable_array( path_var, path_list );
+ for( i=0; i<path_list.size(); i++ )
+ {
const wcstring &ndir_str = path_list.at(i);
- const wchar_t *ndir = (wchar_t *)ndir_str.c_str();
- DIR *dir = wopendir( ndir );
- if( !dir )
- continue;
-
- wcstring name;
- while (wreaddir(dir, name))
- {
- const wchar_t *fn = name.c_str();
- const wchar_t *suffix;
- if( !get_hidden && fn[0] == L'_' )
- continue;
-
+ const wchar_t *ndir = (wchar_t *)ndir_str.c_str();
+ DIR *dir = wopendir( ndir );
+ if( !dir )
+ continue;
+
+ wcstring name;
+ while (wreaddir(dir, name))
+ {
+ const wchar_t *fn = name.c_str();
+ const wchar_t *suffix;
+ if( !get_hidden && fn[0] == L'_' )
+ continue;
+
suffix = wcsrchr( fn, L'.' );
- if( suffix && (wcscmp( suffix, L".fish" ) == 0 ) )
- {
+ if( suffix && (wcscmp( suffix, L".fish" ) == 0 ) )
+ {
wcstring name(fn, suffix - fn);
names.insert(name);
- }
- }
- closedir(dir);
- }
+ }
+ }
+ closedir(dir);
+ }
}
void function_init()
@@ -181,53 +181,53 @@ function_info_t::function_info_t(const function_info_t &data, const wchar_t *fil
void function_add( const function_data_t &data, const parser_t &parser )
{
ASSERT_IS_MAIN_THREAD();
-
- CHECK( ! data.name.empty(), );
- CHECK( data.definition, );
- scoped_lock lock(functions_lock);
-
+
+ CHECK( ! data.name.empty(), );
+ CHECK( data.definition, );
+ scoped_lock lock(functions_lock);
+
/* Remove the old function */
- function_remove( data.name );
-
-
+ function_remove( data.name );
+
+
/* Create and store a new function */
const wchar_t *filename = reader_current_filename();
int def_offset = parser.line_number_of_character_at_offset(parser.current_block->tok_pos) - 1;
const function_map_t::value_type new_pair(data.name, function_info_t(data, filename, def_offset, is_autoload));
loaded_functions.insert(new_pair);
-
+
/* Add event handlers */
- for( std::vector<event_t>::const_iterator iter = data.events.begin(); iter != data.events.end(); ++iter )
- {
- event_add_handler( &*iter );
- }
+ for( std::vector<event_t>::const_iterator iter = data.events.begin(); iter != data.events.end(); ++iter )
+ {
+ event_add_handler( &*iter );
+ }
}
int function_exists( const wcstring &cmd )
{
- if( parser_keywords_is_reserved(cmd) )
- return 0;
+ if( parser_keywords_is_reserved(cmd) )
+ return 0;
scoped_lock lock(functions_lock);
load(cmd);
- return loaded_functions.find(cmd) != loaded_functions.end();
+ return loaded_functions.find(cmd) != loaded_functions.end();
}
int function_exists_no_autoload( const wcstring &cmd, const env_vars_snapshot_t &vars )
{
- if( parser_keywords_is_reserved(cmd) )
- return 0;
+ if( parser_keywords_is_reserved(cmd) )
+ return 0;
scoped_lock lock(functions_lock);
- return loaded_functions.find(cmd) != loaded_functions.end() || function_autoloader.can_load(cmd, vars);
+ return loaded_functions.find(cmd) != loaded_functions.end() || function_autoloader.can_load(cmd, vars);
}
static bool function_remove_ignore_autoload(const wcstring &name)
{
scoped_lock lock(functions_lock);
bool erased = (loaded_functions.erase(name) > 0);
-
- if (erased) {
+
+ if (erased) {
event_t ev(EVENT_ANY);
- ev.function_name=name;
+ ev.function_name=name;
event_remove( &ev );
}
return erased;
@@ -252,7 +252,7 @@ static const function_info_t *function_get(const wcstring &name)
return &iter->second;
}
}
-
+
bool function_get_definition(const wcstring &name, wcstring *out_definition)
{
scoped_lock lock(functions_lock);
@@ -277,7 +277,7 @@ int function_get_shadows(const wcstring &name)
return func ? func->shadows : false;
}
-
+
bool function_get_desc(const wcstring &name, wcstring *out_desc)
{
/* Empty length string goes to NULL */
@@ -293,7 +293,7 @@ bool function_get_desc(const wcstring &name, wcstring *out_desc)
void function_set_desc(const wcstring &name, const wcstring &desc)
{
- load(name);
+ load(name);
scoped_lock lock(functions_lock);
function_map_t::iterator iter = loaded_functions.find(name);
if (iter != loaded_functions.end()) {
@@ -307,24 +307,24 @@ bool function_copy(const wcstring &name, const wcstring &new_name)
scoped_lock lock(functions_lock);
function_map_t::const_iterator iter = loaded_functions.find(name);
if (iter != loaded_functions.end()) {
- // This new instance of the function shouldn't be tied to the definition file of the original, so pass NULL filename, etc.
+ // This new instance of the function shouldn't be tied to the definition file of the original, so pass NULL filename, etc.
const function_map_t::value_type new_pair(new_name, function_info_t(iter->second, NULL, 0, false));
loaded_functions.insert(new_pair);
result = true;
}
- return result;
+ return result;
}
wcstring_list_t function_get_names(int get_hidden)
{
std::set<wcstring> names;
scoped_lock lock(functions_lock);
- autoload_names(names, get_hidden);
-
+ autoload_names(names, get_hidden);
+
function_map_t::const_iterator iter;
for (iter = loaded_functions.begin(); iter != loaded_functions.end(); ++iter) {
const wcstring &name = iter->first;
-
+
/* Maybe skip hidden */
if (! get_hidden) {
if (name.empty() || name.at(0) == L'_') continue;
diff --git a/function.h b/function.h
index 42747912..cfd39de2 100644
--- a/function.h
+++ b/function.h
@@ -1,10 +1,10 @@
-/** \file function.h
+/** \file function.h
Prototypes for functions for storing and retrieving function
- information. These functions also take care of autoloading
- functions in the $fish_function_path. Actual function evaluation
- is taken care of by the parser and to some degree the builtin
- handling library.
+ information. These functions also take care of autoloading
+ functions in the $fish_function_path. Actual function evaluation
+ is taken care of by the parser and to some degree the builtin
+ handling library.
*/
#ifndef FISH_FUNCTION_H
@@ -28,66 +28,66 @@ class env_vars_snapshot_t;
*/
struct function_data_t
{
- /**
- Name of function
- */
- wcstring name;
- /**
- Description of function
- */
- wcstring description;
- /**
- Function definition
- */
- wchar_t *definition;
- /**
- List of all event handlers for this function
- */
- std::vector<event_t> events;
- /**
- List of all named arguments for this function
- */
- wcstring_list_t named_arguments;
- /**
- Set to non-zero if invoking this function shadows the variables
- of the underlying function.
- */
- int shadows;
+ /**
+ Name of function
+ */
+ wcstring name;
+ /**
+ Description of function
+ */
+ wcstring description;
+ /**
+ Function definition
+ */
+ wchar_t *definition;
+ /**
+ List of all event handlers for this function
+ */
+ std::vector<event_t> events;
+ /**
+ List of all named arguments for this function
+ */
+ wcstring_list_t named_arguments;
+ /**
+ Set to non-zero if invoking this function shadows the variables
+ of the underlying function.
+ */
+ int shadows;
};
class function_info_t {
public:
/** Constructs relevant information from the function_data */
function_info_t(const function_data_t &data, const wchar_t *filename, int def_offset, bool autoload);
-
+
/** Used by function_copy */
function_info_t(const function_info_t &data, const wchar_t *filename, int def_offset, bool autoload);
/** Function definition */
const wcstring definition;
-
+
/** Function description. Only the description may be changed after the function is created. */
wcstring description;
-
- /** File where this function was defined (intern'd string) */
+
+ /** File where this function was defined (intern'd string) */
const wchar_t * const definition_file;
-
- /** Line where definition started */
- const int definition_offset;
-
- /** List of all named arguments for this function */
+
+ /** Line where definition started */
+ const int definition_offset;
+
+ /** List of all named arguments for this function */
const wcstring_list_t named_arguments;
-
- /** Flag for specifying that this function was automatically loaded */
+
+ /** Flag for specifying that this function was automatically loaded */
const bool is_autoload;
-
- /** Set to true if invoking this function shadows the variables of the underlying function. */
- const bool shadows;
+
+ /** Set to true if invoking this function shadows the variables of the underlying function. */
+ const bool shadows;
};
/**
- Initialize function data
+ Initialize function data
*/
void function_init();
@@ -128,7 +128,7 @@ int function_exists_no_autoload( const wcstring &name, const env_vars_snapshot_t
/**
Returns all function names.
-
+
\param get_hidden whether to include hidden functions, i.e. ones starting with an underscore
*/
wcstring_list_t function_get_names( int get_hidden );
@@ -139,7 +139,7 @@ wcstring_list_t function_get_names( int get_hidden );
This function does not autoload functions, it will only work on
functions that have already been defined.
-
+
This returns an intern'd string.
*/
const wchar_t *function_get_definition_file( const wcstring &name );
diff --git a/highlight.cpp b/highlight.cpp
index 7f73909b..0cc76502 100644
--- a/highlight.cpp
+++ b/highlight.cpp
@@ -1,5 +1,5 @@
/** \file highlight.c
- Functions for syntax highlighting
+ Functions for syntax highlighting
*/
#include "config.h"
@@ -45,21 +45,21 @@ static void highlight_universal_internal( const wcstring &buff, std::vector<int>
/**
The environment variables used to specify the color of different tokens.
*/
-static const wchar_t * const highlight_var[] =
+static const wchar_t * const highlight_var[] =
{
- L"fish_color_normal",
- L"fish_color_error",
- L"fish_color_command",
- L"fish_color_end",
- L"fish_color_param",
- L"fish_color_comment",
- L"fish_color_match",
- L"fish_color_search_match",
- L"fish_color_operator",
- L"fish_color_escape",
- L"fish_color_quote",
- L"fish_color_redirection",
- L"fish_color_valid_path",
+ L"fish_color_normal",
+ L"fish_color_error",
+ L"fish_color_command",
+ L"fish_color_end",
+ L"fish_color_param",
+ L"fish_color_comment",
+ L"fish_color_match",
+ L"fish_color_search_match",
+ L"fish_color_operator",
+ L"fish_color_escape",
+ L"fish_color_quote",
+ L"fish_color_redirection",
+ L"fish_color_valid_path",
L"fish_color_autosuggestion"
};
@@ -67,7 +67,7 @@ static const wchar_t * const highlight_var[] =
static wcstring apply_working_directory(const wcstring &path, const wcstring &working_directory) {
if (path.empty() || working_directory.empty())
return path;
-
+
/* We're going to make sure that if we want to prepend the wd, that the string has no leading / */
bool prepend_wd;
switch (path.at(0)) {
@@ -79,7 +79,7 @@ static wcstring apply_working_directory(const wcstring &path, const wcstring &wo
prepend_wd = true;
break;
}
-
+
if (! prepend_wd) {
/* No need to prepend the wd, so just return the path we were given */
return path;
@@ -89,12 +89,12 @@ static wcstring apply_working_directory(const wcstring &path, const wcstring &wo
if (string_prefixes_string(L"./", path_component)) {
path_component.erase(0, 2);
}
-
+
/* Removing leading /s */
while (string_prefixes_string(L"/", path_component)) {
path_component.erase(0, 1);
}
-
+
/* Construct and return a new path */
wcstring new_path = working_directory;
append_path_component(new_path, path_component);
@@ -131,18 +131,18 @@ bool fs_is_case_insensitive(const wcstring &path, int fd, case_sensitivity_cache
bool is_potential_path(const wcstring &const_path, const wcstring_list_t &directories, path_flags_t flags, wcstring *out_path)
{
ASSERT_IS_BACKGROUND_THREAD();
-
+
const bool require_dir = !! (flags & PATH_REQUIRE_DIR);
wcstring clean_path;
- int has_magic = 0;
- bool result = false;
-
+ int has_magic = 0;
+ bool result = false;
+
wcstring path(const_path);
if (flags & PATH_EXPAND_TILDE)
expand_tilde(path);
-
- // debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
-
+
+ // debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
+
for( size_t i=0; i < path.size(); i++)
{
wchar_t c = path.at(i);
@@ -159,45 +159,45 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct
case ANY_STRING_RECURSIVE:
{
has_magic = 1;
- break;
+ break;
}
-
+
case INTERNAL_SEPARATOR:
{
break;
}
-
+
default:
{
clean_path.push_back(c);
break;
}
-
+
}
-
+
}
-
+
if( ! has_magic && ! clean_path.empty() )
{
/* Don't test the same path multiple times, which can happen if the path is absolute and the CDPATH contains multiple entries */
std::set<wcstring> checked_paths;
-
+
/* Keep a cache of which paths / filesystems are case sensitive */
case_sensitivity_cache_t case_sensitivity_cache;
-
+
for (size_t wd_idx = 0; wd_idx < directories.size() && ! result; wd_idx++) {
const wcstring &wd = directories.at(wd_idx);
-
+
const wcstring abs_path = apply_working_directory(clean_path, wd);
-
+
/* Skip this if it's empty or we've already checked it */
if (abs_path.empty() || checked_paths.count(abs_path))
continue;
checked_paths.insert(abs_path);
-
+
/* If we end with a slash, then it must be a directory */
bool must_be_full_dir = abs_path.at(abs_path.size()-1) == L'/';
- if (must_be_full_dir)
+ if (must_be_full_dir)
{
struct stat buf;
if (0 == wstat(abs_path, &buf) && S_ISDIR(buf.st_mode)) {
@@ -210,7 +210,7 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct
else
{
DIR *dir = NULL;
-
+
/* We do not end with a slash; it does not have to be a directory */
const wcstring dir_name = wdirname(abs_path);
const wcstring base_name = wbasename(abs_path);
@@ -223,14 +223,14 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct
else if ((dir = wopendir(dir_name))) {
// We opened the dir_name; look for a string where the base name prefixes it
wcstring ent;
-
+
// Check if we're case insensitive
bool case_insensitive = fs_is_case_insensitive(dir_name, dirfd(dir), case_sensitivity_cache);
-
+
// Don't ask for the is_dir value unless we care, because it can cause extra filesystem acces */
bool is_dir = false;
while (wreaddir_resolving(dir, dir_name, ent, require_dir ? &is_dir : NULL))
- {
+ {
/* Determine which function to call to check for prefixes */
bool (*prefix_func)(const wcstring &, const wcstring &);
@@ -245,11 +245,11 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct
result = true;
if (out_path) {
/* We want to return the path in the same "form" as it was given. Take the given path, get its basename. Append that to the output if the basename actually prefixes the path (which it won't if the given path contains no slashes), and isn't a slash (so we don't duplicate slashes). Then append the directory entry. */
-
+
out_path->clear();
const wcstring path_base = wdirname(const_path);
-
-
+
+
if (prefix_func(path_base, const_path)) {
out_path->append(path_base);
if (! string_suffixes_string(L"/", *out_path))
@@ -276,7 +276,7 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct
static bool is_potential_cd_path(const wcstring &path, const wcstring &working_directory, path_flags_t flags, wcstring *out_path)
{
wcstring_list_t directories;
-
+
if (string_prefixes_string(L"./", path)) {
/* Ignore the CDPATH in this case; just use the working directory */
directories.push_back(working_directory);
@@ -285,7 +285,7 @@ static bool is_potential_cd_path(const wcstring &path, const wcstring &working_d
env_var_t cdpath = env_get_string(L"CDPATH");
if (cdpath.missing_or_empty())
cdpath = L".";
-
+
/* Tokenize it into directories */
wcstokenizer tokenizer(cdpath, ARRAY_SEP_STR);
wcstring next_path;
@@ -295,7 +295,7 @@ static bool is_potential_cd_path(const wcstring &path, const wcstring &working_d
directories.push_back(apply_working_directory(next_path, working_directory));
}
}
-
+
/* Call is_potential_path with all of these directories */
bool result = is_potential_path(path, directories, flags | PATH_REQUIRE_DIR, out_path);
#if 0
@@ -308,49 +308,49 @@ static bool is_potential_cd_path(const wcstring &path, const wcstring &working_d
rgb_color_t highlight_get_color( int highlight, bool is_background )
{
- size_t idx=0;
- rgb_color_t result;
-
- if( highlight < 0 )
- return rgb_color_t::normal();
- if( highlight > (1<<VAR_COUNT) )
- return rgb_color_t::normal();
- for( size_t i=0; i<VAR_COUNT; i++ )
- {
- if( highlight & (1<<i ))
- {
- idx = i;
- break;
- }
- }
-
- env_var_t val_wstr = env_get_string( highlight_var[idx]);
-
-// debug( 1, L"%d -> %d -> %ls", highlight, idx, val );
-
- if (val_wstr.missing())
- val_wstr = env_get_string( highlight_var[0]);
-
- if( ! val_wstr.missing() )
- result = parse_color( val_wstr, is_background );
-
- if( highlight & HIGHLIGHT_VALID_PATH )
- {
- env_var_t val2_wstr = env_get_string( L"fish_color_valid_path" );
- const wcstring val2 = val2_wstr.missing() ? L"" : val2_wstr.c_str();
-
- rgb_color_t result2 = parse_color( val2, is_background );
- if( result.is_normal() )
- result = result2;
- else
- {
- if( result2.is_bold() )
- result.set_bold(true);
- if( result2.is_underline() )
- result.set_underline(true);
- }
- }
- return result;
+ size_t idx=0;
+ rgb_color_t result;
+
+ if( highlight < 0 )
+ return rgb_color_t::normal();
+ if( highlight > (1<<VAR_COUNT) )
+ return rgb_color_t::normal();
+ for( size_t i=0; i<VAR_COUNT; i++ )
+ {
+ if( highlight & (1<<i ))
+ {
+ idx = i;
+ break;
+ }
+ }
+
+ env_var_t val_wstr = env_get_string( highlight_var[idx]);
+
+// debug( 1, L"%d -> %d -> %ls", highlight, idx, val );
+
+ if (val_wstr.missing())
+ val_wstr = env_get_string( highlight_var[0]);
+
+ if( ! val_wstr.missing() )
+ result = parse_color( val_wstr, is_background );
+
+ if( highlight & HIGHLIGHT_VALID_PATH )
+ {
+ env_var_t val2_wstr = env_get_string( L"fish_color_valid_path" );
+ const wcstring val2 = val2_wstr.missing() ? L"" : val2_wstr.c_str();
+
+ rgb_color_t result2 = parse_color( val2, is_background );
+ if( result.is_normal() )
+ result = result2;
+ else
+ {
+ if( result2.is_bold() )
+ result.set_bold(true);
+ if( result2.is_underline() )
+ result.set_underline(true);
+ }
+ }
+ return result;
}
@@ -360,301 +360,301 @@ rgb_color_t highlight_get_color( int highlight, bool is_background )
static void highlight_param( const wcstring &buffstr, std::vector<int> &colors, wcstring_list_t *error )
{
const wchar_t * const buff = buffstr.c_str();
- enum {e_unquoted, e_single_quoted, e_double_quoted} mode = e_unquoted;
- size_t in_pos, len = buffstr.size();
- int bracket_count=0;
- int normal_status = colors.at(0);
-
- for (in_pos=0; in_pos<len; in_pos++)
- {
- wchar_t c = buffstr.at(in_pos);
- switch( mode )
- {
+ enum {e_unquoted, e_single_quoted, e_double_quoted} mode = e_unquoted;
+ size_t in_pos, len = buffstr.size();
+ int bracket_count=0;
+ int normal_status = colors.at(0);
+
+ for (in_pos=0; in_pos<len; in_pos++)
+ {
+ wchar_t c = buffstr.at(in_pos);
+ switch( mode )
+ {
/*
Mode 0 means unquoted string
*/
- case e_unquoted:
- {
- if( c == L'\\' )
- {
- size_t start_pos = in_pos;
- in_pos++;
-
- if( wcschr( L"~%", buff[in_pos] ) )
- {
- if( in_pos == 1 )
- {
- colors.at(start_pos) = HIGHLIGHT_ESCAPE;
- colors.at(in_pos+1) = normal_status;
- }
- }
- else if( buff[in_pos]==L',' )
- {
- if( bracket_count )
- {
- colors.at(start_pos) = HIGHLIGHT_ESCAPE;
- colors.at(in_pos+1) = normal_status;
- }
- }
- else if( wcschr( L"abefnrtv*?$(){}[]'\"<>^ \\#;|&", buff[in_pos] ) )
- {
- colors.at(start_pos)=HIGHLIGHT_ESCAPE;
- colors.at(in_pos+1)=normal_status;
- }
- else if( wcschr( L"c", buff[in_pos] ) )
+ case e_unquoted:
+ {
+ if( c == L'\\' )
+ {
+ size_t start_pos = in_pos;
+ in_pos++;
+
+ if( wcschr( L"~%", buff[in_pos] ) )
+ {
+ if( in_pos == 1 )
+ {
+ colors.at(start_pos) = HIGHLIGHT_ESCAPE;
+ colors.at(in_pos+1) = normal_status;
+ }
+ }
+ else if( buff[in_pos]==L',' )
+ {
+ if( bracket_count )
+ {
+ colors.at(start_pos) = HIGHLIGHT_ESCAPE;
+ colors.at(in_pos+1) = normal_status;
+ }
+ }
+ else if( wcschr( L"abefnrtv*?$(){}[]'\"<>^ \\#;|&", buff[in_pos] ) )
+ {
+ colors.at(start_pos)=HIGHLIGHT_ESCAPE;
+ colors.at(in_pos+1)=normal_status;
+ }
+ else if( wcschr( L"c", buff[in_pos] ) )
{
- colors.at(start_pos)=HIGHLIGHT_ESCAPE;
+ colors.at(start_pos)=HIGHLIGHT_ESCAPE;
if (in_pos+2 < colors.size())
colors.at(in_pos+2)=normal_status;
- }
- else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
- {
- int i;
- long long res=0;
- int chars=2;
- int base=16;
-
- wchar_t max_val = ASCII_MAX;
-
- switch( buff[in_pos] )
- {
- case L'u':
- {
- chars=4;
- max_val = UCS2_MAX;
- break;
- }
-
- case L'U':
- {
- chars=8;
- max_val = WCHAR_MAX;
- break;
- }
-
- case L'x':
- {
- break;
- }
-
- case L'X':
- {
- max_val = BYTE_MAX;
- break;
- }
-
- default:
- {
- base=8;
- chars=3;
- in_pos--;
- break;
- }
- }
-
- for( i=0; i<chars; i++ )
- {
- long d = convert_digit( buff[++in_pos],base);
-
- if( d < 0 )
- {
- in_pos--;
- break;
- }
-
- res=(res*base)|d;
- }
-
- if( (res <= max_val) )
- {
- colors.at(start_pos) = HIGHLIGHT_ESCAPE;
- colors.at(in_pos+1) = normal_status;
- }
- else
- {
- colors.at(start_pos) = HIGHLIGHT_ERROR;
- colors.at(in_pos+1) = normal_status;
- }
- }
-
- }
- else
- {
- switch( buff[in_pos]){
- case L'~':
- case L'%':
- {
- if( in_pos == 0 )
- {
- colors.at(in_pos) = HIGHLIGHT_OPERATOR;
- colors.at(in_pos+1) = normal_status;
- }
- break;
- }
-
- case L'$':
- {
- wchar_t n = buff[in_pos+1];
- colors.at(in_pos) = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
- colors.at(in_pos+1) = normal_status;
- break;
- }
-
-
- case L'*':
- case L'?':
- case L'(':
- case L')':
- {
- colors.at(in_pos) = HIGHLIGHT_OPERATOR;
- colors.at(in_pos+1) = normal_status;
- break;
- }
-
- case L'{':
- {
- colors.at(in_pos) = HIGHLIGHT_OPERATOR;
- colors.at(in_pos+1) = normal_status;
- bracket_count++;
- break;
- }
-
- case L'}':
- {
- colors.at(in_pos) = HIGHLIGHT_OPERATOR;
- colors.at(in_pos+1) = normal_status;
- bracket_count--;
- break;
- }
-
- case L',':
- {
- if( bracket_count )
- {
- colors.at(in_pos) = HIGHLIGHT_OPERATOR;
- colors.at(in_pos+1) = normal_status;
- }
-
- break;
- }
-
- case L'\'':
- {
- colors.at(in_pos) = HIGHLIGHT_QUOTE;
- mode = e_single_quoted;
- break;
- }
-
- case L'\"':
- {
- colors.at(in_pos) = HIGHLIGHT_QUOTE;
- mode = e_double_quoted;
- break;
- }
-
- }
- }
- break;
- }
-
+ }
+ else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
+ {
+ int i;
+ long long res=0;
+ int chars=2;
+ int base=16;
+
+ wchar_t max_val = ASCII_MAX;
+
+ switch( buff[in_pos] )
+ {
+ case L'u':
+ {
+ chars=4;
+ max_val = UCS2_MAX;
+ break;
+ }
+
+ case L'U':
+ {
+ chars=8;
+ max_val = WCHAR_MAX;
+ break;
+ }
+
+ case L'x':
+ {
+ break;
+ }
+
+ case L'X':
+ {
+ max_val = BYTE_MAX;
+ break;
+ }
+
+ default:
+ {
+ base=8;
+ chars=3;
+ in_pos--;
+ break;
+ }
+ }
+
+ for( i=0; i<chars; i++ )
+ {
+ long d = convert_digit( buff[++in_pos],base);
+
+ if( d < 0 )
+ {
+ in_pos--;
+ break;
+ }
+
+ res=(res*base)|d;
+ }
+
+ if( (res <= max_val) )
+ {
+ colors.at(start_pos) = HIGHLIGHT_ESCAPE;
+ colors.at(in_pos+1) = normal_status;
+ }
+ else
+ {
+ colors.at(start_pos) = HIGHLIGHT_ERROR;
+ colors.at(in_pos+1) = normal_status;
+ }
+ }
+
+ }
+ else
+ {
+ switch( buff[in_pos]){
+ case L'~':
+ case L'%':
+ {
+ if( in_pos == 0 )
+ {
+ colors.at(in_pos) = HIGHLIGHT_OPERATOR;
+ colors.at(in_pos+1) = normal_status;
+ }
+ break;
+ }
+
+ case L'$':
+ {
+ wchar_t n = buff[in_pos+1];
+ colors.at(in_pos) = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
+ colors.at(in_pos+1) = normal_status;
+ break;
+ }
+
+
+ case L'*':
+ case L'?':
+ case L'(':
+ case L')':
+ {
+ colors.at(in_pos) = HIGHLIGHT_OPERATOR;
+ colors.at(in_pos+1) = normal_status;
+ break;
+ }
+
+ case L'{':
+ {
+ colors.at(in_pos) = HIGHLIGHT_OPERATOR;
+ colors.at(in_pos+1) = normal_status;
+ bracket_count++;
+ break;
+ }
+
+ case L'}':
+ {
+ colors.at(in_pos) = HIGHLIGHT_OPERATOR;
+ colors.at(in_pos+1) = normal_status;
+ bracket_count--;
+ break;
+ }
+
+ case L',':
+ {
+ if( bracket_count )
+ {
+ colors.at(in_pos) = HIGHLIGHT_OPERATOR;
+ colors.at(in_pos+1) = normal_status;
+ }
+
+ break;
+ }
+
+ case L'\'':
+ {
+ colors.at(in_pos) = HIGHLIGHT_QUOTE;
+ mode = e_single_quoted;
+ break;
+ }
+
+ case L'\"':
+ {
+ colors.at(in_pos) = HIGHLIGHT_QUOTE;
+ mode = e_double_quoted;
+ break;
+ }
+
+ }
+ }
+ break;
+ }
+
/*
Mode 1 means single quoted string, i.e 'foo'
*/
- case e_single_quoted:
- {
- if( c == L'\\' )
- {
- size_t start_pos = in_pos;
- switch( buff[++in_pos] )
- {
- case '\\':
- case L'\'':
- {
- colors.at(start_pos) = HIGHLIGHT_ESCAPE;
- colors.at(in_pos+1) = HIGHLIGHT_QUOTE;
- break;
- }
-
- case 0:
- {
- return;
- }
-
- }
-
- }
- if( c == L'\'' )
- {
- mode = e_unquoted;
- colors.at(in_pos+1) = normal_status;
- }
-
- break;
- }
-
+ case e_single_quoted:
+ {
+ if( c == L'\\' )
+ {
+ size_t start_pos = in_pos;
+ switch( buff[++in_pos] )
+ {
+ case '\\':
+ case L'\'':
+ {
+ colors.at(start_pos) = HIGHLIGHT_ESCAPE;
+ colors.at(in_pos+1) = HIGHLIGHT_QUOTE;
+ break;
+ }
+
+ case 0:
+ {
+ return;
+ }
+
+ }
+
+ }
+ if( c == L'\'' )
+ {
+ mode = e_unquoted;
+ colors.at(in_pos+1) = normal_status;
+ }
+
+ break;
+ }
+
/*
Mode 2 means double quoted string, i.e. "foo"
*/
- case e_double_quoted:
- {
- switch( c )
- {
- case '"':
- {
- mode = e_unquoted;
- colors.at(in_pos+1) = normal_status;
- break;
- }
-
- case '\\':
- {
- size_t start_pos = in_pos;
- switch( buff[++in_pos] )
- {
- case L'\0':
- {
- return;
- }
-
- case '\\':
- case L'$':
- case '"':
- {
- colors.at(start_pos) = HIGHLIGHT_ESCAPE;
- colors.at(in_pos+1) = HIGHLIGHT_QUOTE;
- break;
- }
- }
- break;
- }
-
- case '$':
- {
- wchar_t n = buff[in_pos+1];
- colors.at(in_pos) = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
- colors.at(in_pos+1) = HIGHLIGHT_QUOTE;
- break;
- }
-
- }
- break;
- }
- }
- }
+ case e_double_quoted:
+ {
+ switch( c )
+ {
+ case '"':
+ {
+ mode = e_unquoted;
+ colors.at(in_pos+1) = normal_status;
+ break;
+ }
+
+ case '\\':
+ {
+ size_t start_pos = in_pos;
+ switch( buff[++in_pos] )
+ {
+ case L'\0':
+ {
+ return;
+ }
+
+ case '\\':
+ case L'$':
+ case '"':
+ {
+ colors.at(start_pos) = HIGHLIGHT_ESCAPE;
+ colors.at(in_pos+1) = HIGHLIGHT_QUOTE;
+ break;
+ }
+ }
+ break;
+ }
+
+ case '$':
+ {
+ wchar_t n = buff[in_pos+1];
+ colors.at(in_pos) = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
+ colors.at(in_pos+1) = HIGHLIGHT_QUOTE;
+ break;
+ }
+
+ }
+ break;
+ }
+ }
+ }
}
static int has_expand_reserved( const wchar_t *str )
{
- while( *str )
- {
- if( *str >= EXPAND_RESERVED &&
- *str <= EXPAND_RESERVED_END )
- {
- return 1;
- }
- str++;
- }
- return 0;
+ while( *str )
+ {
+ if( *str >= EXPAND_RESERVED &&
+ *str <= EXPAND_RESERVED_END )
+ {
+ return 1;
+ }
+ str++;
+ }
+ return 0;
}
/* Parse a command line. Return by reference the last command, its arguments, and the offset in the string of the beginning of the last argument. This is used by autosuggestions */
@@ -662,17 +662,17 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
{
if (str.empty())
return false;
-
+
wcstring cmd;
wcstring_list_t args;
int arg_pos = -1;
-
+
bool had_cmd = false;
tokenizer tok;
for (tok_init( &tok, str.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS); tok_has_next(&tok); tok_next(&tok))
{
int last_type = tok_last_type(&tok);
-
+
switch( last_type )
{
case TOK_STRING:
@@ -684,7 +684,7 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
arg_pos = tok_get_pos(&tok);
}
else
- {
+ {
/* Command. First check that the command actually exists. */
wcstring local_cmd = tok_last( &tok );
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
@@ -696,12 +696,12 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
{
bool is_subcommand = false;
int mark = tok_get_pos(&tok);
-
+
if (parser_keywords_is_subcommand(cmd))
{
int sw;
tok_next( &tok );
-
+
sw = parser_keywords_is_switch( tok_last( &tok ) );
if( !parser_keywords_is_block( cmd ) &&
sw == ARG_SWITCH )
@@ -711,12 +711,12 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
else
{
if( sw == ARG_SKIP )
- mark = tok_get_pos( &tok );
+ mark = tok_get_pos( &tok );
is_subcommand = true;
}
tok_set_pos( &tok, mark );
}
-
+
if (!is_subcommand)
{
/* It's really a command */
@@ -724,11 +724,11 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
cmd = local_cmd;
}
}
-
+
}
break;
}
-
+
case TOK_REDIRECT_NOCLOB:
case TOK_REDIRECT_OUT:
case TOK_REDIRECT_IN:
@@ -739,10 +739,10 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
{
break;
}
- tok_next( &tok );
+ tok_next( &tok );
break;
}
-
+
case TOK_PIPE:
case TOK_BACKGROUND:
case TOK_END:
@@ -753,17 +753,17 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
arg_pos = -1;
break;
}
-
- case TOK_COMMENT:
+
+ case TOK_COMMENT:
case TOK_ERROR:
default:
{
- break;
- }
+ break;
+ }
}
}
tok_destroy( &tok );
-
+
/* Remember our command if we have one */
if (had_cmd) {
if (out_command) out_command->swap(cmd);
@@ -778,39 +778,39 @@ static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command
bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_directory, wcstring &outSuggestion) {
if (str.empty())
return false;
-
+
ASSERT_IS_BACKGROUND_THREAD();
-
+
/* Parse the string */
wcstring parsed_command;
wcstring_list_t parsed_arguments;
int parsed_last_arg_pos = -1;
if (! autosuggest_parse_command(str, &parsed_command, &parsed_arguments, &parsed_last_arg_pos))
return false;
-
+
bool result = false;
- if (parsed_command == L"cd" && ! parsed_arguments.empty()) {
+ if (parsed_command == L"cd" && ! parsed_arguments.empty()) {
/* We can possibly handle this specially */
const wcstring escaped_dir = parsed_arguments.back();
wcstring suggested_path;
-
+
/* We always return true because we recognized the command. This prevents us from falling back to dumber algorithms; for example we won't suggest a non-directory for the cd command. */
result = true;
outSuggestion.clear();
-
+
/* Unescape the parameter */
wcstring unescaped_dir = escaped_dir;
bool unescaped = unescape_string(unescaped_dir, UNESCAPE_INCOMPLETE);
-
+
/* Determine the quote type we got from the input directory. */
wchar_t quote = L'\0';
parse_util_get_parameter_info(escaped_dir, 0, &quote, NULL, NULL);
-
+
/* Big hack to avoid expanding a tilde inside quotes */
path_flags_t path_flags = (quote == L'\0') ? PATH_EXPAND_TILDE : 0;
if (unescaped && is_potential_cd_path(unescaped_dir, working_directory, path_flags, &suggested_path))
{
-
+
/* Note: this looks really wrong for strings that have an "unescapable" character in them, e.g. a \t, because parse_util_escape_string_with_quote will insert that character */
wcstring escaped_suggested_path = parse_util_escape_string_with_quote(suggested_path, quote);
@@ -832,14 +832,14 @@ bool autosuggest_validate_from_history(const history_item_t &item, file_detectio
bool handled = false, suggestionOK = false;
- /* Parse the string */
+ /* Parse the string */
wcstring parsed_command;
wcstring_list_t parsed_arguments;
int parsed_last_arg_pos = -1;
if (! autosuggest_parse_command(item.str(), &parsed_command, &parsed_arguments, &parsed_last_arg_pos))
return false;
- if (parsed_command == L"cd" && ! parsed_arguments.empty()) {
+ if (parsed_command == L"cd" && ! parsed_arguments.empty()) {
/* We can possibly handle this specially */
wcstring dir = parsed_arguments.back();
if (expand_one(dir, EXPAND_SKIP_CMDSUBST))
@@ -860,9 +860,9 @@ bool autosuggest_validate_from_history(const history_item_t &item, file_detectio
suggestionOK = true;
}
}
- }
- }
-
+ }
+ }
+
/* If not handled specially, handle it here */
if (! handled) {
bool cmd_ok = false;
@@ -894,369 +894,369 @@ 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 size_t pos, wcstring_list_t *error, const wcstring &working_directory, const env_vars_snapshot_t &vars) {
ASSERT_IS_BACKGROUND_THREAD();
-
- wcstring cmd;
- int had_cmd=0;
- wcstring last_cmd;
-
- int accept_switches = 1;
-
- int use_function = 1;
- int use_command = 1;
- int use_builtin = 1;
-
- CHECK( buff, );
+
+ wcstring cmd;
+ int had_cmd=0;
+ wcstring last_cmd;
+
+ int accept_switches = 1;
+
+ int use_function = 1;
+ int use_command = 1;
+ int use_builtin = 1;
+
+ CHECK( buff, );
if (buff[0] == L'\0')
return;
- std::fill(color.begin(), color.end(), -1);
+ std::fill(color.begin(), color.end(), -1);
tokenizer tok;
- for( tok_init( &tok, buff, TOK_SHOW_COMMENTS | TOK_SQUASH_ERRORS );
- tok_has_next( &tok );
- tok_next( &tok ) )
- {
- int last_type = tok_last_type( &tok );
-
- switch( last_type )
- {
- case TOK_STRING:
- {
- if( had_cmd )
- {
-
- /*Parameter */
- wchar_t *param = tok_last( &tok );
- if( param[0] == L'-' )
- {
- if (wcscmp( param, L"--" ) == 0 )
- {
- accept_switches = 0;
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
- }
- else if( accept_switches )
- {
- if( complete_is_valid_option( last_cmd, param, error, false /* no autoload */ ) )
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
- else
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- }
- else
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
- }
- }
- else
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
- }
-
- if( cmd == L"cd" )
- {
+ for( tok_init( &tok, buff, TOK_SHOW_COMMENTS | TOK_SQUASH_ERRORS );
+ tok_has_next( &tok );
+ tok_next( &tok ) )
+ {
+ int last_type = tok_last_type( &tok );
+
+ switch( last_type )
+ {
+ case TOK_STRING:
+ {
+ if( had_cmd )
+ {
+
+ /*Parameter */
+ wchar_t *param = tok_last( &tok );
+ if( param[0] == L'-' )
+ {
+ if (wcscmp( param, L"--" ) == 0 )
+ {
+ accept_switches = 0;
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
+ }
+ else if( accept_switches )
+ {
+ if( complete_is_valid_option( last_cmd, param, error, false /* no autoload */ ) )
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
+ else
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ }
+ else
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
+ }
+ }
+ else
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
+ }
+
+ if( cmd == L"cd" )
+ {
wcstring dir = tok_last( &tok );
if (expand_one(dir, EXPAND_SKIP_CMDSUBST))
- {
- int is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h");
- if( !is_help && ! is_potential_cd_path(dir, working_directory, PATH_EXPAND_TILDE, NULL))
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- }
- }
- }
-
+ {
+ int is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h");
+ if( !is_help && ! is_potential_cd_path(dir, working_directory, PATH_EXPAND_TILDE, NULL))
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ }
+ }
+ }
+
/* Highlight the parameter. highlight_param wants to write one more color than we have characters (hysterical raisins) so allocate one more in the vector. But don't copy it back. */
const wcstring param_str = param;
size_t tok_pos = tok_get_pos(&tok);
-
+
std::vector<int>::const_iterator where = color.begin() + tok_pos;
std::vector<int> subcolors(where, where + param_str.size());
subcolors.push_back(-1);
highlight_param(param_str, subcolors, error);
-
+
/* Copy the subcolors back into our colors array */
std::copy(subcolors.begin(), subcolors.begin() + param_str.size(), color.begin() + tok_pos);
- }
- else
- {
- /*
- Command. First check that the command actually exists.
- */
+ }
+ else
+ {
+ /*
+ Command. First check that the command actually exists.
+ */
cmd = tok_last( &tok );
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS);
- if (! expanded || has_expand_reserved(cmd.c_str()))
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- }
- else
- {
- bool is_cmd = false;
- int is_subcommand = 0;
- int mark = tok_get_pos( &tok );
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND;
-
- if( parser_keywords_is_subcommand( cmd ) )
- {
-
- int sw;
-
- if( cmd == L"builtin")
- {
- use_function = 0;
- use_command = 0;
- use_builtin = 1;
- }
- else if( cmd == L"command")
- {
- use_command = 1;
- use_function = 0;
- use_builtin = 0;
- }
-
- tok_next( &tok );
-
- sw = parser_keywords_is_switch( tok_last( &tok ) );
-
- if( !parser_keywords_is_block( cmd ) &&
- sw == ARG_SWITCH )
- {
- /*
- The 'builtin' and 'command' builtins
- are normally followed by another
- command, but if they are invoked
- with a switch, they aren't.
-
- */
- use_command = 1;
- use_function = 1;
- use_builtin = 2;
- }
- else
- {
- if( sw == ARG_SKIP )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
- mark = tok_get_pos( &tok );
- }
-
- is_subcommand = 1;
- }
- tok_set_pos( &tok, mark );
- }
-
- if( !is_subcommand )
- {
- /*
- OK, this is a command, it has been
- successfully expanded and everything
- looks ok. Lets check if the command
- exists.
- */
-
- /*
- First check if it is a builtin or
- function, since we don't have to stat
- any files for that
- */
- if (! is_cmd && use_builtin )
- is_cmd = builtin_exists( cmd );
-
- if (! is_cmd && use_function )
- is_cmd = function_exists_no_autoload( cmd, vars );
-
- /*
- Moving on to expensive tests
- */
-
- /*
- Check if this is a regular command
- */
- if (! is_cmd && use_command )
+ if (! expanded || has_expand_reserved(cmd.c_str()))
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ }
+ else
+ {
+ bool is_cmd = false;
+ int is_subcommand = 0;
+ int mark = tok_get_pos( &tok );
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND;
+
+ if( parser_keywords_is_subcommand( cmd ) )
+ {
+
+ int sw;
+
+ if( cmd == L"builtin")
+ {
+ use_function = 0;
+ use_command = 0;
+ use_builtin = 1;
+ }
+ else if( cmd == L"command")
+ {
+ use_command = 1;
+ use_function = 0;
+ use_builtin = 0;
+ }
+
+ tok_next( &tok );
+
+ sw = parser_keywords_is_switch( tok_last( &tok ) );
+
+ if( !parser_keywords_is_block( cmd ) &&
+ sw == ARG_SWITCH )
+ {
+ /*
+ The 'builtin' and 'command' builtins
+ are normally followed by another
+ command, but if they are invoked
+ with a switch, they aren't.
+
+ */
+ use_command = 1;
+ use_function = 1;
+ use_builtin = 2;
+ }
+ else
+ {
+ if( sw == ARG_SKIP )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_PARAM;
+ mark = tok_get_pos( &tok );
+ }
+
+ is_subcommand = 1;
+ }
+ tok_set_pos( &tok, mark );
+ }
+
+ if( !is_subcommand )
+ {
+ /*
+ OK, this is a command, it has been
+ successfully expanded and everything
+ looks ok. Lets check if the command
+ exists.
+ */
+
+ /*
+ First check if it is a builtin or
+ function, since we don't have to stat
+ any files for that
+ */
+ if (! is_cmd && use_builtin )
+ is_cmd = builtin_exists( cmd );
+
+ if (! is_cmd && use_function )
+ is_cmd = function_exists_no_autoload( cmd, vars );
+
+ /*
+ Moving on to expensive tests
+ */
+
+ /*
+ Check if this is a regular command
+ */
+ if (! is_cmd && use_command )
{
- is_cmd = path_get_path( cmd, NULL, vars );
+ is_cmd = path_get_path( cmd, NULL, vars );
}
-
+
/* Maybe it is a path for a implicit cd command. */
if (! is_cmd)
{
if (use_builtin || (use_function && function_exists_no_autoload( L"cd", vars)))
is_cmd = path_can_be_implicit_cd(cmd, NULL, working_directory.c_str(), vars);
}
-
- if( is_cmd )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND;
- }
- else
- {
- if( error ) {
+
+ if( is_cmd )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND;
+ }
+ else
+ {
+ if( error ) {
error->push_back(format_string(L"Unknown command \'%ls\'", cmd.c_str()));
}
- color.at(tok_get_pos( &tok )) = (HIGHLIGHT_ERROR);
- }
- had_cmd = 1;
- }
-
- if( had_cmd )
- {
- last_cmd = tok_last( &tok );
- }
- }
-
- }
- break;
- }
-
- case TOK_REDIRECT_NOCLOB:
- case TOK_REDIRECT_OUT:
- case TOK_REDIRECT_IN:
- case TOK_REDIRECT_APPEND:
- case TOK_REDIRECT_FD:
- {
- if( !had_cmd )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- if( error )
+ color.at(tok_get_pos( &tok )) = (HIGHLIGHT_ERROR);
+ }
+ had_cmd = 1;
+ }
+
+ if( had_cmd )
+ {
+ last_cmd = tok_last( &tok );
+ }
+ }
+
+ }
+ break;
+ }
+
+ case TOK_REDIRECT_NOCLOB:
+ case TOK_REDIRECT_OUT:
+ case TOK_REDIRECT_IN:
+ case TOK_REDIRECT_APPEND:
+ case TOK_REDIRECT_FD:
+ {
+ if( !had_cmd )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ if( error )
error->push_back(L"Redirection without a command");
- break;
- }
-
+ break;
+ }
+
wcstring target_str;
- const wchar_t *target=NULL;
-
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_REDIRECTION;
- tok_next( &tok );
-
- /*
- Check that we are redirecting into a file
- */
-
- switch( tok_last_type( &tok ) )
- {
- case TOK_STRING:
- {
+ const wchar_t *target=NULL;
+
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_REDIRECTION;
+ tok_next( &tok );
+
+ /*
+ Check that we are redirecting into a file
+ */
+
+ switch( tok_last_type( &tok ) )
+ {
+ case TOK_STRING:
+ {
target_str = tok_last( &tok );
if (expand_one(target_str, EXPAND_SKIP_CMDSUBST)) {
target = target_str.c_str();
}
- /*
- Redirect filename may contain a cmdsubst.
- If so, it will be ignored/not flagged.
- */
- }
- break;
- default:
- {
+ /*
+ Redirect filename may contain a cmdsubst.
+ If so, it will be ignored/not flagged.
+ */
+ }
+ break;
+ default:
+ {
size_t pos = tok_get_pos(&tok);
if (pos < color.size()) {
color.at(pos) = HIGHLIGHT_ERROR;
}
- if( error )
+ if( error )
error->push_back(L"Invalid redirection");
- }
-
- }
-
- if( target != 0 )
- {
+ }
+
+ }
+
+ if( target != 0 )
+ {
wcstring dir = target;
size_t slash_idx = dir.find_last_of(L'/');
- struct stat buff;
- /*
- If file is in directory other than '.', check
- that the directory exists.
- */
- if( slash_idx != wcstring::npos )
- {
- dir.resize(slash_idx);
- if( wstat( dir, &buff ) == -1 )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- if( error )
+ struct stat buff;
+ /*
+ If file is in directory other than '.', check
+ that the directory exists.
+ */
+ if( slash_idx != wcstring::npos )
+ {
+ dir.resize(slash_idx);
+ if( wstat( dir, &buff ) == -1 )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ if( error )
error->push_back(format_string(L"Directory \'%ls\' does not exist", dir.c_str()));
-
- }
- }
-
- /*
- If the file is read from or appended to, check
- if it exists.
- */
- if( last_type == TOK_REDIRECT_IN ||
- last_type == TOK_REDIRECT_APPEND )
- {
- if( wstat( target, &buff ) == -1 )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- if( error )
+
+ }
+ }
+
+ /*
+ If the file is read from or appended to, check
+ if it exists.
+ */
+ if( last_type == TOK_REDIRECT_IN ||
+ last_type == TOK_REDIRECT_APPEND )
+ {
+ if( wstat( target, &buff ) == -1 )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ if( error )
error->push_back(format_string(L"File \'%ls\' does not exist", target));
- }
- }
- if( last_type == TOK_REDIRECT_NOCLOB )
- {
- if( wstat( target, &buff ) != -1 )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- if( error )
+ }
+ }
+ if( last_type == TOK_REDIRECT_NOCLOB )
+ {
+ if( wstat( target, &buff ) != -1 )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ if( error )
error->push_back(format_string(L"File \'%ls\' exists", target));
- }
- }
- }
- break;
- }
-
- case TOK_PIPE:
- case TOK_BACKGROUND:
- {
- if( had_cmd )
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_END;
- had_cmd = 0;
- use_command = 1;
- use_function = 1;
- use_builtin = 1;
- accept_switches = 1;
- }
- else
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- if( error )
+ }
+ }
+ }
+ break;
+ }
+
+ case TOK_PIPE:
+ case TOK_BACKGROUND:
+ {
+ if( had_cmd )
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_END;
+ had_cmd = 0;
+ use_command = 1;
+ use_function = 1;
+ use_builtin = 1;
+ accept_switches = 1;
+ }
+ else
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ if( error )
error->push_back(L"No job to put in background" );
- }
-
- break;
- }
-
- case TOK_END:
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_END;
- had_cmd = 0;
- use_command = 1;
- use_function = 1;
- use_builtin = 1;
- accept_switches = 1;
- break;
- }
-
- case TOK_COMMENT:
- {
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMENT;
- break;
- }
-
- case TOK_ERROR:
- default:
- {
- /*
- If the tokenizer reports an error, highlight it as such.
- */
- if( error )
+ }
+
+ break;
+ }
+
+ case TOK_END:
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_END;
+ had_cmd = 0;
+ use_command = 1;
+ use_function = 1;
+ use_builtin = 1;
+ accept_switches = 1;
+ break;
+ }
+
+ case TOK_COMMENT:
+ {
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMENT;
+ break;
+ }
+
+ case TOK_ERROR:
+ default:
+ {
+ /*
+ If the tokenizer reports an error, highlight it as such.
+ */
+ if( error )
error->push_back(tok_last( &tok));
- color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
- break;
- }
- }
- }
+ color.at(tok_get_pos( &tok )) = HIGHLIGHT_ERROR;
+ break;
+ }
+ }
+ }
tok_destroy( &tok );
}
@@ -1265,14 +1265,14 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
void highlight_shell( const wcstring &buff, std::vector<int> &color, size_t pos, wcstring_list_t *error, const env_vars_snapshot_t &vars )
{
ASSERT_IS_BACKGROUND_THREAD();
-
+
const size_t length = buff.size();
assert(buff.size() == color.size());
- if( length == 0 )
- return;
-
+ if( length == 0 )
+ return;
+
std::fill(color.begin(), color.end(), -1);
/* Do something sucky and get the current working directory on this background thread. This should really be passed in. Note that we also need this as a vector (of one directory). */
@@ -1281,78 +1281,78 @@ void highlight_shell( const wcstring &buff, std::vector<int> &color, size_t pos,
/* Tokenize the string */
tokenize(buff.c_str(), color, pos, error, working_directory, vars);
- /*
- Locate and syntax highlight cmdsubsts recursively
- */
+ /*
+ Locate and syntax highlight cmdsubsts recursively
+ */
- wchar_t * const subbuff = wcsdup(buff.c_str());
+ wchar_t * const subbuff = wcsdup(buff.c_str());
wchar_t * subpos = subbuff;
- int done=0;
-
- while( 1 )
- {
- wchar_t *begin, *end;
-
- if( parse_util_locate_cmdsubst(subpos, &begin, &end, 1) <= 0)
- {
- break;
- }
-
- if( !*end )
- done=1;
- else
- *end=0;
-
+ int done=0;
+
+ while( 1 )
+ {
+ wchar_t *begin, *end;
+
+ if( parse_util_locate_cmdsubst(subpos, &begin, &end, 1) <= 0)
+ {
+ break;
+ }
+
+ if( !*end )
+ done=1;
+ else
+ *end=0;
+
//our subcolors start at color + (begin-subbuff)+1
size_t start = begin - subbuff + 1, len = wcslen(begin + 1);
std::vector<int> subcolors(len, -1);
-
- highlight_shell( begin+1, subcolors, -1, error, vars );
-
+
+ highlight_shell( begin+1, subcolors, -1, error, vars );
+
// insert subcolors
std::copy(subcolors.begin(), subcolors.end(), color.begin() + start);
-
+
// highlight the end of the subcommand
assert(end >= subbuff);
if ((size_t)(end - subbuff) < length) {
color.at(end-subbuff)=HIGHLIGHT_OPERATOR;
}
-
- if( done )
- break;
-
- subpos = end+1;
- }
+
+ if( done )
+ break;
+
+ subpos = end+1;
+ }
free(subbuff);
- /*
- The highlighting code only changes the first element when the
- color changes. This fills in the rest.
- */
- int last_val=0;
- for( size_t i=0; i < buff.size(); i++ )
- {
- if( color.at(i) >= 0 )
- last_val = color.at(i);
- else
- color.at(i) = last_val;
- }
-
- /*
- Color potentially valid paths in a special path color if they
- are the current token.
+ /*
+ The highlighting code only changes the first element when the
+ color changes. This fills in the rest.
+ */
+ int last_val=0;
+ for( size_t i=0; i < buff.size(); i++ )
+ {
+ if( color.at(i) >= 0 )
+ last_val = color.at(i);
+ else
+ color.at(i) = last_val;
+ }
+
+ /*
+ Color potentially valid paths in a special path color if they
+ are the current token.
For reasons that I don't yet understand, it's required that pos be allowed to be length (e.g. when backspacing).
- */
- if( pos <= length )
- {
-
+ */
+ if( pos <= length )
+ {
+
const wchar_t *cbuff = buff.c_str();
- const wchar_t *tok_begin, *tok_end;
- parse_util_token_extent( cbuff, pos, &tok_begin, &tok_end, 0, 0 );
- if( tok_begin && tok_end )
- {
- wcstring token(tok_begin, tok_end-tok_begin);
- const wcstring_list_t working_directory_list(1, working_directory);
+ const wchar_t *tok_begin, *tok_end;
+ parse_util_token_extent( cbuff, pos, &tok_begin, &tok_end, 0, 0 );
+ if( tok_begin && tok_end )
+ {
+ wcstring token(tok_begin, tok_end-tok_begin);
+ const wcstring_list_t working_directory_list(1, working_directory);
if (unescape_string(token, 1))
{
/* Big hack: is_potential_path expects a tilde, but unescape_string gives us HOME_DIRECTORY. Put it back. */
@@ -1369,22 +1369,22 @@ void highlight_shell( const wcstring &buff, std::vector<int> &color, size_t pos,
}
}
}
- }
- }
-
-
- highlight_universal_internal( buff, color, pos );
-
- /*
- Spaces should not be highlighted at all, since it makes cursor look funky in some terminals
- */
- for( size_t i=0; i < buff.size(); i++ )
- {
- if( iswspace(buff.at(i)) )
- {
- color.at(i)=0;
- }
- }
+ }
+ }
+
+
+ highlight_universal_internal( buff, color, pos );
+
+ /*
+ Spaces should not be highlighted at all, since it makes cursor look funky in some terminals
+ */
+ for( size_t i=0; i < buff.size(); i++ )
+ {
+ if( iswspace(buff.at(i)) )
+ {
+ color.at(i)=0;
+ }
+ }
}
@@ -1393,115 +1393,115 @@ void highlight_shell( const wcstring &buff, std::vector<int> &color, size_t pos,
Perform quote and parenthesis highlighting on the specified string.
*/
static void highlight_universal_internal( const wcstring &buffstr, std::vector<int> &color, size_t pos )
-{
+{
assert(buffstr.size() == color.size());
- if( pos < buffstr.size() )
- {
-
- /*
- Highlight matching quotes
- */
- if( (buffstr.at(pos) == L'\'') || (buffstr.at(pos) == L'\"') )
- {
- std::vector<long> lst;
-
- int level=0;
- wchar_t prev_q=0;
-
+ if( pos < buffstr.size() )
+ {
+
+ /*
+ Highlight matching quotes
+ */
+ if( (buffstr.at(pos) == L'\'') || (buffstr.at(pos) == L'\"') )
+ {
+ std::vector<long> lst;
+
+ int level=0;
+ wchar_t prev_q=0;
+
const wchar_t * const buff = buffstr.c_str();
- const wchar_t *str = buff;
-
- int match_found=0;
-
- while(*str)
- {
- switch( *str )
- {
- case L'\\':
- str++;
- break;
- case L'\"':
- case L'\'':
- if( level == 0 )
- {
- level++;
+ const wchar_t *str = buff;
+
+ int match_found=0;
+
+ while(*str)
+ {
+ switch( *str )
+ {
+ case L'\\':
+ str++;
+ break;
+ case L'\"':
+ case L'\'':
+ if( level == 0 )
+ {
+ level++;
lst.push_back(str-buff);
- prev_q = *str;
- }
- else
- {
- if( prev_q == *str )
- {
- long pos1, pos2;
-
- level--;
+ prev_q = *str;
+ }
+ else
+ {
+ if( prev_q == *str )
+ {
+ long pos1, pos2;
+
+ level--;
pos1 = lst.back();
- pos2 = str-buff;
- if( pos1==pos || pos2==pos )
- {
- color.at(pos1)|=HIGHLIGHT_MATCH<<16;
- color.at(pos2)|=HIGHLIGHT_MATCH<<16;
- match_found = 1;
-
- }
- prev_q = *str==L'\"'?L'\'':L'\"';
- }
- else
- {
- level++;
+ pos2 = str-buff;
+ if( pos1==pos || pos2==pos )
+ {
+ color.at(pos1)|=HIGHLIGHT_MATCH<<16;
+ color.at(pos2)|=HIGHLIGHT_MATCH<<16;
+ match_found = 1;
+
+ }
+ prev_q = *str==L'\"'?L'\'':L'\"';
+ }
+ else
+ {
+ level++;
lst.push_back(str-buff);
- prev_q = *str;
- }
- }
-
- break;
- }
- if( (*str == L'\0'))
- break;
-
- str++;
- }
-
- if( !match_found )
- color.at(pos) = HIGHLIGHT_ERROR<<16;
- }
-
- /*
- Highlight matching parenthesis
- */
+ prev_q = *str;
+ }
+ }
+
+ break;
+ }
+ if( (*str == L'\0'))
+ break;
+
+ str++;
+ }
+
+ if( !match_found )
+ color.at(pos) = HIGHLIGHT_ERROR<<16;
+ }
+
+ /*
+ Highlight matching parenthesis
+ */
const wchar_t c = buffstr.at(pos);
- if( wcschr( L"()[]{}", c ) )
- {
- int step = wcschr(L"({[", c)?1:-1;
- wchar_t dec_char = *(wcschr( L"()[]{}", c ) + step);
- wchar_t inc_char = c;
- int level = 0;
- int match_found=0;
+ if( wcschr( L"()[]{}", c ) )
+ {
+ int step = wcschr(L"({[", c)?1:-1;
+ wchar_t dec_char = *(wcschr( L"()[]{}", c ) + step);
+ wchar_t inc_char = c;
+ int level = 0;
+ int match_found=0;
for (long i=pos; i >= 0 && (size_t)i < buffstr.size(); i+=step) {
- const wchar_t test_char = buffstr.at(i);
+ const wchar_t test_char = buffstr.at(i);
if( test_char == inc_char )
- level++;
- if( test_char == dec_char )
- level--;
- if( level == 0 )
- {
- long pos2 = i;
- color.at(pos)|=HIGHLIGHT_MATCH<<16;
- color.at(pos2)|=HIGHLIGHT_MATCH<<16;
- match_found=1;
- break;
- }
- }
-
- if( !match_found )
- color[pos] = HIGHLIGHT_ERROR<<16;
- }
- }
+ level++;
+ if( test_char == dec_char )
+ level--;
+ if( level == 0 )
+ {
+ long pos2 = i;
+ color.at(pos)|=HIGHLIGHT_MATCH<<16;
+ color.at(pos2)|=HIGHLIGHT_MATCH<<16;
+ match_found=1;
+ break;
+ }
+ }
+
+ if( !match_found )
+ color[pos] = HIGHLIGHT_ERROR<<16;
+ }
+ }
}
void highlight_universal( const wcstring &buff, std::vector<int> &color, size_t pos, wcstring_list_t *error, const env_vars_snapshot_t &vars )
{
assert(buff.size() == color.size());
- std::fill(color.begin(), color.end(), 0);
- highlight_universal_internal( buff, color, pos );
+ std::fill(color.begin(), color.end(), 0);
+ highlight_universal_internal( buff, color, pos );
}
diff --git a/highlight.h b/highlight.h
index 22121e48..dc8a0305 100644
--- a/highlight.h
+++ b/highlight.h
@@ -1,5 +1,5 @@
/** \file highlight.h
- Prototypes for functions for syntax highlighting
+ Prototypes for functions for syntax highlighting
*/
#ifndef FISH_HIGHLIGHT_H
@@ -59,7 +59,7 @@
/**
Internal value representing highlighting of an IO redirection
*/
-#define HIGHLIGHT_REDIRECTION 0x800
+#define HIGHLIGHT_REDIRECTION 0x800
/**
Internal value representing highlighting a potentially valid path
*/
@@ -79,7 +79,7 @@ struct file_detection_context_t;
for each character in buff.
\param buff The buffer on which to perform syntax highlighting
- \param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
+ \param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
\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.
*/
@@ -91,7 +91,7 @@ void highlight_shell( const wcstring &buffstr, std::vector<int> &color, size_t p
for each character in buff.
\param buff The buffer on which to perform syntax highlighting
- \param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
+ \param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
\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.
*/
@@ -101,7 +101,7 @@ void highlight_universal( const wcstring &buffstr, std::vector<int> &color, size
Translate from HIGHLIGHT_* to FISH_COLOR_* according to environment
variables. Defaults to FISH_COLOR_NORMAL.
- Example:
+ Example:
If the environment variable FISH_FISH_COLOR_ERROR is set to 'red', a
call to highlight_get_color( HIGHLIGHT_ERROR) will return
@@ -125,7 +125,7 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
enum {
/* The path must be to a directory */
PATH_REQUIRE_DIR = 1 << 0,
-
+
/* Expand any leading tilde in the path */
PATH_EXPAND_TILDE = 1 << 1
};
diff --git a/history.cpp b/history.cpp
index fd7b328f..39595e7e 100644
--- a/history.cpp
+++ b/history.cpp
@@ -1,5 +1,5 @@
/** \file history.c
- History functions, part of the user interface.
+ History functions, part of the user interface.
*/
#include "config.h"
@@ -42,7 +42,7 @@ Our history format is intended to be valid YAML. Here it is:
paths:
- /path/to/something
- /path/to/something_else
-
+
Newlines are replaced by \n. Backslashes are replaced by \\.
*/
@@ -64,14 +64,14 @@ class time_profiler_t {
const char *what;
double start;
public:
-
+
time_profiler_t(const char *w) {
if (LOG_TIMES) {
what = w;
start = timef();
}
}
-
+
~time_profiler_t() {
if (LOG_TIMES) {
double end = timef();
@@ -90,13 +90,13 @@ class history_lru_node_t : public lru_node_t {
timestamp(item.timestamp()),
required_paths(item.required_paths)
{}
-
+
bool write_yaml_to_file(FILE *f) const;
};
class history_lru_cache_t : public lru_cache_t<history_lru_node_t> {
protected:
-
+
/* Override to delete evicted nodes */
virtual void node_was_evicted(history_lru_node_t *node) {
delete node;
@@ -104,13 +104,13 @@ class history_lru_cache_t : public lru_cache_t<history_lru_node_t> {
public:
history_lru_cache_t(size_t max) : lru_cache_t<history_lru_node_t>(max) { }
-
+
/* Function to add a history item */
void add_item(const history_item_t &item) {
/* Skip empty items */
if (item.empty())
return;
-
+
/* See if it's in the cache. If it is, update the timestamp. If not, we create a new node and add it. Note that calling get_node promotes the node to the front. */
history_lru_node_t *node = this->get_node(item.str());
if (node != NULL) {
@@ -159,15 +159,15 @@ history_item_t::history_item_t(const wcstring &str, time_t when, const path_list
bool history_item_t::matches_search(const wcstring &term, enum history_search_type_t type) const {
switch (type) {
-
+
case HISTORY_SEARCH_TYPE_CONTAINS:
/* We consider equal strings to NOT match a contains search (so that you don't have to see history equal to what you typed). The length check ensures that. */
return contents.size() > term.size() && contents.find(term) != wcstring::npos;
-
+
case HISTORY_SEARCH_TYPE_PREFIX:
/* We consider equal strings to match a prefix search, so that autosuggest will allow suggesting what you've typed */
return string_prefixes_string(term, contents);
-
+
default:
sanity_lose();
return false;
@@ -180,18 +180,18 @@ bool history_lru_node_t::write_yaml_to_file(FILE *f) const {
escape_yaml(cmd);
if (fprintf(f, "- cmd: %s\n", cmd.c_str()) < 0)
return false;
-
+
if (fprintf(f, " when: %ld\n", (long)timestamp) < 0)
return false;
-
+
if (! required_paths.empty()) {
if (fputs(" paths:\n", f) < 0)
return false;
-
+
for (path_list_t::const_iterator iter = required_paths.begin(); iter != required_paths.end(); ++iter) {
std::string path = wcs2string(*iter);
escape_yaml(path);
-
+
if (fprintf(f, " - %s\n", path.c_str()) < 0)
return false;
}
@@ -207,17 +207,17 @@ static bool parse_timestamp(const char *str, time_t *out_when) {
/* Advance past spaces */
while (*cursor == ' ')
cursor++;
-
+
/* Look for "when:" */
size_t when_len = 5;
if (strncmp(cursor, "when:", when_len) != 0)
return false;
cursor += when_len;
-
+
/* Advance past spaces */
while (*cursor == ' ')
cursor++;
-
+
/* Try to parse a timestamp. */
long timestamp = 0;
if (isdigit(*cursor) && (timestamp = strtol(cursor, NULL, 0)) > 0) {
@@ -234,10 +234,10 @@ static const char *next_line(const char *start, size_t length) {
/* Handle the hopeless case */
if (length < 1)
return NULL;
-
+
/* Get a pointer to the end, that we must not pass */
const char * const end = start + length;
-
+
/* Skip past the next newline */
const char *nextline = (const char *)memchr(start, '\n', length);
if (! nextline || nextline >= end) {
@@ -247,13 +247,13 @@ static const char *next_line(const char *start, size_t length) {
if (++nextline >= end) {
return NULL;
}
-
+
/* Make sure this new line is itself "newline terminated". If it's not, return NULL; */
const char *next_newline = (const char *)memchr(nextline, '\n', end - nextline);
if (! next_newline) {
return NULL;
}
-
+
/* Done */
return nextline;
}
@@ -269,12 +269,12 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
size_t result = (size_t)(-1);
while (cursor < mmap_length) {
const char * const line_start = begin + cursor;
-
+
/* Advance the cursor to the next line */
const char *newline = (const char *)memchr(line_start, '\n', mmap_length - cursor);
if (newline == NULL)
break;
-
+
/* Advance the cursor past this line. +1 is for the newline */
size_t line_len = newline - line_start;
cursor += line_len + 1;
@@ -282,11 +282,11 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
/* Skip lines with a leading space, since these are in the interior of one of our items */
if (line_start[0] == ' ')
continue;
-
+
/* Skip very short lines to make one of the checks below easier */
if (line_len < 3)
continue;
-
+
/* Try to be a little YAML compatible. Skip lines with leading %, ---, or ... */
if (! memcmp(line_start, "%", 1) ||
! memcmp(line_start, "---", 3) ||
@@ -298,7 +298,7 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
/* Hackish fast way to skip items created after our timestamp. This is the mechanism by which we avoid "seeing" commands from other sessions that started after we started. We try hard to ensure that our items are sorted by their timestamps, so in theory we could just break, but I don't think that works well if (for example) the clock changes. So we'll read all subsequent items.
*/
const char * const end = begin + mmap_length;
-
+
/* Walk over lines that we think are interior. These lines are not null terminated, but are guaranteed to contain a newline. */
bool has_timestamp = false;
time_t timestamp;
@@ -306,18 +306,18 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
for (interior_line = next_line(line_start, end - line_start);
interior_line != NULL && ! has_timestamp;
interior_line = next_line(interior_line, end - interior_line)) {
-
+
/* If the first character is not a space, it's not an interior line, so we're done */
if (interior_line[0] != ' ')
break;
-
+
/* Hackish optimization: since we just stepped over some interior line, update the cursor so we don't have to look at these lines next time */
cursor = interior_line - begin;
-
+
/* Try parsing a timestamp from this line. If we succeed, the loop will break. */
has_timestamp = parse_timestamp(interior_line, &timestamp);
}
-
+
/* Skip this item if the timestamp is at or after our cutoff. */
if (has_timestamp && timestamp >= cutoff_timestamp) {
continue;
@@ -338,47 +338,47 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
static size_t offset_of_next_item_fish_1_x(const char *begin, size_t mmap_length, size_t *inout_cursor, time_t cutoff_timestamp) {
if (mmap_length == 0 || *inout_cursor >= mmap_length)
return (size_t)(-1);
-
- const char *end = begin + mmap_length;
- const char *pos;
- bool ignore_newline = false;
- bool do_push = true;
+ const char *end = begin + mmap_length;
+ const char *pos;
+
+ bool ignore_newline = false;
+ bool do_push = true;
bool all_done = false;
size_t result = *inout_cursor;
- for( pos = begin + *inout_cursor; pos < end && ! all_done; pos++ )
- {
-
- if( do_push )
- {
- ignore_newline = (*pos == '#');
- do_push = false;
- }
-
- switch( *pos )
- {
- case '\\':
- {
- pos++;
- break;
- }
-
- case '\n':
- {
- if( ignore_newline )
- {
- ignore_newline = false;
- }
- else
- {
+ for( pos = begin + *inout_cursor; pos < end && ! all_done; pos++ )
+ {
+
+ if( do_push )
+ {
+ ignore_newline = (*pos == '#');
+ do_push = false;
+ }
+
+ switch( *pos )
+ {
+ case '\\':
+ {
+ pos++;
+ break;
+ }
+
+ case '\n':
+ {
+ if( ignore_newline )
+ {
+ ignore_newline = false;
+ }
+ else
+ {
/* Note: pos will be left pointing just after this newline, because of the ++ in the loop */
all_done = true;
- }
- break;
- }
- }
- }
+ }
+ break;
+ }
+ }
+ }
*inout_cursor = (pos - begin);
return result;
}
@@ -390,11 +390,11 @@ static size_t offset_of_next_item(const char *begin, size_t mmap_length, history
case history_type_fish_2_0:
result = offset_of_next_item_fish_2_0(begin, mmap_length, inout_cursor, cutoff_timestamp);
break;
-
+
case history_type_fish_1_x:
result = offset_of_next_item_fish_1_x(begin, mmap_length, inout_cursor, cutoff_timestamp);
break;
-
+
default:
case history_type_unknown:
// Oh well
@@ -433,7 +433,7 @@ history_t::~history_t()
void history_t::add(const history_item_t &item)
{
scoped_lock locker(lock);
-
+
/* Try merging with the last item */
if (! new_items.empty() && new_items.back().merge(item)) {
/* We merged, so we don't have to add anything */
@@ -444,16 +444,16 @@ void history_t::add(const history_item_t &item)
new_items.push_back(item);
unsaved_item_count++;
}
-
+
/* Prevent the first write from always triggering a save */
time_t now = time(NULL);
if (! save_timestamp)
save_timestamp = now;
-
+
/* This might be a good candidate for moving to a background thread */
if((now > save_timestamp + SAVE_INTERVAL) || (unsaved_item_count >= SAVE_COUNT)) {
time_profiler_t profiler("save_internal");
- this->save_internal();
+ this->save_internal();
}
}
@@ -467,7 +467,7 @@ void history_t::remove(const wcstring &str)
{
/* Add to our list of deleted items */
deleted_items.insert(str);
-
+
/* Remove from our list of new items */
for (std::vector<history_item_t>::iterator iter = new_items.begin(); iter != new_items.end();)
{
@@ -482,9 +482,9 @@ void history_t::remove(const wcstring &str)
void history_t::get_string_representation(wcstring &result, const wcstring &separator)
{
scoped_lock locker(lock);
-
+
bool first = true;
-
+
/* Append new items */
for (std::vector<history_item_t>::const_reverse_iterator iter=new_items.rbegin(); iter < new_items.rend(); ++iter) {
if (! first)
@@ -492,10 +492,10 @@ void history_t::get_string_representation(wcstring &result, const wcstring &sepa
result.append(iter->str());
first = false;
}
-
+
/* Append old items */
load_old_if_needed();
- for (std::vector<size_t>::const_reverse_iterator iter = old_item_offsets.rbegin(); iter != old_item_offsets.rend(); ++iter) {
+ for (std::vector<size_t>::const_reverse_iterator iter = old_item_offsets.rbegin(); iter != old_item_offsets.rend(); ++iter) {
size_t offset = *iter;
const history_item_t item = history_t::decode_item(mmap_start + offset, mmap_length - offset, mmap_type);
if (! first)
@@ -507,17 +507,17 @@ void history_t::get_string_representation(wcstring &result, const wcstring &sepa
history_item_t history_t::item_at_index(size_t idx) {
scoped_lock locker(lock);
-
+
/* 0 is considered an invalid index */
assert(idx > 0);
idx--;
-
+
/* idx=0 corresponds to last item in new_items */
size_t new_item_count = new_items.size();
if (idx < new_item_count) {
return new_items.at(new_item_count - idx - 1);
}
-
+
/* Now look in our old items */
idx -= new_item_count;
load_old_if_needed();
@@ -527,7 +527,7 @@ history_item_t history_t::item_at_index(size_t idx) {
size_t offset = old_item_offsets.at(old_item_count - idx - 1);
return history_t::decode_item(mmap_start + offset, mmap_length - offset, mmap_type);
}
-
+
/* Index past the valid range, so return an empty history item */
return history_item_t(wcstring(), 0);
}
@@ -541,7 +541,7 @@ static size_t read_line(const char *base, size_t cursor, size_t len, std::string
if (newline != NULL) {
/* We found a newline. */
result.assign(start, newline - start);
-
+
/* Return the amount to advance the cursor; skip over the newline */
return newline - start + 1;
} else {
@@ -564,13 +564,13 @@ static bool extract_prefix(std::string &key, std::string &value, const std::stri
size_t where = line.find(":");
if (where != std::string::npos) {
key = line.substr(0, where);
-
+
// skip a space after the : if necessary
size_t val_start = where + 1;
if (val_start < line.size() && line.at(val_start) == ' ')
val_start++;
value = line.substr(val_start);
-
+
unescape_yaml(key);
unescape_yaml(value);
}
@@ -582,16 +582,16 @@ history_item_t history_t::decode_item_fish_2_0(const char *base, size_t len) {
wcstring cmd;
time_t when = 0;
path_list_t paths;
-
+
size_t indent = 0, cursor = 0;
std::string key, value, line;
-
+
/* Read the "- cmd:" line */
size_t advance = read_line(base, cursor, len, line);
trim_leading_spaces(line);
if (! extract_prefix(key, value, line) || key != "- cmd")
goto done;
-
+
cursor += advance;
cmd = str2wcstring(value);
@@ -599,22 +599,22 @@ history_item_t history_t::decode_item_fish_2_0(const char *base, size_t len) {
for (;;) {
/* Read a line */
size_t advance = read_line(base, cursor, len, line);
-
+
/* Count and trim leading spaces */
size_t this_indent = trim_leading_spaces(line);
if (indent == 0)
indent = this_indent;
-
+
if (this_indent == 0 || indent != this_indent)
break;
-
+
if (! extract_prefix(key, value, line))
break;
-
+
/* We are definitely going to consume this line */
unescape_yaml(value);
cursor += advance;
-
+
if (key == "when") {
/* Parse an int from the timestamp */
long tmp = 0;
@@ -627,13 +627,13 @@ history_item_t history_t::decode_item_fish_2_0(const char *base, size_t len) {
size_t advance = read_line(base, cursor, len, line);
if (trim_leading_spaces(line) <= indent)
break;
-
+
if (strncmp(line.c_str(), "- ", 2))
break;
-
+
/* We're going to consume this line */
cursor += advance;
-
+
/* Skip the leading dash-space and then store this path it */
line.erase(0, 2);
unescape_yaml(line);
@@ -660,21 +660,21 @@ history_item_t history_t::decode_item(const char *base, size_t len, history_file
static wcstring history_unescape_newlines_fish_1_x( const wcstring &in_str )
{
wcstring out;
- for (const wchar_t *in = in_str.c_str(); *in; in++)
- {
- if( *in == L'\\' )
- {
- if( *(in+1)!= L'\n')
- {
- out.push_back(*in);
- }
- }
- else
- {
- out.push_back(*in);
- }
- }
- return out;
+ for (const wchar_t *in = in_str.c_str(); *in; in++)
+ {
+ if( *in == L'\\' )
+ {
+ if( *(in+1)!= L'\n')
+ {
+ out.push_back(*in);
+ }
+ }
+ else
+ {
+ out.push_back(*in);
+ }
+ }
+ return out;
}
@@ -689,7 +689,7 @@ history_item_t history_t::decode_item_fish_1_x(const char *begin, size_t length)
bool first_char = true;
bool timestamp_mode = false;
time_t timestamp = 0;
-
+
while( 1 )
{
wchar_t c;
@@ -761,7 +761,7 @@ history_item_t history_t::decode_item_fish_1_x(const char *begin, size_t length)
was_backslash = ( (c == L'\\') && !was_backslash);
}
-
+
out = history_unescape_newlines_fish_1_x(out);
return history_item_t(out, timestamp);
}
@@ -793,7 +793,7 @@ void history_t::populate_from_mmap(void)
break;
// Remember this item
- old_item_offsets.push_back(offset);
+ old_item_offsets.push_back(offset);
}
}
@@ -805,25 +805,25 @@ static bool map_file(const wcstring &name, const char **out_map_start, size_t *o
if (! filename.empty())
{
int fd;
- if((fd = wopen_cloexec(filename, O_RDONLY)) > 0)
- {
- off_t len = lseek( fd, 0, SEEK_END );
- if(len != (off_t)-1)
- {
- size_t mmap_length = (size_t)len;
- if(lseek(fd, 0, SEEK_SET) == 0)
- {
+ if((fd = wopen_cloexec(filename, O_RDONLY)) > 0)
+ {
+ off_t len = lseek( fd, 0, SEEK_END );
+ if(len != (off_t)-1)
+ {
+ size_t mmap_length = (size_t)len;
+ if(lseek(fd, 0, SEEK_SET) == 0)
+ {
char *mmap_start;
- if ((mmap_start = (char *)mmap(0, mmap_length, PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED)
- {
- result = true;
+ if ((mmap_start = (char *)mmap(0, mmap_length, PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED)
+ {
+ result = true;
*out_map_start = mmap_start;
*out_map_len = mmap_length;
- }
- }
- }
- close( fd );
- }
+ }
+ }
+ }
+ close( fd );
+ }
}
return result;
}
@@ -832,20 +832,20 @@ bool history_t::load_old_if_needed(void)
{
if (loaded_old) return true;
loaded_old = true;
-
-
+
+
// PCA not sure why signals were blocked here
- //signal_block();
-
- bool ok = false;
+ //signal_block();
+
+ bool ok = false;
if (map_file(name, &mmap_start, &mmap_length)) {
// Here we've mapped the file
ok = true;
time_profiler_t profiler("populate_from_mmap");
this->populate_from_mmap();
- }
-
- //signal_unblock();
+ }
+
+ //signal_unblock();
return ok;
}
@@ -874,10 +874,10 @@ bool history_search_t::go_backwards() {
size_t idx = 0;
if (! prev_matches.empty())
idx = prev_matches.back().first;
-
+
if (idx == max_idx)
return false;
-
+
while (++idx < max_idx) {
const history_item_t item = history->item_at_index(idx);
/* We're done if it's empty */
@@ -915,7 +915,7 @@ void history_search_t::go_to_beginning(void) {
history_item_t history_search_t::current_item() const {
- assert(! prev_matches.empty());
+ assert(! prev_matches.empty());
return prev_matches.back().second;
}
@@ -974,7 +974,7 @@ static wcstring history_filename(const wcstring &name, const wcstring &suffix)
wcstring path;
if (! path_get_config(path))
return L"";
-
+
wcstring result = path;
result.append(L"/");
result.append(name);
@@ -1014,25 +1014,25 @@ void history_t::save_internal()
{
/* This must be called while locked */
ASSERT_IS_LOCKED(lock);
-
+
/* Nothing to do if there's no new items */
if (new_items.empty() && deleted_items.empty())
return;
-
+
/* Compact our new items so we don't have duplicates */
this->compact_new_items();
-
- bool ok = true;
-
- wcstring tmp_name = history_filename(name, L".tmp");
- if( ! tmp_name.empty() )
- {
+
+ bool ok = true;
+
+ wcstring tmp_name = history_filename(name, L".tmp");
+ if( ! tmp_name.empty() )
+ {
/* Make an LRU cache to save only the last N elements */
history_lru_cache_t lru(HISTORY_SAVE_MAX);
-
+
/* Insert old items in, from old to new. Merge them with our new items, inserting items with earlier timestamps first. */
std::vector<history_item_t>::const_iterator new_item_iter = new_items.begin();
-
+
/* Map in existing items (which may have changed out from underneath us, so don't trust our old mmap'd data) */
const char *local_mmap_start = NULL;
size_t local_mmap_size = 0;
@@ -1062,24 +1062,24 @@ void history_t::save_internal()
break;
}
}
-
+
/* Now add this old item */
lru.add_item(old_item);
}
munmap((void *)local_mmap_start, local_mmap_size);
}
-
+
/* Insert any remaining new items */
for (; new_item_iter != new_items.end(); ++new_item_iter)
{
lru.add_item(*new_item_iter);
}
-
+
signal_block();
-
+
FILE *out;
- if( (out=wfopen( tmp_name, "w" ) ) )
- {
+ if( (out=wfopen( tmp_name, "w" ) ) )
+ {
/* Write them out */
for (history_lru_cache_t::iterator iter = lru.begin(); iter != lru.end(); ++iter) {
const history_lru_node_t *node = *iter;
@@ -1088,36 +1088,36 @@ void history_t::save_internal()
break;
}
}
-
- if( fclose( out ) || !ok )
- {
- /*
- This message does not have high enough priority to
- be shown by default.
- */
- debug( 2, L"Error when writing history file" );
- }
- else
- {
+
+ if( fclose( out ) || !ok )
+ {
+ /*
+ This message does not have high enough priority to
+ be shown by default.
+ */
+ debug( 2, L"Error when writing history file" );
+ }
+ else
+ {
wcstring new_name = history_filename(name, wcstring());
- wrename(tmp_name, new_name);
- }
- }
-
+ wrename(tmp_name, new_name);
+ }
+ }
+
signal_unblock();
-
+
/* Make sure we clear all nodes, since this doesn't happen automatically */
lru.evict_all_nodes();
-
+
/* We've saved everything, so we have no more unsaved items */
unsaved_item_count = 0;
- }
+ }
- if( ok )
- {
- /* Our history has been written to the file, so clear our state so we can re-reference the file. */
- this->clear_file_state();
- }
+ if( ok )
+ {
+ /* Our history has been written to the file, so clear our state so we can re-reference the file. */
+ this->clear_file_state();
+ }
}
void history_t::save(void)
@@ -1137,7 +1137,7 @@ void history_t::clear(void)
if (! filename.empty())
wunlink(filename);
this->clear_file_state();
-
+
}
bool history_t::is_empty(void)
@@ -1157,24 +1157,24 @@ static bool should_import_bash_history_line(const std::string &line)
{
if (line.empty())
return false;
-
+
/* Very naive tests! Skip export; probably should skip others. */
const char * const ignore_prefixes[] = {
"export ",
"#"
};
-
+
for (size_t i=0; i < sizeof ignore_prefixes / sizeof *ignore_prefixes; i++) {
const char *prefix = ignore_prefixes[i];
if (! line.compare(0, strlen(prefix), prefix)) {
return false;
}
}
-
+
/* Skip lines with backticks */
if (line.find('`') != std::string::npos)
return false;
-
+
return true;
}
@@ -1187,7 +1187,7 @@ void history_t::populate_from_bash(FILE *stream)
for (;;) {
line.clear();
bool success = false, has_newline = false;
-
+
/* Loop until we've read a line */
do {
char buff[128];
@@ -1197,17 +1197,17 @@ void history_t::populate_from_bash(FILE *stream)
char *newline = strchr(buff, '\n');
if (newline) *newline = '\0';
has_newline = (newline != NULL);
-
+
/* Append what we've got */
line.append(buff);
}
} while (success && ! has_newline);
-
+
/* Maybe add this line */
if (should_import_bash_history_line(line)) {
this->add(str2wcstring(line));
}
-
+
if (line.empty())
break;
}
@@ -1229,16 +1229,16 @@ void history_destroy()
void history_sanity_check()
{
- /*
- No sanity checking implemented yet...
- */
+ /*
+ No sanity checking implemented yet...
+ */
}
int file_detection_context_t::perform_file_detection(bool test_all) {
ASSERT_IS_BACKGROUND_THREAD();
valid_paths.clear();
int result = 1;
- for (path_list_t::const_iterator iter = potential_paths.begin(); iter != potential_paths.end(); ++iter) {
+ for (path_list_t::const_iterator iter = potential_paths.begin(); iter != potential_paths.end(); ++iter) {
if (path_is_valid(*iter, working_directory)) {
/* Push the original (possibly relative) path */
valid_paths.push_back(*iter);
@@ -1274,7 +1274,7 @@ static int threaded_perform_file_detection(file_detection_context_t *ctx) {
static void perform_file_detection_done(file_detection_context_t *ctx, int success) {
/* Now that file detection is done, create the history item */
ctx->history->add(ctx->command, ctx->valid_paths);
-
+
/* Done with the context. */
delete ctx;
}
@@ -1290,7 +1290,7 @@ void history_t::add_with_file_detection(const wcstring &str)
{
ASSERT_IS_MAIN_THREAD();
path_list_t potential_paths;
-
+
tokenizer tokenizer;
for( tok_init( &tokenizer, str.c_str(), TOK_SQUASH_ERRORS );
tok_has_next( &tokenizer );
@@ -1308,11 +1308,11 @@ void history_t::add_with_file_detection(const wcstring &str)
}
}
tok_destroy(&tokenizer);
-
+
if (! potential_paths.empty()) {
/* We have some paths. Make a context. */
file_detection_context_t *context = new file_detection_context_t(this, str);
-
+
/* Store the potential paths. Reverse them to put them in the same order as in the command. */
context->potential_paths.swap(potential_paths);
iothread_perform(threaded_perform_file_detection, perform_file_detection_done, context);
diff --git a/history.h b/history.h
index 9bfb2a51..3d083acb 100644
--- a/history.h
+++ b/history.h
@@ -18,7 +18,7 @@ typedef std::vector<wcstring> path_list_t;
enum history_search_type_t {
/** The history searches for strings containing the given string */
HISTORY_SEARCH_TYPE_CONTAINS,
-
+
/** The history searches for strings starting with the given string */
HISTORY_SEARCH_TYPE_PREFIX
};
@@ -31,30 +31,30 @@ class history_item_t {
private:
explicit history_item_t(const wcstring &);
explicit history_item_t(const wcstring &, time_t, const path_list_t &paths = path_list_t());
-
+
/** Attempts to merge two compatible history items together */
bool merge(const history_item_t &item);
- /** The actual contents of the entry */
- wcstring contents;
-
- /** Original creation time for the entry */
- time_t creation_timestamp;
-
+ /** The actual contents of the entry */
+ wcstring contents;
+
+ /** Original creation time for the entry */
+ time_t creation_timestamp;
+
/** Paths that we require to be valid for this item to be autosuggested */
path_list_t required_paths;
-
+
public:
const wcstring &str() const { return contents; }
bool empty() const { return contents.empty(); }
-
+
/* Whether our contents matches a search term. */
bool matches_search(const wcstring &term, enum history_search_type_t type) const;
-
+
time_t timestamp() const { return creation_timestamp; }
-
+
const path_list_t &get_required_paths() const { return required_paths; }
-
+
bool operator==(const history_item_t &other) const {
return contents == other.contents &&
creation_timestamp == other.creation_timestamp &&
@@ -78,36 +78,36 @@ private:
/** Private creator */
history_t(const wcstring &pname);
-
+
/** Privately add an item */
void add(const history_item_t &item);
-
+
/** Destructor */
~history_t();
/** Lock for thread safety */
pthread_mutex_t lock;
-
+
/** Internal function */
void clear_file_state();
- /** The name of this list. Used for picking a suitable filename and for switching modes. */
- const wcstring name;
-
- /** New items. */
- std::vector<history_item_t> new_items;
+ /** The name of this list. Used for picking a suitable filename and for switching modes. */
+ const wcstring name;
+
+ /** New items. */
+ std::vector<history_item_t> new_items;
+
+ /** Deleted item contents. */
+ std::set<wcstring> deleted_items;
- /** Deleted item contents. */
- std::set<wcstring> deleted_items;
+ /** How many items we've added without saving */
+ size_t unsaved_item_count;
- /** How many items we've added without saving */
- size_t unsaved_item_count;
-
- /** The mmaped region for the history file */
- const char *mmap_start;
+ /** The mmaped region for the history file */
+ const char *mmap_start;
- /** The size of the mmap'd region */
- size_t mmap_length;
+ /** The size of the mmap'd region */
+ size_t mmap_length;
/** The type of file we mmap'd */
history_file_type_t mmap_type;
@@ -115,23 +115,23 @@ private:
/** Timestamp of when this history was created */
const time_t birth_timestamp;
- /** Timestamp of last save */
- time_t save_timestamp;
-
+ /** Timestamp of last save */
+ time_t save_timestamp;
+
void populate_from_mmap(void);
-
+
/** List of old items, as offsets into out mmap data */
std::vector<size_t> old_item_offsets;
-
+
/** Whether we've loaded old items */
bool loaded_old;
-
+
/** Loads old if necessary */
bool load_old_if_needed(void);
-
+
/** Deletes duplicates in new_items. */
void compact_new_items();
-
+
/** Saves history */
void save_internal();
@@ -139,38 +139,38 @@ private:
static history_item_t decode_item_fish_2_0(const char *base, size_t len);
static history_item_t decode_item_fish_1_x(const char *base, size_t len);
static history_item_t decode_item(const char *base, size_t len, history_file_type_t type);
-
+
public:
/** Returns history with the given name, creating it if necessary */
static history_t & history_with_name(const wcstring &name);
-
+
/** Determines whether the history is empty. Unfortunately this cannot be const, since it may require populating the history. */
bool is_empty(void);
-
+
/** Add a new history item to the end */
void add(const wcstring &str, const path_list_t &valid_paths = path_list_t());
/** Remove a history item */
void remove(const wcstring &str);
-
+
/** Add a new history item to the end */
void add_with_file_detection(const wcstring &str);
-
+
/** Saves history */
void save();
-
+
/** Irreversibly clears history */
void clear();
-
+
/** Populates from a bash history file */
void populate_from_bash(FILE *f);
-
+
/* Gets all the history into a string with ARRAY_SEP_STR. This is intended for the $history environment variable. This may be long! */
void get_string_representation(wcstring &str, const wcstring &separator);
-
+
/** Return the specified history at the specified index. 0 is the index of the current commandline. (So the most recent item is at index 1.) */
history_item_t item_at_index(size_t idx);
-
+
bool is_deleted(const history_item_t &item) const;
};
@@ -178,10 +178,10 @@ class history_search_t {
/** The history in which we are searching */
history_t * history;
-
+
/** Our type */
enum history_search_type_t search_type;
-
+
/** Our list of previous matches as index, value. The end is the current match. */
typedef std::pair<size_t, history_item_t> prev_match_t;
std::vector<prev_match_t> prev_matches;
@@ -191,14 +191,14 @@ class history_search_t {
/** The search term */
wcstring term;
-
+
/** Additional strings to skip (sorted) */
wcstring_list_t external_skips;
-
+
bool should_skip_match(const wcstring &str) const;
-
+
public:
-
+
/** Gets the search term */
const wcstring &get_term() const { return term; }
@@ -207,22 +207,22 @@ class history_search_t {
/** Finds the next search term (forwards in time). Returns true if one was found. */
bool go_forwards(void);
-
+
/** Finds the previous search result (backwards in time). Returns true if one was found. */
bool go_backwards(void);
-
+
/** Goes to the end (forwards) */
void go_to_end(void);
-
+
/** Returns if we are at the end. We start out at the end. */
bool is_at_end(void) const;
-
+
/** Goes to the beginning (backwards) */
void go_to_beginning(void);
-
+
/** Returns the current search result item. asserts if there is no current item. */
history_item_t current_item(void) const;
-
+
/** Returns the current search result item contents. asserts if there is no current item. */
wcstring current_string(void) const;
@@ -233,14 +233,14 @@ class history_search_t {
search_type(type),
term(str)
{}
-
+
/* Default constructor */
history_search_t() :
history(),
search_type(HISTORY_SEARCH_TYPE_CONTAINS),
term()
{}
-
+
};
@@ -266,31 +266,31 @@ struct file_detection_context_t {
/* Constructor */
file_detection_context_t(history_t *hist, const wcstring &cmd);
-
+
/* Determine which of potential_paths are valid, and put them in valid_paths */
int perform_file_detection();
-
+
/* The history associated with this context */
history_t *history;
-
+
/* The command */
wcstring command;
-
+
/* When the command was issued */
time_t when;
-
+
/* The working directory at the time the command was issued */
wcstring working_directory;
-
+
/* Paths to test */
path_list_t potential_paths;
-
+
/* Paths that were found to be valid */
path_list_t valid_paths;
-
+
/* Performs file detection. Returns 1 if every path in potential_paths is valid, 0 otherwise. If test_all is true, tests every path; otherwise stops as soon as it reaches an invalid path. */
int perform_file_detection(bool test_all);
-
+
/* Determine whether the given paths are all valid */
bool paths_are_valid(const path_list_t &paths);
};
diff --git a/input.cpp b/input.cpp
index 1db104f7..ac57b83c 100644
--- a/input.cpp
+++ b/input.cpp
@@ -74,10 +74,10 @@
*/
struct input_mapping_t
{
- wcstring seq; /**< Character sequence which generates this event */
- wcstring command; /**< command that should be evaluated by this mapping */
-
-
+ wcstring seq; /**< Character sequence which generates this event */
+ wcstring command; /**< command that should be evaluated by this mapping */
+
+
input_mapping_t(const wcstring &s, const wcstring &c) : seq(s), command(c) {}
};
@@ -86,9 +86,9 @@ struct input_mapping_t
*/
struct terminfo_mapping_t
{
- const wchar_t *name; /**< Name of key */
- const char *seq; /**< Character sequence generated on keypress. Constant string. */
-
+ const wchar_t *name; /**< Name of key */
+ const char *seq; /**< Character sequence generated on keypress. Constant string. */
+
};
@@ -97,43 +97,43 @@ struct terminfo_mapping_t
*/
static const wchar_t * const name_arr[] =
{
- L"beginning-of-line",
- L"end-of-line",
- L"forward-char",
- L"backward-char",
- L"forward-word",
- L"backward-word",
- L"history-search-backward",
- L"history-search-forward",
- L"delete-char",
- L"backward-delete-char",
- L"kill-line",
- L"yank",
- L"yank-pop",
- L"complete",
- L"beginning-of-history",
- L"end-of-history",
- L"backward-kill-line",
- L"kill-whole-line",
- L"kill-word",
- L"backward-kill-word",
- L"dump-functions",
- L"history-token-search-backward",
- L"history-token-search-forward",
- L"self-insert",
- L"null",
- L"eof",
- L"vi-arg-digit",
- L"execute",
- L"beginning-of-buffer",
- L"end-of-buffer",
- L"repaint",
- L"up-line",
- L"down-line",
- L"suppress-autosuggestion",
- L"accept-autosuggestion"
+ L"beginning-of-line",
+ L"end-of-line",
+ L"forward-char",
+ L"backward-char",
+ L"forward-word",
+ L"backward-word",
+ L"history-search-backward",
+ L"history-search-forward",
+ L"delete-char",
+ L"backward-delete-char",
+ L"kill-line",
+ L"yank",
+ L"yank-pop",
+ L"complete",
+ L"beginning-of-history",
+ L"end-of-history",
+ L"backward-kill-line",
+ L"kill-whole-line",
+ L"kill-word",
+ L"backward-kill-word",
+ L"dump-functions",
+ L"history-token-search-backward",
+ L"history-token-search-forward",
+ L"self-insert",
+ L"null",
+ L"eof",
+ L"vi-arg-digit",
+ L"execute",
+ L"beginning-of-buffer",
+ L"end-of-buffer",
+ L"repaint",
+ L"up-line",
+ L"down-line",
+ L"suppress-autosuggestion",
+ L"accept-autosuggestion"
}
- ;
+ ;
/**
Description of each supported input function
@@ -141,82 +141,82 @@ static const wchar_t * const name_arr[] =
/*
static const wchar_t *desc_arr[] =
{
- L"Move to beginning of line",
- L"Move to end of line",
- L"Move forward one character",
- L"Move backward one character",
- L"Move forward one word",
- L"Move backward one word",
- L"Search backward through list of previous commands",
- L"Search forward through list of previous commands",
- L"Delete one character forward",
- L"Delete one character backward",
- L"Move contents from cursor to end of line to killring",
- L"Paste contents of killring",
- L"Rotate to previous killring entry",
- L"Guess the rest of the next input token",
- L"Move to first item of history",
- L"Move to last item of history",
- L"Clear current line",
- L"Move contents from beginning of line to cursor to killring",
- L"Move entire line to killring",
- L"Move next word to killring",
- L"Move previous word to killring",
- L"Write out key bindings",
- L"Clear entire screen",
- L"Quit the running program",
- L"Search backward through list of previous commands for matching token",
- L"Search forward through list of previous commands for matching token",
- L"Insert the pressed key",
- L"Do nothing",
- L"End of file",
- L"Repeat command"
+ L"Move to beginning of line",
+ L"Move to end of line",
+ L"Move forward one character",
+ L"Move backward one character",
+ L"Move forward one word",
+ L"Move backward one word",
+ L"Search backward through list of previous commands",
+ L"Search forward through list of previous commands",
+ L"Delete one character forward",
+ L"Delete one character backward",
+ L"Move contents from cursor to end of line to killring",
+ L"Paste contents of killring",
+ L"Rotate to previous killring entry",
+ L"Guess the rest of the next input token",
+ L"Move to first item of history",
+ L"Move to last item of history",
+ L"Clear current line",
+ L"Move contents from beginning of line to cursor to killring",
+ L"Move entire line to killring",
+ L"Move next word to killring",
+ L"Move previous word to killring",
+ L"Write out key bindings",
+ L"Clear entire screen",
+ L"Quit the running program",
+ L"Search backward through list of previous commands for matching token",
+ L"Search forward through list of previous commands for matching token",
+ L"Insert the pressed key",
+ L"Do nothing",
+ L"End of file",
+ L"Repeat command"
}
- ;
+ ;
*/
/**
Internal code for each supported input function
*/
-static const wchar_t code_arr[] =
+static const wchar_t code_arr[] =
{
- R_BEGINNING_OF_LINE,
- R_END_OF_LINE,
- R_FORWARD_CHAR,
- R_BACKWARD_CHAR,
- R_FORWARD_WORD,
- R_BACKWARD_WORD,
- R_HISTORY_SEARCH_BACKWARD,
- R_HISTORY_SEARCH_FORWARD,
- R_DELETE_CHAR,
- R_BACKWARD_DELETE_CHAR,
- R_KILL_LINE,
- R_YANK,
- R_YANK_POP,
- R_COMPLETE,
- R_BEGINNING_OF_HISTORY,
- R_END_OF_HISTORY,
- R_BACKWARD_KILL_LINE,
- R_KILL_WHOLE_LINE,
- R_KILL_WORD,
- R_BACKWARD_KILL_WORD,
- R_DUMP_FUNCTIONS,
- R_HISTORY_TOKEN_SEARCH_BACKWARD,
- R_HISTORY_TOKEN_SEARCH_FORWARD,
- R_SELF_INSERT,
- R_NULL,
- R_EOF,
- R_VI_ARG_DIGIT,
- R_EXECUTE,
- R_BEGINNING_OF_BUFFER,
- R_END_OF_BUFFER,
- R_REPAINT,
- R_UP_LINE,
- R_DOWN_LINE,
- R_SUPPRESS_AUTOSUGGESTION,
- R_ACCEPT_AUTOSUGGESTION
+ R_BEGINNING_OF_LINE,
+ R_END_OF_LINE,
+ R_FORWARD_CHAR,
+ R_BACKWARD_CHAR,
+ R_FORWARD_WORD,
+ R_BACKWARD_WORD,
+ R_HISTORY_SEARCH_BACKWARD,
+ R_HISTORY_SEARCH_FORWARD,
+ R_DELETE_CHAR,
+ R_BACKWARD_DELETE_CHAR,
+ R_KILL_LINE,
+ R_YANK,
+ R_YANK_POP,
+ R_COMPLETE,
+ R_BEGINNING_OF_HISTORY,
+ R_END_OF_HISTORY,
+ R_BACKWARD_KILL_LINE,
+ R_KILL_WHOLE_LINE,
+ R_KILL_WORD,
+ R_BACKWARD_KILL_WORD,
+ R_DUMP_FUNCTIONS,
+ R_HISTORY_TOKEN_SEARCH_BACKWARD,
+ R_HISTORY_TOKEN_SEARCH_FORWARD,
+ R_SELF_INSERT,
+ R_NULL,
+ R_EOF,
+ R_VI_ARG_DIGIT,
+ R_EXECUTE,
+ R_BEGINNING_OF_BUFFER,
+ R_END_OF_BUFFER,
+ R_REPAINT,
+ R_UP_LINE,
+ R_DOWN_LINE,
+ R_SUPPRESS_AUTOSUGGESTION,
+ R_ACCEPT_AUTOSUGGESTION
}
- ;
+ ;
/** Mappings for the current input mode */
static std::vector<input_mapping_t> mapping_list;
@@ -234,7 +234,7 @@ static std::vector<terminfo_mapping_t> mappings;
/**
- Set to one when the input subsytem has been initialized.
+ Set to one when the input subsytem has been initialized.
*/
static int is_init = 0;
@@ -249,25 +249,25 @@ static void input_terminfo_init();
*/
void input_mapping_add( const wchar_t *sequence,
- const wchar_t *command )
+ const wchar_t *command )
{
- size_t i;
- CHECK( sequence, );
- CHECK( command, );
-
- // debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) );
-
-
- for( i=0; i<mapping_list.size(); i++ )
- {
- input_mapping_t &m = mapping_list.at(i);
- if( m.seq == sequence )
- {
- m.command = command;
- return;
- }
- }
- mapping_list.push_back(input_mapping_t(sequence, command));
+ size_t i;
+ CHECK( sequence, );
+ CHECK( command, );
+
+ // debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) );
+
+
+ for( i=0; i<mapping_list.size(); i++ )
+ {
+ input_mapping_t &m = mapping_list.at(i);
+ if( m.seq == sequence )
+ {
+ m.command = command;
+ return;
+ }
+ }
+ mapping_list.push_back(input_mapping_t(sequence, command));
}
/**
@@ -276,29 +276,29 @@ void input_mapping_add( const wchar_t *sequence,
*/
static int interrupt_handler()
{
- /*
- Fire any pending events
- */
- event_fire( NULL );
-
- /*
- Reap stray processes, including printing exit status messages
- */
- if( job_reap( 1 ) )
- reader_repaint_needed();
-
- /*
- Tell the reader an event occured
- */
- if( reader_interrupted() )
- {
- /*
- Return 3, i.e. the character read by a Control-C.
- */
- return 3;
- }
-
- return R_NULL;
+ /*
+ Fire any pending events
+ */
+ event_fire( NULL );
+
+ /*
+ Reap stray processes, including printing exit status messages
+ */
+ if( job_reap( 1 ) )
+ reader_repaint_needed();
+
+ /*
+ Tell the reader an event occured
+ */
+ if( reader_interrupted() )
+ {
+ /*
+ Return 3, i.e. the character read by a Control-C.
+ */
+ return 3;
+ }
+
+ return R_NULL;
}
void update_fish_term256(void)
@@ -329,54 +329,54 @@ void update_fish_term256(void)
int input_init()
{
- if( is_init )
- return 1;
-
- is_init = 1;
-
- input_common_init( &interrupt_handler );
-
- if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
- {
- debug( 0, _( L"Could not set up terminal" ) );
- exit_without_destructors(1);
- }
+ if( is_init )
+ return 1;
+
+ is_init = 1;
+
+ input_common_init( &interrupt_handler );
+
+ if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
+ {
+ debug( 0, _( L"Could not set up terminal" ) );
+ exit_without_destructors(1);
+ }
const env_var_t term = env_get_string( L"TERM" );
assert(! term.missing());
- output_set_term( term.c_str() );
-
- input_terminfo_init();
-
+ output_set_term( term.c_str() );
+
+ input_terminfo_init();
+
update_fish_term256();
- /* If we have no keybindings, add a few simple defaults */
- if( mapping_list.empty() )
- {
- input_mapping_add( L"", L"self-insert" );
- input_mapping_add( L"\n", L"execute" );
- input_mapping_add( L"\t", L"complete" );
- input_mapping_add( L"\x3", L"commandline \"\"" );
- input_mapping_add( L"\x4", L"exit" );
- input_mapping_add( L"\x5", L"bind" );
- }
-
- return 1;
+ /* If we have no keybindings, add a few simple defaults */
+ if( mapping_list.empty() )
+ {
+ input_mapping_add( L"", L"self-insert" );
+ input_mapping_add( L"\n", L"execute" );
+ input_mapping_add( L"\t", L"complete" );
+ input_mapping_add( L"\x3", L"commandline \"\"" );
+ input_mapping_add( L"\x4", L"exit" );
+ input_mapping_add( L"\x5", L"bind" );
+ }
+
+ return 1;
}
void input_destroy()
{
- if( !is_init )
- return;
-
-
- is_init=0;
-
- input_common_destroy();
-
- if( del_curterm( cur_term ) == ERR )
- {
- debug( 0, _(L"Error while closing terminfo") );
- }
+ if( !is_init )
+ return;
+
+
+ is_init=0;
+
+ input_common_destroy();
+
+ if( del_curterm( cur_term ) == ERR )
+ {
+ debug( 0, _(L"Error while closing terminfo") );
+ }
}
/**
@@ -384,50 +384,50 @@ void input_destroy()
*/
static wint_t input_exec_binding( const input_mapping_t &m, const wcstring &seq )
{
- wchar_t code = input_function_get_code( m.command );
- if( code != -1 )
- {
- switch( code )
- {
-
- case R_SELF_INSERT:
- {
- return seq[0];
- }
-
- default:
- {
- return code;
- }
-
- }
- }
- else
- {
-
- /*
- This key sequence is bound to a command, which
- is sent to the parser for evaluation.
- */
- int last_status = proc_get_last_status();
-
- parser_t::principal_parser().eval( m.command.c_str(), io_chain_t(), TOP );
-
- proc_set_last_status( last_status );
-
- /*
- We still need to return something to the caller, R_NULL
- tells the reader that no key press needs to be handled,
- and no repaint is needed.
-
- Bindings that produce output should emit a R_REPAINT
- function by calling 'commandline -f repaint' to tell
- fish that a repaint is in order.
- */
-
- return R_NULL;
-
- }
+ wchar_t code = input_function_get_code( m.command );
+ if( code != -1 )
+ {
+ switch( code )
+ {
+
+ case R_SELF_INSERT:
+ {
+ return seq[0];
+ }
+
+ default:
+ {
+ return code;
+ }
+
+ }
+ }
+ else
+ {
+
+ /*
+ This key sequence is bound to a command, which
+ is sent to the parser for evaluation.
+ */
+ int last_status = proc_get_last_status();
+
+ parser_t::principal_parser().eval( m.command.c_str(), io_chain_t(), TOP );
+
+ proc_set_last_status( last_status );
+
+ /*
+ We still need to return something to the caller, R_NULL
+ tells the reader that no key press needs to be handled,
+ and no repaint is needed.
+
+ Bindings that produce output should emit a R_REPAINT
+ function by calling 'commandline -f repaint' to tell
+ fish that a repaint is in order.
+ */
+
+ return R_NULL;
+
+ }
}
@@ -437,18 +437,18 @@ static wint_t input_exec_binding( const input_mapping_t &m, const wcstring &seq
*/
static wint_t input_try_mapping( const input_mapping_t &m)
{
- wint_t c=0;
- int j;
-
- /*
- Check if the actual function code of this mapping is on the stack
- */
- c = input_common_readch( 0 );
- if( c == input_function_get_code( m.command ) )
- {
- return input_exec_binding( m, m.seq );
- }
- input_unreadch( c );
+ wint_t c=0;
+ int j;
+
+ /*
+ Check if the actual function code of this mapping is on the stack
+ */
+ c = input_common_readch( 0 );
+ if( c == input_function_get_code( m.command ) )
+ {
+ return input_exec_binding( m, m.seq );
+ }
+ input_unreadch( c );
const wchar_t *str = m.seq.c_str();
for (j=0; str[j] != L'\0'; j++)
@@ -458,7 +458,7 @@ static wint_t input_try_mapping( const input_mapping_t &m)
if (str[j] != c)
break;
}
-
+
if( str[j] == L'\0' )
{
/* We matched the entire sequence */
@@ -476,130 +476,130 @@ static wint_t input_try_mapping( const input_mapping_t &m)
input_unreadch( m.seq[k] );
}
}
- return 0;
-
+ return 0;
+
}
void input_unreadch( wint_t ch )
{
- input_common_unreadch( ch );
+ input_common_unreadch( ch );
}
wint_t input_readch()
{
-
- size_t i;
-
- CHECK_BLOCK( R_NULL );
-
- /*
+
+ size_t i;
+
+ CHECK_BLOCK( R_NULL );
+
+ /*
Clear the interrupted flag
*/
- reader_interrupted();
-
- /*
+ reader_interrupted();
+
+ /*
Search for sequence in mapping tables
*/
-
- while( 1 )
- {
- const input_mapping_t *generic = 0;
- for( i=0; i<mapping_list.size(); i++ )
- {
- const input_mapping_t &m = mapping_list.at(i);
- wint_t res = input_try_mapping( m );
- if( res )
- return res;
-
- if( m.seq.length() == 0 )
- {
- generic = &m;
- }
-
- }
-
- /*
+
+ while( 1 )
+ {
+ const input_mapping_t *generic = 0;
+ for( i=0; i<mapping_list.size(); i++ )
+ {
+ const input_mapping_t &m = mapping_list.at(i);
+ wint_t res = input_try_mapping( m );
+ if( res )
+ return res;
+
+ if( m.seq.length() == 0 )
+ {
+ generic = &m;
+ }
+
+ }
+
+ /*
No matching exact mapping, try to find generic mapping.
*/
-
- if( generic )
- {
- wchar_t arr[2]=
+
+ if( generic )
+ {
+ wchar_t arr[2]=
{
- 0,
+ 0,
0
}
- ;
- arr[0] = input_common_readch(0);
-
- return input_exec_binding( *generic, arr );
- }
-
- /*
+ ;
+ arr[0] = input_common_readch(0);
+
+ return input_exec_binding( *generic, arr );
+ }
+
+ /*
No action to take on specified character, ignore it
and move to next one.
*/
- wchar_t c = input_common_readch( 0 );
-
+ wchar_t c = input_common_readch( 0 );
+
/* If it's closed, then just return */
if (c == R_EOF)
{
return WEOF;
}
- }
+ }
}
void input_mapping_get_names( wcstring_list_t &lst )
{
- size_t i;
-
- for( i=0; i<mapping_list.size(); i++ )
- {
- const input_mapping_t &m = mapping_list.at(i);
+ size_t i;
+
+ for( i=0; i<mapping_list.size(); i++ )
+ {
+ const input_mapping_t &m = mapping_list.at(i);
lst.push_back(wcstring(m.seq));
- }
-
+ }
+
}
bool input_mapping_erase( const wchar_t *sequence )
{
ASSERT_IS_MAIN_THREAD();
- bool result = false;
- size_t i, sz = mapping_list.size();
-
- for( i=0; i<sz; i++ )
- {
- const input_mapping_t &m = mapping_list.at(i);
- if( sequence == m.seq )
- {
- if( i != (sz-1 ) )
- {
+ bool result = false;
+ size_t i, sz = mapping_list.size();
+
+ for( i=0; i<sz; i++ )
+ {
+ const input_mapping_t &m = mapping_list.at(i);
+ if( sequence == m.seq )
+ {
+ if( i != (sz-1 ) )
+ {
mapping_list[i] = mapping_list[sz-1];
- }
+ }
mapping_list.pop_back();
- result = true;
- break;
-
- }
- }
- return result;
+ result = true;
+ break;
+
+ }
+ }
+ return result;
}
bool input_mapping_get( const wcstring &sequence, wcstring &cmd )
{
- size_t i, sz = mapping_list.size();
-
- for( i=0; i<sz; i++ )
- {
- const input_mapping_t &m = mapping_list.at(i);
- if( sequence == m.seq )
- {
- cmd = m.command;
+ size_t i, sz = mapping_list.size();
+
+ for( i=0; i<sz; i++ )
+ {
+ const input_mapping_t &m = mapping_list.at(i);
+ if( sequence == m.seq )
+ {
+ cmd = m.command;
return true;
- }
- }
- return false;
+ }
+ }
+ return false;
}
/**
@@ -655,11 +655,11 @@ static void input_terminfo_init()
TERMINFO_ADD(key_f19),
TERMINFO_ADD(key_f20),
/*
- I know of no keyboard with more than 20 function keys, so
- adding the rest here makes very little sense, since it will
- take up a lot of room in any listings (like tab completions),
- but with no benefit.
- */
+ I know of no keyboard with more than 20 function keys, so
+ adding the rest here makes very little sense, since it will
+ take up a lot of room in any listings (like tab completions),
+ but with no benefit.
+ */
/*
TERMINFO_ADD(key_f21),
TERMINFO_ADD(key_f22),
@@ -773,76 +773,76 @@ static void input_terminfo_init()
const wchar_t *input_terminfo_get_sequence( const wchar_t *name )
{
ASSERT_IS_MAIN_THREAD();
-
- const char *res = 0;
+
+ const char *res = 0;
static wcstring buff;
- int err = ENOENT;
-
- CHECK( name, 0 );
- input_init();
-
- for( size_t i=0; i<terminfo_mappings.size(); i++ )
- {
- const terminfo_mapping_t &m = terminfo_mappings.at(i);
- if( !wcscmp( name, m.name ) )
- {
- res = m.seq;
- err = EILSEQ;
- break;
- }
- }
-
- if( !res )
- {
- errno = err;
- return 0;
- }
-
+ int err = ENOENT;
+
+ CHECK( name, 0 );
+ input_init();
+
+ for( size_t i=0; i<terminfo_mappings.size(); i++ )
+ {
+ const terminfo_mapping_t &m = terminfo_mappings.at(i);
+ if( !wcscmp( name, m.name ) )
+ {
+ res = m.seq;
+ err = EILSEQ;
+ break;
+ }
+ }
+
+ if( !res )
+ {
+ errno = err;
+ return 0;
+ }
+
buff = format_string(L"%s", res);
- return buff.c_str();
-
+ return buff.c_str();
+
}
bool input_terminfo_get_name( const wcstring &seq, wcstring &name )
{
- input_init();
-
- for( size_t i=0; i<terminfo_mappings.size(); i++ )
- {
- terminfo_mapping_t &m = terminfo_mappings.at(i);
-
- if( !m.seq )
- {
- continue;
- }
-
+ input_init();
+
+ for( size_t i=0; i<terminfo_mappings.size(); i++ )
+ {
+ terminfo_mapping_t &m = terminfo_mappings.at(i);
+
+ if( !m.seq )
+ {
+ continue;
+ }
+
const wcstring map_buf = format_string(L"%s", m.seq);
if (map_buf == seq) {
name = m.name;
return true;
}
}
-
- return false;
+
+ return false;
}
wcstring_list_t input_terminfo_get_names( bool skip_null )
{
wcstring_list_t result;
result.reserve(terminfo_mappings.size());
-
- input_init();
-
- for( size_t i=0; i<terminfo_mappings.size(); i++ )
- {
- terminfo_mapping_t &m = terminfo_mappings.at(i);
-
- if( skip_null && !m.seq )
- {
- continue;
- }
+
+ input_init();
+
+ for( size_t i=0; i<terminfo_mappings.size(); i++ )
+ {
+ terminfo_mapping_t &m = terminfo_mappings.at(i);
+
+ if( skip_null && !m.seq )
+ {
+ continue;
+ }
result.push_back(wcstring(m.name));
- }
+ }
return result;
}
@@ -855,13 +855,13 @@ wcstring_list_t input_function_get_names( void )
wchar_t input_function_get_code( const wcstring &name )
{
- size_t i;
- for( i = 0; i<(sizeof( code_arr )/sizeof(wchar_t)) ; i++ )
- {
- if( name == name_arr[i] )
- {
- return code_arr[i];
- }
- }
- return -1;
+ size_t i;
+ for( i = 0; i<(sizeof( code_arr )/sizeof(wchar_t)) ; i++ )
+ {
+ if( name == name_arr[i] )
+ {
+ return code_arr[i];
+ }
+ }
+ return -1;
}
diff --git a/input.h b/input.h
index 28c09d49..78b17248 100644
--- a/input.h
+++ b/input.h
@@ -17,40 +17,40 @@ inputrc information for key bindings.
*/
enum
{
- R_BEGINNING_OF_LINE = R_NULL+10, /* This give input_common ten slots for lowlevel keycodes */
- R_END_OF_LINE,
- R_FORWARD_CHAR,
- R_BACKWARD_CHAR,
- R_FORWARD_WORD,
- R_BACKWARD_WORD,
- R_HISTORY_SEARCH_BACKWARD,
- R_HISTORY_SEARCH_FORWARD,
- R_DELETE_CHAR,
- R_BACKWARD_DELETE_CHAR,
- R_KILL_LINE,
- R_YANK,
- R_YANK_POP,
- R_COMPLETE,
- R_BEGINNING_OF_HISTORY,
- R_END_OF_HISTORY,
- R_BACKWARD_KILL_LINE,
- R_KILL_WHOLE_LINE,
- R_KILL_WORD,
- R_BACKWARD_KILL_WORD,
- R_DUMP_FUNCTIONS,
- R_HISTORY_TOKEN_SEARCH_BACKWARD,
- R_HISTORY_TOKEN_SEARCH_FORWARD,
- R_SELF_INSERT,
- R_VI_ARG_DIGIT,
- R_VI_DELETE_TO,
- R_EXECUTE,
- R_BEGINNING_OF_BUFFER,
- R_END_OF_BUFFER,
- R_REPAINT,
- R_UP_LINE,
- R_DOWN_LINE,
- R_SUPPRESS_AUTOSUGGESTION,
- R_ACCEPT_AUTOSUGGESTION
+ R_BEGINNING_OF_LINE = R_NULL+10, /* This give input_common ten slots for lowlevel keycodes */
+ R_END_OF_LINE,
+ R_FORWARD_CHAR,
+ R_BACKWARD_CHAR,
+ R_FORWARD_WORD,
+ R_BACKWARD_WORD,
+ R_HISTORY_SEARCH_BACKWARD,
+ R_HISTORY_SEARCH_FORWARD,
+ R_DELETE_CHAR,
+ R_BACKWARD_DELETE_CHAR,
+ R_KILL_LINE,
+ R_YANK,
+ R_YANK_POP,
+ R_COMPLETE,
+ R_BEGINNING_OF_HISTORY,
+ R_END_OF_HISTORY,
+ R_BACKWARD_KILL_LINE,
+ R_KILL_WHOLE_LINE,
+ R_KILL_WORD,
+ R_BACKWARD_KILL_WORD,
+ R_DUMP_FUNCTIONS,
+ R_HISTORY_TOKEN_SEARCH_BACKWARD,
+ R_HISTORY_TOKEN_SEARCH_FORWARD,
+ R_SELF_INSERT,
+ R_VI_ARG_DIGIT,
+ R_VI_DELETE_TO,
+ R_EXECUTE,
+ R_BEGINNING_OF_BUFFER,
+ R_END_OF_BUFFER,
+ R_REPAINT,
+ R_UP_LINE,
+ R_DOWN_LINE,
+ R_SUPPRESS_AUTOSUGGESTION,
+ R_ACCEPT_AUTOSUGGESTION
}
;
@@ -85,7 +85,7 @@ wint_t input_readch();
/**
Push a character or a readline function onto the stack of unread
characters that input_readch will return before actually reading from fd
- 0.
+ 0.
*/
void input_unreadch( wint_t ch );
diff --git a/input_common.cpp b/input_common.cpp
index 6f410c35..8f973836 100644
--- a/input_common.cpp
+++ b/input_common.cpp
@@ -1,5 +1,5 @@
/** \file input_common.c
-
+
Implementation file for the low level input library
*/
@@ -53,7 +53,7 @@ static void (*poll_handler)();
void input_common_init( int (*ih)() )
{
- interrupt_handler = ih;
+ interrupt_handler = ih;
}
void input_common_set_poll_callback(void (*handler)(void))
@@ -63,7 +63,7 @@ void input_common_set_poll_callback(void (*handler)(void))
void input_common_destroy()
{
-
+
}
/**
@@ -73,192 +73,192 @@ void input_common_destroy()
static wint_t readb()
{
/* do_loop must be set on every path through the loop; leaving it uninitialized allows the static analyzer to assist in catching mistakes. */
- unsigned char arr[1];
- bool do_loop;
-
- do
- {
+ unsigned char arr[1];
+ bool do_loop;
+
+ do
+ {
/* Invoke any poll handler */
if (poll_handler)
poll_handler();
-
- fd_set fdset;
- int fd_max=0;
- int ioport = iothread_port();
- int res;
-
- FD_ZERO( &fdset );
- FD_SET( 0, &fdset );
- if( env_universal_server.fd > 0 )
- {
- FD_SET( env_universal_server.fd, &fdset );
- if (fd_max < env_universal_server.fd) fd_max = env_universal_server.fd;
- }
- if (ioport > 0) {
- FD_SET( ioport, &fdset );
- if (fd_max < ioport) fd_max = ioport;
- }
-
- res = select( fd_max + 1, &fdset, 0, 0, 0 );
- if( res==-1 )
- {
- switch( errno )
- {
- case EINTR:
- case EAGAIN:
- {
- if( interrupt_handler )
- {
- int res = interrupt_handler();
- if( res )
- {
- return res;
- }
- if( lookahead_count )
- {
- return lookahead_arr[--lookahead_count];
- }
-
- }
-
-
- do_loop = true;
- break;
- }
- default:
- {
- /*
- The terminal has been closed. Save and exit.
- */
- return R_EOF;
- }
- }
- }
- else
- {
+
+ fd_set fdset;
+ int fd_max=0;
+ int ioport = iothread_port();
+ int res;
+
+ FD_ZERO( &fdset );
+ FD_SET( 0, &fdset );
+ if( env_universal_server.fd > 0 )
+ {
+ FD_SET( env_universal_server.fd, &fdset );
+ if (fd_max < env_universal_server.fd) fd_max = env_universal_server.fd;
+ }
+ if (ioport > 0) {
+ FD_SET( ioport, &fdset );
+ if (fd_max < ioport) fd_max = ioport;
+ }
+
+ res = select( fd_max + 1, &fdset, 0, 0, 0 );
+ if( res==-1 )
+ {
+ switch( errno )
+ {
+ case EINTR:
+ case EAGAIN:
+ {
+ if( interrupt_handler )
+ {
+ int res = interrupt_handler();
+ if( res )
+ {
+ return res;
+ }
+ if( lookahead_count )
+ {
+ return lookahead_arr[--lookahead_count];
+ }
+
+ }
+
+
+ do_loop = true;
+ break;
+ }
+ default:
+ {
+ /*
+ The terminal has been closed. Save and exit.
+ */
+ return R_EOF;
+ }
+ }
+ }
+ else
+ {
/* Assume we loop unless we see a character in stdin */
do_loop = true;
-
+
if( env_universal_server.fd > 0 && FD_ISSET( env_universal_server.fd, &fdset ) )
{
- debug( 3, L"Wake up on universal variable event" );
+ debug( 3, L"Wake up on universal variable event" );
env_universal_read_all();
if( lookahead_count )
{
return lookahead_arr[--lookahead_count];
}
- }
-
- if ( ioport > 0 && FD_ISSET(ioport, &fdset))
- {
+ }
+
+ if ( ioport > 0 && FD_ISSET(ioport, &fdset))
+ {
iothread_service_completion();
if( lookahead_count )
{
return lookahead_arr[--lookahead_count];
}
- }
-
- if( FD_ISSET( STDIN_FILENO, &fdset ) )
- {
- if( read_blocked( 0, arr, 1 ) != 1 )
- {
- /* The teminal has been closed. Save and exit. */
- return R_EOF;
- }
-
+ }
+
+ if( FD_ISSET( STDIN_FILENO, &fdset ) )
+ {
+ if( read_blocked( 0, arr, 1 ) != 1 )
+ {
+ /* The teminal has been closed. Save and exit. */
+ return R_EOF;
+ }
+
/* We read from stdin, so don't loop */
- do_loop = false;
- }
- }
- }
- while( do_loop );
-
- return arr[0];
+ do_loop = false;
+ }
+ }
+ }
+ while( do_loop );
+
+ return arr[0];
}
wchar_t input_common_readch( int timed )
{
- if( lookahead_count == 0 )
- {
- if( timed )
- {
- int count;
- fd_set fds;
- struct timeval tm=
- {
- 0,
- 1000 * WAIT_ON_ESCAPE
- }
- ;
-
- FD_ZERO( &fds );
- FD_SET( 0, &fds );
- count = select(1, &fds, 0, 0, &tm);
-
- switch( count )
- {
- case 0:
- return WEOF;
-
- case -1:
- return WEOF;
- break;
- default:
- break;
-
- }
- }
-
- wchar_t res;
- static mbstate_t state;
-
- while(1)
- {
- wint_t b = readb();
- char bb;
-
- size_t sz;
-
- if( (b >= R_NULL) && (b < R_NULL + 1000) )
- return b;
-
- bb=b;
-
- sz = mbrtowc( &res, &bb, 1, &state );
-
- switch( sz )
- {
- case (size_t)(-1):
- memset (&state, '\0', sizeof (state));
- debug( 2, L"Illegal input" );
- return R_NULL;
- case (size_t)(-2):
- break;
- case 0:
- return 0;
- default:
-
- return res;
- }
- }
- }
- else
- {
- if( !timed )
- {
- while( (lookahead_count >= 0) && (lookahead_arr[lookahead_count-1] == WEOF) )
- lookahead_count--;
- if( lookahead_count == 0 )
- return input_common_readch(0);
- }
-
- return lookahead_arr[--lookahead_count];
- }
+ if( lookahead_count == 0 )
+ {
+ if( timed )
+ {
+ int count;
+ fd_set fds;
+ struct timeval tm=
+ {
+ 0,
+ 1000 * WAIT_ON_ESCAPE
+ }
+ ;
+
+ FD_ZERO( &fds );
+ FD_SET( 0, &fds );
+ count = select(1, &fds, 0, 0, &tm);
+
+ switch( count )
+ {
+ case 0:
+ return WEOF;
+
+ case -1:
+ return WEOF;
+ break;
+ default:
+ break;
+
+ }
+ }
+
+ wchar_t res;
+ static mbstate_t state;
+
+ while(1)
+ {
+ wint_t b = readb();
+ char bb;
+
+ size_t sz;
+
+ if( (b >= R_NULL) && (b < R_NULL + 1000) )
+ return b;
+
+ bb=b;
+
+ sz = mbrtowc( &res, &bb, 1, &state );
+
+ switch( sz )
+ {
+ case (size_t)(-1):
+ memset (&state, '\0', sizeof (state));
+ debug( 2, L"Illegal input" );
+ return R_NULL;
+ case (size_t)(-2):
+ break;
+ case 0:
+ return 0;
+ default:
+
+ return res;
+ }
+ }
+ }
+ else
+ {
+ if( !timed )
+ {
+ while( (lookahead_count >= 0) && (lookahead_arr[lookahead_count-1] == WEOF) )
+ lookahead_count--;
+ if( lookahead_count == 0 )
+ return input_common_readch(0);
+ }
+
+ return lookahead_arr[--lookahead_count];
+ }
}
void input_common_unreadch( wint_t ch )
{
- lookahead_arr[lookahead_count++] = ch;
+ lookahead_arr[lookahead_count++] = ch;
}
diff --git a/input_common.h b/input_common.h
index 759bc9ce..9b5e0e63 100644
--- a/input_common.h
+++ b/input_common.h
@@ -1,5 +1,5 @@
/** \file input_common.h
-
+
Header file for the low level input library
*/
@@ -15,15 +15,15 @@ Header file for the low level input library
enum
{
- /**
- R_NULL is sometimes returned by the input when a character was
- requested but none could be delivered, or when an exception
- happened.
- */
- R_NULL = INPUT_COMMON_RESERVED,
- R_EOF
+ /**
+ R_NULL is sometimes returned by the input when a character was
+ requested but none could be delivered, or when an exception
+ happened.
+ */
+ R_NULL = INPUT_COMMON_RESERVED,
+ R_EOF
}
- ;
+ ;
/**
Init the library
diff --git a/intern.cpp b/intern.cpp
index 87480ea1..015182cb 100644
--- a/intern.cpp
+++ b/intern.cpp
@@ -45,17 +45,17 @@ static pthread_mutex_t intern_lock = PTHREAD_MUTEX_INITIALIZER;
static const wchar_t *intern_with_dup( const wchar_t *in, bool dup )
{
- if( !in )
- return NULL;
-
-// debug( 0, L"intern %ls", in );
+ if( !in )
+ return NULL;
+
+// debug( 0, L"intern %ls", in );
scoped_lock lock(intern_lock);
const wchar_t *result;
-
+
#if USE_SET
string_table_t::const_iterator iter = string_table.find(in);
if (iter != string_table.end()) {
- result = *iter;
+ result = *iter;
} else {
result = dup ? wcsdup(in) : in;
string_table.insert(result);
@@ -74,11 +74,11 @@ static const wchar_t *intern_with_dup( const wchar_t *in, bool dup )
const wchar_t *intern( const wchar_t *in )
{
- return intern_with_dup(in, true);
+ return intern_with_dup(in, true);
}
const wchar_t *intern_static( const wchar_t *in )
{
- return intern_with_dup(in, false);
+ return intern_with_dup(in, false);
}
diff --git a/io.cpp b/io.cpp
index a956bbbc..525f438b 100644
--- a/io.cpp
+++ b/io.cpp
@@ -1,7 +1,7 @@
/** \file io.c
Utilities for io redirection.
-
+
*/
#include "config.h"
@@ -53,105 +53,105 @@ Utilities for io redirection.
void io_buffer_read( io_data_t *d )
{
- exec_close(d->param1.pipe_fd[1] );
-
- if( d->io_mode == IO_BUFFER )
- {
-/* if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) )
- {
- wperror( L"fcntl" );
- return;
- } */
- debug( 4, L"io_buffer_read: blocking read on fd %d", d->param1.pipe_fd[0] );
- while(1)
- {
- char b[4096];
- long l;
- l=read_blocked( d->param1.pipe_fd[0], b, 4096 );
- if( l==0 )
- {
- break;
- }
- else if( l<0 )
- {
- /*
- exec_read_io_buffer is only called on jobs that have
- exited, and will therefore never block. But a broken
- pipe seems to cause some flags to reset, causing the
- EOF flag to not be set. Therefore, EAGAIN is ignored
- and we exit anyway.
- */
- if( errno != EAGAIN )
- {
- debug( 1,
- _(L"An error occured while reading output from code block on file descriptor %d"),
- d->param1.pipe_fd[0] );
- wperror( L"io_buffer_read" );
- }
-
- break;
- }
- else
- {
- d->out_buffer_append( b, l );
- }
- }
- }
+ exec_close(d->param1.pipe_fd[1] );
+
+ if( d->io_mode == IO_BUFFER )
+ {
+/* if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) )
+ {
+ wperror( L"fcntl" );
+ return;
+ } */
+ debug( 4, L"io_buffer_read: blocking read on fd %d", d->param1.pipe_fd[0] );
+ while(1)
+ {
+ char b[4096];
+ long l;
+ l=read_blocked( d->param1.pipe_fd[0], b, 4096 );
+ if( l==0 )
+ {
+ break;
+ }
+ else if( l<0 )
+ {
+ /*
+ exec_read_io_buffer is only called on jobs that have
+ exited, and will therefore never block. But a broken
+ pipe seems to cause some flags to reset, causing the
+ EOF flag to not be set. Therefore, EAGAIN is ignored
+ and we exit anyway.
+ */
+ if( errno != EAGAIN )
+ {
+ debug( 1,
+ _(L"An error occured while reading output from code block on file descriptor %d"),
+ d->param1.pipe_fd[0] );
+ wperror( L"io_buffer_read" );
+ }
+
+ break;
+ }
+ else
+ {
+ d->out_buffer_append( b, l );
+ }
+ }
+ }
}
io_data_t *io_buffer_create( bool is_input )
{
bool success = true;
- io_data_t *buffer_redirect = new io_data_t;
- buffer_redirect->out_buffer_create();
- buffer_redirect->io_mode = IO_BUFFER;
- buffer_redirect->is_input = is_input ? true : false;
- buffer_redirect->fd=is_input?0:1;
-
- if( exec_pipe( buffer_redirect->param1.pipe_fd ) == -1 )
- {
- debug( 1, PIPE_ERROR );
- wperror (L"pipe");
- success = false;
- }
- else if( fcntl( buffer_redirect->param1.pipe_fd[0],
- F_SETFL,
- O_NONBLOCK ) )
- {
- debug( 1, PIPE_ERROR );
- wperror( L"fcntl" );
- success = false;
- }
-
+ io_data_t *buffer_redirect = new io_data_t;
+ buffer_redirect->out_buffer_create();
+ buffer_redirect->io_mode = IO_BUFFER;
+ buffer_redirect->is_input = is_input ? true : false;
+ buffer_redirect->fd=is_input?0:1;
+
+ if( exec_pipe( buffer_redirect->param1.pipe_fd ) == -1 )
+ {
+ debug( 1, PIPE_ERROR );
+ wperror (L"pipe");
+ success = false;
+ }
+ else if( fcntl( buffer_redirect->param1.pipe_fd[0],
+ F_SETFL,
+ O_NONBLOCK ) )
+ {
+ debug( 1, PIPE_ERROR );
+ wperror( L"fcntl" );
+ success = false;
+ }
+
if (! success)
{
delete buffer_redirect;
buffer_redirect = NULL;
}
-
- return buffer_redirect;
+
+ return buffer_redirect;
}
void io_buffer_destroy( io_data_t *io_buffer )
{
- /**
- If this is an input buffer, then io_read_buffer will not have
- been called, and we need to close the output fd as well.
- */
- if( io_buffer->is_input )
- {
- exec_close(io_buffer->param1.pipe_fd[1] );
- }
-
- exec_close( io_buffer->param1.pipe_fd[0] );
-
- /*
- Dont free fd for writing. This should already be free'd before
- calling exec_read_io_buffer on the buffer
- */
- delete io_buffer;
+ /**
+ If this is an input buffer, then io_read_buffer will not have
+ been called, and we need to close the output fd as well.
+ */
+ if( io_buffer->is_input )
+ {
+ exec_close(io_buffer->param1.pipe_fd[1] );
+ }
+
+ exec_close( io_buffer->param1.pipe_fd[0] );
+
+ /*
+ Dont free fd for writing. This should already be free'd before
+ calling exec_read_io_buffer on the buffer
+ */
+ delete io_buffer;
}
void io_chain_t::remove(const io_data_t *element)
@@ -216,7 +216,7 @@ void io_print(const io_chain_t &chain)
fprintf(stderr, "Empty chain %p\n", &chain);
return;
}
-
+
fprintf(stderr, "Chain %p (%ld items):\n", &chain, (long)chain.size());
for (size_t i=0; i < chain.size(); i++) {
const io_data_t *io = chain.at(i);
@@ -247,7 +247,7 @@ void io_duplicate_prepend( const io_chain_t &src, io_chain_t &dst )
return dst.duplicate_prepend(src);
}
-void io_chain_destroy(io_chain_t &chain)
+void io_chain_destroy(io_chain_t &chain)
{
chain.destroy();
}
diff --git a/io.h b/io.h
index 540c8141..249995dd 100644
--- a/io.h
+++ b/io.h
@@ -10,7 +10,7 @@ using std::tr1::shared_ptr;
*/
enum io_mode
{
- IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE
+ IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE
};
/** Represents an FD redirection */
@@ -24,35 +24,35 @@ private:
void operator=(const io_data_t &rhs);
public:
- /** Type of redirect */
- int io_mode;
- /** FD to redirect */
- int fd;
-
- /**
- Type-specific parameter for redirection
- */
- union
- {
- /** Fds for IO_PIPE and for IO_BUFFER */
- int pipe_fd[2];
- /** fd to redirect specified fd to, for IO_FD */
- int old_fd;
- } param1;
-
-
- /** Second type-specific paramter for redirection */
- union
- {
- /** file creation flags to send to open for IO_FILE */
- int flags;
- /** Whether to close old_fd for IO_FD */
- int close_old;
- } param2;
-
+ /** Type of redirect */
+ int io_mode;
+ /** FD to redirect */
+ int fd;
+
+ /**
+ Type-specific parameter for redirection
+ */
+ union
+ {
+ /** Fds for IO_PIPE and for IO_BUFFER */
+ int pipe_fd[2];
+ /** fd to redirect specified fd to, for IO_FD */
+ int old_fd;
+ } param1;
+
+
+ /** Second type-specific paramter for redirection */
+ union
+ {
+ /** file creation flags to send to open for IO_FILE */
+ int flags;
+ /** Whether to close old_fd for IO_FD */
+ int close_old;
+ } param2;
+
/** Filename IO_FILE. malloc'd. This needs to be used after fork, so don't use wcstring here. */
const char *filename_cstr;
-
+
/** Convenience to set filename_cstr via wcstring */
void set_filename(const wcstring &str) {
free((void *)filename_cstr);
@@ -63,33 +63,33 @@ public:
void out_buffer_create() {
out_buffer.reset(new std::vector<char>);
}
-
+
/** Function to append to the buffer */
void out_buffer_append(const char *ptr, size_t count) {
- assert(out_buffer.get() != NULL);
+ assert(out_buffer.get() != NULL);
out_buffer->insert(out_buffer->end(), ptr, ptr + count);
}
-
+
/** Function to get a pointer to the buffer */
char *out_buffer_ptr(void) {
assert(out_buffer.get() != NULL);
return out_buffer->empty() ? NULL : &out_buffer->at(0);
}
-
+
const char *out_buffer_ptr(void) const {
assert(out_buffer.get() != NULL);
return out_buffer->empty() ? NULL : &out_buffer->at(0);
}
-
+
/** Function to get the size of the buffer */
size_t out_buffer_size(void) const {
assert(out_buffer.get() != NULL);
return out_buffer->size();
}
- /** Set to true if this is an input io redirection */
- bool is_input;
-
+ /** Set to true if this is an input io redirection */
+ bool is_input;
+
io_data_t() :
out_buffer(),
io_mode(0),
@@ -100,7 +100,7 @@ public:
is_input(0)
{
}
-
+
io_data_t(const io_data_t &rhs) :
out_buffer(rhs.out_buffer),
io_mode(rhs.io_mode),
@@ -111,7 +111,7 @@ public:
is_input(rhs.is_input)
{
}
-
+
~io_data_t() {
free((void *)filename_cstr);
}
@@ -121,15 +121,15 @@ class io_chain_t : public std::vector<io_data_t *> {
public:
io_chain_t();
io_chain_t(io_data_t *);
-
+
void remove(const io_data_t *element);
io_chain_t duplicate() const;
void duplicate_prepend(const io_chain_t &src);
void destroy();
-
+
const io_data_t *get_io_for_fd(int fd) const;
io_data_t *get_io_for_fd(int fd);
-
+
};
/**
diff --git a/iothread.cpp b/iothread.cpp
index 3665df30..8e2ece1c 100644
--- a/iothread.cpp
+++ b/iothread.cpp
@@ -27,24 +27,24 @@ static int s_active_thread_count;
typedef unsigned char ThreadIndex_t;
static struct WorkerThread_t {
- ThreadIndex_t idx;
- pthread_t thread;
+ ThreadIndex_t idx;
+ pthread_t thread;
} threads[IO_MAX_THREADS];
struct ThreadedRequest_t {
- int sequenceNumber;
-
- int (*handler)(void *);
- void (*completionCallback)(void *, int);
- void *context;
- int handlerResult;
+ int sequenceNumber;
+
+ int (*handler)(void *);
+ void (*completionCallback)(void *, int);
+ void *context;
+ int handlerResult;
};
static struct WorkerThread_t *next_vacant_thread_slot(void) {
- for (ThreadIndex_t i=0; i < IO_MAX_THREADS; i++) {
- if (! threads[i].thread) return &threads[i];
- }
- return NULL;
+ for (ThreadIndex_t i=0; i < IO_MAX_THREADS; i++) {
+ if (! threads[i].thread) return &threads[i];
+ }
+ return NULL;
}
static pthread_mutex_t s_request_queue_lock;
@@ -53,32 +53,32 @@ static int s_last_sequence_number;
static int s_read_pipe, s_write_pipe;
static void iothread_init(void) {
- static bool inited = false;
- if (! inited) {
- inited = true;
-
- /* Initialize the queue lock */
- VOMIT_ON_FAILURE(pthread_mutex_init(&s_request_queue_lock, NULL));
-
- /* Initialize the completion pipes */
- int pipes[2] = {0, 0};
- VOMIT_ON_FAILURE(pipe(pipes));
- s_read_pipe = pipes[0];
- s_write_pipe = pipes[1];
-
+ static bool inited = false;
+ if (! inited) {
+ inited = true;
+
+ /* Initialize the queue lock */
+ VOMIT_ON_FAILURE(pthread_mutex_init(&s_request_queue_lock, NULL));
+
+ /* Initialize the completion pipes */
+ int pipes[2] = {0, 0};
+ VOMIT_ON_FAILURE(pipe(pipes));
+ s_read_pipe = pipes[0];
+ s_write_pipe = pipes[1];
+
// 0 means success to VOMIT_ON_FAILURE. Arrange to pass 0 if fcntl returns anything other than -1.
VOMIT_ON_FAILURE(-1 == fcntl(s_read_pipe, F_SETFD, FD_CLOEXEC));
VOMIT_ON_FAILURE(-1 == fcntl(s_write_pipe, F_SETFD, FD_CLOEXEC));
-
- /* Tell each thread its index */
- for (ThreadIndex_t i=0; i < IO_MAX_THREADS; i++) {
- threads[i].idx = i;
- }
- }
+
+ /* Tell each thread its index */
+ for (ThreadIndex_t i=0; i < IO_MAX_THREADS; i++) {
+ threads[i].idx = i;
+ }
+ }
}
static void add_to_queue(struct ThreadedRequest_t *req) {
- ASSERT_IS_LOCKED(s_request_queue_lock);
+ ASSERT_IS_LOCKED(s_request_queue_lock);
s_request_queue.push(req);
}
@@ -94,117 +94,117 @@ static ThreadedRequest_t *dequeue_request(void) {
/* The function that does thread work. */
static void *iothread_worker(void *threadPtr) {
- assert(threadPtr != NULL);
- struct WorkerThread_t *thread = (struct WorkerThread_t *)threadPtr;
-
- /* Grab a request off of the queue */
- struct ThreadedRequest_t *req = dequeue_request();
-
- /* Run the handler and store the result */
- if (req) {
- req->handlerResult = req->handler(req->context);
- }
-
- /* Write our index to wake up the main thread */
- VOMIT_ON_FAILURE(! write_loop(s_write_pipe, (const char *)&thread->idx, sizeof thread->idx));
-
- /* We're done */
- return req;
+ assert(threadPtr != NULL);
+ struct WorkerThread_t *thread = (struct WorkerThread_t *)threadPtr;
+
+ /* Grab a request off of the queue */
+ struct ThreadedRequest_t *req = dequeue_request();
+
+ /* Run the handler and store the result */
+ if (req) {
+ req->handlerResult = req->handler(req->context);
+ }
+
+ /* Write our index to wake up the main thread */
+ VOMIT_ON_FAILURE(! write_loop(s_write_pipe, (const char *)&thread->idx, sizeof thread->idx));
+
+ /* We're done */
+ return req;
}
/* Spawn another thread if there's work to be done. */
static void iothread_spawn_if_needed(void) {
ASSERT_IS_LOCKED(s_request_queue_lock);
- if (! s_request_queue.empty() && s_active_thread_count < IO_MAX_THREADS) {
- struct WorkerThread_t *thread = next_vacant_thread_slot();
- assert(thread != NULL);
-
+ if (! s_request_queue.empty() && s_active_thread_count < IO_MAX_THREADS) {
+ struct WorkerThread_t *thread = next_vacant_thread_slot();
+ assert(thread != NULL);
+
/* The spawned thread inherits our signal mask. We don't want the thread to ever receive signals on the spawned thread, so temporarily block all signals, spawn the thread, and then restore it. */
sigset_t newSet, savedSet;
sigfillset(&newSet);
VOMIT_ON_FAILURE(pthread_sigmask(SIG_BLOCK, &newSet, &savedSet));
-
- /* Spawn a thread. */
- int err;
- do {
- err = 0;
- if (pthread_create(&thread->thread, NULL, iothread_worker, thread)) {
- err = errno;
- }
- } while (err == EAGAIN);
-
+
+ /* Spawn a thread. */
+ int err;
+ do {
+ err = 0;
+ if (pthread_create(&thread->thread, NULL, iothread_worker, thread)) {
+ err = errno;
+ }
+ } while (err == EAGAIN);
+
/* Need better error handling - perhaps try again later. */
- assert(err == 0);
-
- /* Note that we are spawned another thread */
- s_active_thread_count += 1;
-
+ assert(err == 0);
+
+ /* Note that we are spawned another thread */
+ s_active_thread_count += 1;
+
/* Restore our sigmask */
VOMIT_ON_FAILURE(pthread_sigmask(SIG_SETMASK, &savedSet, NULL));
- }
+ }
}
int iothread_perform_base(int (*handler)(void *), void (*completionCallback)(void *, int), void *context) {
ASSERT_IS_MAIN_THREAD();
ASSERT_IS_NOT_FORKED_CHILD();
- iothread_init();
-
- /* Create and initialize a request. */
- struct ThreadedRequest_t *req = new ThreadedRequest_t();
- req->handler = handler;
- req->completionCallback = completionCallback;
- req->context = context;
- req->sequenceNumber = ++s_last_sequence_number;
+ iothread_init();
+
+ /* Create and initialize a request. */
+ struct ThreadedRequest_t *req = new ThreadedRequest_t();
+ req->handler = handler;
+ req->completionCallback = completionCallback;
+ req->context = context;
+ req->sequenceNumber = ++s_last_sequence_number;
/* Take our lock */
scoped_lock lock(s_request_queue_lock);
-
+
/* Add to the queue */
add_to_queue(req);
-
+
/* Spawn a thread if necessary */
iothread_spawn_if_needed();
return 0;
}
int iothread_port(void) {
- iothread_init();
- return s_read_pipe;
+ iothread_init();
+ return s_read_pipe;
}
void iothread_service_completion(void) {
ASSERT_IS_MAIN_THREAD();
- ThreadIndex_t threadIdx = (ThreadIndex_t)-1;
- VOMIT_ON_FAILURE(1 != read_loop(iothread_port(), &threadIdx, sizeof threadIdx));
- assert(threadIdx < IO_MAX_THREADS);
-
- struct WorkerThread_t *thread = &threads[threadIdx];
- assert(thread->thread != 0);
-
- struct ThreadedRequest_t *req = NULL;
- VOMIT_ON_FAILURE(pthread_join(thread->thread, (void **)&req));
-
- /* Free up this thread */
- thread->thread = 0;
- assert(s_active_thread_count > 0);
- s_active_thread_count -= 1;
-
- /* Handle the request */
+ ThreadIndex_t threadIdx = (ThreadIndex_t)-1;
+ VOMIT_ON_FAILURE(1 != read_loop(iothread_port(), &threadIdx, sizeof threadIdx));
+ assert(threadIdx < IO_MAX_THREADS);
+
+ struct WorkerThread_t *thread = &threads[threadIdx];
+ assert(thread->thread != 0);
+
+ struct ThreadedRequest_t *req = NULL;
+ VOMIT_ON_FAILURE(pthread_join(thread->thread, (void **)&req));
+
+ /* Free up this thread */
+ thread->thread = 0;
+ assert(s_active_thread_count > 0);
+ s_active_thread_count -= 1;
+
+ /* Handle the request */
if (req) {
- if (req->completionCallback)
+ if (req->completionCallback)
req->completionCallback(req->context, req->handlerResult);
delete req;
}
-
- /* Maybe spawn another thread, if there's more work to be done. */
- VOMIT_ON_FAILURE(pthread_mutex_lock(&s_request_queue_lock));
- iothread_spawn_if_needed();
- VOMIT_ON_FAILURE(pthread_mutex_unlock(&s_request_queue_lock));
+
+ /* Maybe spawn another thread, if there's more work to be done. */
+ VOMIT_ON_FAILURE(pthread_mutex_lock(&s_request_queue_lock));
+ iothread_spawn_if_needed();
+ VOMIT_ON_FAILURE(pthread_mutex_unlock(&s_request_queue_lock));
}
void iothread_drain_all(void) {
ASSERT_IS_MAIN_THREAD();
- ASSERT_IS_NOT_FORKED_CHILD();
+ ASSERT_IS_NOT_FORKED_CHILD();
if (s_active_thread_count == 0)
return;
#define TIME_DRAIN 0
diff --git a/iothread.h b/iothread.h
index bca951ea..8ca10359 100644
--- a/iothread.h
+++ b/iothread.h
@@ -7,7 +7,7 @@
/**
Runs a command on a thread.
-
+
\param handler The function to execute on a background thread. Accepts an arbitrary context pointer, and returns an int, which is passed to the completionCallback.
\param completionCallback The function to execute on the main thread once the background thread is complete. Accepts an int (the return value of handler) and the context.
\param context A arbitary context pointer to pass to the handler and completion callback.
@@ -15,9 +15,9 @@
*/
int iothread_perform_base(int (*handler)(void *), void (*completionCallback)(void *, int), void *context);
-/**
+/**
Gets the fd on which to listen for completion callbacks.
-
+
\return A file descriptor on which to listen for completion callbacks.
*/
int iothread_port(void);
diff --git a/key_reader.cpp b/key_reader.cpp
index c61e80b7..d126af7b 100644
--- a/key_reader.cpp
+++ b/key_reader.cpp
@@ -1,9 +1,9 @@
/*
A small utility to print the resulting key codes from pressing a
- key. Servers the same function as hitting ^V in bash, but I prefer
- the way key_reader works.
+ key. Servers the same function as hitting ^V in bash, but I prefer
+ the way key_reader works.
- Type ^C to exit the program.
+ Type ^C to exit the program.
*/
#include "config.h"
@@ -22,76 +22,76 @@
int writestr( char *str )
{
- write( 1, str, strlen(str) );
- return 0;
+ write( 1, str, strlen(str) );
+ return 0;
}
int main( int argc, char **argv)
{
- set_main_thread();
+ set_main_thread();
setup_fork_guards();
- setlocale( LC_ALL, "" );
-
-
- if( argc == 2 )
- {
- static char term_buffer[2048];
- char *termtype = getenv ("TERM");
- char *tbuff = new char[9999];
- char *res;
-
- tgetent( term_buffer, termtype );
- res = tgetstr( argv[1], &tbuff );
- if( res != 0 )
- {
- while( *res != 0 )
- {
- printf("%d ", *res );
-
-
- res++;
- }
- printf( "\n" );
- }
- else
- {
- printf("Undefined sequence\n");
- }
- }
- else
- {
- char scratch[1024];
- unsigned int c;
-
- struct termios modes, /* so we can change the modes */
- savemodes; /* so we can reset the modes when we're done */
-
- input_common_init(0);
-
-
- tcgetattr(0,&modes); /* get the current terminal modes */
- savemodes = modes; /* save a copy so we can reset them */
-
- modes.c_lflag &= ~ICANON; /* turn off canonical mode */
- modes.c_lflag &= ~ECHO; /* turn off echo mode */
- modes.c_cc[VMIN]=1;
- modes.c_cc[VTIME]=0;
- tcsetattr(0,TCSANOW,&modes); /* set the new modes */
- while(1)
- {
- if( (c=input_common_readch(0)) == EOF )
- break;
- if( (c > 31) && (c != 127) )
- sprintf( scratch, "dec: %d hex: %x char: %c\n", c, c, c );
- else
- sprintf( scratch, "dec: %d hex: %x\n", c, c );
- writestr( scratch );
- }
- /* reset the terminal to the saved mode */
- tcsetattr(0,TCSANOW,&savemodes);
-
- input_common_destroy();
- }
-
- return 0;
+ setlocale( LC_ALL, "" );
+
+
+ if( argc == 2 )
+ {
+ static char term_buffer[2048];
+ char *termtype = getenv ("TERM");
+ char *tbuff = new char[9999];
+ char *res;
+
+ tgetent( term_buffer, termtype );
+ res = tgetstr( argv[1], &tbuff );
+ if( res != 0 )
+ {
+ while( *res != 0 )
+ {
+ printf("%d ", *res );
+
+
+ res++;
+ }
+ printf( "\n" );
+ }
+ else
+ {
+ printf("Undefined sequence\n");
+ }
+ }
+ else
+ {
+ char scratch[1024];
+ unsigned int c;
+
+ struct termios modes, /* so we can change the modes */
+ savemodes; /* so we can reset the modes when we're done */
+
+ input_common_init(0);
+
+
+ tcgetattr(0,&modes); /* get the current terminal modes */
+ savemodes = modes; /* save a copy so we can reset them */
+
+ modes.c_lflag &= ~ICANON; /* turn off canonical mode */
+ modes.c_lflag &= ~ECHO; /* turn off echo mode */
+ modes.c_cc[VMIN]=1;
+ modes.c_cc[VTIME]=0;
+ tcsetattr(0,TCSANOW,&modes); /* set the new modes */
+ while(1)
+ {
+ if( (c=input_common_readch(0)) == EOF )
+ break;
+ if( (c > 31) && (c != 127) )
+ sprintf( scratch, "dec: %d hex: %x char: %c\n", c, c, c );
+ else
+ sprintf( scratch, "dec: %d hex: %x\n", c, c );
+ writestr( scratch );
+ }
+ /* reset the terminal to the saved mode */
+ tcsetattr(0,TCSANOW,&savemodes);
+
+ input_common_destroy();
+ }
+
+ return 0;
}
diff --git a/kill.cpp b/kill.cpp
index f7d7cf0f..99f36799 100644
--- a/kill.cpp
+++ b/kill.cpp
@@ -1,9 +1,9 @@
/** \file kill.c
- The killring.
+ The killring.
- Works like the killring in emacs and readline. The killring is cut
- and paste with a memory of previous cuts. It supports integration
- with the X clipboard.
+ Works like the killring in emacs and readline. The killring is cut
+ and paste with a memory of previous cuts. It supports integration
+ with the X clipboard.
*/
#include "config.h"
@@ -57,12 +57,12 @@ static wchar_t *cut_buffer=0;
*/
static int has_xsel()
{
- static int res=-1;
- if (res < 0) {
- res = !! path_get_path(L"xsel", NULL);
+ static int res=-1;
+ if (res < 0) {
+ res = !! path_get_path(L"xsel", NULL);
}
-
- return res;
+
+ return res;
}
void kill_add( const wcstring &str )
@@ -70,57 +70,57 @@ void kill_add( const wcstring &str )
ASSERT_IS_MAIN_THREAD();
if (str.empty())
return;
-
- wcstring cmd;
+
+ wcstring cmd;
wchar_t *escaped_str = NULL;
- kill_list.push_front(str);
+ kill_list.push_front(str);
- /*
- Check to see if user has set the FISH_CLIPBOARD_CMD variable,
- and, if so, use it instead of checking the display, etc.
+ /*
+ Check to see if user has set the FISH_CLIPBOARD_CMD variable,
+ and, if so, use it instead of checking the display, etc.
- I couldn't think of a safe way to allow overide of the echo
- command too, so, the command used must accept the input via stdin.
- */
+ I couldn't think of a safe way to allow overide of the echo
+ command too, so, the command used must accept the input via stdin.
+ */
- const env_var_t clipboard_wstr = env_get_string(L"FISH_CLIPBOARD_CMD");
- if( !clipboard_wstr.missing() )
- {
- escaped_str = escape( str.c_str(), 1 );
+ const env_var_t clipboard_wstr = env_get_string(L"FISH_CLIPBOARD_CMD");
+ if( !clipboard_wstr.missing() )
+ {
+ escaped_str = escape( str.c_str(), 1 );
cmd.assign(L"echo -n ");
cmd.append(escaped_str);
cmd.append(clipboard_wstr);
- }
- else
- {
- /* This is for sending the kill to the X copy-and-paste buffer */
- if( !has_xsel() ) {
- return;
- }
-
- const env_var_t disp_wstr = env_get_string( L"DISPLAY" );
- if( !disp_wstr.missing() )
- {
- escaped_str = escape( str.c_str(), 1 );
+ }
+ else
+ {
+ /* This is for sending the kill to the X copy-and-paste buffer */
+ if( !has_xsel() ) {
+ return;
+ }
+
+ const env_var_t disp_wstr = env_get_string( L"DISPLAY" );
+ if( !disp_wstr.missing() )
+ {
+ escaped_str = escape( str.c_str(), 1 );
cmd.assign(L"echo ");
cmd.append(escaped_str);
cmd.append(L"|xsel -b" );
- }
- }
-
- if (! cmd.empty())
- {
- if( exec_subshell(cmd) == -1 )
- {
- /*
- Do nothing on failiure
- */
- }
-
- free( cut_buffer );
-
- cut_buffer = escaped_str;
- }
+ }
+ }
+
+ if (! cmd.empty())
+ {
+ if( exec_subshell(cmd) == -1 )
+ {
+ /*
+ Do nothing on failiure
+ */
+ }
+
+ free( cut_buffer );
+
+ cut_buffer = escaped_str;
+ }
}
/**
@@ -133,13 +133,13 @@ static void kill_remove( const wcstring &s )
if (iter != kill_list.end())
kill_list.erase(iter);
}
-
-
+
+
void kill_replace( const wcstring &old, const wcstring &newv )
{
- kill_remove( old );
- kill_add( newv );
+ kill_remove( old );
+ kill_add( newv );
}
const wchar_t *kill_yank_rotate()
@@ -159,50 +159,50 @@ const wchar_t *kill_yank_rotate()
clipboard contents to the fish killring.
*/
static void kill_check_x_buffer()
-{
- if( !has_xsel() )
- return;
-
- const env_var_t disp = env_get_string(L"DISPLAY");
- if( ! disp.missing())
- {
- size_t i;
- wcstring cmd = L"xsel -t 500 -b";
- wcstring new_cut_buffer=L"";
+{
+ if( !has_xsel() )
+ return;
+
+ const env_var_t disp = env_get_string(L"DISPLAY");
+ if( ! disp.missing())
+ {
+ size_t i;
+ wcstring cmd = L"xsel -t 500 -b";
+ wcstring new_cut_buffer=L"";
wcstring_list_t list;
- if( exec_subshell( cmd, list ) != -1 )
- {
-
- for( i=0; i<list.size(); i++ )
- {
- wcstring next_line = escape_string( list.at(i), 0 );
+ if( exec_subshell( cmd, list ) != -1 )
+ {
+
+ for( i=0; i<list.size(); i++ )
+ {
+ wcstring next_line = escape_string( list.at(i), 0 );
if (i > 0) new_cut_buffer += L"\\n";
new_cut_buffer += next_line;
- }
-
- if( new_cut_buffer.size() > 0 )
- {
- /*
- The buffer is inserted with backslash escapes,
- since we don't really like tabs, newlines,
- etc. anyway.
- */
-
+ }
+
+ if( new_cut_buffer.size() > 0 )
+ {
+ /*
+ The buffer is inserted with backslash escapes,
+ since we don't really like tabs, newlines,
+ etc. anyway.
+ */
+
if (cut_buffer == NULL || cut_buffer != new_cut_buffer)
{
free(cut_buffer);
cut_buffer = wcsdup(new_cut_buffer.c_str());
kill_list.push_front( new_cut_buffer );
}
- }
- }
- }
+ }
+ }
+ }
}
const wchar_t *kill_yank()
{
- kill_check_x_buffer();
+ kill_check_x_buffer();
if (kill_list.empty()) {
return L"";
} else {
@@ -220,7 +220,7 @@ void kill_init()
void kill_destroy()
{
- if( cut_buffer )
- free( cut_buffer );
+ if( cut_buffer )
+ free( cut_buffer );
}
diff --git a/kill.h b/kill.h
index 8cf4a3ed..6997341a 100644
--- a/kill.h
+++ b/kill.h
@@ -1,7 +1,7 @@
/** \file kill.h
- Prototypes for the killring.
+ Prototypes for the killring.
- Works like the killring in emacs and readline. The killring is cut and paste whith a memory of previous cuts.
+ Works like the killring in emacs and readline. The killring is cut and paste whith a memory of previous cuts.
*/
#ifndef FISH_KILL_H
diff --git a/lru.h b/lru.h
index 2da9ab23..ca49417a 100644
--- a/lru.h
+++ b/lru.h
@@ -20,17 +20,17 @@ struct dereference_less_t {
class lru_node_t {
template<class T> friend class lru_cache_t;
-
+
/** Our linked list pointer */
lru_node_t *prev, *next;
-
+
public:
/** The key used to look up in the cache */
const wcstring key;
-
+
/** Constructor */
lru_node_t(const wcstring &pkey) : prev(NULL), next(NULL), key(pkey) { }
-
+
/** operator< for std::set */
bool operator<(const lru_node_t &other) const { return key < other.key; }
};
@@ -41,29 +41,29 @@ class lru_cache_t {
/** Max node count */
const size_t max_node_count;
-
+
/** Count of nodes */
size_t node_count;
-
+
/** The set of nodes */
typedef std::set<lru_node_t *, dereference_less_t> node_set_t;
node_set_t node_set;
-
+
void promote_node(node_type_t *node) {
/* We should never promote the mouth */
assert(node != &mouth);
-
+
/* First unhook us */
node->prev->next = node->next;
node->next->prev = node->prev;
-
+
/* Put us after the mouth */
node->next = mouth.next;
node->next->prev = node;
node->prev = &mouth;
mouth.next = node;
}
-
+
void evict_node(node_type_t *condemned_node) {
/* We should never evict the mouth */
assert(condemned_node != NULL && condemned_node != &mouth);
@@ -79,42 +79,42 @@ class lru_cache_t {
/* Tell ourselves */
this->node_was_evicted(condemned_node);
}
-
+
void evict_last_node(void) {
/* Simple */
evict_node((node_type_t *)mouth.prev);
}
-
+
protected:
-
+
/** Head of the linked list */
lru_node_t mouth;
/** Overridable callback for when a node is evicted */
virtual void node_was_evicted(node_type_t *node) { }
-
+
public:
-
+
/** Constructor */
lru_cache_t(size_t max_size = 1024 ) : max_node_count(max_size), node_count(0), mouth(wcstring()) {
/* Hook up the mouth to itself: a one node circularly linked list! */
mouth.prev = mouth.next = &mouth;
}
-
+
/** Note that we do not evict nodes in our destructor (even though they typically need to be deleted by their creator). */
virtual ~lru_cache_t() { }
-
+
/** Returns the node for a given key, or NULL */
node_type_t *get_node(const wcstring &key) {
node_type_t *result = NULL;
-
+
/* Construct a fake node as our key */
lru_node_t node_key(key);
-
+
/* Look for it in the set */
node_set_t::iterator iter = node_set.find(&node_key);
-
+
/* If we found a node, promote and return it */
if (iter != node_set.end()) {
result = static_cast<node_type_t*>(*iter);
@@ -122,73 +122,73 @@ class lru_cache_t {
}
return result;
}
-
+
/** Evicts the node for a given key, returning true if a node was evicted. */
bool evict_node(const wcstring &key) {
/* Construct a fake node as our key */
lru_node_t node_key(key);
-
+
/* Look for it in the set */
node_set_t::iterator iter = node_set.find(&node_key);
if (iter == node_set.end())
return false;
-
+
/* Evict the given node */
evict_node(static_cast<node_type_t*>(*iter));
return true;
}
-
+
/** Adds a node under the given key. Returns true if the node was added, false if the node was not because a node with that key is already in the set. */
bool add_node(node_type_t *node) {
/* Add our node without eviction */
if (! this->add_node_without_eviction(node))
return false;
-
+
/* Evict */
while (node_count > max_node_count)
evict_last_node();
-
+
/* Success */
return true;
}
-
+
/** Adds a node under the given key without triggering eviction. Returns true if the node was added, false if the node was not because a node with that key is already in the set. */
bool add_node_without_eviction(node_type_t *node) {
assert(node != NULL && node != &mouth);
-
+
/* Try inserting; return false if it was already in the set */
if (! node_set.insert(node).second)
return false;
-
+
/* Add the node after the mouth */
node->next = mouth.next;
node->next->prev = node;
node->prev = &mouth;
mouth.next = node;
-
+
/* Update the count */
node_count++;
-
+
/* Evict */
while (node_count > max_node_count)
evict_last_node();
-
+
/* Success */
return true;
}
-
+
/** Counts nodes */
size_t size(void) {
return node_count;
}
-
+
/** Evicts all nodes */
void evict_all_nodes(void) {
while (node_count > 0) {
evict_last_node();
}
}
-
+
/** Iterator for walking nodes, from least recently used to most */
class iterator {
lru_node_t *node;
@@ -200,7 +200,7 @@ class lru_cache_t {
bool operator!=(const iterator &other) { return !(*this == other); }
node_type_t *operator*() { return static_cast<node_type_t *>(node); }
};
-
+
iterator begin() { return iterator(mouth.prev); }
iterator end() { return iterator(&mouth); }
};
diff --git a/mimedb.cpp b/mimedb.cpp
index 919e2033..d70e682e 100644
--- a/mimedb.cpp
+++ b/mimedb.cpp
@@ -1,8 +1,8 @@
-/** \file mimedb.c
+/** \file mimedb.c
mimedb is a program for checking the mimetype, description and
default action associated with a file or mimetype. It uses the
-xdgmime library written by the fine folks at freedesktop.org. There does
+xdgmime library written by the fine folks at freedesktop.org. There does
not seem to be any standard way for the user to change the preferred
application yet.
@@ -102,7 +102,7 @@ typedef std::vector<std::string> string_list_t;
/**
Error message if system call goes wrong.
*/
-#define ERROR_SYSTEM "%s: Could not execute command \"%s\"\n"
+#define ERROR_SYSTEM "%s: Could not execute command \"%s\"\n"
/**
Exit code if system call goes wrong.
@@ -115,12 +115,12 @@ typedef std::vector<std::string> string_list_t;
*/
enum
{
- FILEDATA,
- FILENAME,
- MIMETYPE,
- DESCRIPTION,
- ACTION,
- LAUNCH
+ FILEDATA,
+ FILENAME,
+ MIMETYPE,
+ DESCRIPTION,
+ ACTION,
+ LAUNCH
}
;
@@ -166,13 +166,13 @@ static int launch_pos=0;
*/
void *my_malloc( size_t s )
{
- void *res = malloc( s );
- if( !s )
- {
- error=1;
- fprintf( stderr, _("%s: Out of memory\n"), MIMEDB );
- }
- return res;
+ void *res = malloc( s );
+ if( !s )
+ {
+ error=1;
+ fprintf( stderr, _("%s: Out of memory\n"), MIMEDB );
+ }
+ return res;
}
/**
@@ -180,13 +180,13 @@ void *my_malloc( size_t s )
*/
char *my_strdup( const char *s )
{
- char *res = strdup( s );
- if( !s )
- {
- error=1;
- fprintf( stderr, _("%s: Out of memory\n"), MIMEDB );
- }
- return res;
+ char *res = strdup( s );
+ if( !s )
+ {
+ error=1;
+ fprintf( stderr, _("%s: Out of memory\n"), MIMEDB );
+ }
+ return res;
}
@@ -197,47 +197,47 @@ char *my_strdup( const char *s )
static const char * search_ini( const char *filename, const char *match )
{
/* OK to not use CLO_EXEC here because mimedb is single threaded */
- FILE *f = fopen( filename, "r" );
- char buf[4096];
- int len=strlen(match);
- int done = 0;
-
- if(!f )
- {
- perror( "fopen" );
- error=1;
- return 0;
- }
- while( !done )
- {
- if( !fgets( buf, 4096, f ) )
- {
- if( !feof( f ) )
- {
- perror( "fgets" );
- error=1;
- }
- buf[0]=0;
- done = 1;
- }
- else if( strncmp( buf, match, len ) == 0 && buf[len] == '=' )
- {
- done=1;
- }
- }
- fclose( f );
- if( buf[0] )
- {
- char *res=strdup(buf);
- if( res )
- {
- if(res[strlen(res)-1]=='\n' )
- res[strlen(res)-1]='\0';
- }
- return res;
- }
- else
- return (char *)0;
+ FILE *f = fopen( filename, "r" );
+ char buf[4096];
+ int len=strlen(match);
+ int done = 0;
+
+ if(!f )
+ {
+ perror( "fopen" );
+ error=1;
+ return 0;
+ }
+ while( !done )
+ {
+ if( !fgets( buf, 4096, f ) )
+ {
+ if( !feof( f ) )
+ {
+ perror( "fgets" );
+ error=1;
+ }
+ buf[0]=0;
+ done = 1;
+ }
+ else if( strncmp( buf, match, len ) == 0 && buf[len] == '=' )
+ {
+ done=1;
+ }
+ }
+ fclose( f );
+ if( buf[0] )
+ {
+ char *res=strdup(buf);
+ if( res )
+ {
+ if(res[strlen(res)-1]=='\n' )
+ res[strlen(res)-1]='\0';
+ }
+ return res;
+ }
+ else
+ return (char *)0;
}
/**
@@ -246,48 +246,48 @@ static const char * search_ini( const char *filename, const char *match )
*/
static char *file_exists( const char *dir, const char *in )
{
- int dir_len = strlen( dir );
- int need_sep = dir[dir_len - 1] != '/';
- char *filename = (char *)my_malloc( dir_len + need_sep + strlen( in ) + 1 );
+ int dir_len = strlen( dir );
+ int need_sep = dir[dir_len - 1] != '/';
+ char *filename = (char *)my_malloc( dir_len + need_sep + strlen( in ) + 1 );
char *replaceme;
- struct stat buf;
-
-// fprintf( stderr, "Check %s%s\n", dir, in );
-
- if( !filename )
- {
- return 0;
- }
- strcpy( filename, dir );
- if ( need_sep )
- filename[dir_len++] = '/';
- strcpy( filename + dir_len, in );
-
- if( !stat( filename, &buf ) )
- return filename;
-
- free( filename );
-
- /*
- DOH! File does not exist. But all is not lost. KDE sometimes uses
- a slash in the name as a directory separator. We try to replace
- a dash with a slash and try again.
- */
- replaceme = const_cast<char*>(strchr( in, '-' ));
- if( replaceme )
- {
- char *res;
-
- *replaceme = '/';
- res = file_exists( dir, in );
- *replaceme = '-';
- return res;
- }
- /*
- OK, no more slashes left. We really are screwed. Nothing to to
- but admit defeat and go home.
- */
- return 0;
+ struct stat buf;
+
+// fprintf( stderr, "Check %s%s\n", dir, in );
+
+ if( !filename )
+ {
+ return 0;
+ }
+ strcpy( filename, dir );
+ if ( need_sep )
+ filename[dir_len++] = '/';
+ strcpy( filename + dir_len, in );
+
+ if( !stat( filename, &buf ) )
+ return filename;
+
+ free( filename );
+
+ /*
+ DOH! File does not exist. But all is not lost. KDE sometimes uses
+ a slash in the name as a directory separator. We try to replace
+ a dash with a slash and try again.
+ */
+ replaceme = const_cast<char*>(strchr( in, '-' ));
+ if( replaceme )
+ {
+ char *res;
+
+ *replaceme = '/';
+ res = file_exists( dir, in );
+ *replaceme = '-';
+ return res;
+ }
+ /*
+ OK, no more slashes left. We really are screwed. Nothing to to
+ but admit defeat and go home.
+ */
+ return 0;
}
@@ -303,94 +303,94 @@ static char *file_exists( const char *dir, const char *in )
*/
static int append_filenames( string_list_t &list, const char *f, int all )
{
- size_t prev_count = list.size();
- char *result;
- const char *xdg_data_home;
- const char *xdg_data_dirs;
- const char *ptr;
-
- xdg_data_home = getenv ("XDG_DATA_HOME");
- if (xdg_data_home)
+ size_t prev_count = list.size();
+ char *result;
+ const char *xdg_data_home;
+ const char *xdg_data_dirs;
+ const char *ptr;
+
+ xdg_data_home = getenv ("XDG_DATA_HOME");
+ if (xdg_data_home)
+ {
+ result = file_exists( xdg_data_home, f );
+ if (result)
{
- result = file_exists( xdg_data_home, f );
- if (result)
- {
list.push_back(result);
- if ( !all )
- return 1;
- }
+ if ( !all )
+ return 1;
}
- else
+ }
+ else
+ {
+ const char *home;
+
+ home = getenv ("HOME");
+ if (home != NULL)
{
- const char *home;
-
- home = getenv ("HOME");
- if (home != NULL)
- {
- char *guessed_xdg_home;
-
- guessed_xdg_home = (char *)my_malloc (strlen (home) + strlen ("/.local/share") + 1);
- if( !guessed_xdg_home )
- return 0;
-
- strcpy (guessed_xdg_home, home);
- strcat (guessed_xdg_home, "/.local/share");
- result = file_exists( guessed_xdg_home, f );
- free (guessed_xdg_home);
-
- if (result)
- {
+ char *guessed_xdg_home;
+
+ guessed_xdg_home = (char *)my_malloc (strlen (home) + strlen ("/.local/share") + 1);
+ if( !guessed_xdg_home )
+ return 0;
+
+ strcpy (guessed_xdg_home, home);
+ strcat (guessed_xdg_home, "/.local/share");
+ result = file_exists( guessed_xdg_home, f );
+ free (guessed_xdg_home);
+
+ if (result)
+ {
list.push_back(result);
- if ( !all )
- return 1;
- }
- }
+ if ( !all )
+ return 1;
+ }
+ }
}
- xdg_data_dirs = getenv ("XDG_DATA_DIRS");
- if (xdg_data_dirs == NULL)
- xdg_data_dirs = "/usr/local/share:/usr/share";
+ xdg_data_dirs = getenv ("XDG_DATA_DIRS");
+ if (xdg_data_dirs == NULL)
+ xdg_data_dirs = "/usr/local/share:/usr/share";
- ptr = xdg_data_dirs;
+ ptr = xdg_data_dirs;
- while (*ptr != '\000')
+ while (*ptr != '\000')
{
- const char *end_ptr;
- char *dir;
- int len;
+ const char *end_ptr;
+ char *dir;
+ int len;
- end_ptr = ptr;
- while (*end_ptr != ':' && *end_ptr != '\000')
- end_ptr ++;
+ end_ptr = ptr;
+ while (*end_ptr != ':' && *end_ptr != '\000')
+ end_ptr ++;
- if (end_ptr == ptr)
- {
- ptr++;
- continue;
- }
+ if (end_ptr == ptr)
+ {
+ ptr++;
+ continue;
+ }
len = end_ptr - ptr;
- dir = (char *)my_malloc (len + 1);
- if( !dir )
- return 0;
-
- strncpy (dir, ptr, len);
- dir[len] = '\0';
- result = file_exists( dir, f );
-
- free (dir);
-
- if (result)
- {
+ dir = (char *)my_malloc (len + 1);
+ if( !dir )
+ return 0;
+
+ strncpy (dir, ptr, len);
+ dir[len] = '\0';
+ result = file_exists( dir, f );
+
+ free (dir);
+
+ if (result)
+ {
list.push_back(result);
- if ( !all ) {
- return 1;
- }
- }
+ if ( !all ) {
+ return 1;
+ }
+ }
- ptr = end_ptr;
+ ptr = end_ptr;
}
- return list.size() - prev_count;
+ return list.size() - prev_count;
}
/**
@@ -400,7 +400,7 @@ static std::string get_filename( char *f )
{
string_list_t list;
- append_filenames( list, f, 0 );
+ append_filenames( list, f, 0 );
if (list.empty()) {
return "";
} else {
@@ -415,49 +415,49 @@ static std::string get_filename( char *f )
*/
static char *munge( char *in )
{
- char *out = (char *)my_malloc( strlen( in )+1 );
- char *p=out;
- int had_whitespace = 0;
- int printed = 0;
- if( !out )
- {
- return 0;
- }
-
- while( 1 )
- {
-// fprintf( stderr, "%c\n", *in );
-
- switch( *in )
- {
- case ' ':
- case '\n':
- case '\t':
- case '\r':
- {
- had_whitespace = 1;
- break;
- }
- case '\0':
- *p = '\0';
- return out;
- default:
- {
- if( printed && had_whitespace )
- {
- *(p++)=' ';
- }
- printed=1;
- had_whitespace=0;
- *(p++)=*in;
- break;
- }
- }
- in++;
- }
- fprintf( stderr, _( "%s: Unknown error in munge()\n"), MIMEDB );
- error=1;
- return 0;
+ char *out = (char *)my_malloc( strlen( in )+1 );
+ char *p=out;
+ int had_whitespace = 0;
+ int printed = 0;
+ if( !out )
+ {
+ return 0;
+ }
+
+ while( 1 )
+ {
+// fprintf( stderr, "%c\n", *in );
+
+ switch( *in )
+ {
+ case ' ':
+ case '\n':
+ case '\t':
+ case '\r':
+ {
+ had_whitespace = 1;
+ break;
+ }
+ case '\0':
+ *p = '\0';
+ return out;
+ default:
+ {
+ if( printed && had_whitespace )
+ {
+ *(p++)=' ';
+ }
+ printed=1;
+ had_whitespace=0;
+ *(p++)=*in;
+ break;
+ }
+ }
+ in++;
+ }
+ fprintf( stderr, _( "%s: Unknown error in munge()\n"), MIMEDB );
+ error=1;
+ return 0;
}
/**
@@ -465,325 +465,325 @@ static char *munge( char *in )
*/
static char *get_lang_re()
{
-
- static char buff[BUFF_SIZE];
- const char *lang = setlocale( LC_MESSAGES, 0 );
- int close=0;
- char *out=buff;
-
- if( (1+strlen(lang)*4) >= BUFF_SIZE )
- {
- fprintf( stderr, _( "%s: Locale string too long\n"), MIMEDB );
- error = 1;
- return 0;
- }
-
- for( ; *lang; lang++ )
- {
- switch( *lang )
- {
- case '@':
- case '.':
- case '_':
- if( close )
- {
- *out++ = ')';
- *out++ = '?';
- }
-
- close=1;
- *out++ = '(';
- *out++ = *lang;
- break;
-
- default:
- *out++ = *lang;
- }
- }
-
- if( close )
- {
- *out++ = ')';
- *out++ = '?';
- }
- *out++=0;
-
- return buff;
+
+ static char buff[BUFF_SIZE];
+ const char *lang = setlocale( LC_MESSAGES, 0 );
+ int close=0;
+ char *out=buff;
+
+ if( (1+strlen(lang)*4) >= BUFF_SIZE )
+ {
+ fprintf( stderr, _( "%s: Locale string too long\n"), MIMEDB );
+ error = 1;
+ return 0;
+ }
+
+ for( ; *lang; lang++ )
+ {
+ switch( *lang )
+ {
+ case '@':
+ case '.':
+ case '_':
+ if( close )
+ {
+ *out++ = ')';
+ *out++ = '?';
+ }
+
+ close=1;
+ *out++ = '(';
+ *out++ = *lang;
+ break;
+
+ default:
+ *out++ = *lang;
+ }
+ }
+
+ if( close )
+ {
+ *out++ = ')';
+ *out++ = '?';
+ }
+ *out++=0;
+
+ return buff;
}
/**
- Get description for a specified mimetype.
+ Get description for a specified mimetype.
*/
static char *get_description( const char *mimetype )
{
- char *fn_part;
-
- std::string fn;
- int fd;
- struct stat st;
- char *contents;
- char *start=0, *stop=0, *best_start=0;
-
- if( !start_re )
- {
- char *lang;
- char buff[BUFF_SIZE];
-
- lang = get_lang_re();
- if( !lang )
- return 0;
-
- snprintf( buff, BUFF_SIZE, START_TAG, lang, lang );
-
- start_re = (regex_t *)my_malloc( sizeof(regex_t));
- stop_re = (regex_t *)my_malloc( sizeof(regex_t));
-
+ char *fn_part;
+
+ std::string fn;
+ int fd;
+ struct stat st;
+ char *contents;
+ char *start=0, *stop=0, *best_start=0;
+
+ if( !start_re )
+ {
+ char *lang;
+ char buff[BUFF_SIZE];
+
+ lang = get_lang_re();
+ if( !lang )
+ return 0;
+
+ snprintf( buff, BUFF_SIZE, START_TAG, lang, lang );
+
+ start_re = (regex_t *)my_malloc( sizeof(regex_t));
+ stop_re = (regex_t *)my_malloc( sizeof(regex_t));
+
int reg_status;
- if( ( reg_status = regcomp( start_re, buff, REG_EXTENDED ) ) )
+ if( ( reg_status = regcomp( start_re, buff, REG_EXTENDED ) ) )
{
char regerrbuf[BUFF_SIZE];
regerror(reg_status, start_re, regerrbuf, BUFF_SIZE);
- fprintf( stderr, _( "%s: Could not compile regular expressions %s with error %s\n"), MIMEDB, buff, regerrbuf);
- error=1;
-
+ fprintf( stderr, _( "%s: Could not compile regular expressions %s with error %s\n"), MIMEDB, buff, regerrbuf);
+ error=1;
+
}
else if ( ( reg_status = regcomp( stop_re, STOP_TAG, REG_EXTENDED ) ) )
- {
+ {
char regerrbuf[BUFF_SIZE];
regerror(reg_status, stop_re, regerrbuf, BUFF_SIZE);
- fprintf( stderr, _( "%s: Could not compile regular expressions %s with error %s\n"), MIMEDB, buff, regerrbuf);
- error=1;
-
+ fprintf( stderr, _( "%s: Could not compile regular expressions %s with error %s\n"), MIMEDB, buff, regerrbuf);
+ error=1;
+
}
if( error )
{
- free( start_re );
- free( stop_re );
- start_re = stop_re = 0;
+ free( start_re );
+ free( stop_re );
+ start_re = stop_re = 0;
- return 0;
+ return 0;
}
- }
-
- fn_part = (char *)my_malloc( strlen(MIME_DIR) + strlen( mimetype) + strlen(MIME_SUFFIX) + 1 );
-
- if( !fn_part )
- {
- return 0;
- }
-
- strcpy( fn_part, MIME_DIR );
- strcat( fn_part, mimetype );
- strcat( fn_part, MIME_SUFFIX );
-
- fn = get_filename(fn_part); //malloc( strlen(MIME_DIR) +strlen( MIME_SUFFIX)+ strlen( mimetype ) + 1 );
- free(fn_part );
-
- if( fn.empty() )
- {
- return 0;
- }
+ }
+
+ fn_part = (char *)my_malloc( strlen(MIME_DIR) + strlen( mimetype) + strlen(MIME_SUFFIX) + 1 );
+
+ if( !fn_part )
+ {
+ return 0;
+ }
+
+ strcpy( fn_part, MIME_DIR );
+ strcat( fn_part, mimetype );
+ strcat( fn_part, MIME_SUFFIX );
+
+ fn = get_filename(fn_part); //malloc( strlen(MIME_DIR) +strlen( MIME_SUFFIX)+ strlen( mimetype ) + 1 );
+ free(fn_part );
+
+ if( fn.empty() )
+ {
+ return 0;
+ }
/* OK to not use CLO_EXEC here because mimedb is single threaded */
- fd = open( fn.c_str(), O_RDONLY );
-
-// fprintf( stderr, "%s\n", fn );
-
- if( fd == -1 )
- {
- perror( "open" );
- error=1;
- return 0;
- }
-
- if( stat( fn.c_str(), &st) )
- {
- perror( "stat" );
- error=1;
- return 0;
- }
-
- contents = (char *)my_malloc( st.st_size + 1 );
- if( !contents )
- {
- return 0;
- }
-
- if( read( fd, contents, st.st_size ) != st.st_size )
- {
- perror( "read" );
- error=1;
+ fd = open( fn.c_str(), O_RDONLY );
+
+// fprintf( stderr, "%s\n", fn );
+
+ if( fd == -1 )
+ {
+ perror( "open" );
+ error=1;
+ return 0;
+ }
+
+ if( stat( fn.c_str(), &st) )
+ {
+ perror( "stat" );
+ error=1;
+ return 0;
+ }
+
+ contents = (char *)my_malloc( st.st_size + 1 );
+ if( !contents )
+ {
+ return 0;
+ }
+
+ if( read( fd, contents, st.st_size ) != st.st_size )
+ {
+ perror( "read" );
+ error=1;
free((void *)contents);
- return 0;
- }
-
- /*
- Don't need to check exit status of close on read-only file descriptors
- */
- close( fd );
-
- contents[st.st_size]=0;
- regmatch_t match[1];
- int w = -1;
-
- start=contents;
-
- /*
- On multiple matches, use the longest match, should be a pretty
- good heuristic for best match...
- */
- while( !regexec(start_re, start, 1, match, 0) )
- {
- int new_w = match[0].rm_eo - match[0].rm_so;
- start += match[0].rm_eo;
-
- if( new_w > w )
- {
- /*
- New match is for a longer match then the previous
- match, so we use the new match
- */
- w=new_w;
- best_start = start;
- }
- }
-
- if( w != -1 )
- {
- start = best_start;
- if( !regexec(stop_re, start, 1, match, 0) )
- {
- /*
- We've found the beginning and the end of a suitable description
- */
- char *res;
-
- stop = start + match[0].rm_so;
- *stop = '\0';
- res = munge( start );
- free( contents );
- return res;
- }
- }
- free( contents );
- fprintf( stderr, _( "%s: No description for type %s\n"), MIMEDB, mimetype );
- error=1;
- return 0;
+ return 0;
+ }
+
+ /*
+ Don't need to check exit status of close on read-only file descriptors
+ */
+ close( fd );
+
+ contents[st.st_size]=0;
+ regmatch_t match[1];
+ int w = -1;
+
+ start=contents;
+
+ /*
+ On multiple matches, use the longest match, should be a pretty
+ good heuristic for best match...
+ */
+ while( !regexec(start_re, start, 1, match, 0) )
+ {
+ int new_w = match[0].rm_eo - match[0].rm_so;
+ start += match[0].rm_eo;
+
+ if( new_w > w )
+ {
+ /*
+ New match is for a longer match then the previous
+ match, so we use the new match
+ */
+ w=new_w;
+ best_start = start;
+ }
+ }
+
+ if( w != -1 )
+ {
+ start = best_start;
+ if( !regexec(stop_re, start, 1, match, 0) )
+ {
+ /*
+ We've found the beginning and the end of a suitable description
+ */
+ char *res;
+
+ stop = start + match[0].rm_so;
+ *stop = '\0';
+ res = munge( start );
+ free( contents );
+ return res;
+ }
+ }
+ free( contents );
+ fprintf( stderr, _( "%s: No description for type %s\n"), MIMEDB, mimetype );
+ error=1;
+ return 0;
}
/**
- Get default action for a specified mimetype.
+ Get default action for a specified mimetype.
*/
static char *get_action( const char *mimetype )
{
- char *res=0;
-
- const char *launcher, *end;
- string_list_t mime_filenames;
-
- const char *launcher_str = NULL;
- const char *launcher_command_str, *launcher_command;
- char *launcher_full;
-
- if( !append_filenames( mime_filenames, DESKTOP_DEFAULT, 1 ) )
- {
- return 0;
- }
-
- for ( size_t i = 0; i < mime_filenames.size(); i++ )
- {
- launcher_str = search_ini( mime_filenames.at(i).c_str(), mimetype );
- if ( launcher_str )
- break;
- }
-
-
- if( !launcher_str )
- {
- /*
- This type does not have a launcher. Try the supertype!
- */
-// fprintf( stderr, "mimedb: %s does not have launcher, try supertype\n", mimetype );
- const char ** parents = xdg_mime_get_mime_parents(mimetype);
-
- const char **p;
- if( parents )
- {
- for( p=parents; *p; p++ )
- {
- char *a = get_action(*p);
- if( a != 0 )
- return a;
- }
- }
- /*
- Just in case subclassing doesn't work, (It doesn't on Fedora
- Core 3) we also test some common subclassings.
- */
-
- if( strncmp( mimetype, "text/plain", 10) != 0 && strncmp( mimetype, "text/", 5 ) == 0 )
- return get_action( "text/plain" );
-
- return 0;
- }
-
-// fprintf( stderr, "WOOT %s\n", launcher_str );
- launcher = const_cast<char*>(strchr( launcher_str, '=' ));
-
- if( !launcher )
- {
- fprintf( stderr, _("%s: Could not parse launcher string '%s'\n"), MIMEDB, launcher_str );
- error=1;
- return 0;
- }
-
- /* Skip the = */
- launcher++;
-
- /* Make one we can change */
- std::string mut_launcher = launcher;
-
- /* Only use first launcher */
- end = strchr( launcher, ';' );
- if( end )
- mut_launcher.resize(end - launcher);
-
- launcher_full = (char *)my_malloc( mut_launcher.size() + strlen( APPLICATIONS_DIR)+1 );
- if( !launcher_full )
- {
- free( (void *)launcher_str );
- return 0;
- }
-
- strcpy( launcher_full, APPLICATIONS_DIR );
- strcat( launcher_full, mut_launcher.c_str() );
- free( (void *)launcher_str );
-
- std::string launcher_filename = get_filename( launcher_full );
-
- free( launcher_full );
-
- launcher_command_str = search_ini( launcher_filename.c_str(), "Exec" );
-
- if( !launcher_command_str )
- {
- fprintf( stderr,
- _( "%s: Default launcher '%s' does not specify how to start\n"), MIMEDB,
- launcher_filename.c_str() );
- return 0;
- }
-
- launcher_command = strchr( launcher_command_str, '=' );
- launcher_command++;
-
- res = my_strdup( launcher_command );
-
- free( (void *)launcher_command_str );
-
- return res;
+ char *res=0;
+
+ const char *launcher, *end;
+ string_list_t mime_filenames;
+
+ const char *launcher_str = NULL;
+ const char *launcher_command_str, *launcher_command;
+ char *launcher_full;
+
+ if( !append_filenames( mime_filenames, DESKTOP_DEFAULT, 1 ) )
+ {
+ return 0;
+ }
+
+ for ( size_t i = 0; i < mime_filenames.size(); i++ )
+ {
+ launcher_str = search_ini( mime_filenames.at(i).c_str(), mimetype );
+ if ( launcher_str )
+ break;
+ }
+
+
+ if( !launcher_str )
+ {
+ /*
+ This type does not have a launcher. Try the supertype!
+ */
+// fprintf( stderr, "mimedb: %s does not have launcher, try supertype\n", mimetype );
+ const char ** parents = xdg_mime_get_mime_parents(mimetype);
+
+ const char **p;
+ if( parents )
+ {
+ for( p=parents; *p; p++ )
+ {
+ char *a = get_action(*p);
+ if( a != 0 )
+ return a;
+ }
+ }
+ /*
+ Just in case subclassing doesn't work, (It doesn't on Fedora
+ Core 3) we also test some common subclassings.
+ */
+
+ if( strncmp( mimetype, "text/plain", 10) != 0 && strncmp( mimetype, "text/", 5 ) == 0 )
+ return get_action( "text/plain" );
+
+ return 0;
+ }
+
+// fprintf( stderr, "WOOT %s\n", launcher_str );
+ launcher = const_cast<char*>(strchr( launcher_str, '=' ));
+
+ if( !launcher )
+ {
+ fprintf( stderr, _("%s: Could not parse launcher string '%s'\n"), MIMEDB, launcher_str );
+ error=1;
+ return 0;
+ }
+
+ /* Skip the = */
+ launcher++;
+
+ /* Make one we can change */
+ std::string mut_launcher = launcher;
+
+ /* Only use first launcher */
+ end = strchr( launcher, ';' );
+ if( end )
+ mut_launcher.resize(end - launcher);
+
+ launcher_full = (char *)my_malloc( mut_launcher.size() + strlen( APPLICATIONS_DIR)+1 );
+ if( !launcher_full )
+ {
+ free( (void *)launcher_str );
+ return 0;
+ }
+
+ strcpy( launcher_full, APPLICATIONS_DIR );
+ strcat( launcher_full, mut_launcher.c_str() );
+ free( (void *)launcher_str );
+
+ std::string launcher_filename = get_filename( launcher_full );
+
+ free( launcher_full );
+
+ launcher_command_str = search_ini( launcher_filename.c_str(), "Exec" );
+
+ if( !launcher_command_str )
+ {
+ fprintf( stderr,
+ _( "%s: Default launcher '%s' does not specify how to start\n"), MIMEDB,
+ launcher_filename.c_str() );
+ return 0;
+ }
+
+ launcher_command = strchr( launcher_command_str, '=' );
+ launcher_command++;
+
+ res = my_strdup( launcher_command );
+
+ free( (void *)launcher_command_str );
+
+ return res;
}
@@ -792,25 +792,25 @@ static char *get_action( const char *mimetype )
*/
static void writer( char c )
{
- if( launch_len == -1 )
- return;
-
- if( launch_len <= launch_pos )
- {
- int new_len = launch_len?2*launch_len:256;
- char *new_buff = (char *)realloc( launch_buff, new_len );
- if( !new_buff )
- {
- free( launch_buff );
- launch_len = -1;
- error=1;
- return;
- }
- launch_buff = new_buff;
- launch_len = new_len;
-
- }
- launch_buff[launch_pos++]=c;
+ if( launch_len == -1 )
+ return;
+
+ if( launch_len <= launch_pos )
+ {
+ int new_len = launch_len?2*launch_len:256;
+ char *new_buff = (char *)realloc( launch_buff, new_len );
+ if( !new_buff )
+ {
+ free( launch_buff );
+ launch_len = -1;
+ error=1;
+ return;
+ }
+ launch_buff = new_buff;
+ launch_len = new_len;
+
+ }
+ launch_buff[launch_pos++]=c;
}
/**
@@ -818,12 +818,12 @@ static void writer( char c )
*/
static void writer_hex( int num )
{
- int a, b;
- a = num /16;
- b = num %16;
+ int a, b;
+ a = num /16;
+ b = num %16;
- writer( a>9?('A'+a-10):('0'+a));
- writer( b>9?('A'+b-10):('0'+b));
+ writer( a>9?('A'+a-10):('0'+a));
+ writer( b>9?('A'+b-10):('0'+b));
}
/**
@@ -831,17 +831,17 @@ static void writer_hex( int num )
*/
static char *my_getcwd ()
{
- size_t size = 100;
- while (1)
- {
- char *buffer = (char *) malloc (size);
- if (getcwd (buffer, size) == buffer)
- return buffer;
- free (buffer);
- if (errno != ERANGE)
- return 0;
- size *= 2;
- }
+ size_t size = 100;
+ while (1)
+ {
+ char *buffer = (char *) malloc (size);
+ if (getcwd (buffer, size) == buffer)
+ return buffer;
+ free (buffer);
+ if (errno != ERANGE)
+ return 0;
+ size *= 2;
+ }
}
/**
@@ -849,39 +849,39 @@ static char *my_getcwd ()
*/
static const char *get_fullfile( const char *file )
{
- const char *fullfile;
-
- if( file[0] == '/' )
- {
- fullfile = file;
- }
- else
- {
- char *cwd = my_getcwd();
- if( !cwd )
- {
- error = 1;
- perror( "getcwd" );
- return 0;
- }
-
- int l = strlen(cwd);
-
- char *tmp = (char *)my_malloc( l + strlen(file)+2 );
- if( !tmp )
- {
- free(cwd);
- return 0;
- }
- strcpy( tmp, cwd );
- if( cwd[l-1] != '/' )
- strcat(tmp, "/" );
- strcat( tmp, file );
-
- free(cwd);
+ const char *fullfile;
+
+ if( file[0] == '/' )
+ {
+ fullfile = file;
+ }
+ else
+ {
+ char *cwd = my_getcwd();
+ if( !cwd )
+ {
+ error = 1;
+ perror( "getcwd" );
+ return 0;
+ }
+
+ int l = strlen(cwd);
+
+ char *tmp = (char *)my_malloc( l + strlen(file)+2 );
+ if( !tmp )
+ {
+ free(cwd);
+ return 0;
+ }
+ strcpy( tmp, cwd );
+ if( cwd[l-1] != '/' )
+ strcat(tmp, "/" );
+ strcat( tmp, file );
+
+ free(cwd);
fullfile = tmp;
- }
- return fullfile;
+ }
+ return fullfile;
}
@@ -890,46 +890,46 @@ static const char *get_fullfile( const char *file )
*/
static void write_url( const char *file )
{
- const char *fullfile = get_fullfile( file );
- const char *str = fullfile;
-
- if( str == 0 )
- {
- launch_len = -1;
- return;
- }
-
- writer( 'f');
- writer( 'i');
- writer( 'l');
- writer( 'e');
- writer( ':');
- writer( '/');
- writer( '/');
- while( *str )
- {
- if( ((*str >= 'a') && (*str <='z')) ||
- ((*str >= 'A') && (*str <='Z')) ||
- ((*str >= '0') && (*str <='9')) ||
- (strchr( "-_.~/",*str) != 0) )
- {
- writer(*str);
- }
- else if(strchr( "()?&=",*str) != 0)
- {
- writer('\\');
- writer(*str);
- }
- else
- {
- writer( '%' );
- writer_hex( (unsigned char)*str );
- }
- str++;
- }
- if( fullfile != file )
- free( (void *)fullfile );
-
+ const char *fullfile = get_fullfile( file );
+ const char *str = fullfile;
+
+ if( str == 0 )
+ {
+ launch_len = -1;
+ return;
+ }
+
+ writer( 'f');
+ writer( 'i');
+ writer( 'l');
+ writer( 'e');
+ writer( ':');
+ writer( '/');
+ writer( '/');
+ while( *str )
+ {
+ if( ((*str >= 'a') && (*str <='z')) ||
+ ((*str >= 'A') && (*str <='Z')) ||
+ ((*str >= '0') && (*str <='9')) ||
+ (strchr( "-_.~/",*str) != 0) )
+ {
+ writer(*str);
+ }
+ else if(strchr( "()?&=",*str) != 0)
+ {
+ writer('\\');
+ writer(*str);
+ }
+ else
+ {
+ writer( '%' );
+ writer_hex( (unsigned char)*str );
+ }
+ str++;
+ }
+ if( fullfile != file )
+ free( (void *)fullfile );
+
}
/**
@@ -937,97 +937,97 @@ static void write_url( const char *file )
*/
static void write_file( const char *file, int print_path )
{
- const char *fullfile;
- const char *str;
- if( print_path )
- {
- fullfile = get_fullfile( file );
- str = fullfile;
- }
- else
- {
- char *tmp = my_strdup( file );
- if( !tmp )
- {
- return;
- }
- str = basename( tmp );
+ const char *fullfile;
+ const char *str;
+ if( print_path )
+ {
+ fullfile = get_fullfile( file );
+ str = fullfile;
+ }
+ else
+ {
+ char *tmp = my_strdup( file );
+ if( !tmp )
+ {
+ return;
+ }
+ str = basename( tmp );
fullfile = tmp;
- }
-
- if( !str )
- {
- error = 1;
- return;
- }
-
- while( *str )
- {
- switch(*str )
- {
- case ')':
- case '(':
- case '-':
- case '#':
- case '$':
- case '}':
- case '{':
- case ']':
- case '[':
- case '*':
- case '?':
- case ' ':
- case '|':
- case '<':
- case '>':
- case '^':
- case '&':
- case '\\':
- case '`':
- case '\'':
- case '\"':
- writer('\\');
- writer(*str);
- break;
-
- case '\n':
- writer('\\');
- writer('n');
- break;
-
- case '\r':
- writer('\\');
- writer('r');
- break;
-
- case '\t':
- writer('\\');
- writer('t');
- break;
-
- case '\b':
- writer('\\');
- writer('b');
- break;
-
- case '\v':
- writer('\\');
- writer('v');
- break;
-
- default:
- writer(*str);
- break;
- }
- str++;
- }
-
- if( fullfile != file )
- free( (void *)fullfile );
+ }
+
+ if( !str )
+ {
+ error = 1;
+ return;
+ }
+
+ while( *str )
+ {
+ switch(*str )
+ {
+ case ')':
+ case '(':
+ case '-':
+ case '#':
+ case '$':
+ case '}':
+ case '{':
+ case ']':
+ case '[':
+ case '*':
+ case '?':
+ case ' ':
+ case '|':
+ case '<':
+ case '>':
+ case '^':
+ case '&':
+ case '\\':
+ case '`':
+ case '\'':
+ case '\"':
+ writer('\\');
+ writer(*str);
+ break;
+
+ case '\n':
+ writer('\\');
+ writer('n');
+ break;
+
+ case '\r':
+ writer('\\');
+ writer('r');
+ break;
+
+ case '\t':
+ writer('\\');
+ writer('t');
+ break;
+
+ case '\b':
+ writer('\\');
+ writer('b');
+ break;
+
+ case '\v':
+ writer('\\');
+ writer('v');
+ break;
+
+ default:
+ writer(*str);
+ break;
+ }
+ str++;
+ }
+
+ if( fullfile != file )
+ free( (void *)fullfile );
}
/**
- Use the specified launch filter to launch all the files in the specified list.
+ Use the specified launch filter to launch all the files in the specified list.
\param filter the action to take
\param files the list of files for which to perform the action
@@ -1035,169 +1035,169 @@ static void write_file( const char *file, int print_path )
*/
static void launch( char *filter, const string_list_t &files, size_t fileno )
{
- char *filter_org=filter;
- int count=0;
- int launch_again=0;
-
- if( files.size() <= fileno )
- return;
-
-
- launch_pos=0;
-
- for( ;*filter && !error; filter++)
- {
- if(*filter == '%')
- {
- filter++;
- switch( *filter )
- {
- case 'u':
- {
- launch_again = 1;
- write_url( files.at(fileno).c_str() );
- break;
- }
- case 'U':
- {
- for( size_t i=0; i<files.size(); i++ )
- {
- if( i != 0 )
- writer( ' ' );
- write_url( files.at(i).c_str() );
- if( error )
- break;
- }
-
- break;
- }
-
- case 'f':
- case 'n':
- {
- launch_again = 1;
- write_file( files.at(fileno).c_str(), *filter == 'f' );
- break;
- }
-
- case 'F':
- case 'N':
- {
- for( size_t i=0; i<files.size(); i++ )
- {
- if( i != 0 )
- writer( ' ' );
- write_file( files.at(i).c_str(), *filter == 'F' );
- if( error )
- break;
- }
- break;
- }
-
-
- case 'd':
- {
- const char *cpy = get_fullfile( files.at(fileno).c_str() );
- char *dir;
-
- launch_again=1;
- /*
- We wish to modify this string, make sure it is only a copy
- */
- if( cpy == files.at(fileno).c_str())
- cpy = my_strdup( cpy );
-
- if( cpy == 0 )
- {
- break;
- }
-
- dir=dirname( (char *)cpy );
- write_file( dir, 1 );
- free( (void *)cpy );
-
- break;
- }
-
- case 'D':
- {
- for( size_t i=0; i<files.size(); i++ )
- {
- const char *cpy = get_fullfile( files.at(i).c_str() );
- char *dir;
-
- /*
- We wish to modify this string, make sure it is only a copy
- */
- if( cpy == files.at(i).c_str() )
- cpy = my_strdup( cpy );
-
- if( cpy == 0 )
- {
- break;
- }
- dir=dirname( (char *)cpy );
-
- if( i != 0 )
- writer( ' ' );
-
- write_file( dir, 1 );
- free( (void *)cpy );
-
- }
- break;
- }
-
- default:
- fprintf( stderr, _("%s: Unsupported switch '%c' in launch string '%s'\n"), MIMEDB, *filter, filter_org );
- launch_len=0;
- break;
-
- }
- }
- else
- {
- writer( *filter );
- count++;
- }
- }
-
- if( error )
- return;
-
- switch( launch_len )
- {
- case -1:
- {
- launch_len = 0;
- fprintf( stderr, _( "%s: Out of memory\n"), MIMEDB );
- return;
- }
- case 0:
- {
- return;
- }
- default:
- {
-
- writer( ' ' );
- writer( '&' );
- writer( '\0' );
-
- if( system( launch_buff ) == -1 )
- {
- fprintf( stderr, _( ERROR_SYSTEM ), MIMEDB, launch_buff );
- exit(STATUS_ERROR_SYSTEM);
- }
-
- break;
- }
- }
- if( launch_again )
- {
- launch( filter_org, files, fileno+1 );
- }
-
+ char *filter_org=filter;
+ int count=0;
+ int launch_again=0;
+
+ if( files.size() <= fileno )
+ return;
+
+
+ launch_pos=0;
+
+ for( ;*filter && !error; filter++)
+ {
+ if(*filter == '%')
+ {
+ filter++;
+ switch( *filter )
+ {
+ case 'u':
+ {
+ launch_again = 1;
+ write_url( files.at(fileno).c_str() );
+ break;
+ }
+ case 'U':
+ {
+ for( size_t i=0; i<files.size(); i++ )
+ {
+ if( i != 0 )
+ writer( ' ' );
+ write_url( files.at(i).c_str() );
+ if( error )
+ break;
+ }
+
+ break;
+ }
+
+ case 'f':
+ case 'n':
+ {
+ launch_again = 1;
+ write_file( files.at(fileno).c_str(), *filter == 'f' );
+ break;
+ }
+
+ case 'F':
+ case 'N':
+ {
+ for( size_t i=0; i<files.size(); i++ )
+ {
+ if( i != 0 )
+ writer( ' ' );
+ write_file( files.at(i).c_str(), *filter == 'F' );
+ if( error )
+ break;
+ }
+ break;
+ }
+
+
+ case 'd':
+ {
+ const char *cpy = get_fullfile( files.at(fileno).c_str() );
+ char *dir;
+
+ launch_again=1;
+ /*
+ We wish to modify this string, make sure it is only a copy
+ */
+ if( cpy == files.at(fileno).c_str())
+ cpy = my_strdup( cpy );
+
+ if( cpy == 0 )
+ {
+ break;
+ }
+
+ dir=dirname( (char *)cpy );
+ write_file( dir, 1 );
+ free( (void *)cpy );
+
+ break;
+ }
+
+ case 'D':
+ {
+ for( size_t i=0; i<files.size(); i++ )
+ {
+ const char *cpy = get_fullfile( files.at(i).c_str() );
+ char *dir;
+
+ /*
+ We wish to modify this string, make sure it is only a copy
+ */
+ if( cpy == files.at(i).c_str() )
+ cpy = my_strdup( cpy );
+
+ if( cpy == 0 )
+ {
+ break;
+ }
+ dir=dirname( (char *)cpy );
+
+ if( i != 0 )
+ writer( ' ' );
+
+ write_file( dir, 1 );
+ free( (void *)cpy );
+
+ }
+ break;
+ }
+
+ default:
+ fprintf( stderr, _("%s: Unsupported switch '%c' in launch string '%s'\n"), MIMEDB, *filter, filter_org );
+ launch_len=0;
+ break;
+
+ }
+ }
+ else
+ {
+ writer( *filter );
+ count++;
+ }
+ }
+
+ if( error )
+ return;
+
+ switch( launch_len )
+ {
+ case -1:
+ {
+ launch_len = 0;
+ fprintf( stderr, _( "%s: Out of memory\n"), MIMEDB );
+ return;
+ }
+ case 0:
+ {
+ return;
+ }
+ default:
+ {
+
+ writer( ' ' );
+ writer( '&' );
+ writer( '\0' );
+
+ if( system( launch_buff ) == -1 )
+ {
+ fprintf( stderr, _( ERROR_SYSTEM ), MIMEDB, launch_buff );
+ exit(STATUS_ERROR_SYSTEM);
+ }
+
+ break;
+ }
+ }
+ if( launch_again )
+ {
+ launch( filter_org, files, fileno+1 );
+ }
+
}
/**
@@ -1205,9 +1205,9 @@ static void launch( char *filter, const string_list_t &files, size_t fileno )
*/
static void locale_init()
{
- setlocale( LC_ALL, "" );
- bindtextdomain( PACKAGE_NAME, LOCALEDIR );
- textdomain( PACKAGE_NAME );
+ setlocale( LC_ALL, "" );
+ bindtextdomain( PACKAGE_NAME, LOCALEDIR );
+ textdomain( PACKAGE_NAME );
}
@@ -1215,245 +1215,245 @@ static void locale_init()
Main function. Parses options and calls helper function for any heavy lifting.
*/
int main (int argc, char *argv[])
-{
- int input_type=FILEDATA;
- int output_type=MIMETYPE;
-
- const char *mimetype;
- char *output=0;
-
- int i;
+{
+ int input_type=FILEDATA;
+ int output_type=MIMETYPE;
+
+ const char *mimetype;
+ char *output=0;
+
+ int i;
typedef std::map<std::string, string_list_t> launch_hash_t;
launch_hash_t launch_hash;
- locale_init();
-
- /*
- Parse options
- */
- while( 1 )
- {
- static struct option
- long_options[] =
- {
- {
- "input-file-data", no_argument, 0, 't'
- }
- ,
- {
- "input-filename", no_argument, 0, 'f'
- }
- ,
- {
- "input-mime", no_argument, 0, 'i'
- }
- ,
- {
- "output-mime", no_argument, 0, 'm'
- }
- ,
- {
- "output-description", no_argument, 0, 'd'
- }
- ,
- {
- "output-action", no_argument, 0, 'a'
- }
- ,
- {
- "help", no_argument, 0, 'h'
- }
- ,
- {
- "version", no_argument, 0, 'v'
- }
- ,
- {
- "launch", no_argument, 0, 'l'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = getopt_long( argc,
- argv,
- GETOPT_STRING,
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- break;
-
- case 't':
- input_type=FILEDATA;
- break;
-
- case 'f':
- input_type=FILENAME;
- break;
-
- case 'i':
- input_type=MIMETYPE;
- break;
-
- case 'm':
- output_type=MIMETYPE;
- break;
-
- case 'd':
- output_type=DESCRIPTION;
- break;
-
- case 'a':
- output_type=ACTION;
- break;
-
- case 'l':
- output_type=LAUNCH;
- break;
-
- case 'h':
- print_help( argv[0], 1 );
- exit(0);
-
- case 'v':
- printf( _("%s, version %s\n"), MIMEDB, PACKAGE_VERSION );
- exit( 0 );
-
- case '?':
- return 1;
-
- }
- }
-
- if( ( output_type == LAUNCH )&&(input_type==MIMETYPE))
- {
- fprintf( stderr, _("%s: Can not launch a mimetype\n"), MIMEDB );
- print_help( argv[0], 2 );
- exit(1);
- }
-
- /*
- Loop over all non option arguments and do the specified lookup
- */
-
- //fprintf( stderr, "Input %d, output %d\n", input_type, output_type );
-
- for (i = optind; (i < argc)&&(!error); i++)
+ locale_init();
+
+ /*
+ Parse options
+ */
+ while( 1 )
+ {
+ static struct option
+ long_options[] =
+ {
+ {
+ "input-file-data", no_argument, 0, 't'
+ }
+ ,
+ {
+ "input-filename", no_argument, 0, 'f'
+ }
+ ,
+ {
+ "input-mime", no_argument, 0, 'i'
+ }
+ ,
+ {
+ "output-mime", no_argument, 0, 'm'
+ }
+ ,
+ {
+ "output-description", no_argument, 0, 'd'
+ }
+ ,
+ {
+ "output-action", no_argument, 0, 'a'
+ }
+ ,
+ {
+ "help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ "version", no_argument, 0, 'v'
+ }
+ ,
+ {
+ "launch", no_argument, 0, 'l'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = getopt_long( argc,
+ argv,
+ GETOPT_STRING,
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ break;
+
+ case 't':
+ input_type=FILEDATA;
+ break;
+
+ case 'f':
+ input_type=FILENAME;
+ break;
+
+ case 'i':
+ input_type=MIMETYPE;
+ break;
+
+ case 'm':
+ output_type=MIMETYPE;
+ break;
+
+ case 'd':
+ output_type=DESCRIPTION;
+ break;
+
+ case 'a':
+ output_type=ACTION;
+ break;
+
+ case 'l':
+ output_type=LAUNCH;
+ break;
+
+ case 'h':
+ print_help( argv[0], 1 );
+ exit(0);
+
+ case 'v':
+ printf( _("%s, version %s\n"), MIMEDB, PACKAGE_VERSION );
+ exit( 0 );
+
+ case '?':
+ return 1;
+
+ }
+ }
+
+ if( ( output_type == LAUNCH )&&(input_type==MIMETYPE))
+ {
+ fprintf( stderr, _("%s: Can not launch a mimetype\n"), MIMEDB );
+ print_help( argv[0], 2 );
+ exit(1);
+ }
+
+ /*
+ Loop over all non option arguments and do the specified lookup
+ */
+
+ //fprintf( stderr, "Input %d, output %d\n", input_type, output_type );
+
+ for (i = optind; (i < argc)&&(!error); i++)
+ {
+ /* Convert from filename to mimetype, if needed */
+ if( input_type == FILENAME )
+ {
+ mimetype = xdg_mime_get_mime_type_from_file_name(argv[i]);
+ }
+ else if( input_type == FILEDATA )
+ {
+ mimetype = xdg_mime_get_mime_type_for_file(argv[i]);
+ }
+ else
+ mimetype = xdg_mime_is_valid_mime_type(argv[i])?argv[i]:0;
+
+ mimetype = xdg_mime_unalias_mime_type (mimetype);
+ if( !mimetype )
+ {
+ fprintf( stderr, _( "%s: Could not parse mimetype from argument '%s'\n"), MIMEDB, argv[i] );
+ error=1;
+ return 1;
+ }
+
+ /*
+ Convert from mimetype to whatever, if needed
+ */
+ switch( output_type )
{
- /* Convert from filename to mimetype, if needed */
- if( input_type == FILENAME )
- {
- mimetype = xdg_mime_get_mime_type_from_file_name(argv[i]);
- }
- else if( input_type == FILEDATA )
- {
- mimetype = xdg_mime_get_mime_type_for_file(argv[i]);
- }
- else
- mimetype = xdg_mime_is_valid_mime_type(argv[i])?argv[i]:0;
-
- mimetype = xdg_mime_unalias_mime_type (mimetype);
- if( !mimetype )
- {
- fprintf( stderr, _( "%s: Could not parse mimetype from argument '%s'\n"), MIMEDB, argv[i] );
- error=1;
- return 1;
- }
-
- /*
- Convert from mimetype to whatever, if needed
- */
- switch( output_type )
- {
- case MIMETYPE:
- {
- output = (char *)mimetype;
- break;
-
- }
- case DESCRIPTION:
- {
- output = get_description( mimetype );
- if( !output )
- output = strdup( _("Unknown") );
-
- break;
- }
- case ACTION:
- {
- output = get_action( mimetype );
- break;
- }
- case LAUNCH:
- {
- /*
- There may be more files using the same launcher, we
- add them all up in little array_list_ts and launched
- them together after all the arguments have been
- parsed.
- */
- output = 0;
+ case MIMETYPE:
+ {
+ output = (char *)mimetype;
+ break;
+
+ }
+ case DESCRIPTION:
+ {
+ output = get_description( mimetype );
+ if( !output )
+ output = strdup( _("Unknown") );
+
+ break;
+ }
+ case ACTION:
+ {
+ output = get_action( mimetype );
+ break;
+ }
+ case LAUNCH:
+ {
+ /*
+ There may be more files using the same launcher, we
+ add them all up in little array_list_ts and launched
+ them together after all the arguments have been
+ parsed.
+ */
+ output = 0;
string_list_t &l = launch_hash[mimetype];
l.push_back(argv[i]);
- }
- }
-
- /*
- Print the glorious result
- */
- if( output )
- {
- printf( "%s\n", output );
- if( output != mimetype )
- free( output );
- }
- output = 0;
+ }
}
- /*
- Perform the actual launching
- */
- if( output_type == LAUNCH && !error )
- {
- for( launch_hash_t::iterator iter = launch_hash.begin(); iter != launch_hash.end(); ++iter)
- {
- const char *mimetype = iter->first.c_str();
- string_list_t &files = iter->second;
-
- char *launcher = get_action( mimetype );
-
- if( launcher )
- {
- launch( launcher, files, 0 );
- free( launcher );
- }
- }
- }
-
- if( launch_buff )
- free( launch_buff );
-
- if( start_re )
- {
- regfree( start_re );
- regfree( stop_re );
- free( start_re );
- free( stop_re );
- }
-
- xdg_mime_shutdown();
-
- return error;
+ /*
+ Print the glorious result
+ */
+ if( output )
+ {
+ printf( "%s\n", output );
+ if( output != mimetype )
+ free( output );
+ }
+ output = 0;
+ }
+
+ /*
+ Perform the actual launching
+ */
+ if( output_type == LAUNCH && !error )
+ {
+ for( launch_hash_t::iterator iter = launch_hash.begin(); iter != launch_hash.end(); ++iter)
+ {
+ const char *mimetype = iter->first.c_str();
+ string_list_t &files = iter->second;
+
+ char *launcher = get_action( mimetype );
+
+ if( launcher )
+ {
+ launch( launcher, files, 0 );
+ free( launcher );
+ }
+ }
+ }
+
+ if( launch_buff )
+ free( launch_buff );
+
+ if( start_re )
+ {
+ regfree( start_re );
+ regfree( stop_re );
+ free( start_re );
+ free( stop_re );
+ }
+
+ xdg_mime_shutdown();
+
+ return error;
}
diff --git a/output.cpp b/output.cpp
index b061693e..49917239 100644
--- a/output.cpp
+++ b/output.cpp
@@ -65,21 +65,21 @@
static int writeb_internal( char c );
/**
- Names of different colors.
+ Names of different colors.
*/
static const wchar_t *col[]=
{
- L"black",
- L"red",
- L"green",
- L"brown",
- L"yellow",
- L"blue",
- L"magenta",
- L"purple",
- L"cyan",
- L"white"
- L"normal"
+ L"black",
+ L"red",
+ L"green",
+ L"brown",
+ L"yellow",
+ L"blue",
+ L"magenta",
+ L"purple",
+ L"cyan",
+ L"white"
+ L"normal"
}
;
@@ -91,17 +91,17 @@ static const wchar_t *col[]=
*/
static const int col_idx[]=
{
- 0,
- 1,
- 2,
- 3,
- 3,
- 4,
- 5,
- 5,
- 6,
- 7,
- FISH_COLOR_NORMAL,
+ 0,
+ 1,
+ 2,
+ 3,
+ 3,
+ 4,
+ 5,
+ 5,
+ 6,
+ 7,
+ FISH_COLOR_NORMAL,
};
/**
@@ -121,13 +121,13 @@ static bool support_term256 = false;
void output_set_writer( int (*writer)(char) )
{
- CHECK( writer, );
- out = writer;
+ CHECK( writer, );
+ out = writer;
}
int (*output_get_writer())(char)
{
- return out;
+ return out;
}
static bool term256_support_is_native(void) {
@@ -166,14 +166,14 @@ static bool write_color(char *todo, unsigned char idx, bool is_fg) {
strcat(buff, is_fg ? "38;5;" : "48;5;");
strcat(buff, stridx);
strcat(buff, "m");
-
+
int (*writer)(char) = output_get_writer();
if (writer) {
for (size_t i=0; buff[i]; i++) {
writer(buff[i]);
}
}
-
+
result = true;
}
return result;
@@ -202,188 +202,188 @@ static bool write_background_color(unsigned char idx) {
void set_color(rgb_color_t c, rgb_color_t c2)
{
-
+
#if 0
wcstring tmp = c.description();
wcstring tmp2 = c2.description();
printf("set_color %ls : %ls\n", tmp.c_str(), tmp2.c_str());
-#endif
+#endif
ASSERT_IS_MAIN_THREAD();
-
+
const rgb_color_t normal = rgb_color_t::normal();
static rgb_color_t last_color = rgb_color_t::normal();
- static rgb_color_t last_color2 = rgb_color_t::normal();
- static int was_bold=0;
- static int was_underline=0;
- int bg_set=0, last_bg_set=0;
-
- int is_bold = 0;
- int is_underline = 0;
-
- /*
+ static rgb_color_t last_color2 = rgb_color_t::normal();
+ static int was_bold=0;
+ static int was_underline=0;
+ int bg_set=0, last_bg_set=0;
+
+ int is_bold = 0;
+ int is_underline = 0;
+
+ /*
Test if we have at least basic support for setting fonts, colors
and related bits - otherwise just give up...
*/
- if( !exit_attribute_mode )
- {
- return;
- }
-
-
- is_bold |= c.is_bold();
- is_bold |= c2.is_bold();
-
- is_underline |= c.is_underline();
- is_underline |= c2.is_underline();
-
- if( c.is_reset() || c2.is_reset())
- {
- c = c2 = normal;
- was_bold=0;
- was_underline=0;
+ if( !exit_attribute_mode )
+ {
+ return;
+ }
+
+
+ is_bold |= c.is_bold();
+ is_bold |= c2.is_bold();
+
+ is_underline |= c.is_underline();
+ is_underline |= c2.is_underline();
+
+ if( c.is_reset() || c2.is_reset())
+ {
+ c = c2 = normal;
+ was_bold=0;
+ was_underline=0;
/*
If we exit attibute mode, we must first set a color, or
previously coloured text might lose it's
color. Terminals are weird...
*/
write_foreground_color(0);
- writembs( exit_attribute_mode );
- return;
- }
-
- if( was_bold && !is_bold )
- {
- /*
- Only way to exit bold mode is a reset of all attributes.
+ writembs( exit_attribute_mode );
+ return;
+ }
+
+ if( was_bold && !is_bold )
+ {
+ /*
+ Only way to exit bold mode is a reset of all attributes.
*/
- writembs( exit_attribute_mode );
- last_color = normal;
- last_color2 = normal;
- was_bold=0;
- was_underline=0;
- }
-
- if( ! last_color2.is_normal() &&
+ writembs( exit_attribute_mode );
+ last_color = normal;
+ last_color2 = normal;
+ was_bold=0;
+ was_underline=0;
+ }
+
+ if( ! last_color2.is_normal() &&
! last_color2.is_reset() &&
! last_color2.is_ignore() )
- {
- /*
+ {
+ /*
Background was set
*/
- last_bg_set=1;
- }
-
- if( ! c2.is_normal() &&
+ last_bg_set=1;
+ }
+
+ if( ! c2.is_normal() &&
! c2.is_ignore())
- {
- /*
+ {
+ /*
Background is set
*/
- bg_set=1;
+ bg_set=1;
if ( c==c2 )
c = (c2==rgb_color_t::white())?rgb_color_t::black():rgb_color_t::white();
- }
-
- if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0))
- {
- if(bg_set && !last_bg_set)
- {
- /*
+ }
+
+ if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0))
+ {
+ if(bg_set && !last_bg_set)
+ {
+ /*
Background color changed and is set, so we enter bold
mode to make reading easier. This means bold mode is
_always_ on when the background color is set.
*/
- writembs( enter_bold_mode );
- }
- if(!bg_set && last_bg_set)
- {
- /*
+ writembs( enter_bold_mode );
+ }
+ if(!bg_set && last_bg_set)
+ {
+ /*
Background color changed and is no longer set, so we
exit bold mode
*/
- writembs( exit_attribute_mode );
- was_bold=0;
- was_underline=0;
- /*
+ writembs( exit_attribute_mode );
+ was_bold=0;
+ was_underline=0;
+ /*
We don't know if exit_attribute_mode resets colors, so
we set it to something known.
*/
- if( write_foreground_color(0))
- {
- last_color=rgb_color_t::black();
- }
- }
- }
-
- if( last_color != c )
- {
- if( c.is_normal() )
- {
- write_foreground_color(0);
- writembs( exit_attribute_mode );
-
- last_color2 = rgb_color_t::normal();
- was_bold=0;
- was_underline=0;
- }
- else if( ! c.is_special() )
- {
+ if( write_foreground_color(0))
+ {
+ last_color=rgb_color_t::black();
+ }
+ }
+ }
+
+ if( last_color != c )
+ {
+ if( c.is_normal() )
+ {
+ write_foreground_color(0);
+ writembs( exit_attribute_mode );
+
+ last_color2 = rgb_color_t::normal();
+ was_bold=0;
+ was_underline=0;
+ }
+ else if( ! c.is_special() )
+ {
write_foreground_color(index_for_color(c));
- }
- }
-
- last_color = c;
-
- if( last_color2 != c2 )
- {
- if( c2.is_normal() )
- {
+ }
+ }
+
+ last_color = c;
+
+ if( last_color2 != c2 )
+ {
+ if( c2.is_normal() )
+ {
write_background_color(0);
-
- writembs( exit_attribute_mode );
- if( ! last_color.is_normal())
- {
+
+ writembs( exit_attribute_mode );
+ if( ! last_color.is_normal())
+ {
write_foreground_color(index_for_color(last_color));
- }
-
-
- was_bold=0;
- was_underline=0;
- last_color2 = c2;
- }
- else if ( ! c2.is_special() )
- {
+ }
+
+
+ was_bold=0;
+ was_underline=0;
+ last_color2 = c2;
+ }
+ else if ( ! c2.is_special() )
+ {
write_background_color(index_for_color(c2));
- last_color2 = c2;
- }
- }
-
- /*
+ last_color2 = c2;
+ }
+ }
+
+ /*
Lastly, we set bold mode and underline mode correctly
*/
- if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
- {
- if( is_bold && !was_bold )
- {
- if( enter_bold_mode )
- {
- writembs( tparm( enter_bold_mode ) );
- }
- }
- was_bold = is_bold;
- }
-
- if( was_underline && !is_underline )
- {
- writembs( exit_underline_mode );
- }
-
- if( !was_underline && is_underline )
- {
- writembs( enter_underline_mode );
- }
- was_underline = is_underline;
-
+ if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
+ {
+ if( is_bold && !was_bold )
+ {
+ if( enter_bold_mode )
+ {
+ writembs( tparm( enter_bold_mode ) );
+ }
+ }
+ was_bold = is_bold;
+ }
+
+ if( was_underline && !is_underline )
+ {
+ writembs( exit_underline_mode );
+ }
+
+ if( !was_underline && is_underline )
+ {
+ writembs( enter_underline_mode );
+ }
+ was_underline = is_underline;
+
}
/**
@@ -391,80 +391,80 @@ void set_color(rgb_color_t c, rgb_color_t c2)
*/
static int writeb_internal( char c )
{
- write_loop( 1, &c, 1 );
- return 0;
+ write_loop( 1, &c, 1 );
+ return 0;
}
int writeb( tputs_arg_t b )
{
- out( b );
- return 0;
+ out( b );
+ return 0;
}
int writembs_internal( char *str )
{
- CHECK( str, 1 );
-
- return tputs(str,1,&writeb)==ERR?1:0;
+ CHECK( str, 1 );
+
+ return tputs(str,1,&writeb)==ERR?1:0;
}
int writech( wint_t ch )
{
- mbstate_t state;
- size_t i;
- char buff[MB_LEN_MAX+1];
- size_t bytes;
-
- if( ( ch >= ENCODE_DIRECT_BASE) &&
+ mbstate_t state;
+ size_t i;
+ char buff[MB_LEN_MAX+1];
+ size_t bytes;
+
+ if( ( ch >= ENCODE_DIRECT_BASE) &&
( ch < ENCODE_DIRECT_BASE+256) )
- {
- buff[0] = ch - ENCODE_DIRECT_BASE;
- bytes=1;
- }
- else
- {
- memset( &state, 0, sizeof(state) );
- bytes= wcrtomb( buff, ch, &state );
-
- switch( bytes )
- {
- case (size_t)(-1):
- {
- return 1;
- }
- }
- }
-
- for( i=0; i<bytes; i++ )
- {
- out( buff[i] );
- }
- return 0;
+ {
+ buff[0] = ch - ENCODE_DIRECT_BASE;
+ bytes=1;
+ }
+ else
+ {
+ memset( &state, 0, sizeof(state) );
+ bytes= wcrtomb( buff, ch, &state );
+
+ switch( bytes )
+ {
+ case (size_t)(-1):
+ {
+ return 1;
+ }
+ }
+ }
+
+ for( i=0; i<bytes; i++ )
+ {
+ out( buff[i] );
+ }
+ return 0;
}
void writestr( const wchar_t *str )
{
- char *pos;
-
- CHECK( str, );
-
- // while( *str )
- // writech( *str++ );
-
- /*
+ char *pos;
+
+ CHECK( str, );
+
+ // while( *str )
+ // writech( *str++ );
+
+ /*
Check amount of needed space
*/
- size_t len = wcstombs( 0, str, 0 );
-
- if( len == (size_t)-1 )
- {
- debug( 1, L"Tried to print invalid wide character string" );
- return;
- }
-
- len++;
-
- /*
+ size_t len = wcstombs( 0, str, 0 );
+
+ if( len == (size_t)-1 )
+ {
+ debug( 1, L"Tried to print invalid wide character string" );
+ return;
+ }
+
+ len++;
+
+ /*
Convert
*/
char *buffer, static_buffer[256];
@@ -472,19 +472,19 @@ void writestr( const wchar_t *str )
buffer = static_buffer;
else
buffer = new char[len];
-
- wcstombs( buffer,
+
+ wcstombs( buffer,
str,
len );
-
- /*
+
+ /*
Write
*/
- for( pos = buffer; *pos; pos++ )
- {
- out( *pos );
- }
-
+ for( pos = buffer; *pos; pos++ )
+ {
+ out( *pos );
+ }
+
if (buffer != static_buffer)
delete[] buffer;
}
@@ -492,93 +492,93 @@ void writestr( const wchar_t *str )
void writestr_ellipsis( const wchar_t *str, int max_width )
{
- int written=0;
- int tot;
-
- CHECK( str, );
-
- tot = my_wcswidth(str);
-
- if( tot <= max_width )
- {
- writestr( str );
- return;
- }
-
- while( *str != 0 )
- {
- int w = fish_wcwidth( *str );
- if( written+w+fish_wcwidth( ellipsis_char )>max_width )
- {
- break;
- }
- written+=w;
- writech( *(str++) );
- }
-
- written += fish_wcwidth( ellipsis_char );
- writech( ellipsis_char );
-
- while( written < max_width )
- {
- written++;
- writestr( L" " );
- }
+ int written=0;
+ int tot;
+
+ CHECK( str, );
+
+ tot = my_wcswidth(str);
+
+ if( tot <= max_width )
+ {
+ writestr( str );
+ return;
+ }
+
+ while( *str != 0 )
+ {
+ int w = fish_wcwidth( *str );
+ if( written+w+fish_wcwidth( ellipsis_char )>max_width )
+ {
+ break;
+ }
+ written+=w;
+ writech( *(str++) );
+ }
+
+ written += fish_wcwidth( ellipsis_char );
+ writech( ellipsis_char );
+
+ while( written < max_width )
+ {
+ written++;
+ writestr( L" " );
+ }
}
int write_escaped_str( const wchar_t *str, int max_len )
{
-
- wchar_t *out;
- int i;
- int len;
- int written=0;
-
- CHECK( str, 0 );
-
- out = escape( str, 1 );
- len = my_wcswidth( out );
-
- if( max_len && (max_len < len))
- {
- for( i=0; (written+fish_wcwidth(out[i]))<=(max_len-1); i++ )
- {
- writech( out[i] );
- written += fish_wcwidth( out[i] );
- }
- writech( ellipsis_char );
- written += fish_wcwidth( ellipsis_char );
-
- for( i=written; i<max_len; i++ )
- {
- writech( L' ' );
- written++;
- }
- }
- else
- {
- written = len;
- writestr( out );
- }
-
- free( out );
- return written;
+
+ wchar_t *out;
+ int i;
+ int len;
+ int written=0;
+
+ CHECK( str, 0 );
+
+ out = escape( str, 1 );
+ len = my_wcswidth( out );
+
+ if( max_len && (max_len < len))
+ {
+ for( i=0; (written+fish_wcwidth(out[i]))<=(max_len-1); i++ )
+ {
+ writech( out[i] );
+ written += fish_wcwidth( out[i] );
+ }
+ writech( ellipsis_char );
+ written += fish_wcwidth( ellipsis_char );
+
+ for( i=written; i<max_len; i++ )
+ {
+ writech( L' ' );
+ written++;
+ }
+ }
+ else
+ {
+ written = len;
+ writestr( out );
+ }
+
+ free( out );
+ return written;
}
int output_color_code( const wcstring &val, bool is_background ) {
- size_t i;
+ size_t i;
int color=FISH_COLOR_NORMAL;
- int is_bold=0;
- int is_underline=0;
-
- if (val.empty())
- return FISH_COLOR_NORMAL;
-
+ int is_bold=0;
+ int is_underline=0;
+
+ if (val.empty())
+ return FISH_COLOR_NORMAL;
+
wcstring_list_t el;
- tokenize_variable_array( val, el );
-
- for(size_t j=0; j < el.size(); j++ ) {
+ tokenize_variable_array( val, el );
+
+ for(size_t j=0; j < el.size(); j++ ) {
const wcstring &next = el.at(j);
wcstring color_name;
if (is_background) {
@@ -587,7 +587,7 @@ int output_color_code( const wcstring &val, bool is_background ) {
if (string_prefixes_string(prefix, next)) {
color_name = wcstring(next, prefix.size());
}
-
+
} else {
if (next == L"--bold" || next == L"-o")
is_bold = true;
@@ -596,7 +596,7 @@ int output_color_code( const wcstring &val, bool is_background ) {
else
color_name = next;
}
-
+
if (! color_name.empty()) {
for( i=0; i<COLORS; i++ )
{
@@ -607,22 +607,22 @@ int output_color_code( const wcstring &val, bool is_background ) {
}
}
}
-
- }
-
- return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
+
+ }
+
+ return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
}
rgb_color_t parse_color( const wcstring &val, bool is_background ) {
int is_bold=0;
- int is_underline=0;
-
+ int is_underline=0;
+
std::vector<rgb_color_t> candidates;
-
+
wcstring_list_t el;
- tokenize_variable_array( val, el );
-
- for(size_t j=0; j < el.size(); j++ ) {
+ tokenize_variable_array( val, el );
+
+ for(size_t j=0; j < el.size(); j++ ) {
const wcstring &next = el.at(j);
wcstring color_name;
if (is_background) {
@@ -639,7 +639,7 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
else
color_name = next;
}
-
+
if (! color_name.empty()) {
rgb_color_t color = rgb_color_t(color_name);
if (! color.is_none()) {
@@ -647,7 +647,7 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
}
}
}
-
+
// Pick the best candidate
rgb_color_t first_rgb = rgb_color_t::none(), first_named = rgb_color_t::none();
for (size_t i=0; i < candidates.size(); i++) {
@@ -657,7 +657,7 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
if (color.is_named() && first_named.is_none())
first_named = color;
}
-
+
// If we have both RGB and named colors, then prefer rgb if term256 is supported
rgb_color_t result;
if ((!first_rgb.is_none() && output_get_supports_term256()) || first_named.is_none()) {
@@ -665,24 +665,24 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
} else {
result = first_named;
}
-
+
if (result.is_none())
result = rgb_color_t::normal();
-
+
result.set_bold(is_bold);
result.set_underline(is_underline);
-
+
#if 0
wcstring desc = result.description();
printf("Parsed %ls from %ls (%s)\n", desc.c_str(), val.c_str(), is_background ? "background" : "foreground");
#endif
-
+
return result;
}
void output_set_term( const wchar_t *term )
{
- current_term = term;
+ current_term = term;
}
const wchar_t *output_get_term()
diff --git a/output.h b/output.h
index 0bc432b8..b88c7bef 100644
--- a/output.h
+++ b/output.h
@@ -1,5 +1,5 @@
/** \file output.h
- Generic output functions
+ Generic output functions
*/
/**
Constants for various character classifications. Each character of a command string can be classified as one of the following types.
@@ -13,22 +13,22 @@
#include "color.h"
/**
- Constants for various colors as used by the set_color function.
+ Constants for various colors as used by the set_color function.
*/
enum
{
- FISH_COLOR_BLACK,
- FISH_COLOR_RED,
- FISH_COLOR_GREEN,
- FISH_COLOR_YELLOW,
- FISH_COLOR_BLUE,
- FISH_COLOR_MAGENTA,
- FISH_COLOR_CYAN,
- FISH_COLOR_WHITE,
- /** The default fg color of the terminal */
- FISH_COLOR_NORMAL,
- FISH_COLOR_IGNORE,
- FISH_COLOR_RESET
+ FISH_COLOR_BLACK,
+ FISH_COLOR_RED,
+ FISH_COLOR_GREEN,
+ FISH_COLOR_YELLOW,
+ FISH_COLOR_BLUE,
+ FISH_COLOR_MAGENTA,
+ FISH_COLOR_CYAN,
+ FISH_COLOR_WHITE,
+ /** The default fg color of the terminal */
+ FISH_COLOR_NORMAL,
+ FISH_COLOR_IGNORE,
+ FISH_COLOR_RESET
}
;
@@ -81,21 +81,21 @@ void set_color(rgb_color_t c, rgb_color_t c2);
#define writembs( mbs ) \
{ \
char *tmp = mbs; \
- if( tmp ) \
- { \
- writembs_internal( tmp ); \
- } \
- else \
- { \
- debug( 0, \
- _(L"Tried to use terminfo string %s on line %d of %s, which is undefined in terminal of type \"%ls\". Please report this error to %s"), \
- #mbs, \
- __LINE__, \
- __FILE__, \
- output_get_term(), \
- PACKAGE_BUGREPORT); \
- } \
- }
+ if( tmp ) \
+ { \
+ writembs_internal( tmp ); \
+ } \
+ else \
+ { \
+ debug( 0, \
+ _(L"Tried to use terminfo string %s on line %d of %s, which is undefined in terminal of type \"%ls\". Please report this error to %s"), \
+ #mbs, \
+ __LINE__, \
+ __FILE__, \
+ output_get_term(), \
+ PACKAGE_BUGREPORT); \
+ } \
+ }
/**
diff --git a/parse_util.cpp b/parse_util.cpp
index f523e38d..dc111657 100644
--- a/parse_util.cpp
+++ b/parse_util.cpp
@@ -3,9 +3,9 @@
Various mostly unrelated utility functions related to parsing,
loading and evaluating fish code.
- This library can be seen as a 'toolbox' for functions that are
- used in many places in fish and that are somehow related to
- parsing the code.
+ This library can be seen as a 'toolbox' for functions that are
+ used in many places in fish and that are somehow related to
+ parsing the code.
*/
#include "config.h"
@@ -53,566 +53,566 @@
int parse_util_lineno( const wchar_t *str, size_t offset )
{
- if (! str)
- return 0;
-
- int res = 1;
- for( size_t i=0; str[i] && i<offset; i++ )
- {
- if( str[i] == L'\n' )
- {
- res++;
- }
- }
- return res;
+ if (! str)
+ return 0;
+
+ int res = 1;
+ for( size_t i=0; str[i] && i<offset; i++ )
+ {
+ if( str[i] == L'\n' )
+ {
+ res++;
+ }
+ }
+ return res;
}
int parse_util_get_line_from_offset( const wcstring &str, size_t pos )
{
const wchar_t *buff = str.c_str();
- int count = 0;
- for( size_t i=0; i<pos; i++ )
- {
- if( !buff[i] )
- {
- return -1;
- }
-
- if( buff[i] == L'\n' )
- {
- count++;
- }
- }
- return count;
+ int count = 0;
+ for( size_t i=0; i<pos; i++ )
+ {
+ if( !buff[i] )
+ {
+ return -1;
+ }
+
+ if( buff[i] == L'\n' )
+ {
+ count++;
+ }
+ }
+ return count;
}
size_t parse_util_get_offset_from_line( const wcstring &str, int line )
{
const wchar_t *buff = str.c_str();
- size_t i;
- int count = 0;
-
- if( line < 0 )
- {
- return (size_t)(-1);
- }
-
- if( line == 0 )
- return 0;
-
- for( i=0;; i++ )
- {
- if( !buff[i] )
- {
- return -1;
- }
-
- if( buff[i] == L'\n' )
- {
- count++;
- if( count == line )
- {
- return (i+1)<str.size()?i+1:i;
- }
-
- }
- }
+ size_t i;
+ int count = 0;
+
+ if( line < 0 )
+ {
+ return (size_t)(-1);
+ }
+
+ if( line == 0 )
+ return 0;
+
+ for( i=0;; i++ )
+ {
+ if( !buff[i] )
+ {
+ return -1;
+ }
+
+ if( buff[i] == L'\n' )
+ {
+ count++;
+ if( count == line )
+ {
+ return (i+1)<str.size()?i+1:i;
+ }
+
+ }
+ }
}
size_t parse_util_get_offset( const wcstring &str, int line, long line_offset )
{
const wchar_t *buff = str.c_str();
- size_t off = parse_util_get_offset_from_line( buff, line );
- size_t off2 = parse_util_get_offset_from_line( buff, line+1 );
- long line_offset2 = line_offset;
-
- if( off == (size_t)(-1) )
- {
- return -1;
- }
-
- if( off2 == (size_t)(-1) )
- {
- off2 = wcslen( buff )+1;
- }
-
- if( line_offset2 < 0 )
- {
- line_offset2 = 0;
- }
-
- if( line_offset2 >= off2-off-1 )
- {
- line_offset2 = off2-off-1;
- }
-
- return off + line_offset2;
-
+ size_t off = parse_util_get_offset_from_line( buff, line );
+ size_t off2 = parse_util_get_offset_from_line( buff, line+1 );
+ long line_offset2 = line_offset;
+
+ if( off == (size_t)(-1) )
+ {
+ return -1;
+ }
+
+ if( off2 == (size_t)(-1) )
+ {
+ off2 = wcslen( buff )+1;
+ }
+
+ if( line_offset2 < 0 )
+ {
+ line_offset2 = 0;
+ }
+
+ if( line_offset2 >= off2-off-1 )
+ {
+ line_offset2 = off2-off-1;
+ }
+
+ return off + line_offset2;
+
}
-int parse_util_locate_cmdsubst( const wchar_t *in,
- wchar_t **begin,
- wchar_t **end,
- int allow_incomplete )
+int parse_util_locate_cmdsubst( const wchar_t *in,
+ wchar_t **begin,
+ wchar_t **end,
+ int allow_incomplete )
{
- wchar_t *pos;
- wchar_t prev=0;
- int syntax_error=0;
- int paran_count=0;
-
- wchar_t *paran_begin=0, *paran_end=0;
-
- CHECK( in, 0 );
-
- for( pos = (wchar_t *)in; *pos; pos++ )
- {
- if( prev != '\\' )
- {
- if( wcschr( L"\'\"", *pos ) )
- {
- wchar_t *q_end = quote_end( pos );
- if( q_end && *q_end)
- {
- pos=q_end;
- }
- else
- {
- break;
- }
- }
- else
- {
- if( *pos == '(' )
- {
- if(( paran_count == 0)&&(paran_begin==0))
- {
- paran_begin = pos;
- }
-
- paran_count++;
- }
- else if( *pos == ')' )
- {
-
- paran_count--;
-
- if( (paran_count == 0) && (paran_end == 0) )
- {
- paran_end = pos;
- break;
- }
-
- if( paran_count < 0 )
- {
- syntax_error = 1;
- break;
- }
- }
- }
-
- }
- prev = *pos;
- }
-
- syntax_error |= (paran_count < 0 );
- syntax_error |= ((paran_count>0)&&(!allow_incomplete));
-
- if( syntax_error )
- {
- return -1;
- }
-
- if( paran_begin == 0 )
- {
- return 0;
- }
-
- if( begin )
- {
- *begin = paran_begin;
- }
-
- if( end )
- {
- *end = paran_count?(wchar_t *)in+wcslen(in):paran_end;
- }
-
- return 1;
+ wchar_t *pos;
+ wchar_t prev=0;
+ int syntax_error=0;
+ int paran_count=0;
+
+ wchar_t *paran_begin=0, *paran_end=0;
+
+ CHECK( in, 0 );
+
+ for( pos = (wchar_t *)in; *pos; pos++ )
+ {
+ if( prev != '\\' )
+ {
+ if( wcschr( L"\'\"", *pos ) )
+ {
+ wchar_t *q_end = quote_end( pos );
+ if( q_end && *q_end)
+ {
+ pos=q_end;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ if( *pos == '(' )
+ {
+ if(( paran_count == 0)&&(paran_begin==0))
+ {
+ paran_begin = pos;
+ }
+
+ paran_count++;
+ }
+ else if( *pos == ')' )
+ {
+
+ paran_count--;
+
+ if( (paran_count == 0) && (paran_end == 0) )
+ {
+ paran_end = pos;
+ break;
+ }
+
+ if( paran_count < 0 )
+ {
+ syntax_error = 1;
+ break;
+ }
+ }
+ }
+
+ }
+ prev = *pos;
+ }
+
+ syntax_error |= (paran_count < 0 );
+ syntax_error |= ((paran_count>0)&&(!allow_incomplete));
+
+ if( syntax_error )
+ {
+ return -1;
+ }
+
+ if( paran_begin == 0 )
+ {
+ return 0;
+ }
+
+ if( begin )
+ {
+ *begin = paran_begin;
+ }
+
+ if( end )
+ {
+ *end = paran_count?(wchar_t *)in+wcslen(in):paran_end;
+ }
+
+ return 1;
}
void parse_util_cmdsubst_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **a,
- const wchar_t **b )
+ size_t cursor_pos,
+ const wchar_t **a,
+ const wchar_t **b )
{
- wchar_t *begin, *end;
- wchar_t *pos;
- const wchar_t *cursor = buff + cursor_pos;
-
- CHECK( buff, );
-
- if( a )
- {
- *a = (wchar_t *)buff;
- }
-
- if( b )
- {
- *b = (wchar_t *)buff+wcslen(buff);
- }
-
- pos = (wchar_t *)buff;
-
- while( 1 )
- {
- if( parse_util_locate_cmdsubst( pos,
- &begin,
- &end,
- 1 ) <= 0)
- {
- /*
- No subshell found
- */
- break;
- }
-
- if( !end )
- {
- end = (wchar_t *)buff + wcslen(buff);
- }
-
- if(( begin < cursor ) && (end >= cursor) )
- {
- begin++;
-
- if( a )
- {
- *a = begin;
- }
-
- if( b )
- {
- *b = end;
- }
-
- break;
- }
-
- if( !*end )
- {
- break;
- }
-
- pos = end+1;
- }
-
+ wchar_t *begin, *end;
+ wchar_t *pos;
+ const wchar_t *cursor = buff + cursor_pos;
+
+ CHECK( buff, );
+
+ if( a )
+ {
+ *a = (wchar_t *)buff;
+ }
+
+ if( b )
+ {
+ *b = (wchar_t *)buff+wcslen(buff);
+ }
+
+ pos = (wchar_t *)buff;
+
+ while( 1 )
+ {
+ if( parse_util_locate_cmdsubst( pos,
+ &begin,
+ &end,
+ 1 ) <= 0)
+ {
+ /*
+ No subshell found
+ */
+ break;
+ }
+
+ if( !end )
+ {
+ end = (wchar_t *)buff + wcslen(buff);
+ }
+
+ if(( begin < cursor ) && (end >= cursor) )
+ {
+ begin++;
+
+ if( a )
+ {
+ *a = begin;
+ }
+
+ if( b )
+ {
+ *b = end;
+ }
+
+ break;
+ }
+
+ if( !*end )
+ {
+ break;
+ }
+
+ pos = end+1;
+ }
+
}
/**
Get the beginning and end of the job or process definition under the cursor
*/
static void job_or_process_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **a,
- const wchar_t **b,
- int process )
+ size_t cursor_pos,
+ const wchar_t **a,
+ const wchar_t **b,
+ int process )
{
- const wchar_t *begin, *end;
- long pos;
- wchar_t *buffcpy;
- int finished=0;
-
- tokenizer tok;
-
- CHECK( buff, );
-
- if( a )
- {
- *a=0;
- }
-
- if( b )
- {
- *b = 0;
- }
-
- parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
- if( !end || !begin )
- {
- return;
- }
-
- pos = cursor_pos - (begin - buff);
-
- if( a )
- {
- *a = begin;
- }
-
- if( b )
- {
- *b = end;
- }
-
- buffcpy = wcsndup( begin, end-begin );
-
- if( !buffcpy )
- {
- DIE_MEM();
- }
-
- for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
- tok_has_next( &tok ) && !finished;
- tok_next( &tok ) )
- {
- int tok_begin = tok_get_pos( &tok );
-
- switch( tok_last_type( &tok ) )
- {
- case TOK_PIPE:
- {
- if( !process )
- {
- break;
- }
- }
-
- case TOK_END:
- case TOK_BACKGROUND:
- {
-
- if( tok_begin >= pos )
- {
- finished=1;
- if( b )
- {
- *b = (wchar_t *)buff + tok_begin;
- }
- }
- else
- {
- if( a )
- {
- *a = (wchar_t *)buff + tok_begin+1;
- }
- }
-
- break;
- }
- }
- }
-
- free( buffcpy);
-
- tok_destroy( &tok );
+ const wchar_t *begin, *end;
+ long pos;
+ wchar_t *buffcpy;
+ int finished=0;
+
+ tokenizer tok;
+
+ CHECK( buff, );
+
+ if( a )
+ {
+ *a=0;
+ }
+
+ if( b )
+ {
+ *b = 0;
+ }
+
+ parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
+ if( !end || !begin )
+ {
+ return;
+ }
+
+ pos = cursor_pos - (begin - buff);
+
+ if( a )
+ {
+ *a = begin;
+ }
+
+ if( b )
+ {
+ *b = end;
+ }
+
+ buffcpy = wcsndup( begin, end-begin );
+
+ if( !buffcpy )
+ {
+ DIE_MEM();
+ }
+
+ for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
+ tok_has_next( &tok ) && !finished;
+ tok_next( &tok ) )
+ {
+ int tok_begin = tok_get_pos( &tok );
+
+ switch( tok_last_type( &tok ) )
+ {
+ case TOK_PIPE:
+ {
+ if( !process )
+ {
+ break;
+ }
+ }
+
+ case TOK_END:
+ case TOK_BACKGROUND:
+ {
+
+ if( tok_begin >= pos )
+ {
+ finished=1;
+ if( b )
+ {
+ *b = (wchar_t *)buff + tok_begin;
+ }
+ }
+ else
+ {
+ if( a )
+ {
+ *a = (wchar_t *)buff + tok_begin+1;
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ free( buffcpy);
+
+ tok_destroy( &tok );
}
void parse_util_process_extent( const wchar_t *buff,
- size_t pos,
- const wchar_t **a,
- const wchar_t **b )
+ size_t pos,
+ const wchar_t **a,
+ const wchar_t **b )
{
- job_or_process_extent( buff, pos, a, b, 1 );
+ job_or_process_extent( buff, pos, a, b, 1 );
}
void parse_util_job_extent( const wchar_t *buff,
- size_t pos,
- const wchar_t **a,
- const wchar_t **b )
+ size_t pos,
+ const wchar_t **a,
+ const wchar_t **b )
{
- job_or_process_extent( buff,pos,a, b, 0 );
+ job_or_process_extent( buff,pos,a, b, 0 );
}
void parse_util_token_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **tok_begin,
- const wchar_t **tok_end,
- const wchar_t **prev_begin,
- const wchar_t **prev_end )
+ size_t cursor_pos,
+ const wchar_t **tok_begin,
+ const wchar_t **tok_end,
+ const wchar_t **prev_begin,
+ const wchar_t **prev_end )
{
- const wchar_t *begin, *end;
- long pos;
- wchar_t *buffcpy;
-
- tokenizer tok;
-
- const wchar_t *a = NULL, *b = NULL, *pa = NULL, *pb = NULL;
-
- CHECK( buff, );
-
- assert( cursor_pos >= 0 );
-
- parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
-
- if( !end || !begin )
- {
- return;
- }
-
- pos = cursor_pos - (begin - buff);
-
- a = buff + pos;
- b = a;
- pa = buff + pos;
- pb = pa;
-
- assert( begin >= buff );
- assert( begin <= (buff+wcslen(buff) ) );
- assert( end >= begin );
- assert( end <= (buff+wcslen(buff) ) );
-
- buffcpy = wcsndup( begin, end-begin );
-
- if( !buffcpy )
- {
- DIE_MEM();
- }
-
- for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
- tok_has_next( &tok );
- tok_next( &tok ) )
- {
- size_t tok_begin = tok_get_pos( &tok );
- size_t tok_end = tok_begin;
-
- /*
- Calculate end of token
- */
- if( tok_last_type( &tok ) == TOK_STRING )
- {
- tok_end += wcslen(tok_last(&tok));
- }
-
- /*
- Cursor was before beginning of this token, means that the
- cursor is between two tokens, so we set it to a zero element
- string and break
- */
- if( tok_begin > pos )
- {
- a = b = (wchar_t *)buff + pos;
- break;
- }
-
- /*
- If cursor is inside the token, this is the token we are
- looking for. If so, set a and b and break
- */
- if( (tok_last_type( &tok ) == TOK_STRING) && (tok_end >= pos ) )
- {
- a = begin + tok_get_pos( &tok );
- b = a + wcslen(tok_last(&tok));
- break;
- }
-
- /*
- Remember previous string token
- */
- if( tok_last_type( &tok ) == TOK_STRING )
- {
- pa = begin + tok_get_pos( &tok );
- pb = pa + wcslen(tok_last(&tok));
- }
- }
-
- free( buffcpy);
-
- tok_destroy( &tok );
-
- if( tok_begin )
- {
- *tok_begin = a;
- }
-
- if( tok_end )
- {
- *tok_end = b;
- }
-
- if( prev_begin )
- {
- *prev_begin = pa;
- }
-
- if( prev_end )
- {
- *prev_end = pb;
- }
-
- assert( pa >= buff );
- assert( pa <= (buff+wcslen(buff) ) );
- assert( pb >= pa );
- assert( pb <= (buff+wcslen(buff) ) );
+ const wchar_t *begin, *end;
+ long pos;
+ wchar_t *buffcpy;
+
+ tokenizer tok;
+
+ const wchar_t *a = NULL, *b = NULL, *pa = NULL, *pb = NULL;
+
+ CHECK( buff, );
+
+ assert( cursor_pos >= 0 );
+
+ parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
+
+ if( !end || !begin )
+ {
+ return;
+ }
+
+ pos = cursor_pos - (begin - buff);
+
+ a = buff + pos;
+ b = a;
+ pa = buff + pos;
+ pb = pa;
+
+ assert( begin >= buff );
+ assert( begin <= (buff+wcslen(buff) ) );
+ assert( end >= begin );
+ assert( end <= (buff+wcslen(buff) ) );
+
+ buffcpy = wcsndup( begin, end-begin );
+
+ if( !buffcpy )
+ {
+ DIE_MEM();
+ }
+
+ for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
+ tok_has_next( &tok );
+ tok_next( &tok ) )
+ {
+ size_t tok_begin = tok_get_pos( &tok );
+ size_t tok_end = tok_begin;
+
+ /*
+ Calculate end of token
+ */
+ if( tok_last_type( &tok ) == TOK_STRING )
+ {
+ tok_end += wcslen(tok_last(&tok));
+ }
+
+ /*
+ Cursor was before beginning of this token, means that the
+ cursor is between two tokens, so we set it to a zero element
+ string and break
+ */
+ if( tok_begin > pos )
+ {
+ a = b = (wchar_t *)buff + pos;
+ break;
+ }
+
+ /*
+ If cursor is inside the token, this is the token we are
+ looking for. If so, set a and b and break
+ */
+ if( (tok_last_type( &tok ) == TOK_STRING) && (tok_end >= pos ) )
+ {
+ a = begin + tok_get_pos( &tok );
+ b = a + wcslen(tok_last(&tok));
+ break;
+ }
+
+ /*
+ Remember previous string token
+ */
+ if( tok_last_type( &tok ) == TOK_STRING )
+ {
+ pa = begin + tok_get_pos( &tok );
+ pb = pa + wcslen(tok_last(&tok));
+ }
+ }
+
+ free( buffcpy);
+
+ tok_destroy( &tok );
+
+ if( tok_begin )
+ {
+ *tok_begin = a;
+ }
+
+ if( tok_end )
+ {
+ *tok_end = b;
+ }
+
+ if( prev_begin )
+ {
+ *prev_begin = pa;
+ }
+
+ if( prev_end )
+ {
+ *prev_end = pb;
+ }
+
+ assert( pa >= buff );
+ assert( pa <= (buff+wcslen(buff) ) );
+ assert( pb >= pa );
+ assert( pb <= (buff+wcslen(buff) ) );
}
void parse_util_set_argv( const wchar_t * const *argv, const wcstring_list_t &named_arguments )
{
- if( *argv )
- {
- const wchar_t * const *arg;
- wcstring sb;
-
- for( arg=argv; *arg; arg++ )
- {
- if( arg != argv )
- {
- sb.append(ARRAY_SEP_STR);
- }
+ if( *argv )
+ {
+ const wchar_t * const *arg;
+ wcstring sb;
+
+ for( arg=argv; *arg; arg++ )
+ {
+ if( arg != argv )
+ {
+ sb.append(ARRAY_SEP_STR);
+ }
sb.append(*arg);
- }
-
- env_set( L"argv", sb.c_str(), ENV_LOCAL );
- }
- else
- {
- env_set( L"argv", 0, ENV_LOCAL );
- }
-
- if( named_arguments.size() )
- {
- const wchar_t * const *arg;
- size_t i;
-
- for( i=0, arg=argv; i < named_arguments.size(); i++ )
- {
- env_set( named_arguments.at(i).c_str(), *arg, ENV_LOCAL );
-
- if( *arg )
- arg++;
- }
-
-
- }
-
+ }
+
+ env_set( L"argv", sb.c_str(), ENV_LOCAL );
+ }
+ else
+ {
+ env_set( L"argv", 0, ENV_LOCAL );
+ }
+
+ if( named_arguments.size() )
+ {
+ const wchar_t * const *arg;
+ size_t i;
+
+ for( i=0, arg=argv; i < named_arguments.size(); i++ )
+ {
+ env_set( named_arguments.at(i).c_str(), *arg, ENV_LOCAL );
+
+ if( *arg )
+ arg++;
+ }
+
+
+ }
+
}
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
{
- wchar_t *in, *out;
- wchar_t *unescaped;
-
- CHECK( str, 0 );
-
- unescaped = wcsdup(str);
-
- if( !unescaped )
- {
- DIE_MEM();
- }
-
- for( in=out=unescaped; *in; in++ )
- {
- switch( *in )
- {
- case L'\\':
- {
+ wchar_t *in, *out;
+ wchar_t *unescaped;
+
+ CHECK( str, 0 );
+
+ unescaped = wcsdup(str);
+
+ if( !unescaped )
+ {
+ DIE_MEM();
+ }
+
+ for( in=out=unescaped; *in; in++ )
+ {
+ switch( *in )
+ {
+ case L'\\':
+ {
switch ( *(in + 1) )
{
case L'*':
@@ -635,30 +635,30 @@ wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
break;
}
}
- break;
- }
-
- case L'*':
- {
- *(out++)=ANY_STRING;
- break;
- }
-
- case L'?':
- {
- *(out++)=ANY_CHAR;
- break;
- }
-
- default:
- {
- *(out++)=*in;
- break;
- }
- }
- }
+ break;
+ }
+
+ case L'*':
+ {
+ *(out++)=ANY_STRING;
+ break;
+ }
+
+ case L'?':
+ {
+ *(out++)=ANY_CHAR;
+ break;
+ }
+
+ default:
+ {
+ *(out++)=*in;
+ break;
+ }
+ }
+ }
*out = *in;
- return unescaped;
+ return unescaped;
}
@@ -669,105 +669,105 @@ wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
*/
static wchar_t get_quote( const wchar_t *cmd, size_t len )
{
- size_t i=0;
- wchar_t res=0;
-
- while( 1 )
- {
- if( !cmd[i] )
- break;
-
- if( cmd[i] == L'\\' )
- {
- i++;
- if( !cmd[i] )
- break;
- i++;
- }
- else
- {
- if( cmd[i] == L'\'' || cmd[i] == L'\"' )
- {
- const wchar_t *end = quote_end( &cmd[i] );
- //fwprintf( stderr, L"Jump %d\n", end-cmd );
- if(( end == 0 ) || (!*end) || (end-cmd > len))
- {
- res = cmd[i];
- break;
- }
- i = end-cmd+1;
- }
- else
- i++;
- }
- }
-
- return res;
+ size_t i=0;
+ wchar_t res=0;
+
+ while( 1 )
+ {
+ if( !cmd[i] )
+ break;
+
+ if( cmd[i] == L'\\' )
+ {
+ i++;
+ if( !cmd[i] )
+ break;
+ i++;
+ }
+ else
+ {
+ if( cmd[i] == L'\'' || cmd[i] == L'\"' )
+ {
+ const wchar_t *end = quote_end( &cmd[i] );
+ //fwprintf( stderr, L"Jump %d\n", end-cmd );
+ if(( end == 0 ) || (!*end) || (end-cmd > len))
+ {
+ res = cmd[i];
+ break;
+ }
+ i = end-cmd+1;
+ }
+ else
+ i++;
+ }
+ }
+
+ return res;
}
void parse_util_get_parameter_info( const wcstring &cmd, const size_t pos, wchar_t *quote, size_t *offset, int *type )
{
- size_t prev_pos=0;
- wchar_t last_quote = '\0';
- int unfinished;
+ size_t prev_pos=0;
+ wchar_t last_quote = '\0';
+ int unfinished;
+
+ tokenizer tok;
+ tok_init( &tok, cmd.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
- tokenizer tok;
- tok_init( &tok, cmd.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
+ for( ; tok_has_next( &tok ); tok_next( &tok ) )
+ {
+ if( tok_get_pos( &tok ) > pos )
+ break;
- for( ; tok_has_next( &tok ); tok_next( &tok ) )
- {
- if( tok_get_pos( &tok ) > pos )
- break;
+ if( tok_last_type( &tok ) == TOK_STRING )
+ last_quote = get_quote( tok_last( &tok ),
+ pos - tok_get_pos( &tok ) );
- if( tok_last_type( &tok ) == TOK_STRING )
- last_quote = get_quote( tok_last( &tok ),
- pos - tok_get_pos( &tok ) );
+ if( type != NULL )
+ *type = tok_last_type( &tok );
- if( type != NULL )
- *type = tok_last_type( &tok );
+ prev_pos = tok_get_pos( &tok );
+ }
- prev_pos = tok_get_pos( &tok );
- }
+ tok_destroy( &tok );
- tok_destroy( &tok );
-
wchar_t *cmd_tmp = wcsdup(cmd.c_str());
- cmd_tmp[pos]=0;
- size_t cmdlen = wcslen( cmd_tmp );
- unfinished = (cmdlen==0);
- if( !unfinished )
- {
- unfinished = (quote != 0);
-
- if( !unfinished )
- {
- if( wcschr( L" \t\n\r", cmd_tmp[cmdlen-1] ) != 0 )
- {
- if( ( cmdlen == 1) || (cmd_tmp[cmdlen-2] != L'\\') )
- {
- unfinished=1;
- }
- }
- }
- }
-
- if( quote )
- *quote = last_quote;
-
- if( offset != 0 )
- {
- if( !unfinished )
- {
- while( (cmd_tmp[prev_pos] != 0) && (wcschr( L";|",cmd_tmp[prev_pos])!= 0) )
- prev_pos++;
-
- *offset = prev_pos;
- }
- else
- {
- *offset = pos;
- }
- }
+ cmd_tmp[pos]=0;
+ size_t cmdlen = wcslen( cmd_tmp );
+ unfinished = (cmdlen==0);
+ if( !unfinished )
+ {
+ unfinished = (quote != 0);
+
+ if( !unfinished )
+ {
+ if( wcschr( L" \t\n\r", cmd_tmp[cmdlen-1] ) != 0 )
+ {
+ if( ( cmdlen == 1) || (cmd_tmp[cmdlen-2] != L'\\') )
+ {
+ unfinished=1;
+ }
+ }
+ }
+ }
+
+ if( quote )
+ *quote = last_quote;
+
+ if( offset != 0 )
+ {
+ if( !unfinished )
+ {
+ while( (cmd_tmp[prev_pos] != 0) && (wcschr( L";|",cmd_tmp[prev_pos])!= 0) )
+ prev_pos++;
+
+ *offset = prev_pos;
+ }
+ else
+ {
+ *offset = pos;
+ }
+ }
free(cmd_tmp);
}
@@ -799,7 +799,7 @@ wcstring parse_util_escape_string_with_quote( const wcstring &cmd, wchar_t quote
break;
}
}
-
+
if (unescapable)
{
result = escape_string(cmd, ESCAPE_ALL | ESCAPE_NO_QUOTED);
diff --git a/parse_util.h b/parse_util.h
index 27719851..4b8699f8 100644
--- a/parse_util.h
+++ b/parse_util.h
@@ -14,7 +14,7 @@
/**
Find the beginning and end of the first subshell in the specified string.
-
+
\param in the string to search for subshells
\param begin the starting paranthesis of the subshell
\param end the ending paranthesis of the subshell
@@ -22,10 +22,10 @@
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
*/
-int parse_util_locate_cmdsubst( const wchar_t *in,
- wchar_t **begin,
- wchar_t **end,
- int flags );
+int parse_util_locate_cmdsubst( const wchar_t *in,
+ wchar_t **begin,
+ wchar_t **end,
+ int flags );
/**
Find the beginning and end of the command substitution under the
@@ -40,9 +40,9 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
\param b the end of the searched string
*/
void parse_util_cmdsubst_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **a,
- const wchar_t **b );
+ size_t cursor_pos,
+ const wchar_t **a,
+ const wchar_t **b );
/**
Find the beginning and end of the process definition under the cursor
@@ -53,9 +53,9 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
\param b the end of the searched string
*/
void parse_util_process_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **a,
- const wchar_t **b );
+ size_t cursor_pos,
+ const wchar_t **a,
+ const wchar_t **b );
/**
@@ -67,9 +67,9 @@ void parse_util_process_extent( const wchar_t *buff,
\param b the end of the searched string
*/
void parse_util_job_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **a,
- const wchar_t **b );
+ size_t cursor_pos,
+ const wchar_t **a,
+ const wchar_t **b );
/**
Find the beginning and end of the token under the cursor and the
@@ -84,11 +84,11 @@ void parse_util_job_extent( const wchar_t *buff,
\param prev_end the end of the token before the current token
*/
void parse_util_token_extent( const wchar_t *buff,
- size_t cursor_pos,
- const wchar_t **tok_begin,
- const wchar_t **tok_end,
- const wchar_t **prev_begin,
- const wchar_t **prev_end );
+ size_t cursor_pos,
+ const wchar_t **tok_begin,
+ const wchar_t **tok_end,
+ const wchar_t **prev_begin,
+ const wchar_t **prev_end );
/**
@@ -114,7 +114,7 @@ size_t parse_util_get_offset( const wcstring &str, int line, long line_offset );
/**
Set the argv environment variable to the specified null-terminated
- array of strings.
+ array of strings.
*/
void parse_util_set_argv( const wchar_t * const *argv, const wcstring_list_t &named_arguments );
diff --git a/parser.cpp b/parser.cpp
index 1824cebd..48b96fb3 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -191,7 +191,7 @@ The fish parser. Contains functions for parsing and evaluating code.
/**
While block description
-*/
+*/
#define WHILE_BLOCK N_( L"'while' block" )
/**
@@ -199,10 +199,10 @@ The fish parser. Contains functions for parsing and evaluating code.
*/
#define FOR_BLOCK N_( L"'for' block" )
-/**
- Breakpoint block
+/**
+ Breakpoint block
*/
-#define BREAKPOINT_BLOCK N_( L"Block created by breakpoint" )
+#define BREAKPOINT_BLOCK N_( L"Block created by breakpoint" )
@@ -282,87 +282,87 @@ The fish parser. Contains functions for parsing and evaluating code.
struct block_lookup_entry
{
- /**
- The block type id. The legal values are defined in parser.h.
- */
- block_type_t type;
-
- /**
- The name of the builtin that creates this type of block, if any.
- */
- const wchar_t *name;
-
- /**
- A description of this block type
- */
- const wchar_t *desc;
+ /**
+ The block type id. The legal values are defined in parser.h.
+ */
+ block_type_t type;
+
+ /**
+ The name of the builtin that creates this type of block, if any.
+ */
+ const wchar_t *name;
+
+ /**
+ A description of this block type
+ */
+ const wchar_t *desc;
}
- ;
+ ;
/**
List of all legal block types
*/
static const struct block_lookup_entry block_lookup[]=
{
- {
- WHILE, L"while", WHILE_BLOCK
- }
- ,
- {
- FOR, L"for", FOR_BLOCK
- }
- ,
- {
- IF, L"if", IF_BLOCK
- }
- ,
- {
- FUNCTION_DEF, L"function", FUNCTION_DEF_BLOCK
- }
- ,
- {
- FUNCTION_CALL, 0, FUNCTION_CALL_BLOCK
- }
- ,
- {
- FUNCTION_CALL_NO_SHADOW, 0, FUNCTION_CALL_NO_SHADOW_BLOCK
- }
- ,
- {
- SWITCH, L"switch", SWITCH_BLOCK
- }
- ,
- {
- FAKE, 0, FAKE_BLOCK
- }
- ,
- {
- TOP, 0, TOP_BLOCK
- }
- ,
- {
- SUBST, 0, SUBST_BLOCK
- }
- ,
- {
- BEGIN, L"begin", BEGIN_BLOCK
- }
- ,
- {
- SOURCE, L".", SOURCE_BLOCK
- }
- ,
- {
- EVENT, 0, EVENT_BLOCK
- }
- ,
- {
- BREAKPOINT, L"breakpoint", BREAKPOINT_BLOCK
- }
- ,
- {
- (block_type_t)0, 0, 0
- }
+ {
+ WHILE, L"while", WHILE_BLOCK
+ }
+ ,
+ {
+ FOR, L"for", FOR_BLOCK
+ }
+ ,
+ {
+ IF, L"if", IF_BLOCK
+ }
+ ,
+ {
+ FUNCTION_DEF, L"function", FUNCTION_DEF_BLOCK
+ }
+ ,
+ {
+ FUNCTION_CALL, 0, FUNCTION_CALL_BLOCK
+ }
+ ,
+ {
+ FUNCTION_CALL_NO_SHADOW, 0, FUNCTION_CALL_NO_SHADOW_BLOCK
+ }
+ ,
+ {
+ SWITCH, L"switch", SWITCH_BLOCK
+ }
+ ,
+ {
+ FAKE, 0, FAKE_BLOCK
+ }
+ ,
+ {
+ TOP, 0, TOP_BLOCK
+ }
+ ,
+ {
+ SUBST, 0, SUBST_BLOCK
+ }
+ ,
+ {
+ BEGIN, L"begin", BEGIN_BLOCK
+ }
+ ,
+ {
+ SOURCE, L".", SOURCE_BLOCK
+ }
+ ,
+ {
+ EVENT, 0, EVENT_BLOCK
+ }
+ ,
+ {
+ BREAKPOINT, L"breakpoint", BREAKPOINT_BLOCK
+ }
+ ,
+ {
+ (block_type_t)0, 0, 0
+ }
};
static bool job_should_skip_elseif(const job_t *job, const block_t *current_block);
@@ -379,7 +379,7 @@ parser_t::parser_t(enum parser_type_t type, bool errors) :
current_block(NULL),
block_io(NULL)
{
-
+
}
/* A pointer to the principal parser (which is a static local) */
@@ -420,91 +420,91 @@ void parser_t::skip_all_blocks(void)
static int block_count( block_t *b )
{
- if( b==0)
- return 0;
- return( block_count(b->outer)+1);
+ if( b==0)
+ return 0;
+ return( block_count(b->outer)+1);
}
*/
void parser_t::push_block( block_t *newv )
{
const enum block_type_t type = newv->type();
- newv->src_lineno = parser_t::get_lineno();
- newv->src_filename = parser_t::current_filename()?intern(parser_t::current_filename()):0;
-
- newv->outer = current_block;
+ newv->src_lineno = parser_t::get_lineno();
+ newv->src_filename = parser_t::current_filename()?intern(parser_t::current_filename()):0;
+
+ newv->outer = current_block;
if (current_block && current_block->skip)
newv->mark_as_fake();
-
- /*
- New blocks should be skipped if the outer block is skipped,
- except TOP ans SUBST block, which open up new environments. Fake
- blocks should always be skipped. Rather complicated... :-(
- */
- newv->skip=current_block?current_block->skip:0;
-
- /*
- Type TOP and SUBST are never skipped
- */
- if( type == TOP || type == SUBST )
- {
- newv->skip = 0;
- }
-
- /*
- Fake blocks and function definition blocks are never executed
- */
- if( type == FAKE || type == FUNCTION_DEF )
- {
- newv->skip = 1;
- }
-
- newv->job = 0;
- newv->loop_status=LOOP_NORMAL;
-
- current_block = newv;
-
- if( (newv->type() != FUNCTION_DEF) &&
- (newv->type() != FAKE) &&
- (newv->type() != TOP) )
- {
- env_push( type == FUNCTION_CALL );
+
+ /*
+ New blocks should be skipped if the outer block is skipped,
+ except TOP ans SUBST block, which open up new environments. Fake
+ blocks should always be skipped. Rather complicated... :-(
+ */
+ newv->skip=current_block?current_block->skip:0;
+
+ /*
+ Type TOP and SUBST are never skipped
+ */
+ if( type == TOP || type == SUBST )
+ {
+ newv->skip = 0;
+ }
+
+ /*
+ Fake blocks and function definition blocks are never executed
+ */
+ if( type == FAKE || type == FUNCTION_DEF )
+ {
+ newv->skip = 1;
+ }
+
+ newv->job = 0;
+ newv->loop_status=LOOP_NORMAL;
+
+ current_block = newv;
+
+ if( (newv->type() != FUNCTION_DEF) &&
+ (newv->type() != FAKE) &&
+ (newv->type() != TOP) )
+ {
+ env_push( type == FUNCTION_CALL );
newv->wants_pop_env = true;
- }
+ }
}
void parser_t::pop_block()
{
- block_t *old = current_block;
- if( !current_block )
- {
- debug( 1,
- L"function %s called on empty block stack.",
- __func__);
- bugreport();
- return;
- }
-
- current_block = current_block->outer;
-
+ block_t *old = current_block;
+ if( !current_block )
+ {
+ debug( 1,
+ L"function %s called on empty block stack.",
+ __func__);
+ bugreport();
+ return;
+ }
+
+ current_block = current_block->outer;
+
if (old->wants_pop_env)
env_pop();
-
+
delete old;
}
const wchar_t *parser_t::get_block_desc( int block ) const
{
- int i;
-
- for( i=0; block_lookup[i].desc; i++ )
- {
- if( block_lookup[i].type == block )
- {
- return _( block_lookup[i].desc );
- }
- }
- return _(UNKNOWN_BLOCK);
+ int i;
+
+ for( i=0; block_lookup[i].desc; i++ )
+ {
+ if( block_lookup[i].type == block )
+ {
+ return _( block_lookup[i].desc );
+ }
+ }
+ return _(UNKNOWN_BLOCK);
}
/**
@@ -512,12 +512,12 @@ const wchar_t *parser_t::get_block_desc( int block ) const
*/
static int parser_is_pipe_forbidden( const wcstring &word )
{
- return contains( word,
- L"exec",
- L"case",
- L"break",
- L"return",
- L"continue" );
+ return contains( word,
+ L"exec",
+ L"case",
+ L"break",
+ L"return",
+ L"continue" );
}
/**
@@ -525,87 +525,87 @@ static int parser_is_pipe_forbidden( const wcstring &word )
*/
static const wchar_t *parser_find_end( const wchar_t * buff )
{
- tokenizer tok;
- int had_cmd=0;
- int count = 0;
- int error=0;
- int mark=0;
-
- CHECK( buff, 0 );
-
- for( tok_init( &tok, buff, 0 );
- tok_has_next( &tok ) && !error;
- tok_next( &tok ) )
- {
- int last_type = tok_last_type( &tok );
- switch( last_type )
- {
- case TOK_STRING:
- {
- if( !had_cmd )
- {
- if( wcscmp(tok_last(&tok), L"end")==0)
- {
- count--;
- }
- else if( parser_keywords_is_block( tok_last(&tok) ) )
- {
- count++;
- }
-
- if( count < 0 )
- {
- error = 1;
- }
- had_cmd = 1;
- }
- break;
- }
-
- case TOK_END:
- {
- had_cmd = 0;
- break;
- }
-
- case TOK_PIPE:
- case TOK_BACKGROUND:
- {
- if( had_cmd )
- {
- had_cmd = 0;
- }
- else
- {
- error = 1;
- }
- break;
-
- }
-
- case TOK_ERROR:
- error = 1;
- break;
-
- default:
- break;
-
- }
- if(!count)
- {
- tok_next( &tok );
- mark = tok_get_pos( &tok );
- break;
- }
-
- }
-
- tok_destroy( &tok );
- if(!count && !error){
-
- return buff+mark;
- }
- return 0;
+ tokenizer tok;
+ int had_cmd=0;
+ int count = 0;
+ int error=0;
+ int mark=0;
+
+ CHECK( buff, 0 );
+
+ for( tok_init( &tok, buff, 0 );
+ tok_has_next( &tok ) && !error;
+ tok_next( &tok ) )
+ {
+ int last_type = tok_last_type( &tok );
+ switch( last_type )
+ {
+ case TOK_STRING:
+ {
+ if( !had_cmd )
+ {
+ if( wcscmp(tok_last(&tok), L"end")==0)
+ {
+ count--;
+ }
+ else if( parser_keywords_is_block( tok_last(&tok) ) )
+ {
+ count++;
+ }
+
+ if( count < 0 )
+ {
+ error = 1;
+ }
+ had_cmd = 1;
+ }
+ break;
+ }
+
+ case TOK_END:
+ {
+ had_cmd = 0;
+ break;
+ }
+
+ case TOK_PIPE:
+ case TOK_BACKGROUND:
+ {
+ if( had_cmd )
+ {
+ had_cmd = 0;
+ }
+ else
+ {
+ error = 1;
+ }
+ break;
+
+ }
+
+ case TOK_ERROR:
+ error = 1;
+ break;
+
+ default:
+ break;
+
+ }
+ if(!count)
+ {
+ tok_next( &tok );
+ mark = tok_get_pos( &tok );
+ break;
+ }
+
+ }
+
+ tok_destroy( &tok );
+ if(!count && !error){
+
+ return buff+mark;
+ }
+ return 0;
}
@@ -626,16 +626,16 @@ void parser_t::allow_function()
void parser_t::error( int ec, int p, const wchar_t *str, ... )
{
- va_list va;
+ va_list va;
- CHECK( str, );
-
- error_code = ec;
- err_pos = p;
+ CHECK( str, );
- va_start( va, str );
+ error_code = ec;
+ err_pos = p;
+
+ va_start( va, str );
err_buff = vformat_string(str, va);
- va_end( va );
+ va_end( va );
}
@@ -643,108 +643,108 @@ void parser_t::error( int ec, int p, const wchar_t *str, ... )
Print profiling information to the specified stream
*/
static void print_profile( const std::vector<profile_item_t> &items,
- size_t pos,
- FILE *out )
+ size_t pos,
+ FILE *out )
{
- const profile_item_t *me, *prev;
- size_t i;
- int my_time;
-
- if( pos >= items.size() )
- {
- return;
- }
-
- me= &items.at(pos);
- if( !me->skipped )
- {
- my_time=me->parse+me->exec;
-
- for( i=pos+1; i<items.size(); i++ )
- {
- prev = &items.at(i);
- if( prev->skipped )
- {
- continue;
- }
-
- if( prev->level <= me->level )
- {
- break;
- }
-
- if( prev->level > me->level+1 )
- {
- continue;
- }
-
- my_time -= prev->parse;
- my_time -= prev->exec;
- }
-
- if( me->cmd.size() > 0 )
- {
- if( fwprintf( out, L"%d\t%d\t", my_time, me->parse+me->exec ) < 0 )
- {
- wperror( L"fwprintf" );
- return;
- }
-
- for( i=0; i<me->level; i++ )
- {
- if( fwprintf( out, L"-" ) < 0 )
- {
- wperror( L"fwprintf" );
- return;
- }
-
- }
- if( fwprintf( out, L"> %ls\n", me->cmd.c_str() ) < 0 )
- {
- wperror( L"fwprintf" );
- return;
- }
-
- }
- }
- print_profile( items, pos+1, out );
+ const profile_item_t *me, *prev;
+ size_t i;
+ int my_time;
+
+ if( pos >= items.size() )
+ {
+ return;
+ }
+
+ me= &items.at(pos);
+ if( !me->skipped )
+ {
+ my_time=me->parse+me->exec;
+
+ for( i=pos+1; i<items.size(); i++ )
+ {
+ prev = &items.at(i);
+ if( prev->skipped )
+ {
+ continue;
+ }
+
+ if( prev->level <= me->level )
+ {
+ break;
+ }
+
+ if( prev->level > me->level+1 )
+ {
+ continue;
+ }
+
+ my_time -= prev->parse;
+ my_time -= prev->exec;
+ }
+
+ if( me->cmd.size() > 0 )
+ {
+ if( fwprintf( out, L"%d\t%d\t", my_time, me->parse+me->exec ) < 0 )
+ {
+ wperror( L"fwprintf" );
+ return;
+ }
+
+ for( i=0; i<me->level; i++ )
+ {
+ if( fwprintf( out, L"-" ) < 0 )
+ {
+ wperror( L"fwprintf" );
+ return;
+ }
+
+ }
+ if( fwprintf( out, L"> %ls\n", me->cmd.c_str() ) < 0 )
+ {
+ wperror( L"fwprintf" );
+ return;
+ }
+
+ }
+ }
+ print_profile( items, pos+1, out );
}
void parser_t::destroy()
{
- if( profile )
- {
- /* Save profiling information. OK to not use CLO_EXEC here because this is called while fish is dying (and hence will not fork) */
- FILE *f = fopen( profile, "w" );
- if( !f )
- {
- debug( 1,
- _(L"Could not write profiling information to file '%s'"),
- profile );
- }
- else
- {
- if( fwprintf( f,
- _(L"Time\tSum\tCommand\n"),
- profile_items.size() ) < 0 )
- {
- wperror( L"fwprintf" );
- }
- else
- {
- print_profile( profile_items, 0, f );
- }
-
- if( fclose( f ) )
- {
- wperror( L"fclose" );
- }
- }
- }
+ if( profile )
+ {
+ /* Save profiling information. OK to not use CLO_EXEC here because this is called while fish is dying (and hence will not fork) */
+ FILE *f = fopen( profile, "w" );
+ if( !f )
+ {
+ debug( 1,
+ _(L"Could not write profiling information to file '%s'"),
+ profile );
+ }
+ else
+ {
+ if( fwprintf( f,
+ _(L"Time\tSum\tCommand\n"),
+ profile_items.size() ) < 0 )
+ {
+ wperror( L"fwprintf" );
+ }
+ else
+ {
+ print_profile( profile_items, 0, f );
+ }
+
+ if( fclose( f ) )
+ {
+ wperror( L"fclose" );
+ }
+ }
+ }
lineinfo.clear();
- forbidden_function.clear();
+ forbidden_function.clear();
}
@@ -756,21 +756,21 @@ void parser_t::destroy()
*/
void parser_t::print_errors( wcstring &target, const wchar_t *prefix )
{
- CHECK( prefix, );
-
- if( error_code && ! err_buff.empty() )
- {
- int tmp;
+ CHECK( prefix, );
+
+ if( error_code && ! err_buff.empty() )
+ {
+ int tmp;
- append_format( target, L"%ls: %ls\n", prefix, err_buff.c_str() );
+ append_format( target, L"%ls: %ls\n", prefix, err_buff.c_str() );
- tmp = current_tokenizer_pos;
- current_tokenizer_pos = err_pos;
+ tmp = current_tokenizer_pos;
+ current_tokenizer_pos = err_pos;
- append_format( target, L"%ls", this->current_line() );
+ append_format( target, L"%ls", this->current_line() );
- current_tokenizer_pos=tmp;
- }
+ current_tokenizer_pos=tmp;
+ }
}
/**
@@ -778,215 +778,215 @@ void parser_t::print_errors( wcstring &target, const wchar_t *prefix )
*/
void parser_t::print_errors_stderr()
{
- if( error_code && ! err_buff.empty() )
- {
- debug( 0, L"%ls", err_buff.c_str() );
- int tmp;
-
- tmp = current_tokenizer_pos;
- current_tokenizer_pos = err_pos;
-
- fwprintf( stderr, L"%ls", this->current_line() );
-
- current_tokenizer_pos=tmp;
- }
-
+ if( error_code && ! err_buff.empty() )
+ {
+ debug( 0, L"%ls", err_buff.c_str() );
+ int tmp;
+
+ tmp = current_tokenizer_pos;
+ current_tokenizer_pos = err_pos;
+
+ fwprintf( stderr, L"%ls", this->current_line() );
+
+ current_tokenizer_pos=tmp;
+ }
+
}
int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
{
- tokenizer tok;
-
+ tokenizer tok;
+
expand_flags_t eflags = 0;
if (! show_errors)
eflags |= EXPAND_NO_DESCRIPTIONS;
if (this->parser_type != PARSER_TYPE_GENERAL)
eflags |= EXPAND_SKIP_CMDSUBST;
-
- /*
- eval_args may be called while evaulating another command, so we
- save the previous tokenizer and restore it on exit
- */
- tokenizer *previous_tokenizer=current_tokenizer;
- int previous_pos=current_tokenizer_pos;
- int do_loop=1;
-
- CHECK( line, 1 );
-// CHECK( args, 1 );
-
+
+ /*
+ eval_args may be called while evaulating another command, so we
+ save the previous tokenizer and restore it on exit
+ */
+ tokenizer *previous_tokenizer=current_tokenizer;
+ int previous_pos=current_tokenizer_pos;
+ int do_loop=1;
+
+ CHECK( line, 1 );
+// CHECK( args, 1 );
+
// PCA we need to suppress calling proc_push_interactive off of the main thread. I'm not sure exactly what it does.
if (this->parser_type == PARSER_TYPE_GENERAL)
proc_push_interactive(0);
-
- current_tokenizer = &tok;
- current_tokenizer_pos = 0;
-
- tok_init( &tok, line, (show_errors ? 0 : TOK_SQUASH_ERRORS) );
- error_code=0;
-
- for(;do_loop && tok_has_next( &tok) ; tok_next( &tok ) )
- {
- current_tokenizer_pos = tok_get_pos( &tok );
- switch(tok_last_type( &tok ) )
- {
- case TOK_STRING:
- {
- const wcstring tmp = tok_last(&tok);
- if( expand_string(tmp, args, eflags) == EXPAND_ERROR )
- {
- err_pos=tok_get_pos( &tok );
- do_loop=0;
- }
- break;
- }
-
- case TOK_END:
- {
- break;
- }
-
- case TOK_ERROR:
- {
- if (show_errors)
+
+ current_tokenizer = &tok;
+ current_tokenizer_pos = 0;
+
+ tok_init( &tok, line, (show_errors ? 0 : TOK_SQUASH_ERRORS) );
+ error_code=0;
+
+ for(;do_loop && tok_has_next( &tok) ; tok_next( &tok ) )
+ {
+ current_tokenizer_pos = tok_get_pos( &tok );
+ switch(tok_last_type( &tok ) )
+ {
+ case TOK_STRING:
+ {
+ const wcstring tmp = tok_last(&tok);
+ if( expand_string(tmp, args, eflags) == EXPAND_ERROR )
+ {
+ err_pos=tok_get_pos( &tok );
+ do_loop=0;
+ }
+ break;
+ }
+
+ case TOK_END:
+ {
+ break;
+ }
+
+ case TOK_ERROR:
+ {
+ if (show_errors)
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
TOK_ERR_MSG,
tok_last(&tok) );
- do_loop=0;
- break;
- }
+ do_loop=0;
+ break;
+ }
- default:
- {
+ default:
+ {
if (show_errors)
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
UNEXPECTED_TOKEN_ERR_MSG,
tok_get_desc( tok_last_type(&tok)) );
- do_loop=0;
- break;
- }
- }
- }
+ do_loop=0;
+ break;
+ }
+ }
+ }
if (show_errors)
this->print_errors_stderr();
-
- tok_destroy( &tok );
-
- current_tokenizer=previous_tokenizer;
- current_tokenizer_pos = previous_pos;
-
+
+ tok_destroy( &tok );
+
+ current_tokenizer=previous_tokenizer;
+ current_tokenizer_pos = previous_pos;
+
if (this->parser_type == PARSER_TYPE_GENERAL)
proc_pop_interactive();
- return 1;
+ return 1;
}
void parser_t::stack_trace( block_t *b, wcstring &buff)
-{
- /*
- Check if we should end the recursion
- */
- if( !b )
- return;
-
- if( b->type()==EVENT )
- {
- /*
- This is an event handler
- */
+{
+ /*
+ Check if we should end the recursion
+ */
+ if( !b )
+ return;
+
+ if( b->type()==EVENT )
+ {
+ /*
+ This is an event handler
+ */
const event_block_t *eb = static_cast<const event_block_t *>(b);
wcstring description = event_get_desc( eb->event );
- append_format( buff, _(L"in event handler: %ls\n"), description.c_str());
- buff.append( L"\n" );
-
- /*
- Stop recursing at event handler. No reason to belive that
- any other code is relevant.
-
- It might make sense in the future to continue printing the
- stack trace of the code that invoked the event, if this is a
- programmatic event, but we can't currently detect that.
- */
- return;
- }
-
- if( b->type() == FUNCTION_CALL || b->type()==SOURCE || b->type()==SUBST)
- {
- /*
- These types of blocks should be printed
- */
-
- int i;
-
- switch( b->type())
- {
- case SOURCE:
- {
+ append_format( buff, _(L"in event handler: %ls\n"), description.c_str());
+ buff.append( L"\n" );
+
+ /*
+ Stop recursing at event handler. No reason to belive that
+ any other code is relevant.
+
+ It might make sense in the future to continue printing the
+ stack trace of the code that invoked the event, if this is a
+ programmatic event, but we can't currently detect that.
+ */
+ return;
+ }
+
+ if( b->type() == FUNCTION_CALL || b->type()==SOURCE || b->type()==SUBST)
+ {
+ /*
+ These types of blocks should be printed
+ */
+
+ int i;
+
+ switch( b->type())
+ {
+ case SOURCE:
+ {
const source_block_t *sb = static_cast<const source_block_t*>(b);
const wchar_t *source_dest = sb->source_file;
- append_format( buff, _(L"in . (source) call of file '%ls',\n"), source_dest );
- break;
- }
- case FUNCTION_CALL:
- {
+ append_format( buff, _(L"in . (source) call of file '%ls',\n"), source_dest );
+ break;
+ }
+ case FUNCTION_CALL:
+ {
const function_block_t *fb = static_cast<const function_block_t*>(b);
- append_format( buff, _(L"in function '%ls',\n"), fb->name.c_str() );
- break;
- }
- case SUBST:
- {
- append_format( buff, _(L"in command substitution\n") );
- break;
- }
-
+ append_format( buff, _(L"in function '%ls',\n"), fb->name.c_str() );
+ break;
+ }
+ case SUBST:
+ {
+ append_format( buff, _(L"in command substitution\n") );
+ break;
+ }
+
default: /* Can't get here */
break;
- }
-
- const wchar_t *file = b->src_filename;
-
- if( file )
- {
- append_format( buff,
- _(L"\tcalled on line %d of file '%ls',\n"),
- b->src_lineno,
- file );
- }
- else
- {
- append_format( buff,
- _(L"\tcalled on standard input,\n") );
- }
-
- if( b->type() == FUNCTION_CALL )
+ }
+
+ const wchar_t *file = b->src_filename;
+
+ if( file )
+ {
+ append_format( buff,
+ _(L"\tcalled on line %d of file '%ls',\n"),
+ b->src_lineno,
+ file );
+ }
+ else
+ {
+ append_format( buff,
+ _(L"\tcalled on standard input,\n") );
+ }
+
+ if( b->type() == FUNCTION_CALL )
{
const function_block_t *fb = static_cast<const function_block_t *>(b);
const process_t * const process = fb->process;
- if( process->argv(1) )
- {
- wcstring tmp;
-
- for( i=1; process->argv(i); i++ )
- {
+ if( process->argv(1) )
+ {
+ wcstring tmp;
+
+ for( i=1; process->argv(i); i++ )
+ {
if (i > 1)
tmp.push_back(L' ');
tmp.append(process->argv(i));
- }
- append_format( buff, _(L"\twith parameter list '%ls'\n"), tmp.c_str() );
- }
- }
-
- append_format( buff, L"\n" );
- }
-
- /*
- Recursively print the next block
- */
- parser_t::stack_trace( b->outer, buff );
+ }
+ append_format( buff, _(L"\twith parameter list '%ls'\n"), tmp.c_str() );
+ }
+ }
+
+ append_format( buff, L"\n" );
+ }
+
+ /*
+ Recursively print the next block
+ */
+ parser_t::stack_trace( b->outer, buff );
}
/**
@@ -1000,47 +1000,47 @@ const wchar_t *parser_t::is_function() const
// PCA: Have to make this a string somehow
ASSERT_IS_MAIN_THREAD();
wcstring result;
-
- block_t *b = current_block;
- while( 1 )
- {
- if( !b )
- {
- return NULL;
- }
- if( b->type() == FUNCTION_CALL )
- {
+
+ block_t *b = current_block;
+ while( 1 )
+ {
+ if( !b )
+ {
+ return NULL;
+ }
+ if( b->type() == FUNCTION_CALL )
+ {
const function_block_t *fb = static_cast<const function_block_t *>(b);
- return fb->name.c_str();
- }
- b=b->outer;
- }
+ return fb->name.c_str();
+ }
+ b=b->outer;
+ }
}
int parser_t::get_lineno() const
{
- int lineno;
-
+ int lineno;
+
if( ! current_tokenizer || ! tok_string( current_tokenizer ))
- return -1;
-
+ return -1;
+
lineno = current_tokenizer->line_number_of_character_at_offset(current_tokenizer_pos);
-
+
const wchar_t *function_name;
- if( (function_name = is_function()) )
- {
- lineno += function_get_definition_offset( function_name );
- }
+ if( (function_name = is_function()) )
+ {
+ lineno += function_get_definition_offset( function_name );
+ }
- return lineno;
+ return lineno;
}
int parser_t::line_number_of_character_at_offset(size_t idx) const
{
if( ! current_tokenizer)
return -1;
-
+
int result = current_tokenizer->line_number_of_character_at_offset(idx);
//assert(result == parse_util_lineno(tok_string( current_tokenizer ), idx));
return result;
@@ -1051,22 +1051,22 @@ const wchar_t *parser_t::current_filename() const
/* We query a global array for the current file name, so it only makes sense to ask this on the principal parser. */
ASSERT_IS_MAIN_THREAD();
assert(this == &principal_parser());
-
- block_t *b = current_block;
-
- while( 1 )
- {
- if( !b )
- {
- return reader_current_filename();
- }
- if( b->type() == FUNCTION_CALL )
- {
+
+ block_t *b = current_block;
+
+ while( 1 )
+ {
+ if( !b )
+ {
+ return reader_current_filename();
+ }
+ if( b->type() == FUNCTION_CALL )
+ {
const function_block_t *fb = static_cast<const function_block_t *>(b);
- return function_get_definition_file(fb->name);
- }
- b=b->outer;
- }
+ return function_get_definition_file(fb->name);
+ }
+ b=b->outer;
+ }
}
/**
@@ -1077,184 +1077,184 @@ const wchar_t *parser_t::current_filename() const
*/
static int printed_width( const wchar_t *str, int len )
{
- int res=0;
- int i;
-
- CHECK( str, 0 );
-
- for( i=0; str[i] && i<len; i++ )
- {
- if( str[i] == L'\t' )
- {
- res=(res+8)&~7;
- }
- else
- {
- res += fish_wcwidth( str[i] );
- }
- }
- return res;
+ int res=0;
+ int i;
+
+ CHECK( str, 0 );
+
+ for( i=0; str[i] && i<len; i++ )
+ {
+ if( str[i] == L'\t' )
+ {
+ res=(res+8)&~7;
+ }
+ else
+ {
+ res += fish_wcwidth( str[i] );
+ }
+ }
+ return res;
}
const wchar_t *parser_t::current_line()
{
- int lineno=1;
+ int lineno=1;
+
+ const wchar_t *file;
+ const wchar_t *whole_str;
+ const wchar_t *line;
+ const wchar_t *line_end;
+ int i;
+ int offset;
+ int current_line_width;
+ const wchar_t *function_name=0;
+ int current_line_start=0;
+
+ if( !current_tokenizer )
+ {
+ return L"";
+ }
- const wchar_t *file;
- const wchar_t *whole_str;
- const wchar_t *line;
- const wchar_t *line_end;
- int i;
- int offset;
- int current_line_width;
- const wchar_t *function_name=0;
- int current_line_start=0;
+ file = parser_t::current_filename();
+ whole_str = tok_string( current_tokenizer );
+ line = whole_str;
- if( !current_tokenizer )
- {
- return L"";
- }
+ if( !line )
+ return L"";
- file = parser_t::current_filename();
- whole_str = tok_string( current_tokenizer );
- line = whole_str;
- if( !line )
- return L"";
+ lineinfo.clear();
+ /*
+ Calculate line number, line offset, etc.
+ */
+ for( i=0; i<current_tokenizer_pos && whole_str[i]; i++ )
+ {
+ if( whole_str[i] == L'\n' )
+ {
+ lineno++;
+ current_line_start=i+1;
+ line = &whole_str[i+1];
+ }
+ }
- lineinfo.clear();
+// lineno = current_tokenizer_pos;
+
+
+ current_line_width=printed_width( whole_str+current_line_start,
+ current_tokenizer_pos-current_line_start );
- /*
- Calculate line number, line offset, etc.
- */
- for( i=0; i<current_tokenizer_pos && whole_str[i]; i++ )
- {
- if( whole_str[i] == L'\n' )
- {
- lineno++;
- current_line_start=i+1;
- line = &whole_str[i+1];
- }
- }
-
-// lineno = current_tokenizer_pos;
-
-
- current_line_width=printed_width( whole_str+current_line_start,
- current_tokenizer_pos-current_line_start );
-
- if( (function_name = is_function()) )
- {
- lineno += function_get_definition_offset( function_name );
- }
-
- /*
- Copy current line from whole string
- */
- line_end = wcschr( line, L'\n' );
- if( !line_end )
- line_end = line+wcslen(line);
-
- line = wcsndup( line, line_end-line );
-
- /**
- If we are not going to print a stack trace, at least print the line number and filename
- */
- if( !get_is_interactive() || is_function() )
- {
- int prev_width = my_wcswidth( lineinfo.c_str() );
- if( file )
- append_format( lineinfo,
- _(L"%ls (line %d): "),
- file,
- lineno );
- else
- append_format( lineinfo,
- L"%ls: ",
- _(L"Standard input"),
- lineno );
- offset = my_wcswidth( lineinfo.c_str() ) - prev_width;
- }
- else
- {
- offset=0;
- }
-
-// debug( 1, L"Current pos %d, line pos %d, file_length %d, is_interactive %d, offset %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str), is_interactive, offset);
- /*
- Skip printing character position if we are in interactive mode
- and the error was on the first character of the line.
- */
- if( !get_is_interactive() || is_function() || (current_line_width!=0) )
- {
- // Workaround since it seems impossible to print 0 copies of a character using %*lc
- if( offset+current_line_width )
- {
- append_format( lineinfo,
- L"%ls\n%*lc^\n",
- line,
- offset+current_line_width,
- L' ' );
- }
- else
- {
- append_format( lineinfo,
- L"%ls\n^\n",
- line );
- }
- }
-
- free( (void *)line );
- parser_t::stack_trace( current_block, lineinfo );
-
- return lineinfo.c_str();
+ if( (function_name = is_function()) )
+ {
+ lineno += function_get_definition_offset( function_name );
+ }
+
+ /*
+ Copy current line from whole string
+ */
+ line_end = wcschr( line, L'\n' );
+ if( !line_end )
+ line_end = line+wcslen(line);
+
+ line = wcsndup( line, line_end-line );
+
+ /**
+ If we are not going to print a stack trace, at least print the line number and filename
+ */
+ if( !get_is_interactive() || is_function() )
+ {
+ int prev_width = my_wcswidth( lineinfo.c_str() );
+ if( file )
+ append_format( lineinfo,
+ _(L"%ls (line %d): "),
+ file,
+ lineno );
+ else
+ append_format( lineinfo,
+ L"%ls: ",
+ _(L"Standard input"),
+ lineno );
+ offset = my_wcswidth( lineinfo.c_str() ) - prev_width;
+ }
+ else
+ {
+ offset=0;
+ }
+
+// debug( 1, L"Current pos %d, line pos %d, file_length %d, is_interactive %d, offset %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str), is_interactive, offset);
+ /*
+ Skip printing character position if we are in interactive mode
+ and the error was on the first character of the line.
+ */
+ if( !get_is_interactive() || is_function() || (current_line_width!=0) )
+ {
+ // Workaround since it seems impossible to print 0 copies of a character using %*lc
+ if( offset+current_line_width )
+ {
+ append_format( lineinfo,
+ L"%ls\n%*lc^\n",
+ line,
+ offset+current_line_width,
+ L' ' );
+ }
+ else
+ {
+ append_format( lineinfo,
+ L"%ls\n^\n",
+ line );
+ }
+ }
+
+ free( (void *)line );
+ parser_t::stack_trace( current_block, lineinfo );
+
+ return lineinfo.c_str();
}
int parser_t::get_pos() const
{
- return tok_get_pos( current_tokenizer );
+ return tok_get_pos( current_tokenizer );
}
int parser_t::get_job_pos() const
{
- return job_start_pos;
+ return job_start_pos;
}
void parser_t::set_pos( int p)
{
- tok_set_pos( current_tokenizer, p );
+ tok_set_pos( current_tokenizer, p );
}
const wchar_t *parser_t::get_buffer() const
{
- return tok_string( current_tokenizer );
+ return tok_string( current_tokenizer );
}
int parser_t::is_help( const wchar_t *s, int min_match ) const
{
- CHECK( s, 0 );
+ CHECK( s, 0 );
+
+ size_t len = wcslen(s);
- size_t len = wcslen(s);
+ min_match = maxi( min_match, 3 );
- min_match = maxi( min_match, 3 );
-
- return ( wcscmp( L"-h", s ) == 0 ) ||
- ( len >= min_match && (wcsncmp( L"--help", s, len ) == 0) );
+ return ( wcscmp( L"-h", s ) == 0 ) ||
+ ( len >= min_match && (wcsncmp( L"--help", s, len ) == 0) );
}
job_t *parser_t::job_create(void)
{
job_t *res = new job_t(acquire_job_id());
this->my_job_list.push_front(res);
-
- job_set_flag( res,
- JOB_CONTROL,
- (job_control_mode==JOB_CONTROL_ALL) ||
- ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (get_is_interactive())) );
+
+ job_set_flag( res,
+ JOB_CONTROL,
+ (job_control_mode==JOB_CONTROL_ALL) ||
+ ((job_control_mode == JOB_CONTROL_INTERACTIVE) && (get_is_interactive())) );
return res;
}
@@ -1265,8 +1265,8 @@ bool parser_t::job_remove( job_t *j )
my_job_list.erase(iter);
return true;
} else {
- debug( 1, _( L"Job inconsistency" ) );
- sanity_lose();
+ debug( 1, _( L"Job inconsistency" ) );
+ sanity_lose();
return false;
}
}
@@ -1275,7 +1275,7 @@ void parser_t::job_promote(job_t *job)
{
job_list_t::iterator loc = std::find(my_job_list.begin(), my_job_list.end(), job);
assert(loc != my_job_list.end());
-
+
/* Move the job to the beginning */
my_job_list.splice(my_job_list.begin(), my_job_list, loc);
}
@@ -1287,8 +1287,8 @@ job_t *parser_t::job_get(job_id_t id)
while ((job = jobs.next())) {
if( id <= 0 || job->job_id == id)
return job;
- }
- return NULL;
+ }
+ return NULL;
}
job_t *parser_t::job_get_from_pid( int pid )
@@ -1296,10 +1296,10 @@ job_t *parser_t::job_get_from_pid( int pid )
job_iterator_t jobs;
job_t *job;
while ((job = jobs.next())) {
- if( job->pgid == pid )
- return job;
- }
- return 0;
+ if( job->pgid == pid )
+ return job;
+ }
+ return 0;
}
/**
@@ -1312,115 +1312,115 @@ job_t *parser_t::job_get_from_pid( int pid )
\param args unskip whether we should ignore current_block->skip. Big hack because of our dumb handling of if statements.
*/
void parser_t::parse_job_argument_list( process_t *p,
- job_t *j,
- tokenizer *tok,
- std::vector<completion_t> &args,
+ job_t *j,
+ tokenizer *tok,
+ std::vector<completion_t> &args,
bool unskip )
{
- int is_finished=0;
-
- int proc_is_count=0;
-
- int matched_wildcard = 0, unmatched_wildcard = 0;
-
- wcstring unmatched;
- int unmatched_pos=0;
-
- /*
- Test if this is the 'count' command. We need to special case
- count in the shell, since it should display a help message on
- 'count -h', but not on 'set foo -h; count $foo'. This is an ugly
- workaround and a huge hack, but as near as I can tell, the
- alternatives are worse.
- */
- proc_is_count = ( args.at(0).completion == L"count" );
-
- while( 1 )
- {
-
- switch( tok_last_type( tok ) )
- {
- case TOK_PIPE:
- {
- wchar_t *end;
-
- if (p->type == INTERNAL_EXEC)
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- EXEC_ERR_MSG );
- return;
- }
-
- errno = 0;
- p->pipe_write_fd = fish_wcstoi( tok_last( tok ), &end, 10 );
- if( p->pipe_write_fd < 0 || errno || *end )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- ILLEGAL_FD_ERR_MSG,
- tok_last( tok ) );
- return;
- }
-
+ int is_finished=0;
+
+ int proc_is_count=0;
+
+ int matched_wildcard = 0, unmatched_wildcard = 0;
+
+ wcstring unmatched;
+ int unmatched_pos=0;
+
+ /*
+ Test if this is the 'count' command. We need to special case
+ count in the shell, since it should display a help message on
+ 'count -h', but not on 'set foo -h; count $foo'. This is an ugly
+ workaround and a huge hack, but as near as I can tell, the
+ alternatives are worse.
+ */
+ proc_is_count = ( args.at(0).completion == L"count" );
+
+ while( 1 )
+ {
+
+ switch( tok_last_type( tok ) )
+ {
+ case TOK_PIPE:
+ {
+ wchar_t *end;
+
+ if (p->type == INTERNAL_EXEC)
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ EXEC_ERR_MSG );
+ return;
+ }
+
+ errno = 0;
+ p->pipe_write_fd = fish_wcstoi( tok_last( tok ), &end, 10 );
+ if( p->pipe_write_fd < 0 || errno || *end )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ ILLEGAL_FD_ERR_MSG,
+ tok_last( tok ) );
+ return;
+ }
+
p->set_argv(completions_to_wcstring_list(args));
- p->next = new process_t();
-
- tok_next( tok );
-
- /*
- Don't do anything on failiure. parse_job will notice
- the error flag and report any errors for us
- */
- parse_job( p->next, j, tok );
-
- is_finished = 1;
- break;
- }
-
- case TOK_BACKGROUND:
- {
- job_set_flag( j, JOB_FOREGROUND, 0 );
- }
-
- case TOK_END:
- {
- if( !p->get_argv() )
- p->set_argv(completions_to_wcstring_list(args));
- if( tok_has_next(tok))
- tok_next(tok);
-
- is_finished = 1;
-
- break;
- }
-
- case TOK_STRING:
- {
- int skip=0;
-
- if( job_get_flag( j, JOB_SKIP ) )
- {
- skip = 1;
- }
- else if( current_block->skip && ! unskip )
- {
- /*
- If this command should be skipped, we do not expand the arguments
- */
- skip=1;
-
- /* But if this is in fact a case statement or an elseif statement, then it should be evaluated */
+ p->next = new process_t();
+
+ tok_next( tok );
+
+ /*
+ Don't do anything on failiure. parse_job will notice
+ the error flag and report any errors for us
+ */
+ parse_job( p->next, j, tok );
+
+ is_finished = 1;
+ break;
+ }
+
+ case TOK_BACKGROUND:
+ {
+ job_set_flag( j, JOB_FOREGROUND, 0 );
+ }
+
+ case TOK_END:
+ {
+ if( !p->get_argv() )
+ p->set_argv(completions_to_wcstring_list(args));
+ if( tok_has_next(tok))
+ tok_next(tok);
+
+ is_finished = 1;
+
+ break;
+ }
+
+ case TOK_STRING:
+ {
+ int skip=0;
+
+ if( job_get_flag( j, JOB_SKIP ) )
+ {
+ skip = 1;
+ }
+ else if( current_block->skip && ! unskip )
+ {
+ /*
+ If this command should be skipped, we do not expand the arguments
+ */
+ skip=1;
+
+ /* But if this is in fact a case statement or an elseif statement, then it should be evaluated */
block_type_t type = current_block->type();
- if( type == SWITCH && args.at(0).completion == L"case" && p->type == INTERNAL_BUILTIN )
- {
- skip=0;
- }
+ if( type == SWITCH && args.at(0).completion == L"case" && p->type == INTERNAL_BUILTIN )
+ {
+ skip=0;
+ }
else if (job_get_flag(j, JOB_ELSEIF) && ! job_should_skip_elseif(j, current_block))
{
skip=0;
}
- }
+ }
else
{
/* If this is an else if, and we should skip it, then don't expand any arguments */
@@ -1430,264 +1430,264 @@ void parser_t::parse_job_argument_list( process_t *p,
}
}
- if( !skip )
- {
- if( ( proc_is_count ) &&
- ( args.size() == 1) &&
- ( parser_t::is_help( tok_last(tok), 0) ) &&
- ( p->type == INTERNAL_BUILTIN ) )
- {
- /*
- Display help for count
- */
- p->count_help_magic = 1;
- }
-
- switch( expand_string( tok_last( tok ), args, 0 ) )
- {
- case EXPAND_ERROR:
- {
- err_pos=tok_get_pos( tok );
- if( error_code == 0 )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- _(L"Could not expand string '%ls'"),
- tok_last(tok) );
-
- }
- break;
- }
-
- case EXPAND_WILDCARD_NO_MATCH:
- {
- unmatched_wildcard = 1;
- if( unmatched.empty() )
- {
+ if( !skip )
+ {
+ if( ( proc_is_count ) &&
+ ( args.size() == 1) &&
+ ( parser_t::is_help( tok_last(tok), 0) ) &&
+ ( p->type == INTERNAL_BUILTIN ) )
+ {
+ /*
+ Display help for count
+ */
+ p->count_help_magic = 1;
+ }
+
+ switch( expand_string( tok_last( tok ), args, 0 ) )
+ {
+ case EXPAND_ERROR:
+ {
+ err_pos=tok_get_pos( tok );
+ if( error_code == 0 )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ _(L"Could not expand string '%ls'"),
+ tok_last(tok) );
+
+ }
+ break;
+ }
+
+ case EXPAND_WILDCARD_NO_MATCH:
+ {
+ unmatched_wildcard = 1;
+ if( unmatched.empty() )
+ {
unmatched = tok_last(tok);
- unmatched_pos = tok_get_pos( tok );
- }
+ unmatched_pos = tok_get_pos( tok );
+ }
- break;
- }
+ break;
+ }
- case EXPAND_WILDCARD_MATCH:
- {
- matched_wildcard = 1;
- break;
- }
+ case EXPAND_WILDCARD_MATCH:
+ {
+ matched_wildcard = 1;
+ break;
+ }
- case EXPAND_OK:
- {
- break;
- }
+ case EXPAND_OK:
+ {
+ break;
+ }
- }
+ }
- }
+ }
- break;
- }
+ break;
+ }
- case TOK_REDIRECT_OUT:
- case TOK_REDIRECT_IN:
- case TOK_REDIRECT_APPEND:
- case TOK_REDIRECT_FD:
- case TOK_REDIRECT_NOCLOB:
- {
- int type = tok_last_type( tok );
+ case TOK_REDIRECT_OUT:
+ case TOK_REDIRECT_IN:
+ case TOK_REDIRECT_APPEND:
+ case TOK_REDIRECT_FD:
+ case TOK_REDIRECT_NOCLOB:
+ {
+ int type = tok_last_type( tok );
std::auto_ptr<io_data_t> new_io;
wcstring target;
- bool has_target = false;
- wchar_t *end;
-
- /*
- Don't check redirections in skipped part
-
- Otherwise, bogus errors may be the result. (Do check
- that token is string, though)
- */
- if( current_block->skip && ! unskip )
- {
- tok_next( tok );
- if( tok_last_type( tok ) != TOK_STRING )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- REDIRECT_TOKEN_ERR_MSG,
- tok_get_desc( tok_last_type(tok)) );
- }
-
- break;
- }
-
- new_io.reset(new io_data_t);
-
- errno = 0;
- new_io->fd = fish_wcstoi( tok_last( tok ),
- &end,
- 10 );
- if( new_io->fd < 0 || errno || *end )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- ILLEGAL_FD_ERR_MSG,
- tok_last( tok ) );
- }
- else
- {
-
- tok_next( tok );
-
- switch( tok_last_type( tok ) )
- {
- case TOK_STRING:
- {
+ bool has_target = false;
+ wchar_t *end;
+
+ /*
+ Don't check redirections in skipped part
+
+ Otherwise, bogus errors may be the result. (Do check
+ that token is string, though)
+ */
+ if( current_block->skip && ! unskip )
+ {
+ tok_next( tok );
+ if( tok_last_type( tok ) != TOK_STRING )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ REDIRECT_TOKEN_ERR_MSG,
+ tok_get_desc( tok_last_type(tok)) );
+ }
+
+ break;
+ }
+
+ new_io.reset(new io_data_t);
+
+ errno = 0;
+ new_io->fd = fish_wcstoi( tok_last( tok ),
+ &end,
+ 10 );
+ if( new_io->fd < 0 || errno || *end )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ ILLEGAL_FD_ERR_MSG,
+ tok_last( tok ) );
+ }
+ else
+ {
+
+ tok_next( tok );
+
+ switch( tok_last_type( tok ) )
+ {
+ case TOK_STRING:
+ {
target = tok_last( tok );
has_target = expand_one(target, no_exec ? EXPAND_SKIP_VARIABLES : 0);
- if( ! has_target && error_code == 0 )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- REDIRECT_TOKEN_ERR_MSG,
- tok_last( tok ) );
-
- }
- break;
- }
-
- default:
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- REDIRECT_TOKEN_ERR_MSG,
- tok_get_desc( tok_last_type(tok)) );
- }
-
- if( ! has_target || target.empty() )
- {
- if( error_code == 0 )
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- _(L"Invalid IO redirection") );
- tok_next(tok);
- }
- else
- {
-
- switch( type )
- {
- case TOK_REDIRECT_APPEND:
- new_io->io_mode = IO_FILE;
- new_io->param2.flags = O_CREAT | O_APPEND | O_WRONLY;
- new_io->set_filename(target);
- break;
-
- case TOK_REDIRECT_OUT:
- new_io->io_mode = IO_FILE;
- new_io->param2.flags = O_CREAT | O_WRONLY | O_TRUNC;
- new_io->set_filename(target);
- break;
-
- case TOK_REDIRECT_NOCLOB:
- new_io->io_mode = IO_FILE;
- new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY;
- new_io->set_filename(target);
- break;
-
- case TOK_REDIRECT_IN:
- new_io->io_mode = IO_FILE;
- new_io->param2.flags = O_RDONLY;
- new_io->set_filename(target);
- break;
-
- case TOK_REDIRECT_FD:
- {
- if( target == L"-" )
- {
- new_io->io_mode = IO_CLOSE;
- }
- else
- {
- wchar_t *end;
-
- new_io->io_mode = IO_FD;
- errno = 0;
-
- new_io->param1.old_fd = fish_wcstoi( target.c_str(), &end, 10 );
-
- if( ( new_io->param1.old_fd < 0 ) ||
- errno || *end )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- _(L"Requested redirection to something that is not a file descriptor %ls"),
- target.c_str() );
-
- tok_next(tok);
- }
- }
- break;
- }
- }
-
- }
- }
-
- j->io.push_back(new_io.release());
-
- }
- break;
-
- case TOK_ERROR:
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- TOK_ERR_MSG,
- tok_last(tok) );
-
- return;
- }
-
- default:
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- UNEXPECTED_TOKEN_ERR_MSG,
- tok_get_desc( tok_last_type(tok)) );
-
- tok_next(tok);
- break;
- }
-
- if( (is_finished) || (error_code != 0) )
- break;
-
- tok_next( tok );
- }
-
- if( !error_code )
- {
- if( unmatched_wildcard && !matched_wildcard )
- {
- job_set_flag( j, JOB_WILDCARD_ERROR, 1 );
- proc_set_last_status( STATUS_UNMATCHED_WILDCARD );
- if( get_is_interactive() && !is_block )
- {
- int tmp;
-
- debug( 1, WILDCARD_ERR_MSG, unmatched.c_str() );
- tmp = current_tokenizer_pos;
- current_tokenizer_pos = unmatched_pos;
-
- fwprintf( stderr, L"%ls", parser_t::current_line() );
-
- current_tokenizer_pos=tmp;
- }
-
- }
- }
-
- return;
+ if( ! has_target && error_code == 0 )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ REDIRECT_TOKEN_ERR_MSG,
+ tok_last( tok ) );
+
+ }
+ break;
+ }
+
+ default:
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ REDIRECT_TOKEN_ERR_MSG,
+ tok_get_desc( tok_last_type(tok)) );
+ }
+
+ if( ! has_target || target.empty() )
+ {
+ if( error_code == 0 )
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ _(L"Invalid IO redirection") );
+ tok_next(tok);
+ }
+ else
+ {
+
+ switch( type )
+ {
+ case TOK_REDIRECT_APPEND:
+ new_io->io_mode = IO_FILE;
+ new_io->param2.flags = O_CREAT | O_APPEND | O_WRONLY;
+ new_io->set_filename(target);
+ break;
+
+ case TOK_REDIRECT_OUT:
+ new_io->io_mode = IO_FILE;
+ new_io->param2.flags = O_CREAT | O_WRONLY | O_TRUNC;
+ new_io->set_filename(target);
+ break;
+
+ case TOK_REDIRECT_NOCLOB:
+ new_io->io_mode = IO_FILE;
+ new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY;
+ new_io->set_filename(target);
+ break;
+
+ case TOK_REDIRECT_IN:
+ new_io->io_mode = IO_FILE;
+ new_io->param2.flags = O_RDONLY;
+ new_io->set_filename(target);
+ break;
+
+ case TOK_REDIRECT_FD:
+ {
+ if( target == L"-" )
+ {
+ new_io->io_mode = IO_CLOSE;
+ }
+ else
+ {
+ wchar_t *end;
+
+ new_io->io_mode = IO_FD;
+ errno = 0;
+
+ new_io->param1.old_fd = fish_wcstoi( target.c_str(), &end, 10 );
+
+ if( ( new_io->param1.old_fd < 0 ) ||
+ errno || *end )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ _(L"Requested redirection to something that is not a file descriptor %ls"),
+ target.c_str() );
+
+ tok_next(tok);
+ }
+ }
+ break;
+ }
+ }
+
+ }
+ }
+
+ j->io.push_back(new_io.release());
+
+ }
+ break;
+
+ case TOK_ERROR:
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ TOK_ERR_MSG,
+ tok_last(tok) );
+
+ return;
+ }
+
+ default:
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ UNEXPECTED_TOKEN_ERR_MSG,
+ tok_get_desc( tok_last_type(tok)) );
+
+ tok_next(tok);
+ break;
+ }
+
+ if( (is_finished) || (error_code != 0) )
+ break;
+
+ tok_next( tok );
+ }
+
+ if( !error_code )
+ {
+ if( unmatched_wildcard && !matched_wildcard )
+ {
+ job_set_flag( j, JOB_WILDCARD_ERROR, 1 );
+ proc_set_last_status( STATUS_UNMATCHED_WILDCARD );
+ if( get_is_interactive() && !is_block )
+ {
+ int tmp;
+
+ debug( 1, WILDCARD_ERR_MSG, unmatched.c_str() );
+ tmp = current_tokenizer_pos;
+ current_tokenizer_pos = unmatched_pos;
+
+ fwprintf( stderr, L"%ls", parser_t::current_line() );
+
+ current_tokenizer_pos=tmp;
+ }
+
+ }
+ }
+
+ return;
}
/*
@@ -1696,11 +1696,11 @@ void parser_t::parse_job_argument_list( process_t *p,
if( !b )
return;
print_block_stack( b->outer );
-
- debug( 0, L"Block type %ls, skip: %d", parser_get_block_desc( b->type ), b->skip );
+
+ debug( 0, L"Block type %ls, skip: %d", parser_get_block_desc( b->type ), b->skip );
}
*/
-
+
/**
Fully parse a single job. Does not call exec on it, but any command substitutions in the job will be executed.
@@ -1711,213 +1711,213 @@ f
\return 1 on success, 0 on error
*/
int parser_t::parse_job( process_t *p,
- job_t *j,
- tokenizer *tok )
+ job_t *j,
+ tokenizer *tok )
{
std::vector<completion_t> args; // The list that will become the argc array for the program
- int use_function = 1; // May functions be considered when checking what action this command represents
- int use_builtin = 1; // May builtins be considered when checking what action this command represents
- int use_command = 1; // May commands be considered when checking what action this command represents
- int is_new_block=0; // Does this command create a new block?
- bool unskip = false; // Maybe we are an elseif inside an if block; if so we may want to evaluate this even if the if block is currently set to skip
- bool allow_bogus_command = false; // If we are an elseif that will not be executed, or an AND or OR that will have been short circuited, don't complain about non-existent commands
+ int use_function = 1; // May functions be considered when checking what action this command represents
+ int use_builtin = 1; // May builtins be considered when checking what action this command represents
+ int use_command = 1; // May commands be considered when checking what action this command represents
+ int is_new_block=0; // Does this command create a new block?
+ bool unskip = false; // Maybe we are an elseif inside an if block; if so we may want to evaluate this even if the if block is currently set to skip
+ bool allow_bogus_command = false; // If we are an elseif that will not be executed, or an AND or OR that will have been short circuited, don't complain about non-existent commands
- block_t *prev_block = current_block;
- int prev_tokenizer_pos = current_tokenizer_pos;
+ block_t *prev_block = current_block;
+ int prev_tokenizer_pos = current_tokenizer_pos;
- current_tokenizer_pos = tok_get_pos( tok );
+ current_tokenizer_pos = tok_get_pos( tok );
- while( args.empty() )
- {
- wcstring nxt;
+ while( args.empty() )
+ {
+ wcstring nxt;
bool has_nxt = false;
- bool consumed = false; // Set to one if the command requires a second command, like e.g. while does
- int mark; // Use to save the position of the beginning of the token
-
- switch( tok_last_type( tok ))
- {
- case TOK_STRING:
- {
+ bool consumed = false; // Set to one if the command requires a second command, like e.g. while does
+ int mark; // Use to save the position of the beginning of the token
+
+ switch( tok_last_type( tok ))
+ {
+ case TOK_STRING:
+ {
nxt = tok_last( tok );
has_nxt = expand_one(nxt, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
-
- if( ! has_nxt)
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- ILLEGAL_CMD_ERR_MSG,
- tok_last( tok ) );
-
- current_tokenizer_pos = prev_tokenizer_pos;
- return 0;
- }
- break;
- }
-
- case TOK_ERROR:
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- TOK_ERR_MSG,
- tok_last(tok) );
-
- current_tokenizer_pos = prev_tokenizer_pos;
- return 0;
- }
-
- case TOK_PIPE:
- {
- const wchar_t *str = tok_string( tok );
- if( tok_get_pos(tok)>0 && str[tok_get_pos(tok)-1] == L'|' )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- CMD_OR_ERR_MSG,
- tok_get_desc( tok_last_type(tok) ) );
- }
- else
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(tok) ) );
- }
-
- current_tokenizer_pos = prev_tokenizer_pos;
- return 0;
- }
-
- default:
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(tok) ) );
-
- current_tokenizer_pos = prev_tokenizer_pos;
- return 0;
- }
- }
-
- mark = tok_get_pos( tok );
-
- if( contains( nxt,
- L"command",
- L"builtin",
- L"not",
- L"and",
- L"or",
- L"exec" ) )
- {
- int sw;
- int is_exec = nxt == L"exec";
-
- if( is_exec && (p != j->first_process) )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- EXEC_ERR_MSG );
- current_tokenizer_pos = prev_tokenizer_pos;
- return 0;
- }
-
- tok_next( tok );
- sw = parser_keywords_is_switch( tok_last( tok ) );
-
- if( sw == ARG_SWITCH )
- {
- tok_set_pos( tok, mark);
- }
- else
- {
- if( sw == ARG_SKIP )
- {
- tok_next( tok );
- }
-
- consumed = true;
-
- if( nxt == L"command" || nxt == L"builtin" )
- {
- use_function = 0;
- if( nxt == L"command" )
- {
- use_builtin = 0;
- use_command = 1;
- }
- else
- {
- use_builtin = 1;
- use_command = 0;
- }
- }
- else if( nxt == L"not" )
- {
- job_set_flag( j, JOB_NEGATE, !job_get_flag( j, JOB_NEGATE ) );
- }
- else if( nxt == L"and" )
- {
+
+ if( ! has_nxt)
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ ILLEGAL_CMD_ERR_MSG,
+ tok_last( tok ) );
+
+ current_tokenizer_pos = prev_tokenizer_pos;
+ return 0;
+ }
+ break;
+ }
+
+ case TOK_ERROR:
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ TOK_ERR_MSG,
+ tok_last(tok) );
+
+ current_tokenizer_pos = prev_tokenizer_pos;
+ return 0;
+ }
+
+ case TOK_PIPE:
+ {
+ const wchar_t *str = tok_string( tok );
+ if( tok_get_pos(tok)>0 && str[tok_get_pos(tok)-1] == L'|' )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ CMD_OR_ERR_MSG,
+ tok_get_desc( tok_last_type(tok) ) );
+ }
+ else
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(tok) ) );
+ }
+
+ current_tokenizer_pos = prev_tokenizer_pos;
+ return 0;
+ }
+
+ default:
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(tok) ) );
+
+ current_tokenizer_pos = prev_tokenizer_pos;
+ return 0;
+ }
+ }
+
+ mark = tok_get_pos( tok );
+
+ if( contains( nxt,
+ L"command",
+ L"builtin",
+ L"not",
+ L"and",
+ L"or",
+ L"exec" ) )
+ {
+ int sw;
+ int is_exec = nxt == L"exec";
+
+ if( is_exec && (p != j->first_process) )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ EXEC_ERR_MSG );
+ current_tokenizer_pos = prev_tokenizer_pos;
+ return 0;
+ }
+
+ tok_next( tok );
+ sw = parser_keywords_is_switch( tok_last( tok ) );
+
+ if( sw == ARG_SWITCH )
+ {
+ tok_set_pos( tok, mark);
+ }
+ else
+ {
+ if( sw == ARG_SKIP )
+ {
+ tok_next( tok );
+ }
+
+ consumed = true;
+
+ if( nxt == L"command" || nxt == L"builtin" )
+ {
+ use_function = 0;
+ if( nxt == L"command" )
+ {
+ use_builtin = 0;
+ use_command = 1;
+ }
+ else
+ {
+ use_builtin = 1;
+ use_command = 0;
+ }
+ }
+ else if( nxt == L"not" )
+ {
+ job_set_flag( j, JOB_NEGATE, !job_get_flag( j, JOB_NEGATE ) );
+ }
+ else if( nxt == L"and" )
+ {
bool skip = (proc_get_last_status() != 0);
- job_set_flag( j, JOB_SKIP, skip);
+ job_set_flag( j, JOB_SKIP, skip);
allow_bogus_command = skip;
- }
- else if( nxt == L"or" )
- {
+ }
+ else if( nxt == L"or" )
+ {
bool skip = (proc_get_last_status() == 0);
- job_set_flag( j, JOB_SKIP, skip);
+ job_set_flag( j, JOB_SKIP, skip);
allow_bogus_command = skip;
- }
- else if( is_exec )
- {
- use_function = 0;
- use_builtin=0;
- p->type=INTERNAL_EXEC;
- current_tokenizer_pos = prev_tokenizer_pos;
- }
- }
- }
- else if( nxt == L"while" )
- {
- bool new_block = false;
- tok_next( tok );
+ }
+ else if( is_exec )
+ {
+ use_function = 0;
+ use_builtin=0;
+ p->type=INTERNAL_EXEC;
+ current_tokenizer_pos = prev_tokenizer_pos;
+ }
+ }
+ }
+ else if( nxt == L"while" )
+ {
+ bool new_block = false;
+ tok_next( tok );
while_block_t *wb = NULL;
- if( ( current_block->type() != WHILE ) )
- {
- new_block = true;
- }
- else if( (wb = static_cast<while_block_t*>(current_block))->status == WHILE_TEST_AGAIN )
- {
- wb->status = WHILE_TEST_FIRST;
- }
- else
- {
- new_block = true;
- }
-
- if( new_block )
- {
+ if( ( current_block->type() != WHILE ) )
+ {
+ new_block = true;
+ }
+ else if( (wb = static_cast<while_block_t*>(current_block))->status == WHILE_TEST_AGAIN )
+ {
+ wb->status = WHILE_TEST_FIRST;
+ }
+ else
+ {
+ new_block = true;
+ }
+
+ if( new_block )
+ {
while_block_t *wb = new while_block_t();
- wb->status = WHILE_TEST_FIRST;
- wb->tok_pos = mark;
- this->push_block( wb );
- }
+ wb->status = WHILE_TEST_FIRST;
+ wb->tok_pos = mark;
+ this->push_block( wb );
+ }
- consumed = true;
- is_new_block=1;
+ consumed = true;
+ is_new_block=1;
- }
- else if( nxt == L"if" )
- {
- tok_next( tok );
+ }
+ else if( nxt == L"if" )
+ {
+ tok_next( tok );
if_block_t *ib = new if_block_t();
- this->push_block( ib );
- ib->tok_pos = mark;
+ this->push_block( ib );
+ ib->tok_pos = mark;
- is_new_block=1;
- consumed = true;
- }
+ is_new_block=1;
+ consumed = true;
+ }
else if (nxt == L"else")
{
/* Record where the else is for error reporting */
@@ -1927,7 +1927,7 @@ int parser_t::parse_job( process_t *p,
if (tok_last_type(tok) == TOK_STRING && current_block->type() == IF)
{
const if_block_t *ib = static_cast<const if_block_t *>(current_block);
-
+
/* If we've already encountered an else, complain */
if (ib->else_evaluated)
{
@@ -1939,16 +1939,16 @@ int parser_t::parse_job( process_t *p,
}
else
{
-
+
job_set_flag( j, JOB_ELSEIF, 1 );
consumed = true;
-
+
/* We're at the IF. Go past it. */
tok_next(tok);
-
+
/* We want to execute this ELSEIF if the IF expression was evaluated, it failed, and so has every other ELSEIF (if any) */
unskip = (ib->if_expr_evaluated && ! ib->any_branch_taken);
-
+
/* But if we're not executing it, don't complain about its command if it doesn't exist */
if (! unskip)
allow_bogus_command = true;
@@ -1956,44 +1956,44 @@ int parser_t::parse_job( process_t *p,
}
}
- /*
- Test if we need another command
- */
- if( consumed )
- {
- /*
- Yes we do, around in the loop for another lap, then!
- */
- continue;
- }
-
- if( use_function && ( unskip || ! current_block->skip ))
- {
- bool nxt_forbidden=false;
- wcstring forbid;
-
- int is_function_call=0;
-
- /*
- This is a bit fragile. It is a test to see if we are
- inside of function call, but not inside a block in that
- function call. If, in the future, the rules for what
- block scopes are pushed on function invocation changes,
- then this check will break.
- */
- if( ( current_block->type() == TOP ) &&
- ( current_block->outer ) &&
- ( current_block->outer->type() == FUNCTION_CALL ) )
- is_function_call = 1;
-
- /*
- If we are directly in a function, and this is the first
- command of the block, then the function we are executing
- may not be called, since that would mean an infinite
- recursion.
- */
- if( is_function_call && !current_block->had_command )
- {
+ /*
+ Test if we need another command
+ */
+ if( consumed )
+ {
+ /*
+ Yes we do, around in the loop for another lap, then!
+ */
+ continue;
+ }
+
+ if( use_function && ( unskip || ! current_block->skip ))
+ {
+ bool nxt_forbidden=false;
+ wcstring forbid;
+
+ int is_function_call=0;
+
+ /*
+ This is a bit fragile. It is a test to see if we are
+ inside of function call, but not inside a block in that
+ function call. If, in the future, the rules for what
+ block scopes are pushed on function invocation changes,
+ then this check will break.
+ */
+ if( ( current_block->type() == TOP ) &&
+ ( current_block->outer ) &&
+ ( current_block->outer->type() == FUNCTION_CALL ) )
+ is_function_call = 1;
+
+ /*
+ If we are directly in a function, and this is the first
+ command of the block, then the function we are executing
+ may not be called, since that would mean an infinite
+ recursion.
+ */
+ if( is_function_call && !current_block->had_command )
+ {
forbid = forbidden_function.empty() ? wcstring(L"") : forbidden_function.back();
if (forbid == nxt)
{
@@ -2001,57 +2001,57 @@ int parser_t::parse_job( process_t *p,
nxt_forbidden = true;
error( SYNTAX_ERROR, tok_get_pos( tok ), INFINITE_RECURSION_ERR_MSG );
}
- }
-
- if( !nxt_forbidden && has_nxt && function_exists( nxt ) )
- {
- /*
- Check if we have reached the maximum recursion depth
- */
- if( forbidden_function.size() > MAX_RECURSION_DEPTH )
- {
- error( SYNTAX_ERROR, tok_get_pos( tok ), OVERFLOW_RECURSION_ERR_MSG );
- }
- else
- {
- p->type = INTERNAL_FUNCTION;
- }
- }
- }
- args.push_back(completion_t(nxt));
- }
-
- if( error_code == 0 )
- {
- if( !p->type )
- {
- if( use_builtin &&
- builtin_exists(args.at(0).completion))
- {
- p->type = INTERNAL_BUILTIN;
- is_new_block |= parser_keywords_is_block( args.at( 0 ).completion );
- }
- }
-
- if( (!p->type || (p->type == INTERNAL_EXEC) ) )
- {
- /*
- If we are not executing the current block, allow
- non-existent commands.
- */
+ }
+
+ if( !nxt_forbidden && has_nxt && function_exists( nxt ) )
+ {
+ /*
+ Check if we have reached the maximum recursion depth
+ */
+ if( forbidden_function.size() > MAX_RECURSION_DEPTH )
+ {
+ error( SYNTAX_ERROR, tok_get_pos( tok ), OVERFLOW_RECURSION_ERR_MSG );
+ }
+ else
+ {
+ p->type = INTERNAL_FUNCTION;
+ }
+ }
+ }
+ args.push_back(completion_t(nxt));
+ }
+
+ if( error_code == 0 )
+ {
+ if( !p->type )
+ {
+ if( use_builtin &&
+ builtin_exists(args.at(0).completion))
+ {
+ p->type = INTERNAL_BUILTIN;
+ is_new_block |= parser_keywords_is_block( args.at( 0 ).completion );
+ }
+ }
+
+ if( (!p->type || (p->type == INTERNAL_EXEC) ) )
+ {
+ /*
+ If we are not executing the current block, allow
+ non-existent commands.
+ */
if (current_block->skip && ! unskip)
allow_bogus_command = true; //note this may already be true for other reasons
-
- if (allow_bogus_command)
- {
- p->actual_cmd.clear();
- }
- else
- {
- int err;
+
+ if (allow_bogus_command)
+ {
+ p->actual_cmd.clear();
+ }
+ else
+ {
+ int err;
bool has_command = path_get_path(args.at(0).completion, &p->actual_cmd);
- err = errno;
-
+ err = errno;
+
bool use_implicit_cd = false;
if (! has_command)
{
@@ -2063,7 +2063,7 @@ int parser_t::parse_job( process_t *p,
args.clear();
args.push_back(completion_t(L"cd"));
args.push_back(completion_t(implicit_cd_path));
-
+
/* If we have defined a wrapper around cd, use it, otherwise use the cd builtin */
if (use_function && function_exists(L"cd"))
p->type = INTERNAL_FUNCTION;
@@ -2071,17 +2071,17 @@ int parser_t::parse_job( process_t *p,
p->type = INTERNAL_BUILTIN;
}
}
-
- /* Check if the specified command exists */
- if( ! has_command && ! use_implicit_cd )
- {
-
- int tmp;
+
+ /* Check if the specified command exists */
+ if( ! has_command && ! use_implicit_cd )
+ {
+
+ int tmp;
const wchar_t *cmd = args.at( 0 ).completion.c_str();
-
- /*
+
+ /*
We couldn't find the specified command.
-
+
What we want to happen now is that the
specified job won't get executed, and an
error message is printed on-screen, but
@@ -2101,20 +2101,20 @@ int parser_t::parse_job( process_t *p,
wchar_t *cpy = wcsdup( cmd );
wchar_t *valpart = wcschr( cpy, L'=' );
*valpart++=0;
-
+
debug( 0,
COMMAND_ASSIGN_ERR_MSG,
cmd,
cpy,
valpart);
free(cpy);
-
+
}
else if(cmd[0]==L'$')
{
-
+
const env_var_t val_wstr = env_get_string( cmd+1 );
- const wchar_t *val = val_wstr.missing() ? NULL : val_wstr.c_str();
+ const wchar_t *val = val_wstr.missing() ? NULL : val_wstr.c_str();
if( val )
{
debug( 0,
@@ -2128,7 +2128,7 @@ int parser_t::parse_job( process_t *p,
debug( 0,
_(L"Variables may not be used as commands. Instead, define a function. See the help section for the function command by typing 'help function'." ),
cmd );
- }
+ }
}
else if(wcschr( cmd, L'$' ))
{
@@ -2144,155 +2144,155 @@ int parser_t::parse_job( process_t *p,
cmd?cmd:L"UNKNOWN" );
}
else
- {
+ {
debug( 0,
_(L"Unknown command '%ls'"),
cmd?cmd:L"UNKNOWN" );
}
-
+
tmp = current_tokenizer_pos;
current_tokenizer_pos = tok_get_pos(tok);
-
+
fwprintf( stderr, L"%ls", parser_t::current_line() );
-
+
current_tokenizer_pos=tmp;
-
+
job_set_flag( j, JOB_SKIP, 1 );
event_fire_generic(L"fish_command_not_found", (wchar_t *)( args.at( 0 ).completion.c_str() ) );
proc_set_last_status( err==ENOENT?STATUS_UNKNOWN_COMMAND:STATUS_NOT_EXECUTABLE );
- }
- }
- }
-
- if( (p->type == EXTERNAL) && !use_command )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- UNKNOWN_BUILTIN_ERR_MSG,
- args.back().completion.c_str() );
- }
- }
-
-
- if( is_new_block )
- {
-
- const wchar_t *end=parser_find_end( tok_string( tok ) +
- current_tokenizer_pos );
- tokenizer subtok;
- int make_sub_block = j->first_process != p;
-
- if( !end )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- BLOCK_END_ERR_MSG );
-
- }
- else
- {
-
- if( !make_sub_block )
- {
- int done=0;
-
- for( tok_init( &subtok, end, 0 );
- !done && tok_has_next( &subtok );
- tok_next( &subtok ) )
- {
-
- switch( tok_last_type( &subtok ) )
- {
- case TOK_END:
- done = 1;
- break;
-
- case TOK_REDIRECT_OUT:
- case TOK_REDIRECT_NOCLOB:
- case TOK_REDIRECT_APPEND:
- case TOK_REDIRECT_IN:
- case TOK_REDIRECT_FD:
- case TOK_PIPE:
- {
- done = 1;
- make_sub_block = 1;
- break;
- }
-
- case TOK_STRING:
- {
- break;
- }
-
- default:
- {
- done = 1;
- error( SYNTAX_ERROR,
- current_tokenizer_pos,
- BLOCK_END_ERR_MSG );
- }
- }
- }
-
- tok_destroy( &subtok );
- }
-
- if( make_sub_block )
- {
-
- long end_pos = end-tok_string( tok );
+ }
+ }
+ }
+
+ if( (p->type == EXTERNAL) && !use_command )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ UNKNOWN_BUILTIN_ERR_MSG,
+ args.back().completion.c_str() );
+ }
+ }
+
+
+ if( is_new_block )
+ {
+
+ const wchar_t *end=parser_find_end( tok_string( tok ) +
+ current_tokenizer_pos );
+ tokenizer subtok;
+ int make_sub_block = j->first_process != p;
+
+ if( !end )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ BLOCK_END_ERR_MSG );
+
+ }
+ else
+ {
+
+ if( !make_sub_block )
+ {
+ int done=0;
+
+ for( tok_init( &subtok, end, 0 );
+ !done && tok_has_next( &subtok );
+ tok_next( &subtok ) )
+ {
+
+ switch( tok_last_type( &subtok ) )
+ {
+ case TOK_END:
+ done = 1;
+ break;
+
+ case TOK_REDIRECT_OUT:
+ case TOK_REDIRECT_NOCLOB:
+ case TOK_REDIRECT_APPEND:
+ case TOK_REDIRECT_IN:
+ case TOK_REDIRECT_FD:
+ case TOK_PIPE:
+ {
+ done = 1;
+ make_sub_block = 1;
+ break;
+ }
+
+ case TOK_STRING:
+ {
+ break;
+ }
+
+ default:
+ {
+ done = 1;
+ error( SYNTAX_ERROR,
+ current_tokenizer_pos,
+ BLOCK_END_ERR_MSG );
+ }
+ }
+ }
+
+ tok_destroy( &subtok );
+ }
+
+ if( make_sub_block )
+ {
+
+ long end_pos = end-tok_string( tok );
const wcstring sub_block(tok_string( tok ) + current_tokenizer_pos, end_pos - current_tokenizer_pos);
-
- p->type = INTERNAL_BLOCK;
- args.at( 0 ) = completion_t(sub_block);
-
- tok_set_pos( tok, (int)end_pos );
-
- while( prev_block != current_block )
- {
- parser_t::pop_block();
- }
-
- }
- else tok_next( tok );
- }
-
- }
- else tok_next( tok );
-
- if( !error_code )
- {
- if( p->type == INTERNAL_BUILTIN && parser_keywords_skip_arguments(args.at(0).completion))
- {
- if( !p->get_argv() )
+
+ p->type = INTERNAL_BLOCK;
+ args.at( 0 ) = completion_t(sub_block);
+
+ tok_set_pos( tok, (int)end_pos );
+
+ while( prev_block != current_block )
+ {
+ parser_t::pop_block();
+ }
+
+ }
+ else tok_next( tok );
+ }
+
+ }
+ else tok_next( tok );
+
+ if( !error_code )
+ {
+ if( p->type == INTERNAL_BUILTIN && parser_keywords_skip_arguments(args.at(0).completion))
+ {
+ if( !p->get_argv() )
p->set_argv(completions_to_wcstring_list(args));
- }
- else
- {
- parse_job_argument_list(p, j, tok, args, unskip);
- }
- }
-
- if( !error_code )
- {
- if( !is_new_block )
- {
- current_block->had_command = true;
- }
- }
-
- if( error_code )
- {
- /*
- Make sure the block stack is consistent
- */
- while( prev_block != current_block )
- {
- parser_t::pop_block();
- }
- }
- current_tokenizer_pos = prev_tokenizer_pos;
- return !error_code;
+ }
+ else
+ {
+ parse_job_argument_list(p, j, tok, args, unskip);
+ }
+ }
+
+ if( !error_code )
+ {
+ if( !is_new_block )
+ {
+ current_block->had_command = true;
+ }
+ }
+
+ if( error_code )
+ {
+ /*
+ Make sure the block stack is consistent
+ */
+ while( prev_block != current_block )
+ {
+ parser_t::pop_block();
+ }
+ }
+ current_tokenizer_pos = prev_tokenizer_pos;
+ return !error_code;
}
/**
@@ -2305,32 +2305,32 @@ int parser_t::parse_job( process_t *p,
*/
void parser_t::skipped_exec( job_t * j )
{
- process_t *p;
+ process_t *p;
/* Handle other skipped guys */
- for( p = j->first_process; p; p=p->next )
- {
- if( p->type == INTERNAL_BUILTIN )
- {
- if(( wcscmp( p->argv0(), L"for" )==0) ||
- ( wcscmp( p->argv0(), L"switch" )==0) ||
- ( wcscmp( p->argv0(), L"begin" )==0) ||
- ( wcscmp( p->argv0(), L"function" )==0))
- {
- this->push_block( new fake_block_t() );
- }
- else if( wcscmp( p->argv0(), L"end" )==0)
- {
- if(!current_block->outer->skip )
- {
- exec( *this, j );
- return;
- }
- parser_t::pop_block();
- }
- else if( wcscmp( p->argv0(), L"else" )==0)
- {
- if (current_block->type() == IF)
+ for( p = j->first_process; p; p=p->next )
+ {
+ if( p->type == INTERNAL_BUILTIN )
+ {
+ if(( wcscmp( p->argv0(), L"for" )==0) ||
+ ( wcscmp( p->argv0(), L"switch" )==0) ||
+ ( wcscmp( p->argv0(), L"begin" )==0) ||
+ ( wcscmp( p->argv0(), L"function" )==0))
+ {
+ this->push_block( new fake_block_t() );
+ }
+ else if( wcscmp( p->argv0(), L"end" )==0)
+ {
+ if(!current_block->outer->skip )
+ {
+ exec( *this, j );
+ return;
+ }
+ parser_t::pop_block();
+ }
+ else if( wcscmp( p->argv0(), L"else" )==0)
+ {
+ if (current_block->type() == IF)
{
/* Evaluate this ELSE if the IF expression failed, and so has every ELSEIF (if any) expression thus far */
const if_block_t *ib = static_cast<const if_block_t*>(current_block);
@@ -2341,17 +2341,17 @@ void parser_t::skipped_exec( job_t * j )
}
}
}
- else if( wcscmp( p->argv0(), L"case" )==0)
- {
- if(current_block->type() == SWITCH)
- {
- exec( *this, j );
- return;
- }
- }
- }
- }
- job_free( j );
+ else if( wcscmp( p->argv0(), L"case" )==0)
+ {
+ if(current_block->type() == SWITCH)
+ {
+ exec( *this, j );
+ return;
+ }
+ }
+ }
+ }
+ job_free( j );
}
/* Return whether we should skip the current block, if it is an elseif. */
@@ -2366,10 +2366,10 @@ static bool job_should_skip_elseif(const job_t *job, const block_t *current_bloc
{
/* We are an IF block */
const if_block_t *ib = static_cast<const if_block_t *>(current_block);
-
+
/* Execute this ELSEIF if the IF expression has been evaluated, it evaluated to false, and all ELSEIFs so far have evaluated to false. */
bool execute_elseif = (ib->if_expr_evaluated && ! ib->any_branch_taken);
-
+
/* Invert the sense */
return ! execute_elseif;
}
@@ -2385,83 +2385,83 @@ static bool job_should_skip_elseif(const job_t *job, const block_t *current_bloc
void parser_t::eval_job( tokenizer *tok )
{
ASSERT_IS_MAIN_THREAD();
- job_t *j;
+ job_t *j;
+
+ int start_pos = job_start_pos = tok_get_pos( tok );
+ long long t1=0, t2=0, t3=0;
+
- int start_pos = job_start_pos = tok_get_pos( tok );
- long long t1=0, t2=0, t3=0;
-
-
profile_item_t *profile_item = NULL;
- bool skip = false;
- int job_begin_pos, prev_tokenizer_pos;
- const bool do_profile = profile;
-
- if( do_profile )
- {
+ bool skip = false;
+ int job_begin_pos, prev_tokenizer_pos;
+ const bool do_profile = profile;
+
+ if( do_profile )
+ {
profile_items.resize(profile_items.size() + 1);
profile_item = &profile_items.back();
profile_item->cmd = L"";
- profile_item->skipped = 1;
- t1 = get_time();
- }
-
- switch( tok_last_type( tok ) )
- {
- case TOK_STRING:
- {
- j = this->job_create();
- job_set_flag( j, JOB_FOREGROUND, 1 );
- job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) );
- job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) \
- && (!is_subshell && !is_event));
- job_set_flag( j, JOB_SKIP_NOTIFICATION, is_subshell \
- || is_block \
- || is_event \
- || (!get_is_interactive()));
-
- current_block->job = j;
-
- if( get_is_interactive() )
- {
- if( tcgetattr (0, &j->tmodes) )
- {
- tok_next( tok );
- wperror( L"tcgetattr" );
- job_free( j );
- break;
- }
- }
-
- j->first_process = new process_t();
- job_begin_pos = tok_get_pos( tok );
-
- if( parse_job( j->first_process, j, tok ) &&
- j->first_process->get_argv() )
- {
- if( job_start_pos < tok_get_pos( tok ) )
- {
- long stop_pos = tok_get_pos( tok );
- const wchar_t *newline = wcschr(tok_string(tok)+start_pos, L'\n');
- if( newline )
- stop_pos = mini<long>( stop_pos, newline - tok_string(tok) );
-
- j->set_command(wcstring(tok_string(tok)+start_pos, stop_pos-start_pos));
- }
- else
- j->set_command(L"");
-
- if( do_profile )
- {
- t2 = get_time();
- profile_item->cmd = wcsdup( j->command_wcstr() );
- profile_item->skipped=current_block->skip;
- }
-
+ profile_item->skipped = 1;
+ t1 = get_time();
+ }
+
+ switch( tok_last_type( tok ) )
+ {
+ case TOK_STRING:
+ {
+ j = this->job_create();
+ job_set_flag( j, JOB_FOREGROUND, 1 );
+ job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) );
+ job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) \
+ && (!is_subshell && !is_event));
+ job_set_flag( j, JOB_SKIP_NOTIFICATION, is_subshell \
+ || is_block \
+ || is_event \
+ || (!get_is_interactive()));
+
+ current_block->job = j;
+
+ if( get_is_interactive() )
+ {
+ if( tcgetattr (0, &j->tmodes) )
+ {
+ tok_next( tok );
+ wperror( L"tcgetattr" );
+ job_free( j );
+ break;
+ }
+ }
+
+ j->first_process = new process_t();
+ job_begin_pos = tok_get_pos( tok );
+
+ if( parse_job( j->first_process, j, tok ) &&
+ j->first_process->get_argv() )
+ {
+ if( job_start_pos < tok_get_pos( tok ) )
+ {
+ long stop_pos = tok_get_pos( tok );
+ const wchar_t *newline = wcschr(tok_string(tok)+start_pos, L'\n');
+ if( newline )
+ stop_pos = mini<long>( stop_pos, newline - tok_string(tok) );
+
+ j->set_command(wcstring(tok_string(tok)+start_pos, stop_pos-start_pos));
+ }
+ else
+ j->set_command(L"");
+
+ if( do_profile )
+ {
+ t2 = get_time();
+ profile_item->cmd = wcsdup( j->command_wcstr() );
+ profile_item->skipped=current_block->skip;
+ }
+
/* If we're an ELSEIF, then we may want to unskip, if we're skipping because of an IF */
if (job_get_flag(j, JOB_ELSEIF))
{
bool skip_elseif = job_should_skip_elseif(j, current_block);
-
+
/* Record that we're entering an elseif */
if (! skip_elseif)
{
@@ -2469,62 +2469,62 @@ void parser_t::eval_job( tokenizer *tok )
assert(current_block->type() == IF);
static_cast<if_block_t *>(current_block)->is_elseif_entry = true;
}
-
+
/* Record that in the block too. This is similar to what builtin_else does. */
current_block->skip = skip_elseif;
}
-
+
skip = skip || current_block->skip;
- skip = skip || job_get_flag( j, JOB_WILDCARD_ERROR );
- skip = skip || job_get_flag( j, JOB_SKIP );
-
- if(!skip )
- {
- int was_builtin = 0;
- if( j->first_process->type==INTERNAL_BUILTIN && !j->first_process->next)
- was_builtin = 1;
- prev_tokenizer_pos = current_tokenizer_pos;
- current_tokenizer_pos = job_begin_pos;
- exec( *this, j );
- current_tokenizer_pos = prev_tokenizer_pos;
-
- /* Only external commands require a new fishd barrier */
- if( !was_builtin )
- set_proc_had_barrier(false);
- }
- else
- {
- this->skipped_exec( j );
- }
-
- if( do_profile )
- {
- t3 = get_time();
- profile_item->level=eval_level;
- profile_item->parse = (int)(t2-t1);
- profile_item->exec=(int)(t3-t2);
- }
-
- if( current_block->type() == WHILE )
- {
+ skip = skip || job_get_flag( j, JOB_WILDCARD_ERROR );
+ skip = skip || job_get_flag( j, JOB_SKIP );
+
+ if(!skip )
+ {
+ int was_builtin = 0;
+ if( j->first_process->type==INTERNAL_BUILTIN && !j->first_process->next)
+ was_builtin = 1;
+ prev_tokenizer_pos = current_tokenizer_pos;
+ current_tokenizer_pos = job_begin_pos;
+ exec( *this, j );
+ current_tokenizer_pos = prev_tokenizer_pos;
+
+ /* Only external commands require a new fishd barrier */
+ if( !was_builtin )
+ set_proc_had_barrier(false);
+ }
+ else
+ {
+ this->skipped_exec( j );
+ }
+
+ if( do_profile )
+ {
+ t3 = get_time();
+ profile_item->level=eval_level;
+ profile_item->parse = (int)(t2-t1);
+ profile_item->exec=(int)(t3-t2);
+ }
+
+ if( current_block->type() == WHILE )
+ {
while_block_t *wb = static_cast<while_block_t *>(current_block);
- switch( wb->status )
- {
- case WHILE_TEST_FIRST:
- {
- // PCA I added the 'wb->skip ||' part because we couldn't reliably
- // control-C out of loops like this: while test 1 -eq 1; end
- wb->skip = wb->skip || proc_get_last_status()!= 0;
- wb->status = WHILE_TESTED;
- }
- break;
- }
- }
-
- if( current_block->type() == IF )
- {
- if_block_t *ib = static_cast<if_block_t *>(current_block);
-
+ switch( wb->status )
+ {
+ case WHILE_TEST_FIRST:
+ {
+ // PCA I added the 'wb->skip ||' part because we couldn't reliably
+ // control-C out of loops like this: while test 1 -eq 1; end
+ wb->skip = wb->skip || proc_get_last_status()!= 0;
+ wb->status = WHILE_TESTED;
+ }
+ break;
+ }
+ }
+
+ if( current_block->type() == IF )
+ {
+ if_block_t *ib = static_cast<if_block_t *>(current_block);
+
if (ib->skip)
{
/* Nothing */
@@ -2534,10 +2534,10 @@ void parser_t::eval_job( tokenizer *tok )
/* Execute the IF */
bool if_result = (proc_get_last_status() == 0);
ib->any_branch_taken = if_result;
-
+
/* Don't execute if the expression failed */
- current_block->skip = ! if_result;
- ib->if_expr_evaluated = true;
+ current_block->skip = ! if_result;
+ ib->if_expr_evaluated = true;
}
else if (ib->is_elseif_entry && ! ib->any_branch_taken)
{
@@ -2547,200 +2547,200 @@ void parser_t::eval_job( tokenizer *tok )
current_block->skip = ! elseif_taken;
ib->is_elseif_entry = false;
}
- }
-
- }
- else
- {
- /*
- This job could not be properly parsed. We free it
- instead, and set the status to 1. This should be
- rare, since most errors should be detected by the
- ahead of time validator.
- */
- job_free( j );
-
- proc_set_last_status( 1 );
- }
- current_block->job = 0;
- break;
- }
-
- case TOK_END:
- {
- if( tok_has_next( tok ))
- tok_next( tok );
- break;
- }
-
- case TOK_BACKGROUND:
- {
- const wchar_t *str = tok_string( tok );
- if( tok_get_pos(tok)>0 && str[tok_get_pos(tok)-1] == L'&' )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- CMD_AND_ERR_MSG,
- tok_get_desc( tok_last_type(tok) ) );
- }
- else
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(tok) ) );
- }
-
- return;
- }
-
- case TOK_ERROR:
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- TOK_ERR_MSG,
- tok_last(tok) );
-
- return;
- }
-
- default:
- {
- error( SYNTAX_ERROR,
- tok_get_pos( tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(tok)) );
-
- return;
- }
- }
-
- job_reap( 0 );
+ }
+
+ }
+ else
+ {
+ /*
+ This job could not be properly parsed. We free it
+ instead, and set the status to 1. This should be
+ rare, since most errors should be detected by the
+ ahead of time validator.
+ */
+ job_free( j );
+
+ proc_set_last_status( 1 );
+ }
+ current_block->job = 0;
+ break;
+ }
+
+ case TOK_END:
+ {
+ if( tok_has_next( tok ))
+ tok_next( tok );
+ break;
+ }
+
+ case TOK_BACKGROUND:
+ {
+ const wchar_t *str = tok_string( tok );
+ if( tok_get_pos(tok)>0 && str[tok_get_pos(tok)-1] == L'&' )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ CMD_AND_ERR_MSG,
+ tok_get_desc( tok_last_type(tok) ) );
+ }
+ else
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(tok) ) );
+ }
+
+ return;
+ }
+
+ case TOK_ERROR:
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ TOK_ERR_MSG,
+ tok_last(tok) );
+
+ return;
+ }
+
+ default:
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(tok)) );
+
+ return;
+ }
+ }
+
+ job_reap( 0 );
}
int parser_t::eval( const wcstring &cmdStr, const io_chain_t &io, enum block_type_t block_type )
{
const wchar_t * const cmd = cmdStr.c_str();
- size_t forbid_count;
- int code;
- tokenizer *previous_tokenizer=current_tokenizer;
- block_t *start_current_block = current_block;
-
+ size_t forbid_count;
+ int code;
+ tokenizer *previous_tokenizer=current_tokenizer;
+ block_t *start_current_block = current_block;
+
/* Record the current chain so we can put it back later */
const io_chain_t prev_io = block_io;
block_io = io;
-
+
std::vector<wcstring> prev_forbidden = forbidden_function;
- if( block_type == SUBST )
- {
- forbidden_function.clear();
- }
-
- CHECK_BLOCK( 1 );
-
- forbid_count = forbidden_function.size();
-
- block_io = io;
-
- job_reap( 0 );
-
- debug( 4, L"eval: %ls", cmd );
-
- if( !cmd )
- {
- debug( 1,
- EVAL_NULL_ERR_MSG );
- bugreport();
- return 1;
- }
-
- if( (block_type != TOP) &&
- (block_type != SUBST))
- {
- debug( 1,
- INVALID_SCOPE_ERR_MSG,
- parser_t::get_block_desc( block_type ) );
- bugreport();
- return 1;
- }
-
- eval_level++;
-
- this->push_block( new scope_block_t(block_type) );
-
- current_tokenizer = new tokenizer;
- tok_init( current_tokenizer, cmd, 0 );
-
- error_code = 0;
-
- event_fire( NULL );
-
- while( tok_has_next( current_tokenizer ) &&
- !error_code &&
- !sanity_check() &&
- !exit_status() )
- {
- this->eval_job( current_tokenizer );
- event_fire( NULL );
- }
-
- parser_t::pop_block();
-
- while( start_current_block != current_block )
- {
- if( current_block == 0 )
- {
- debug( 0,
- _(L"End of block mismatch. Program terminating.") );
- bugreport();
- FATAL_EXIT();
- break;
- }
-
- if( (!error_code) && (!exit_status()) && (!proc_get_last_status()) )
- {
-
- //debug( 2, L"Status %d\n", proc_get_last_status() );
-
- debug( 1,
- L"%ls", parser_t::get_block_desc( current_block->type() ) );
- debug( 1,
- BLOCK_END_ERR_MSG );
- fwprintf( stderr, L"%ls", parser_t::current_line() );
-
- const wcstring h = builtin_help_get( *this, L"end" );
- if( h.size() )
- fwprintf( stderr, L"%ls", h.c_str() );
- break;
-
- }
- parser_t::pop_block();
- }
-
- this->print_errors_stderr();
-
- tok_destroy( current_tokenizer );
- delete current_tokenizer;
+ if( block_type == SUBST )
+ {
+ forbidden_function.clear();
+ }
+
+ CHECK_BLOCK( 1 );
+
+ forbid_count = forbidden_function.size();
+
+ block_io = io;
+
+ job_reap( 0 );
+
+ debug( 4, L"eval: %ls", cmd );
+
+ if( !cmd )
+ {
+ debug( 1,
+ EVAL_NULL_ERR_MSG );
+ bugreport();
+ return 1;
+ }
+
+ if( (block_type != TOP) &&
+ (block_type != SUBST))
+ {
+ debug( 1,
+ INVALID_SCOPE_ERR_MSG,
+ parser_t::get_block_desc( block_type ) );
+ bugreport();
+ return 1;
+ }
+
+ eval_level++;
+
+ this->push_block( new scope_block_t(block_type) );
+
+ current_tokenizer = new tokenizer;
+ tok_init( current_tokenizer, cmd, 0 );
+
+ error_code = 0;
+
+ event_fire( NULL );
+
+ while( tok_has_next( current_tokenizer ) &&
+ !error_code &&
+ !sanity_check() &&
+ !exit_status() )
+ {
+ this->eval_job( current_tokenizer );
+ event_fire( NULL );
+ }
+
+ parser_t::pop_block();
+
+ while( start_current_block != current_block )
+ {
+ if( current_block == 0 )
+ {
+ debug( 0,
+ _(L"End of block mismatch. Program terminating.") );
+ bugreport();
+ FATAL_EXIT();
+ break;
+ }
+
+ if( (!error_code) && (!exit_status()) && (!proc_get_last_status()) )
+ {
+
+ //debug( 2, L"Status %d\n", proc_get_last_status() );
+
+ debug( 1,
+ L"%ls", parser_t::get_block_desc( current_block->type() ) );
+ debug( 1,
+ BLOCK_END_ERR_MSG );
+ fwprintf( stderr, L"%ls", parser_t::current_line() );
+
+ const wcstring h = builtin_help_get( *this, L"end" );
+ if( h.size() )
+ fwprintf( stderr, L"%ls", h.c_str() );
+ break;
+
+ }
+ parser_t::pop_block();
+ }
+
+ this->print_errors_stderr();
+
+ tok_destroy( current_tokenizer );
+ delete current_tokenizer;
while (forbidden_function.size() > forbid_count)
- parser_t::allow_function();
+ parser_t::allow_function();
- /*
- Restore previous eval state
- */
- forbidden_function = prev_forbidden;
- current_tokenizer=previous_tokenizer;
- block_io = prev_io;
- eval_level--;
+ /*
+ Restore previous eval state
+ */
+ forbidden_function = prev_forbidden;
+ current_tokenizer=previous_tokenizer;
+ block_io = prev_io;
+ eval_level--;
- code=error_code;
- error_code=0;
+ code=error_code;
+ error_code=0;
- job_reap( 0 );
+ job_reap( 0 );
- return code;
+ return code;
}
@@ -2749,16 +2749,16 @@ int parser_t::eval( const wcstring &cmdStr, const io_chain_t &io, enum block_typ
*/
block_type_t parser_get_block_type( const wcstring &cmd )
{
- int i;
-
- for( i=0; block_lookup[i].desc; i++ )
- {
- if( block_lookup[i].name && cmd == block_lookup[i].name )
- {
- return block_lookup[i].type;
- }
- }
- return (block_type_t)-1;
+ int i;
+
+ for( i=0; block_lookup[i].desc; i++ )
+ {
+ if( block_lookup[i].name && cmd == block_lookup[i].name )
+ {
+ return block_lookup[i].type;
+ }
+ }
+ return (block_type_t)-1;
}
/**
@@ -2766,16 +2766,16 @@ block_type_t parser_get_block_type( const wcstring &cmd )
*/
const wchar_t *parser_get_block_command( int type )
{
- int i;
-
- for( i=0; block_lookup[i].desc; i++ )
- {
- if( block_lookup[i].type == type )
- {
- return block_lookup[i].name;
- }
- }
- return 0;
+ int i;
+
+ for( i=0; block_lookup[i].desc; i++ )
+ {
+ if( block_lookup[i].type == type )
+ {
+ return block_lookup[i].name;
+ }
+ }
+ return 0;
}
/**
@@ -2785,349 +2785,349 @@ const wchar_t *parser_get_block_command( int type )
*/
int parser_t::parser_test_argument( const wchar_t *arg, wcstring *out, const wchar_t *prefix, int offset )
{
- wchar_t *unesc;
- wchar_t *pos;
- int err=0;
-
- wchar_t *paran_begin, *paran_end;
- wchar_t *arg_cpy;
- int do_loop = 1;
-
- CHECK( arg, 1 );
-
- arg_cpy = wcsdup( arg );
-
- while( do_loop )
- {
- switch( parse_util_locate_cmdsubst(arg_cpy,
- &paran_begin,
- &paran_end,
- 0 ) )
- {
- case -1:
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- offset,
- L"Mismatched parenthesis" );
- this->print_errors( *out, prefix);
- }
- free( arg_cpy );
- return err;
-
- case 0:
- do_loop = 0;
- break;
-
- case 1:
- {
-
- wchar_t *subst = wcsndup( paran_begin+1, paran_end-paran_begin-1 );
- wcstring tmp;
-
- tmp.append(arg_cpy, paran_begin - arg_cpy);
- tmp.push_back(INTERNAL_SEPARATOR);
+ wchar_t *unesc;
+ wchar_t *pos;
+ int err=0;
+
+ wchar_t *paran_begin, *paran_end;
+ wchar_t *arg_cpy;
+ int do_loop = 1;
+
+ CHECK( arg, 1 );
+
+ arg_cpy = wcsdup( arg );
+
+ while( do_loop )
+ {
+ switch( parse_util_locate_cmdsubst(arg_cpy,
+ &paran_begin,
+ &paran_end,
+ 0 ) )
+ {
+ case -1:
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ offset,
+ L"Mismatched parenthesis" );
+ this->print_errors( *out, prefix);
+ }
+ free( arg_cpy );
+ return err;
+
+ case 0:
+ do_loop = 0;
+ break;
+
+ case 1:
+ {
+
+ wchar_t *subst = wcsndup( paran_begin+1, paran_end-paran_begin-1 );
+ wcstring tmp;
+
+ tmp.append(arg_cpy, paran_begin - arg_cpy);
+ tmp.push_back(INTERNAL_SEPARATOR);
tmp.append(paran_end+1);
-
-// debug( 1, L"%ls -> %ls %ls", arg_cpy, subst, tmp.buff );
-
- err |= parser_t::test( subst, 0, out, prefix );
-
- free( subst );
- free( arg_cpy );
- arg_cpy = wcsdup(tmp.c_str());
-
- /*
- Do _not_ call sb_destroy on this stringbuffer - it's
- buffer is used as the new 'arg_cpy'. It is free'd at
- the end of the loop.
- */
- break;
- }
- }
- }
-
- unesc = unescape( arg_cpy, 1 );
- if( !unesc )
- {
- if( out )
- {
- error( SYNTAX_ERROR,
- offset,
- L"Invalid token '%ls'", arg_cpy );
- print_errors( *out, prefix);
- }
- return 1;
- }
- else
- {
- /*
- Check for invalid variable expansions
- */
- for( pos = unesc; *pos; pos++ )
- {
- switch( *pos )
- {
- case VARIABLE_EXPAND:
- case VARIABLE_EXPAND_SINGLE:
- {
- wchar_t n = *(pos+1);
-
- if( n != VARIABLE_EXPAND &&
- n != VARIABLE_EXPAND_SINGLE &&
- !wcsvarchr(n) )
- {
- err=1;
- if( out )
- {
- expand_variable_error( *this, unesc, pos-unesc, offset );
- print_errors( *out, prefix);
- }
- }
-
- break;
- }
- }
- }
- }
-
- free( arg_cpy );
-
- free( unesc );
- return err;
-
+
+// debug( 1, L"%ls -> %ls %ls", arg_cpy, subst, tmp.buff );
+
+ err |= parser_t::test( subst, 0, out, prefix );
+
+ free( subst );
+ free( arg_cpy );
+ arg_cpy = wcsdup(tmp.c_str());
+
+ /*
+ Do _not_ call sb_destroy on this stringbuffer - it's
+ buffer is used as the new 'arg_cpy'. It is free'd at
+ the end of the loop.
+ */
+ break;
+ }
+ }
+ }
+
+ unesc = unescape( arg_cpy, 1 );
+ if( !unesc )
+ {
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ offset,
+ L"Invalid token '%ls'", arg_cpy );
+ print_errors( *out, prefix);
+ }
+ return 1;
+ }
+ else
+ {
+ /*
+ Check for invalid variable expansions
+ */
+ for( pos = unesc; *pos; pos++ )
+ {
+ switch( *pos )
+ {
+ case VARIABLE_EXPAND:
+ case VARIABLE_EXPAND_SINGLE:
+ {
+ wchar_t n = *(pos+1);
+
+ if( n != VARIABLE_EXPAND &&
+ n != VARIABLE_EXPAND_SINGLE &&
+ !wcsvarchr(n) )
+ {
+ err=1;
+ if( out )
+ {
+ expand_variable_error( *this, unesc, pos-unesc, offset );
+ print_errors( *out, prefix);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ free( arg_cpy );
+
+ free( unesc );
+ return err;
+
}
int parser_t::test_args(const wchar_t * buff, wcstring *out, const wchar_t *prefix )
{
- tokenizer tok;
- tokenizer *previous_tokenizer = current_tokenizer;
- int previous_pos = current_tokenizer_pos;
- int do_loop = 1;
- int err = 0;
-
- CHECK( buff, 1 );
-
- current_tokenizer = &tok;
-
- for( tok_init( &tok, buff, 0 );
- do_loop && tok_has_next( &tok );
- tok_next( &tok ) )
- {
- current_tokenizer_pos = tok_get_pos( &tok );
- switch( tok_last_type( &tok ) )
- {
-
- case TOK_STRING:
- {
- err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
- break;
- }
-
- case TOK_END:
- {
- break;
- }
-
- case TOK_ERROR:
- {
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- TOK_ERR_MSG,
- tok_last(&tok) );
- print_errors( *out, prefix );
- }
- err=1;
- do_loop=0;
- break;
- }
-
- default:
- {
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- UNEXPECTED_TOKEN_ERR_MSG,
- tok_get_desc( tok_last_type(&tok)) );
- print_errors( *out, prefix );
- }
- err=1;
- do_loop=0;
- break;
- }
- }
- }
-
- tok_destroy( &tok );
-
- current_tokenizer=previous_tokenizer;
- current_tokenizer_pos = previous_pos;
-
- error_code=0;
-
- return err;
+ tokenizer tok;
+ tokenizer *previous_tokenizer = current_tokenizer;
+ int previous_pos = current_tokenizer_pos;
+ int do_loop = 1;
+ int err = 0;
+
+ CHECK( buff, 1 );
+
+ current_tokenizer = &tok;
+
+ for( tok_init( &tok, buff, 0 );
+ do_loop && tok_has_next( &tok );
+ tok_next( &tok ) )
+ {
+ current_tokenizer_pos = tok_get_pos( &tok );
+ switch( tok_last_type( &tok ) )
+ {
+
+ case TOK_STRING:
+ {
+ err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
+ break;
+ }
+
+ case TOK_END:
+ {
+ break;
+ }
+
+ case TOK_ERROR:
+ {
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ TOK_ERR_MSG,
+ tok_last(&tok) );
+ print_errors( *out, prefix );
+ }
+ err=1;
+ do_loop=0;
+ break;
+ }
+
+ default:
+ {
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ UNEXPECTED_TOKEN_ERR_MSG,
+ tok_get_desc( tok_last_type(&tok)) );
+ print_errors( *out, prefix );
+ }
+ err=1;
+ do_loop=0;
+ break;
+ }
+ }
+ }
+
+ tok_destroy( &tok );
+
+ current_tokenizer=previous_tokenizer;
+ current_tokenizer_pos = previous_pos;
+
+ error_code=0;
+
+ return err;
}
int parser_t::test( const wchar_t * buff,
- int *block_level,
- wcstring *out,
- const wchar_t *prefix )
+ int *block_level,
+ wcstring *out,
+ const wchar_t *prefix )
{
ASSERT_IS_MAIN_THREAD();
-
- tokenizer tok;
- /*
- Set to one if a command name has been given for the currently
- parsed process specification
- */
- int had_cmd=0;
- int err=0;
- int unfinished = 0;
-
- tokenizer *previous_tokenizer=current_tokenizer;
- int previous_pos=current_tokenizer_pos;
-
- int block_pos[BLOCK_MAX_COUNT] = {};
- block_type_t block_type[BLOCK_MAX_COUNT] = {};
- int count = 0;
- int res = 0;
-
- /*
- Set to 1 if the current command is inside a pipeline
- */
- int is_pipeline = 0;
-
- /*
- Set to one if the currently specified process can not be used inside a pipeline
- */
- int forbid_pipeline = 0;
-
- /*
- Set to one if an additional process specification is needed
- */
- bool needs_cmd = false;
-
- /*
- Counter on the number of arguments this function has encountered
- so far. Is set to -1 when the count is unknown, i.e. after
- encountering an argument that contains substitutions that can
- expand to more/less arguemtns then 1.
- */
- int arg_count=0;
-
- /*
- The currently validated command.
- */
+
+ tokenizer tok;
+ /*
+ Set to one if a command name has been given for the currently
+ parsed process specification
+ */
+ int had_cmd=0;
+ int err=0;
+ int unfinished = 0;
+
+ tokenizer *previous_tokenizer=current_tokenizer;
+ int previous_pos=current_tokenizer_pos;
+
+ int block_pos[BLOCK_MAX_COUNT] = {};
+ block_type_t block_type[BLOCK_MAX_COUNT] = {};
+ int count = 0;
+ int res = 0;
+
+ /*
+ Set to 1 if the current command is inside a pipeline
+ */
+ int is_pipeline = 0;
+
+ /*
+ Set to one if the currently specified process can not be used inside a pipeline
+ */
+ int forbid_pipeline = 0;
+
+ /*
+ Set to one if an additional process specification is needed
+ */
+ bool needs_cmd = false;
+
+ /*
+ Counter on the number of arguments this function has encountered
+ so far. Is set to -1 when the count is unknown, i.e. after
+ encountering an argument that contains substitutions that can
+ expand to more/less arguemtns then 1.
+ */
+ int arg_count=0;
+
+ /*
+ The currently validated command.
+ */
wcstring command;
bool has_command = false;
-
- CHECK( buff, 1 );
-
- if( block_level )
- {
- size_t len = wcslen(buff);
- for( size_t i=0; i<len; i++ )
- {
- block_level[i] = -1;
- }
-
- }
-
- current_tokenizer = &tok;
-
- for( tok_init( &tok, buff, 0 );
- ;
- tok_next( &tok ) )
- {
- current_tokenizer_pos = tok_get_pos( &tok );
-
- int last_type = tok_last_type( &tok );
- int end_of_cmd = 0;
-
- switch( last_type )
- {
- case TOK_STRING:
- {
- if( !had_cmd )
- {
- int mark = tok_get_pos( &tok );
- had_cmd = 1;
- arg_count=0;
-
+
+ CHECK( buff, 1 );
+
+ if( block_level )
+ {
+ size_t len = wcslen(buff);
+ for( size_t i=0; i<len; i++ )
+ {
+ block_level[i] = -1;
+ }
+
+ }
+
+ current_tokenizer = &tok;
+
+ for( tok_init( &tok, buff, 0 );
+ ;
+ tok_next( &tok ) )
+ {
+ current_tokenizer_pos = tok_get_pos( &tok );
+
+ int last_type = tok_last_type( &tok );
+ int end_of_cmd = 0;
+
+ switch( last_type )
+ {
+ case TOK_STRING:
+ {
+ if( !had_cmd )
+ {
+ int mark = tok_get_pos( &tok );
+ had_cmd = 1;
+ arg_count=0;
+
command = tok_last(&tok);
has_command = expand_one(command, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
- if( !has_command )
- {
+ if( !has_command )
+ {
command = L"";
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- ILLEGAL_CMD_ERR_MSG,
- tok_last( &tok ) );
-
- print_errors( *out, prefix );
- }
- break;
- }
-
- if( needs_cmd )
- {
- /*
- end is not a valid command when a followup
- command is needed, such as after 'and' or
- 'while'
- */
- if( contains( command,
- L"end" ) )
- {
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- COND_ERR_MSG );
-
- print_errors( *out, prefix );
- }
- }
-
- needs_cmd = false;
- }
-
- /*
- Decrement block count on end command
- */
- if( command == L"end")
- {
- tok_next( &tok );
- count--;
- tok_set_pos( &tok, mark );
- }
-
- /*
- Store the block level. This needs to be done
- _after_ checking for end commands, but _before_
- checking for block opening commands.
- */
- bool is_else_or_elseif = (command == L"else");
- if( block_level )
- {
- block_level[tok_get_pos( &tok )] = count + (is_else_or_elseif?-1:0);
- }
-
- /*
- Handle block commands
- */
- if( parser_keywords_is_block( command ) )
- {
- if( count >= BLOCK_MAX_COUNT )
- {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ ILLEGAL_CMD_ERR_MSG,
+ tok_last( &tok ) );
+
+ print_errors( *out, prefix );
+ }
+ break;
+ }
+
+ if( needs_cmd )
+ {
+ /*
+ end is not a valid command when a followup
+ command is needed, such as after 'and' or
+ 'while'
+ */
+ if( contains( command,
+ L"end" ) )
+ {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ COND_ERR_MSG );
+
+ print_errors( *out, prefix );
+ }
+ }
+
+ needs_cmd = false;
+ }
+
+ /*
+ Decrement block count on end command
+ */
+ if( command == L"end")
+ {
+ tok_next( &tok );
+ count--;
+ tok_set_pos( &tok, mark );
+ }
+
+ /*
+ Store the block level. This needs to be done
+ _after_ checking for end commands, but _before_
+ checking for block opening commands.
+ */
+ bool is_else_or_elseif = (command == L"else");
+ if( block_level )
+ {
+ block_level[tok_get_pos( &tok )] = count + (is_else_or_elseif?-1:0);
+ }
+
+ /*
+ Handle block commands
+ */
+ if( parser_keywords_is_block( command ) )
+ {
+ if( count >= BLOCK_MAX_COUNT )
+ {
if (out) {
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
@@ -3135,325 +3135,325 @@ int parser_t::test( const wchar_t * buff,
print_errors( *out, prefix );
}
- }
- else
- {
- block_type[count] = parser_get_block_type( command );
- block_pos[count] = current_tokenizer_pos;
- tok_next( &tok );
- count++;
- tok_set_pos( &tok, mark );
- }
- }
-
- /*
- If parser_keywords_is_subcommand is true, the command
- accepts a second command as it's first
- argument. If parser_skip_arguments is true, the
- second argument is optional.
- */
- if( parser_keywords_is_subcommand( command ) && !parser_keywords_skip_arguments(command ) )
- {
- needs_cmd = true;
- had_cmd = 0;
- }
-
- if( contains( command,
- L"or",
- L"and" ) )
- {
- /*
- 'or' and 'and' can not be used inside pipelines
- */
- if( is_pipeline )
- {
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- EXEC_ERR_MSG );
-
- print_errors( *out, prefix );
-
- }
- }
- }
-
- /*
- There are a lot of situations where pipelines
- are forbidden, including when using the exec
- builtin.
- */
- if( parser_is_pipe_forbidden( command ) )
- {
- if( is_pipeline )
- {
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- EXEC_ERR_MSG );
-
- print_errors( *out, prefix );
-
- }
- }
- forbid_pipeline = 1;
- }
-
- /*
- Test that the case builtin is only used directly in a switch block
- */
- if( command == L"case" )
- {
- if( !count || block_type[count-1]!=SWITCH )
- {
- err=1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- INVALID_CASE_ERR_MSG );
-
- print_errors( *out, prefix);
- const wcstring h = builtin_help_get( *this, L"case" );
- if( h.size() )
- append_format( *out, L"%ls", h.c_str() );
- }
- }
- }
-
- /*
- Test that the return bultin is only used within function definitions
- */
- if( command == L"return" )
- {
- int found_func=0;
- int i;
- for( i=count-1; i>=0; i-- )
- {
- if( block_type[i]==FUNCTION_DEF )
- {
- found_func=1;
- break;
- }
- }
-
- if( !found_func )
- {
- /*
- Peek to see if the next argument is
- --help, in which case we'll allow it to
- show the help.
- */
-
- int old_pos = tok_get_pos( &tok );
- int is_help = 0;
-
- tok_next( &tok );
- if( tok_last_type( &tok ) == TOK_STRING )
- {
+ }
+ else
+ {
+ block_type[count] = parser_get_block_type( command );
+ block_pos[count] = current_tokenizer_pos;
+ tok_next( &tok );
+ count++;
+ tok_set_pos( &tok, mark );
+ }
+ }
+
+ /*
+ If parser_keywords_is_subcommand is true, the command
+ accepts a second command as it's first
+ argument. If parser_skip_arguments is true, the
+ second argument is optional.
+ */
+ if( parser_keywords_is_subcommand( command ) && !parser_keywords_skip_arguments(command ) )
+ {
+ needs_cmd = true;
+ had_cmd = 0;
+ }
+
+ if( contains( command,
+ L"or",
+ L"and" ) )
+ {
+ /*
+ 'or' and 'and' can not be used inside pipelines
+ */
+ if( is_pipeline )
+ {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ EXEC_ERR_MSG );
+
+ print_errors( *out, prefix );
+
+ }
+ }
+ }
+
+ /*
+ There are a lot of situations where pipelines
+ are forbidden, including when using the exec
+ builtin.
+ */
+ if( parser_is_pipe_forbidden( command ) )
+ {
+ if( is_pipeline )
+ {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ EXEC_ERR_MSG );
+
+ print_errors( *out, prefix );
+
+ }
+ }
+ forbid_pipeline = 1;
+ }
+
+ /*
+ Test that the case builtin is only used directly in a switch block
+ */
+ if( command == L"case" )
+ {
+ if( !count || block_type[count-1]!=SWITCH )
+ {
+ err=1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ INVALID_CASE_ERR_MSG );
+
+ print_errors( *out, prefix);
+ const wcstring h = builtin_help_get( *this, L"case" );
+ if( h.size() )
+ append_format( *out, L"%ls", h.c_str() );
+ }
+ }
+ }
+
+ /*
+ Test that the return bultin is only used within function definitions
+ */
+ if( command == L"return" )
+ {
+ int found_func=0;
+ int i;
+ for( i=count-1; i>=0; i-- )
+ {
+ if( block_type[i]==FUNCTION_DEF )
+ {
+ found_func=1;
+ break;
+ }
+ }
+
+ if( !found_func )
+ {
+ /*
+ Peek to see if the next argument is
+ --help, in which case we'll allow it to
+ show the help.
+ */
+
+ int old_pos = tok_get_pos( &tok );
+ int is_help = 0;
+
+ tok_next( &tok );
+ if( tok_last_type( &tok ) == TOK_STRING )
+ {
wcstring first_arg = tok_last(&tok);
if (expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3))
- {
- is_help = 1;
- }
- }
-
- tok_set_pos( &tok, old_pos );
-
- if( !is_help )
- {
- err=1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- INVALID_RETURN_ERR_MSG );
- print_errors( *out, prefix );
- }
- }
- }
- }
-
-
- /*
- Test that break and continue are only used within loop blocks
- */
- if( contains( command, L"break", L"continue" ) )
- {
- int found_loop=0;
- int i;
- for( i=count-1; i>=0; i-- )
- {
- if( (block_type[i]==WHILE) ||
- (block_type[i]==FOR) )
- {
- found_loop=1;
- break;
- }
- }
-
- if( !found_loop )
- {
- /*
- Peek to see if the next argument is
- --help, in which case we'll allow it to
- show the help.
- */
-
- int old_pos = tok_get_pos( &tok );
- int is_help = 0;
-
- tok_next( &tok );
- if( tok_last_type( &tok ) == TOK_STRING )
- {
+ {
+ is_help = 1;
+ }
+ }
+
+ tok_set_pos( &tok, old_pos );
+
+ if( !is_help )
+ {
+ err=1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ INVALID_RETURN_ERR_MSG );
+ print_errors( *out, prefix );
+ }
+ }
+ }
+ }
+
+
+ /*
+ Test that break and continue are only used within loop blocks
+ */
+ if( contains( command, L"break", L"continue" ) )
+ {
+ int found_loop=0;
+ int i;
+ for( i=count-1; i>=0; i-- )
+ {
+ if( (block_type[i]==WHILE) ||
+ (block_type[i]==FOR) )
+ {
+ found_loop=1;
+ break;
+ }
+ }
+
+ if( !found_loop )
+ {
+ /*
+ Peek to see if the next argument is
+ --help, in which case we'll allow it to
+ show the help.
+ */
+
+ int old_pos = tok_get_pos( &tok );
+ int is_help = 0;
+
+ tok_next( &tok );
+ if( tok_last_type( &tok ) == TOK_STRING )
+ {
wcstring first_arg = tok_last( &tok );
- if( expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3 ) )
- {
- is_help = 1;
- }
- }
-
- tok_set_pos( &tok, old_pos );
-
- if( !is_help )
- {
- err=1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- INVALID_LOOP_ERR_MSG );
- print_errors( *out, prefix );
- }
- }
- }
- }
-
- /*
- Test that else and else-if are only used directly in an if-block
- */
- if( command == L"else")
- {
- if( !count || block_type[count-1]!=IF )
- {
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- INVALID_ELSE_ERR_MSG,
+ if( expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3 ) )
+ {
+ is_help = 1;
+ }
+ }
+
+ tok_set_pos( &tok, old_pos );
+
+ if( !is_help )
+ {
+ err=1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ INVALID_LOOP_ERR_MSG );
+ print_errors( *out, prefix );
+ }
+ }
+ }
+ }
+
+ /*
+ Test that else and else-if are only used directly in an if-block
+ */
+ if( command == L"else")
+ {
+ if( !count || block_type[count-1]!=IF )
+ {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ INVALID_ELSE_ERR_MSG,
command.c_str());
- print_errors( *out, prefix );
- }
- }
- }
-
- /*
- Test that end is not used when not inside any block
- */
- if( count < 0 )
- {
- err = 1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- INVALID_END_ERR_MSG );
- print_errors( *out, prefix );
- const wcstring h = builtin_help_get( *this, L"end" );
- if( h.size() )
- append_format( *out, L"%ls", h.c_str() );
- }
- }
-
- }
- else
- {
- err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
-
- /* If possible, keep track of number of supplied arguments */
- if( arg_count >= 0 && expand_is_clean( tok_last( &tok ) ) )
- {
- arg_count++;
- }
- else
- {
- arg_count = -1;
- }
-
- if( has_command )
- {
-
- /*
- Try to make sure the second argument to 'for' is 'in'
- */
- if( command == L"for" )
- {
- if( arg_count == 1 )
- {
-
- if( wcsvarname( tok_last( &tok )) )
- {
-
- err = 1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- BUILTIN_FOR_ERR_NAME,
- L"for",
- tok_last( &tok ) );
-
- print_errors( *out, prefix );
- }
- }
-
- }
- else if( arg_count == 2 )
- {
- if( wcscmp( tok_last( &tok ), L"in" ) != 0 )
- {
- err = 1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- BUILTIN_FOR_ERR_IN,
- L"for" );
-
- print_errors( *out, prefix );
- }
- }
- }
- }
+ print_errors( *out, prefix );
+ }
+ }
+ }
+
+ /*
+ Test that end is not used when not inside any block
+ */
+ if( count < 0 )
+ {
+ err = 1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ INVALID_END_ERR_MSG );
+ print_errors( *out, prefix );
+ const wcstring h = builtin_help_get( *this, L"end" );
+ if( h.size() )
+ append_format( *out, L"%ls", h.c_str() );
+ }
+ }
+
+ }
+ else
+ {
+ err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
+
+ /* If possible, keep track of number of supplied arguments */
+ if( arg_count >= 0 && expand_is_clean( tok_last( &tok ) ) )
+ {
+ arg_count++;
+ }
+ else
+ {
+ arg_count = -1;
+ }
+
+ if( has_command )
+ {
+
+ /*
+ Try to make sure the second argument to 'for' is 'in'
+ */
+ if( command == L"for" )
+ {
+ if( arg_count == 1 )
+ {
+
+ if( wcsvarname( tok_last( &tok )) )
+ {
+
+ err = 1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ BUILTIN_FOR_ERR_NAME,
+ L"for",
+ tok_last( &tok ) );
+
+ print_errors( *out, prefix );
+ }
+ }
+
+ }
+ else if( arg_count == 2 )
+ {
+ if( wcscmp( tok_last( &tok ), L"in" ) != 0 )
+ {
+ err = 1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ BUILTIN_FOR_ERR_IN,
+ L"for" );
+
+ print_errors( *out, prefix );
+ }
+ }
+ }
+ }
else if (command == L"else")
{
if (arg_count == 1)
{
/* Any second argument must be "if" */
- if (wcscmp(tok_last(&tok), L"if") != 0)
- {
- err = 1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- BUILTIN_ELSEIF_ERR_ARGUMENT,
- L"else" );
- print_errors( *out, prefix );
- }
- }
+ if (wcscmp(tok_last(&tok), L"if") != 0)
+ {
+ err = 1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ BUILTIN_ELSEIF_ERR_ARGUMENT,
+ L"else" );
+ print_errors( *out, prefix );
+ }
+ }
else
{
/* Successfully detected "else if". Now we need a new command. */
@@ -3462,185 +3462,185 @@ int parser_t::test( const wchar_t * buff,
}
}
}
- }
-
- }
-
- break;
- }
-
- case TOK_REDIRECT_OUT:
- case TOK_REDIRECT_IN:
- case TOK_REDIRECT_APPEND:
- case TOK_REDIRECT_FD:
- case TOK_REDIRECT_NOCLOB:
- {
- if( !had_cmd )
- {
- err = 1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- INVALID_REDIRECTION_ERR_MSG );
- print_errors( *out, prefix );
- }
- }
- break;
- }
-
- case TOK_END:
- {
- if( needs_cmd && !had_cmd )
- {
- err = 1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(&tok)));
- print_errors( *out, prefix );
- }
- }
- needs_cmd = false;
- had_cmd = 0;
- is_pipeline=0;
- forbid_pipeline=0;
- end_of_cmd = 1;
-
- break;
- }
-
- case TOK_PIPE:
- {
- if( !had_cmd )
- {
- err=1;
- if( out )
- {
- if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'|' )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- CMD_OR_ERR_MSG,
- tok_get_desc( tok_last_type(&tok) ) );
-
- }
- else
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(&tok)));
- }
-
- print_errors( *out, prefix );
- }
- }
- else if( forbid_pipeline )
- {
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- EXEC_ERR_MSG );
-
- print_errors( *out, prefix );
- }
- }
- else
- {
- needs_cmd = true;
- is_pipeline=1;
- had_cmd=0;
- end_of_cmd = 1;
-
- }
- break;
- }
-
- case TOK_BACKGROUND:
- {
- if( !had_cmd )
- {
- err = 1;
- if( out )
- {
- if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'&' )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- CMD_AND_ERR_MSG,
- tok_get_desc( tok_last_type(&tok) ) );
-
- }
- else
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- CMD_ERR_MSG,
- tok_get_desc( tok_last_type(&tok)));
- }
-
- print_errors( *out, prefix );
- }
- }
-
- had_cmd = 0;
- end_of_cmd = 1;
-
- break;
- }
-
- case TOK_ERROR:
- default:
- if( tok_get_error( &tok ) == TOK_UNTERMINATED_QUOTE )
- {
- unfinished = 1;
- }
- else
- {
- err = 1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- TOK_ERR_MSG,
- tok_last(&tok) );
-
-
- print_errors( *out, prefix );
- }
- }
-
- break;
- }
-
- if( end_of_cmd )
- {
- if( has_command && command == L"for" )
- {
- if( arg_count >= 0 && arg_count < 2 )
- {
- /*
- Not enough arguments to the for builtin
- */
- err = 1;
-
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- BUILTIN_FOR_ERR_COUNT,
- L"for",
- arg_count );
-
- print_errors( *out, prefix );
- }
- }
- }
+ }
+
+ }
+
+ break;
+ }
+
+ case TOK_REDIRECT_OUT:
+ case TOK_REDIRECT_IN:
+ case TOK_REDIRECT_APPEND:
+ case TOK_REDIRECT_FD:
+ case TOK_REDIRECT_NOCLOB:
+ {
+ if( !had_cmd )
+ {
+ err = 1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ INVALID_REDIRECTION_ERR_MSG );
+ print_errors( *out, prefix );
+ }
+ }
+ break;
+ }
+
+ case TOK_END:
+ {
+ if( needs_cmd && !had_cmd )
+ {
+ err = 1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(&tok)));
+ print_errors( *out, prefix );
+ }
+ }
+ needs_cmd = false;
+ had_cmd = 0;
+ is_pipeline=0;
+ forbid_pipeline=0;
+ end_of_cmd = 1;
+
+ break;
+ }
+
+ case TOK_PIPE:
+ {
+ if( !had_cmd )
+ {
+ err=1;
+ if( out )
+ {
+ if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'|' )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ CMD_OR_ERR_MSG,
+ tok_get_desc( tok_last_type(&tok) ) );
+
+ }
+ else
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(&tok)));
+ }
+
+ print_errors( *out, prefix );
+ }
+ }
+ else if( forbid_pipeline )
+ {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ EXEC_ERR_MSG );
+
+ print_errors( *out, prefix );
+ }
+ }
+ else
+ {
+ needs_cmd = true;
+ is_pipeline=1;
+ had_cmd=0;
+ end_of_cmd = 1;
+
+ }
+ break;
+ }
+
+ case TOK_BACKGROUND:
+ {
+ if( !had_cmd )
+ {
+ err = 1;
+ if( out )
+ {
+ if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'&' )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ CMD_AND_ERR_MSG,
+ tok_get_desc( tok_last_type(&tok) ) );
+
+ }
+ else
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ CMD_ERR_MSG,
+ tok_get_desc( tok_last_type(&tok)));
+ }
+
+ print_errors( *out, prefix );
+ }
+ }
+
+ had_cmd = 0;
+ end_of_cmd = 1;
+
+ break;
+ }
+
+ case TOK_ERROR:
+ default:
+ if( tok_get_error( &tok ) == TOK_UNTERMINATED_QUOTE )
+ {
+ unfinished = 1;
+ }
+ else
+ {
+ err = 1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ TOK_ERR_MSG,
+ tok_last(&tok) );
+
+
+ print_errors( *out, prefix );
+ }
+ }
+
+ break;
+ }
+
+ if( end_of_cmd )
+ {
+ if( has_command && command == L"for" )
+ {
+ if( arg_count >= 0 && arg_count < 2 )
+ {
+ /*
+ Not enough arguments to the for builtin
+ */
+ err = 1;
+
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ BUILTIN_FOR_ERR_COUNT,
+ L"for",
+ arg_count );
+
+ print_errors( *out, prefix );
+ }
+ }
+ }
else if (has_command && command == L"else")
{
if (arg_count == 1)
@@ -3649,133 +3649,133 @@ int parser_t::test( const wchar_t * buff,
err = true;
if (out)
{
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- BUILTIN_ELSEIF_ERR_COUNT,
- L"else",
- arg_count );
-
- print_errors( *out, prefix );
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ BUILTIN_ELSEIF_ERR_COUNT,
+ L"else",
+ arg_count );
+
+ print_errors( *out, prefix );
}
}
}
-
- }
-
- if( !tok_has_next( &tok ) )
- break;
-
- }
-
- if( needs_cmd )
- {
- err=1;
- if( out )
- {
- error( SYNTAX_ERROR,
- tok_get_pos( &tok ),
- COND_ERR_MSG );
-
- print_errors( *out, prefix );
- }
- }
-
-
- if( out && count>0 )
- {
- const wchar_t *cmd;
-
- error( SYNTAX_ERROR,
- block_pos[count-1],
- BLOCK_END_ERR_MSG );
-
- print_errors( *out, prefix );
-
- cmd = parser_get_block_command( block_type[count -1] );
- if( cmd )
- {
- const wcstring h = builtin_help_get( *this, cmd );
- if( h.size() )
- {
- append_format( *out, L"%ls", h.c_str() );
- }
- }
-
-
- }
-
- /*
- Fill in the unset block_level entries. Until now, only places
- where the block level _changed_ have been filled out. This fills
- in the rest.
- */
-
- if( block_level )
- {
- int last_level = 0;
- size_t i, len = wcslen(buff);
- for( i=0; i<len; i++ )
- {
- if( block_level[i] >= 0 )
- {
- last_level = block_level[i];
- /*
- Make all whitespace before a token have the new
- level. This avoid using the wrong indentation level
- if a new line starts with whitespace.
- */
+
+ }
+
+ if( !tok_has_next( &tok ) )
+ break;
+
+ }
+
+ if( needs_cmd )
+ {
+ err=1;
+ if( out )
+ {
+ error( SYNTAX_ERROR,
+ tok_get_pos( &tok ),
+ COND_ERR_MSG );
+
+ print_errors( *out, prefix );
+ }
+ }
+
+
+ if( out && count>0 )
+ {
+ const wchar_t *cmd;
+
+ error( SYNTAX_ERROR,
+ block_pos[count-1],
+ BLOCK_END_ERR_MSG );
+
+ print_errors( *out, prefix );
+
+ cmd = parser_get_block_command( block_type[count -1] );
+ if( cmd )
+ {
+ const wcstring h = builtin_help_get( *this, cmd );
+ if( h.size() )
+ {
+ append_format( *out, L"%ls", h.c_str() );
+ }
+ }
+
+
+ }
+
+ /*
+ Fill in the unset block_level entries. Until now, only places
+ where the block level _changed_ have been filled out. This fills
+ in the rest.
+ */
+
+ if( block_level )
+ {
+ int last_level = 0;
+ size_t i, len = wcslen(buff);
+ for( i=0; i<len; i++ )
+ {
+ if( block_level[i] >= 0 )
+ {
+ last_level = block_level[i];
+ /*
+ Make all whitespace before a token have the new
+ level. This avoid using the wrong indentation level
+ if a new line starts with whitespace.
+ */
size_t prev_char_idx = i;
while (prev_char_idx--)
- {
- if( !wcschr( L" \n\t\r", buff[prev_char_idx] ) )
- break;
- block_level[prev_char_idx] = last_level;
- }
- }
- block_level[i] = last_level;
- }
-
- /*
- Make all trailing whitespace have the block level that the
- validator had at exit. This makes sure a new line is
- correctly indented even if it is empty.
- */
+ {
+ if( !wcschr( L" \n\t\r", buff[prev_char_idx] ) )
+ break;
+ block_level[prev_char_idx] = last_level;
+ }
+ }
+ block_level[i] = last_level;
+ }
+
+ /*
+ Make all trailing whitespace have the block level that the
+ validator had at exit. This makes sure a new line is
+ correctly indented even if it is empty.
+ */
size_t suffix_idx = len;
while (suffix_idx--)
- {
- if( !wcschr( L" \n\t\r", buff[suffix_idx] ) )
- break;
- block_level[suffix_idx] = count;
- }
- }
-
- /*
- Calculate exit status
- */
- if( count!= 0 )
- unfinished = 1;
-
- if( err )
- res |= PARSER_TEST_ERROR;
-
- if( unfinished )
- res |= PARSER_TEST_INCOMPLETE;
-
- /*
- Cleanup
- */
-
- tok_destroy( &tok );
-
- current_tokenizer=previous_tokenizer;
- current_tokenizer_pos = previous_pos;
-
- error_code=0;
-
-
- return res;
-
+ {
+ if( !wcschr( L" \n\t\r", buff[suffix_idx] ) )
+ break;
+ block_level[suffix_idx] = count;
+ }
+ }
+
+ /*
+ Calculate exit status
+ */
+ if( count!= 0 )
+ unfinished = 1;
+
+ if( err )
+ res |= PARSER_TEST_ERROR;
+
+ if( unfinished )
+ res |= PARSER_TEST_INCOMPLETE;
+
+ /*
+ Cleanup
+ */
+
+ tok_destroy( &tok );
+
+ current_tokenizer=previous_tokenizer;
+ current_tokenizer_pos = previous_pos;
+
+ error_code=0;
+
+
+ return res;
+
}
block_t::block_t(block_type_t t) :
diff --git a/parser.h b/parser.h
index ebcfe1c3..1c51323a 100644
--- a/parser.h
+++ b/parser.h
@@ -1,5 +1,5 @@
/** \file parser.h
- The fish parser.
+ The fish parser.
*/
#ifndef FISH_PARSER_H
@@ -21,15 +21,15 @@
*/
struct event_blockage_t
{
- /**
- The types of events to block. This is interpreted as a bitset
- whete the value is 1 for every bit corresponding to a blocked
- event type. For example, if EVENT_VARIABLE type events should
- be blocked, (type & 1<<EVENT_BLOCKED) should be set.
-
- Note that EVENT_ANY can be used to specify any event.
- */
- unsigned int typemask;
+ /**
+ The types of events to block. This is interpreted as a bitset
+ whete the value is 1 for every bit corresponding to a blocked
+ event type. For example, if EVENT_VARIABLE type events should
+ be blocked, (type & 1<<EVENT_BLOCKED) should be set.
+
+ Note that EVENT_ANY can be used to specify any event.
+ */
+ unsigned int typemask;
};
typedef std::list<event_blockage_t> event_blockage_list_t;
@@ -45,30 +45,30 @@ inline bool event_block_list_blocks_type(const event_blockage_list_t &ebls, int
}
-/**
- Types of blocks
+/**
+ Types of blocks
*/
enum block_type_t
{
- WHILE, /**< While loop block */
- FOR, /**< For loop block */
- IF, /**< If block */
- FUNCTION_DEF, /**< Function definition block */
- FUNCTION_CALL, /**< Function invocation block */
- FUNCTION_CALL_NO_SHADOW, /**< Function invocation block with no variable shadowing */
- SWITCH, /**< Switch block */
- FAKE, /**< Fake block */
- SUBST, /**< Command substitution scope */
- TOP, /**< Outermost block */
- BEGIN, /**< Unconditional block */
- SOURCE, /**< Block created by the . (source) builtin */
- EVENT, /**< Block created on event notifier invocation */
- BREAKPOINT, /**< Breakpoint block */
+ WHILE, /**< While loop block */
+ FOR, /**< For loop block */
+ IF, /**< If block */
+ FUNCTION_DEF, /**< Function definition block */
+ FUNCTION_CALL, /**< Function invocation block */
+ FUNCTION_CALL_NO_SHADOW, /**< Function invocation block with no variable shadowing */
+ SWITCH, /**< Switch block */
+ FAKE, /**< Fake block */
+ SUBST, /**< Command substitution scope */
+ TOP, /**< Outermost block */
+ BEGIN, /**< Unconditional block */
+ SOURCE, /**< Block created by the . (source) builtin */
+ EVENT, /**< Block created on event notifier invocation */
+ BREAKPOINT, /**< Breakpoint block */
}
;
/**
- block_t represents a block of commands.
+ block_t represents a block of commands.
*/
struct block_t
{
@@ -77,63 +77,63 @@ struct block_t
block_t(block_type_t t);
private:
- const block_type_t block_type; /**< Type of block. */
+ const block_type_t block_type; /**< Type of block. */
bool made_fake;
public:
block_type_t type() const { return this->made_fake ? FAKE : this->block_type; }
-
+
/** Mark a block as fake; this is used by the return statement. */
void mark_as_fake() { this->made_fake = true; }
- bool skip; /**< Whether execution of the commands in this block should be skipped */
- bool had_command; /**< Set to non-zero once a command has been executed in this block */
- int tok_pos; /**< The start index of the block */
-
- /**
- Status for the current loop block. Can be any of the values from the loop_status enum.
- */
- int loop_status;
+ bool skip; /**< Whether execution of the commands in this block should be skipped */
+ bool had_command; /**< Set to non-zero once a command has been executed in this block */
+ int tok_pos; /**< The start index of the block */
+
+ /**
+ Status for the current loop block. Can be any of the values from the loop_status enum.
+ */
+ int loop_status;
- /**
- The job that is currently evaluated in the specified block.
- */
- job_t *job;
+ /**
+ The job that is currently evaluated in the specified block.
+ */
+ job_t *job;
#if 0
- union
- {
- int while_state; /**< True if the loop condition has not yet been evaluated*/
- wchar_t *for_variable; /**< Name of the variable to loop over */
- int if_state; /**< The state of the if block, can be one of IF_STATE_UNTESTED, IF_STATE_FALSE, IF_STATE_TRUE */
- wchar_t *switch_value; /**< The value to test in a switch block */
- const wchar_t *source_dest; /**< The name of the file to source*/
- event_t *event; /**<The event that triggered this block */
- wchar_t *function_call_name;
- } param1;
+ union
+ {
+ int while_state; /**< True if the loop condition has not yet been evaluated*/
+ wchar_t *for_variable; /**< Name of the variable to loop over */
+ int if_state; /**< The state of the if block, can be one of IF_STATE_UNTESTED, IF_STATE_FALSE, IF_STATE_TRUE */
+ wchar_t *switch_value; /**< The value to test in a switch block */
+ const wchar_t *source_dest; /**< The name of the file to source*/
+ event_t *event; /**<The event that triggered this block */
+ wchar_t *function_call_name;
+ } param1;
#endif
- /**
- Name of file that created this block
- */
- const wchar_t *src_filename;
-
- /**
- Line number where this block was created
- */
- int src_lineno;
-
+ /**
+ Name of file that created this block
+ */
+ const wchar_t *src_filename;
+
+ /**
+ Line number where this block was created
+ */
+ int src_lineno;
+
/** Whether we should pop the environment variable stack when we're popped off of the block stack */
bool wants_pop_env;
-
- /** List of event blocks. */
- event_blockage_list_t event_blocks;
-
+
+ /** List of event blocks. */
+ event_blockage_list_t event_blocks;
+
/**
- Next outer block
- */
- block_t *outer;
-
+ Next outer block
+ */
+ block_t *outer;
+
/** Destructor */
virtual ~block_t();
};
@@ -144,7 +144,7 @@ struct if_block_t : public block_t
bool is_elseif_entry; // whether we're at the beginning of an ELSEIF branch
bool any_branch_taken; // whether the clause of the if statement or any elseif has been found to be true
bool else_evaluated; // whether we've encountered a terminal else block
-
+
if_block_t();
};
@@ -211,11 +211,11 @@ struct breakpoint_block_t : public block_t
/**
Possible states for a loop
*/
-enum loop_status
+enum loop_status
{
- LOOP_NORMAL, /**< Current loop block executed as normal */
- LOOP_BREAK, /**< Current loop block should be removed */
- LOOP_CONTINUE, /**< Current loop block should be skipped */
+ LOOP_NORMAL, /**< Current loop block executed as normal */
+ LOOP_BREAK, /**< Current loop block should be removed */
+ LOOP_CONTINUE, /**< Current loop block should be skipped */
};
@@ -224,9 +224,9 @@ enum loop_status
*/
enum while_status
{
- WHILE_TEST_FIRST, /**< This is the first command of the first lap of a while loop */
- WHILE_TEST_AGAIN, /**< This is not the first lap of the while loop, but it is the first command of the loop */
- WHILE_TESTED, /**< This is not the first command in the loop */
+ WHILE_TEST_FIRST, /**< This is the first command of the first lap of a while loop */
+ WHILE_TEST_AGAIN, /**< This is not the first lap of the while loop, but it is the first command of the loop */
+ WHILE_TESTED, /**< This is not the first command in the loop */
}
;
@@ -234,24 +234,24 @@ enum while_status
/**
Errors that can be generated by the parser
*/
-enum parser_error
+enum parser_error
{
- /**
- No error
- */
- NO_ERR=0,
- /**
- An error in the syntax
- */
- SYNTAX_ERROR,
- /**
- Error occured while evaluating commands
- */
- EVAL_ERROR,
- /**
- Error while evaluating cmdsubst
- */
- CMDSUBST_ERROR,
+ /**
+ No error
+ */
+ NO_ERR=0,
+ /**
+ An error in the syntax
+ */
+ SYNTAX_ERROR,
+ /**
+ Error occured while evaluating commands
+ */
+ EVAL_ERROR,
+ /**
+ Error while evaluating cmdsubst
+ */
+ CMDSUBST_ERROR,
};
enum parser_type_t {
@@ -259,30 +259,30 @@ enum parser_type_t {
PARSER_TYPE_GENERAL,
PARSER_TYPE_FUNCTIONS_ONLY,
PARSER_TYPE_COMPLETIONS_ONLY,
- PARSER_TYPE_ERRORS_ONLY
+ PARSER_TYPE_ERRORS_ONLY
};
struct profile_item_t {
- /**
- Time spent executing the specified command, including parse time for nested blocks.
- */
- int exec;
- /**
- Time spent parsing the specified command, including execution time for command substitutions.
- */
- int parse;
- /**
- The block level of the specified command. nested blocks and command substitutions both increase the block level.
- */
- size_t level;
- /**
- If the execution of this command was skipped.
- */
- int skipped;
- /**
- The command string.
- */
- wcstring cmd;
+ /**
+ Time spent executing the specified command, including parse time for nested blocks.
+ */
+ int exec;
+ /**
+ Time spent parsing the specified command, including execution time for command substitutions.
+ */
+ int parse;
+ /**
+ The block level of the specified command. nested blocks and command substitutions both increase the block level.
+ */
+ size_t level;
+ /**
+ If the execution of this command was skipped.
+ */
+ int skipped;
+ /**
+ The command string.
+ */
+ wcstring cmd;
};
struct tokenizer;
@@ -291,48 +291,48 @@ class parser_t {
private:
enum parser_type_t parser_type;
std::vector<block_t> blocks;
-
+
/** Whether or not we output errors */
const bool show_errors;
-
+
/** Last error code */
int error_code;
-
+
/** Position of last error */
int err_pos;
-
+
/** Description of last error */
wcstring err_buff;
-
+
/** Pointer to the current tokenizer */
tokenizer *current_tokenizer;
-
+
/** String for representing the current line */
wcstring lineinfo;
-
+
/** This is the position of the beginning of the currently parsed command */
int current_tokenizer_pos;
-
+
/** List of called functions, used to help prevent infinite recursion */
wcstring_list_t forbidden_function;
-
+
/** String index where the current job started. */
int job_start_pos;
-
+
/** The jobs associated with this parser */
job_list_t my_job_list;
-
+
/**
Keeps track of how many recursive eval calls have been made. Eval
doesn't call itself directly, recursion happens on blocks and on
command substitutions.
*/
int eval_level;
-
+
/* No copying allowed */
parser_t(const parser_t&);
parser_t& operator=(const parser_t&);
-
+
void parse_job_argument_list( process_t *p, job_t *j, tokenizer *tok, std::vector<completion_t>&, bool );
int parse_job( process_t *p, job_t *j, tokenizer *tok );
void skipped_exec( job_t * j );
@@ -340,10 +340,10 @@ class parser_t {
int parser_test_argument( const wchar_t *arg, wcstring *out, const wchar_t *prefix, int offset );
void print_errors( wcstring &target, const wchar_t *prefix );
void print_errors_stderr();
-
+
public:
std::vector<profile_item_t> profile_items;
-
+
/**
Returns the name of the currently evaluated function if we are
currently evaluating a function, null otherwise. This is tested by
@@ -351,27 +351,27 @@ class parser_t {
type FUNCTION_CALL.
*/
const wchar_t *is_function() const;
-
+
/** Get the "principal" parser, whatever that is */
static parser_t &principal_parser();
-
+
/** Indicates that execution of all blocks in the principal parser should stop.
This is called from signal handlers!
*/
static void skip_all_blocks();
-
+
/** Create a parser of the given type */
parser_t(enum parser_type_t type, bool show_errors);
-
+
/** The current innermost block, allocated with new */
block_t *current_block;
-
+
/** Global event blocks */
event_blockage_list_t global_event_blocks;
-
+
/** Current block level io redirections */
io_chain_t block_io;
-
+
/**
Evaluate the expressions contained in cmd.
@@ -382,7 +382,7 @@ class parser_t {
\return 0 on success, 1 otherwise
*/
int eval( const wcstring &cmdStr, const io_chain_t &io, enum block_type_t block_type );
-
+
/**
Evaluate line as a list of parameters, i.e. tokenize it and perform parameter expansion and cmdsubst execution on the tokens.
The output is inserted into output, and should be freed by the caller.
@@ -390,24 +390,24 @@ class parser_t {
\param line Line to evaluate
\param output List to insert output to
*/
- /**
- \param line Line to evaluate
- \param output List to insert output to
- */
- int eval_args( const wchar_t *line, std::vector<completion_t> &output );
+ /**
+ \param line Line to evaluate
+ \param output List to insert output to
+ */
+ int eval_args( const wchar_t *line, std::vector<completion_t> &output );
/**
- Sets the current evaluation error. This function should only be used by libraries that are called by
+ Sets the current evaluation error. This function should only be used by libraries that are called by
\param ec The new error code
\param p The character offset at which the error occured
\param str The printf-style error message filter
*/
void error( int ec, int p, const wchar_t *str, ... );
-
+
/**
Returns a string describing the current parser pisition in the format 'FILENAME (line LINE_NUMBER): LINE'.
- Example:
+ Example:
init.fish (line 127): ls|grep pancake
*/
@@ -415,7 +415,7 @@ class parser_t {
/** Returns the current line number */
int get_lineno() const;
-
+
/** Returns the line number for the character at the given index */
int line_number_of_character_at_offset(size_t idx) const;
@@ -430,7 +430,7 @@ class parser_t {
/** Get the string currently parsed */
const wchar_t *get_buffer() const;
-
+
/** Get the list of jobs */
job_list_t &job_list() { return my_job_list; }
@@ -445,16 +445,16 @@ class parser_t {
/** Create a job */
job_t *job_create();
-
+
/** Removes a job */
bool job_remove(job_t *job);
-
+
/** Promotes a job to the front of the list */
void job_promote(job_t *job);
-
+
/** Return the job with the specified job id. If id is 0 or less, return the last job used. */
job_t *job_get(int job_id);
-
+
/** Returns the job with the given pid */
job_t *job_get_from_pid( int pid );
@@ -502,7 +502,7 @@ class parser_t {
void destroy();
/**
- This function checks if the specified string is a help option.
+ This function checks if the specified string is a help option.
\param s the string to test
\param min_match is the minimum number of characters that must match in a long style option, i.e. the longest common prefix between --help and any other option. If less than 3, 3 will be assumed.
diff --git a/parser_keywords.cpp b/parser_keywords.cpp
index efc2ff6e..762bb6f2 100644
--- a/parser_keywords.cpp
+++ b/parser_keywords.cpp
@@ -16,8 +16,8 @@ Functions having to do with parser keywords, like testing if a function is a blo
bool parser_keywords_is_switch( const wcstring &cmd )
{
- if (cmd == L"--") {
- return ARG_SKIP;
+ if (cmd == L"--") {
+ return ARG_SKIP;
} else if (! cmd.empty() && cmd.at(0) == L'-') {
return ARG_SWITCH;
} else {
@@ -27,49 +27,49 @@ bool parser_keywords_is_switch( const wcstring &cmd )
bool parser_keywords_skip_arguments( const wcstring &cmd )
{
- return contains( cmd,
- L"else",
- L"begin" );
+ return contains( cmd,
+ L"else",
+ L"begin" );
}
bool parser_keywords_is_subcommand( const wcstring &cmd )
{
- return parser_keywords_skip_arguments( cmd ) ||
- contains( cmd,
- L"command",
- L"builtin",
- L"while",
- L"exec",
- L"if",
- L"and",
- L"or",
- L"not" );
-
+ return parser_keywords_skip_arguments( cmd ) ||
+ contains( cmd,
+ L"command",
+ L"builtin",
+ L"while",
+ L"exec",
+ L"if",
+ L"and",
+ L"or",
+ L"not" );
+
}
bool parser_keywords_is_block( const wcstring &word)
{
- return contains( word,
- L"for",
- L"while",
- L"if",
- L"function",
- L"switch",
- L"begin" );
+ return contains( word,
+ L"for",
+ L"while",
+ L"if",
+ L"function",
+ L"switch",
+ L"begin" );
}
bool parser_keywords_is_reserved( const wcstring &word)
{
- return parser_keywords_is_block(word) ||
- parser_keywords_is_subcommand( word ) ||
- contains( word,
- L"end",
- L"case",
- L"else",
- L"return",
- L"continue",
- L"break" );
+ return parser_keywords_is_block(word) ||
+ parser_keywords_is_subcommand( word ) ||
+ contains( word,
+ L"end",
+ L"case",
+ L"else",
+ L"return",
+ L"continue",
+ L"break" );
}
diff --git a/parser_keywords.h b/parser_keywords.h
index 5bad85aa..d5978c4a 100644
--- a/parser_keywords.h
+++ b/parser_keywords.h
@@ -9,11 +9,11 @@ Functions having to do with parser keywords, like testing if a function is a blo
/**
Return values for parser_keywords_is_switch()
*/
-enum
+enum
{
- ARG_NON_SWITCH,
- ARG_SWITCH,
- ARG_SKIP
+ ARG_NON_SWITCH,
+ ARG_SWITCH,
+ ARG_SKIP
};
diff --git a/path.cpp b/path.cpp
index 2ba524ef..df7a9596 100644
--- a/path.cpp
+++ b/path.cpp
@@ -25,110 +25,110 @@
static bool path_get_path_core(const wcstring &cmd, wcstring *out_path, const env_var_t &bin_path_var)
{
- int err = ENOENT;
-
- debug( 3, L"path_get_path( '%ls' )", cmd.c_str() );
-
+ int err = ENOENT;
+
+ debug( 3, L"path_get_path( '%ls' )", cmd.c_str() );
+
/* If the command has a slash, it must be a full path */
- if (cmd.find(L'/') != wcstring::npos)
- {
- if( waccess( cmd, X_OK )==0 )
- {
- struct stat buff;
- if(wstat( cmd, &buff ))
- {
- return false;
- }
-
- if( S_ISREG(buff.st_mode) )
+ if (cmd.find(L'/') != wcstring::npos)
+ {
+ if( waccess( cmd, X_OK )==0 )
+ {
+ struct stat buff;
+ if(wstat( cmd, &buff ))
+ {
+ return false;
+ }
+
+ if( S_ISREG(buff.st_mode) )
{
- if (out_path)
+ if (out_path)
out_path->assign(cmd);
return true;
}
- else
- {
- errno = EACCES;
- return false;
- }
- }
- else
- {
- struct stat buff;
- wstat( cmd, &buff );
- return false;
- }
-
- }
- else
- {
+ else
+ {
+ errno = EACCES;
+ return false;
+ }
+ }
+ else
+ {
+ struct stat buff;
+ wstat( cmd, &buff );
+ return false;
+ }
+
+ }
+ else
+ {
wcstring bin_path;
- if (! bin_path_var.missing())
+ if (! bin_path_var.missing())
{
bin_path = bin_path_var;
}
else
- {
- 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";
- }
- }
-
+ {
+ 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(bin_path, ARRAY_SEP_STR);
- while (tokenizer.next(nxt_path))
- {
+ while (tokenizer.next(nxt_path))
+ {
if (nxt_path.empty())
continue;
append_path_component(nxt_path, cmd);
- if( waccess( nxt_path, X_OK )==0 )
- {
- struct stat buff;
- if( wstat( nxt_path, &buff )==-1 )
- {
- if( errno != EACCES )
- {
- wperror( L"stat" );
- }
- continue;
- }
- if( S_ISREG(buff.st_mode) )
- {
+ if( waccess( nxt_path, X_OK )==0 )
+ {
+ struct stat buff;
+ if( wstat( nxt_path, &buff )==-1 )
+ {
+ if( errno != EACCES )
+ {
+ wperror( L"stat" );
+ }
+ continue;
+ }
+ if( S_ISREG(buff.st_mode) )
+ {
if (out_path)
out_path->swap(nxt_path);
- return true;
- }
- err = EACCES;
-
- }
- else
- {
- switch( errno )
- {
- case ENOENT:
- case ENAMETOOLONG:
- case EACCES:
- case ENOTDIR:
- break;
- default:
- {
- debug( 1,
+ return true;
+ }
+ err = EACCES;
+
+ }
+ else
+ {
+ switch( errno )
+ {
+ case ENOENT:
+ case ENAMETOOLONG:
+ case EACCES:
+ case ENOTDIR:
+ break;
+ default:
+ {
+ debug( 1,
MISSING_COMMAND_ERR_MSG,
nxt_path.c_str() );
- wperror( L"access" );
- }
- }
- }
- }
- }
-
- errno = err;
- return false;
+ wperror( L"access" );
+ }
+ }
+ }
+ }
+ }
+
+ errno = err;
+ return false;
}
bool path_get_path(const wcstring &cmd, wcstring *out_path, const env_vars_snapshot_t &vars)
@@ -143,94 +143,94 @@ bool path_get_path(const wcstring &cmd, wcstring *out_path)
bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env_var_t &cdpath)
{
- wchar_t *res = 0;
- int err = ENOENT;
+ wchar_t *res = 0;
+ int err = ENOENT;
bool success = false;
-
+
const wchar_t *const dir = dir_str.c_str();
- if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
- {
- struct stat buf;
- if( wstat( dir, &buf ) == 0 )
- {
- if( S_ISDIR(buf.st_mode) )
- {
- result = dir_str;
+ if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
+ {
+ struct stat buf;
+ if( wstat( dir, &buf ) == 0 )
+ {
+ if( S_ISDIR(buf.st_mode) )
+ {
+ result = dir_str;
success = true;
- }
- else
- {
- err = ENOTDIR;
- }
-
- }
- }
- else
- {
-
+ }
+ else
+ {
+ err = ENOTDIR;
+ }
+
+ }
+ }
+ else
+ {
+
wcstring path = L".";
-
+
// Respect CDPATH
env_var_t cdpath = env_get_string(L"CDPATH");
if (! cdpath.missing_or_empty()) {
path = cdpath.c_str();
}
-
+
wcstokenizer tokenizer(path, ARRAY_SEP_STR);
wcstring next_path;
while (tokenizer.next(next_path))
{
expand_tilde(next_path);
if (next_path.size() == 0) continue;
-
+
wcstring whole_path = next_path;
append_path_component(whole_path, dir);
-
- struct stat buf;
- if( wstat( whole_path, &buf ) == 0 )
- {
- if( S_ISDIR(buf.st_mode) )
- {
+
+ struct stat buf;
+ if( wstat( whole_path, &buf ) == 0 )
+ {
+ if( S_ISDIR(buf.st_mode) )
+ {
result = whole_path;
success = true;
- break;
- }
- else
- {
- err = ENOTDIR;
- }
- }
- else
- {
- if( lwstat( whole_path, &buf ) == 0 )
- {
- err = EROTTEN;
- }
- }
+ break;
+ }
+ else
+ {
+ err = ENOTDIR;
+ }
+ }
+ else
+ {
+ if( lwstat( whole_path, &buf ) == 0 )
+ {
+ err = EROTTEN;
+ }
+ }
}
}
-
-
- if( !success )
- {
- errno = err;
- }
-
- return res;
+
+
+ if( !success )
+ {
+ errno = err;
+ }
+
+ return res;
}
bool path_get_cdpath(const wcstring &dir, wcstring *out, const wchar_t *wd, const env_vars_snapshot_t &env_vars)
{
- int err = ENOENT;
- if (dir.empty())
- return false;
-
+ int err = ENOENT;
+ if (dir.empty())
+ return false;
+
if (wd)
{
size_t len = wcslen(wd);
assert(wd[len - 1] == L'/');
}
-
+
wcstring_list_t paths;
if (dir.at(0) == L'/') {
/* Absolute path */
@@ -254,7 +254,7 @@ bool path_get_cdpath(const wcstring &dir, wcstring *out, const wchar_t *wd, cons
wcstokenizer tokenizer(path, ARRAY_SEP_STR);
while (tokenizer.next(nxt_path))
{
-
+
if (nxt_path == L"." && wd != NULL) {
// nxt_path is just '.', and we have a working directory, so use the wd instead
// TODO: if nxt_path starts with ./ we need to replace the . with the wd
@@ -262,39 +262,39 @@ bool path_get_cdpath(const wcstring &dir, wcstring *out, const wchar_t *wd, cons
}
expand_tilde(nxt_path);
-// debug( 2, L"woot %ls\n", expanded_path.c_str() );
+// debug( 2, L"woot %ls\n", expanded_path.c_str() );
if (nxt_path.empty())
continue;
-
+
wcstring whole_path = nxt_path;
append_path_component(whole_path, dir);
paths.push_back(whole_path);
}
}
-
+
bool success = false;
for (wcstring_list_t::const_iterator iter = paths.begin(); iter != paths.end(); ++iter) {
- struct stat buf;
+ struct stat buf;
const wcstring &dir = *iter;
- if( wstat( dir, &buf ) == 0 )
- {
- if( S_ISDIR(buf.st_mode) )
- {
+ if( wstat( dir, &buf ) == 0 )
+ {
+ if( S_ISDIR(buf.st_mode) )
+ {
success = true;
if (out)
out->assign(dir);
break;
- }
- else
- {
- err = ENOTDIR;
- }
- }
+ }
+ else
+ {
+ err = ENOTDIR;
+ }
}
-
+ }
+
if (! success)
- errno = err;
+ errno = err;
return success;
}
@@ -302,7 +302,7 @@ bool path_can_be_implicit_cd(const wcstring &path, wcstring *out_path, const wch
{
wcstring exp_path = path;
expand_tilde(exp_path);
-
+
bool result = false;
if (string_prefixes_string(L"/", exp_path) ||
string_prefixes_string(L"./", exp_path) ||
@@ -317,41 +317,41 @@ bool path_can_be_implicit_cd(const wcstring &path, wcstring *out_path, const wch
bool path_get_config(wcstring &path)
{
- int done = 0;
- wcstring res;
-
- const env_var_t xdg_dir = env_get_string( L"XDG_CONFIG_HOME" );
- if( ! xdg_dir.missing() )
- {
- res = xdg_dir + L"/fish";
- if( !create_directory( res ) )
- {
- done = 1;
- }
- }
- else
- {
- const env_var_t home = env_get_string( L"HOME" );
- if( ! home.missing() )
- {
- res = home + L"/.config/fish";
- if( !create_directory( res ) )
- {
- done = 1;
- }
- }
- }
-
- if( done )
- {
+ int done = 0;
+ wcstring res;
+
+ const env_var_t xdg_dir = env_get_string( L"XDG_CONFIG_HOME" );
+ if( ! xdg_dir.missing() )
+ {
+ res = xdg_dir + L"/fish";
+ if( !create_directory( res ) )
+ {
+ done = 1;
+ }
+ }
+ else
+ {
+ const env_var_t home = env_get_string( L"HOME" );
+ if( ! home.missing() )
+ {
+ res = home + L"/.config/fish";
+ if( !create_directory( res ) )
+ {
+ done = 1;
+ }
+ }
+ }
+
+ if( done )
+ {
path = res;
return true;
- }
- else
- {
- debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
- return false;
- }
+ }
+ else
+ {
+ debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
+ return false;
+ }
}
@@ -375,7 +375,7 @@ void path_make_canonical( wcstring &path )
size = path.size();
replace_all(path, L"//", L"/");
} while (path.size() != size);
-
+
/* Remove trailing slashes, except don't remove the first one */
while (size-- > 1) {
if (path.at(size) != L'/')
@@ -410,7 +410,7 @@ bool path_is_valid(const wcstring &path, const wcstring &working_directory)
bool paths_are_same_file(const wcstring &path1, const wcstring &path2) {
if (path1 == path2)
return true;
-
+
struct stat s1, s2;
if (wstat(path1, &s1) == 0 && wstat(path2, &s2) == 0) {
return s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev;
diff --git a/path.h b/path.h
index 2d3cf83d..aa49b266 100644
--- a/path.h
+++ b/path.h
@@ -1,9 +1,9 @@
/** \file path.h
- Directory utilities. This library contains functions for locating
- configuration directories, for testing if a command with a given
- name can be found in the PATH, and various other path-related
- issues.
+ Directory utilities. This library contains functions for locating
+ configuration directories, for testing if a command with a given
+ name can be found in the PATH, and various other path-related
+ issues.
*/
#ifndef FISH_PATH_H
@@ -27,7 +27,7 @@ bool path_get_config(wcstring &path);
/**
Finds the full path of an executable. Returns YES if successful.
-
+
\param cmd The name of the executable.
\param output_or_NULL If non-NULL, store the full path.
\param vars The environment variables snapshot to use
@@ -42,14 +42,14 @@ bool path_get_path(const wcstring &cmd,
variable as a list of base directories for relative paths. The
returned string is allocated using halloc and the specified
context.
-
+
If no valid path is found, null is returned and errno is set to
ENOTDIR if at least one such path was found, but it did not point
to a directory, EROTTEN if a arotten symbolic link was found, or
ENOENT if no file of the specified name was found. If both a rotten
symlink and a file are found, it is undefined which error status
will be returned.
-
+
\param dir The name of the directory.
\param out_or_NULL If non-NULL, return the path to the resolved directory
\param wd The working directory, or NULL to use the default. The working directory should have a slash appended at the end.
diff --git a/postfork.cpp b/postfork.cpp
index 4379ca2d..2609831f 100644
--- a/postfork.cpp
+++ b/postfork.cpp
@@ -1,6 +1,6 @@
/** \file postfork.cpp
- Functions that we may safely call after fork().
+ Functions that we may safely call after fork().
*/
#include <fcntl.h>
@@ -44,61 +44,61 @@ static void debug_safe_int(int level, const char *format, int val)
// PCA These calls to debug are rather sketchy because they may allocate memory. Fortunately they only occur if an error occurs.
int set_child_group( job_t *j, process_t *p, int print_errors )
{
- int res = 0;
-
- if( job_get_flag( j, JOB_CONTROL ) )
- {
- if (!j->pgid)
- {
- j->pgid = p->pid;
- }
-
- if( setpgid (p->pid, j->pgid) )
- {
- if( getpgid( p->pid) != j->pgid && print_errors )
- {
+ int res = 0;
+
+ if( job_get_flag( j, JOB_CONTROL ) )
+ {
+ if (!j->pgid)
+ {
+ j->pgid = p->pid;
+ }
+
+ if( setpgid (p->pid, j->pgid) )
+ {
+ if( getpgid( p->pid) != j->pgid && print_errors )
+ {
char pid_buff[128];
char job_id_buff[128];
char getpgid_buff[128];
char job_pgid_buff[128];
-
+
format_long_safe(pid_buff, p->pid);
format_long_safe(job_id_buff, j->job_id);
format_long_safe(getpgid_buff, getpgid( p->pid));
format_long_safe(job_pgid_buff, j->pgid);
-
- debug_safe( 1,
- "Could not send process %s, '%s' in job %s, '%s' from group %s to group %s",
- pid_buff,
- p->argv0_cstr(),
- job_id_buff,
- j->command_cstr(),
- getpgid_buff,
- job_pgid_buff );
-
- wperror( L"setpgid" );
- res = -1;
- }
- }
- }
- else
- {
- j->pgid = getpid();
- }
-
- if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
- {
- if( tcsetpgrp (0, j->pgid) && print_errors )
- {
+
+ debug_safe( 1,
+ "Could not send process %s, '%s' in job %s, '%s' from group %s to group %s",
+ pid_buff,
+ p->argv0_cstr(),
+ job_id_buff,
+ j->command_cstr(),
+ getpgid_buff,
+ job_pgid_buff );
+
+ wperror( L"setpgid" );
+ res = -1;
+ }
+ }
+ }
+ else
+ {
+ j->pgid = getpid();
+ }
+
+ if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
+ {
+ if( tcsetpgrp (0, j->pgid) && print_errors )
+ {
char job_id_buff[128];
format_long_safe(job_id_buff, j->job_id);
- debug_safe( 1, "Could not send job %s ('%s') to foreground", job_id_buff, j->command_cstr() );
- wperror( L"tcsetpgrp" );
- res = -1;
- }
- }
+ debug_safe( 1, "Could not send job %s ('%s') to foreground", job_id_buff, j->command_cstr() );
+ wperror( L"tcsetpgrp" );
+ res = -1;
+ }
+ }
- return res;
+ return res;
}
/** Make sure the fd used by each redirection is not used by a pipe. */
@@ -108,7 +108,7 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
for (size_t i = 0; i < max; i++)
{
int fd_to_free = io_chain.at(i)->fd;
-
+
/* We only have to worry about fds beyond the three standard ones */
if (fd_to_free <= 2)
continue;
@@ -120,14 +120,14 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
io_data_t *possible_conflict = io_chain.at(j);
if (possible_conflict->io_mode != IO_PIPE && possible_conflict->io_mode != IO_BUFFER)
continue;
-
+
/* If the pipe is a conflict, dup it to some other value */
for (int k=0; k<2; k++)
{
/* If it's not a conflict, we don't care */
if (possible_conflict->param1.pipe_fd[k] != fd_to_free)
continue;
-
+
/* Repeat until we have a replacement fd */
int replacement_fd = -1;
while (replacement_fd < 0)
@@ -143,7 +143,7 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
possible_conflict->param1.pipe_fd[k] = replacement_fd;
}
}
- }
+ }
}
@@ -162,149 +162,149 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
static int handle_child_io( io_chain_t &io_chain )
{
- close_unused_internal_pipes( io_chain );
+ close_unused_internal_pipes( io_chain );
free_redirected_fds_from_pipes(io_chain);
- for (size_t idx = 0; idx < io_chain.size(); idx++)
- {
+ for (size_t idx = 0; idx < io_chain.size(); idx++)
+ {
io_data_t *io = io_chain.at(idx);
- int tmp;
-
- if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
- {
- continue;
- }
-
- switch( io->io_mode )
- {
- case IO_CLOSE:
- {
- if( close(io->fd) )
- {
- debug_safe_int( 0, "Failed to close file descriptor %s", io->fd );
- wperror( L"close" );
- }
- break;
- }
-
- case IO_FILE:
- {
- // Here we definitely do not want to set CLO_EXEC because our child needs access
- if( (tmp=open( io->filename_cstr,
- io->param2.flags, OPEN_MASK ) )==-1 )
- {
- if( ( io->param2.flags & O_EXCL ) &&
- ( errno ==EEXIST ) )
- {
- debug_safe( 1, NOCLOB_ERROR, io->filename_cstr );
- }
- else
- {
- debug_safe( 1, FILE_ERROR, io->filename_cstr );
- perror( "open" );
- }
-
- return -1;
- }
- else if( tmp != io->fd)
- {
- /*
- This call will sometimes fail, but that is ok,
- this is just a precausion.
- */
- close(io->fd);
-
- if(dup2( tmp, io->fd ) == -1 )
- {
- debug_safe_int( 1, FD_ERROR, io->fd );
- perror( "dup2" );
- return -1;
- }
- exec_close( tmp );
- }
- break;
- }
-
- case IO_FD:
- {
- /*
- This call will sometimes fail, but that is ok,
- this is just a precausion.
- */
- close(io->fd);
-
- if( dup2( io->param1.old_fd, io->fd ) == -1 )
- {
- debug_safe_int( 1, FD_ERROR, io->fd );
- wperror( L"dup2" );
- return -1;
- }
- break;
- }
-
- case IO_BUFFER:
- case IO_PIPE:
- {
+ int tmp;
+
+ if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
+ {
+ continue;
+ }
+
+ switch( io->io_mode )
+ {
+ case IO_CLOSE:
+ {
+ if( close(io->fd) )
+ {
+ debug_safe_int( 0, "Failed to close file descriptor %s", io->fd );
+ wperror( L"close" );
+ }
+ break;
+ }
+
+ case IO_FILE:
+ {
+ // Here we definitely do not want to set CLO_EXEC because our child needs access
+ if( (tmp=open( io->filename_cstr,
+ io->param2.flags, OPEN_MASK ) )==-1 )
+ {
+ if( ( io->param2.flags & O_EXCL ) &&
+ ( errno ==EEXIST ) )
+ {
+ debug_safe( 1, NOCLOB_ERROR, io->filename_cstr );
+ }
+ else
+ {
+ debug_safe( 1, FILE_ERROR, io->filename_cstr );
+ perror( "open" );
+ }
+
+ return -1;
+ }
+ else if( tmp != io->fd)
+ {
+ /*
+ This call will sometimes fail, but that is ok,
+ this is just a precausion.
+ */
+ close(io->fd);
+
+ if(dup2( tmp, io->fd ) == -1 )
+ {
+ debug_safe_int( 1, FD_ERROR, io->fd );
+ perror( "dup2" );
+ return -1;
+ }
+ exec_close( tmp );
+ }
+ break;
+ }
+
+ case IO_FD:
+ {
+ /*
+ This call will sometimes fail, but that is ok,
+ this is just a precausion.
+ */
+ close(io->fd);
+
+ if( dup2( io->param1.old_fd, io->fd ) == -1 )
+ {
+ debug_safe_int( 1, FD_ERROR, io->fd );
+ wperror( L"dup2" );
+ return -1;
+ }
+ break;
+ }
+
+ case IO_BUFFER:
+ case IO_PIPE:
+ {
/* If write_pipe_idx is 0, it means we're connecting to the read end (first pipe fd). If it's 1, we're connecting to the write end (second pipe fd). */
- unsigned int write_pipe_idx = (io->is_input ? 0 : 1);
+ unsigned int write_pipe_idx = (io->is_input ? 0 : 1);
/*
- debug( 0,
- L"%ls %ls on fd %d (%d %d)",
- write_pipe?L"write":L"read",
- (io->io_mode == IO_BUFFER)?L"buffer":L"pipe",
- io->fd,
- io->param1.pipe_fd[0],
- io->param1.pipe_fd[1]);
+ debug( 0,
+ L"%ls %ls on fd %d (%d %d)",
+ write_pipe?L"write":L"read",
+ (io->io_mode == IO_BUFFER)?L"buffer":L"pipe",
+ io->fd,
+ io->param1.pipe_fd[0],
+ io->param1.pipe_fd[1]);
*/
- if( dup2( io->param1.pipe_fd[write_pipe_idx], io->fd ) != io->fd )
- {
- debug_safe( 1, LOCAL_PIPE_ERROR );
- perror( "dup2" );
- return -1;
- }
-
+ if( dup2( io->param1.pipe_fd[write_pipe_idx], io->fd ) != io->fd )
+ {
+ debug_safe( 1, LOCAL_PIPE_ERROR );
+ perror( "dup2" );
+ return -1;
+ }
+
if (io->param1.pipe_fd[0] >= 0)
exec_close( io->param1.pipe_fd[0]);
if (io->param1.pipe_fd[1] >= 0)
exec_close( io->param1.pipe_fd[1]);
- break;
- }
-
- }
- }
-
- return 0;
-
+ break;
+ }
+
+ }
+ }
+
+ return 0;
+
}
int setup_child_process( job_t *j, process_t *p )
{
- bool ok=true;
-
- if( p )
- {
- ok = (0 == set_child_group( j, p, 1 ));
- }
-
- if( ok )
- {
- ok = (0 == handle_child_io( j->io ));
- if( p != 0 && ! ok )
- {
- exit_without_destructors( 1 );
- }
- }
-
- /* Set the handling for job control signals back to the default. */
- if( ok )
- {
- signal_reset_handlers();
- }
-
- /* Remove all signal blocks */
- signal_unblock();
-
- return ok ? 0 : -1;
+ bool ok=true;
+
+ if( p )
+ {
+ ok = (0 == set_child_group( j, p, 1 ));
+ }
+
+ if( ok )
+ {
+ ok = (0 == handle_child_io( j->io ));
+ if( p != 0 && ! ok )
+ {
+ exit_without_destructors( 1 );
+ }
+ }
+
+ /* Set the handling for job control signals back to the default. */
+ if( ok )
+ {
+ signal_reset_handlers();
+ }
+
+ /* Remove all signal blocks */
+ signal_unblock();
+
+ return ok ? 0 : -1;
}
int g_fork_count = 0;
@@ -318,47 +318,47 @@ int g_fork_count = 0;
pid_t execute_fork(bool wait_for_threads_to_die)
{
ASSERT_IS_MAIN_THREAD();
-
+
if (wait_for_threads_to_die) {
/* Make sure we have no outstanding threads before we fork. This is a pretty sketchy thing to do here, both because exec.cpp shouldn't have to know about iothreads, and because the completion handlers may do unexpected things. */
iothread_drain_all();
}
-
- pid_t pid;
- struct timespec pollint;
- int i;
-
+
+ pid_t pid;
+ struct timespec pollint;
+ int i;
+
g_fork_count++;
-
- for( i=0; i<FORK_LAPS; i++ )
- {
- pid = fork();
- if( pid >= 0)
- {
- return pid;
- }
-
- if( errno != EAGAIN )
- {
- break;
- }
-
- pollint.tv_sec = 0;
- pollint.tv_nsec = FORK_SLEEP_TIME;
-
- /*
- Don't sleep on the final lap - sleeping might change the
- value of errno, which will break the error reporting below.
- */
- if( i != FORK_LAPS-1 )
- {
- nanosleep( &pollint, NULL );
- }
- }
-
- debug_safe( 0, FORK_ERROR );
- wperror (L"fork");
- FATAL_EXIT();
+
+ for( i=0; i<FORK_LAPS; i++ )
+ {
+ pid = fork();
+ if( pid >= 0)
+ {
+ return pid;
+ }
+
+ if( errno != EAGAIN )
+ {
+ break;
+ }
+
+ pollint.tv_sec = 0;
+ pollint.tv_nsec = FORK_SLEEP_TIME;
+
+ /*
+ Don't sleep on the final lap - sleeping might change the
+ value of errno, which will break the error reporting below.
+ */
+ if( i != FORK_LAPS-1 )
+ {
+ nanosleep( &pollint, NULL );
+ }
+ }
+
+ debug_safe( 0, FORK_ERROR );
+ wperror (L"fork");
+ FATAL_EXIT();
return 0;
}
@@ -369,18 +369,18 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
if (posix_spawnattr_init(attr) != 0) {
return false;
}
-
+
if (posix_spawn_file_actions_init(actions) != 0) {
posix_spawnattr_destroy(attr);
return false;
}
-
+
bool should_set_parent_group_id = false;
int desired_parent_group_id = 0;
if (job_get_flag(j, JOB_CONTROL))
{
should_set_parent_group_id = true;
-
+
// PCA: I'm quite fuzzy on process groups,
// but I believe that the default value of 0
// means that the process becomes its own
@@ -388,13 +388,13 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
// in this case. So we want this to be 0 if j->pgid is 0.
desired_parent_group_id = j->pgid;
}
-
- /* Set the handling for job control signals back to the default. */
- bool reset_signal_handlers = true;
-
- /* Remove all signal blocks */
- bool reset_sigmask = true;
-
+
+ /* Set the handling for job control signals back to the default. */
+ bool reset_signal_handlers = true;
+
+ /* Remove all signal blocks */
+ bool reset_sigmask = true;
+
/* Set our flags */
short flags = 0;
if (reset_signal_handlers)
@@ -403,7 +403,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
flags |= POSIX_SPAWN_SETSIGMASK;
if (should_set_parent_group_id)
flags |= POSIX_SPAWN_SETPGROUP;
-
+
int err = 0;
if (! err)
err = posix_spawnattr_setflags(attr, flags);
@@ -418,16 +418,16 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
get_signals_with_handlers(&sigdefault);
err = posix_spawnattr_setsigdefault(attr, &sigdefault);
}
-
+
/* No signals blocked */
sigset_t sigmask;
sigemptyset(&sigmask);
if (! err && reset_sigmask)
err = posix_spawnattr_setsigmask(attr, &sigmask);
-
+
/* Make sure that our pipes don't use an fd that the redirection itself wants to use */
free_redirected_fds_from_pipes(j->io);
-
+
/* Close unused internal pipes */
std::vector<int> files_to_close;
get_unused_internal_pipes(files_to_close, j->io);
@@ -435,22 +435,22 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
{
err = posix_spawn_file_actions_addclose(actions, files_to_close.at(i));
}
-
+
for (size_t idx = 0; idx < j->io.size(); idx++)
{
const io_data_t *io = j->io.at(idx);
-
- if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
- {
- continue;
- }
-
- if( io->fd > 2 )
- {
- /* Make sure the fd used by this redirection is not used by e.g. a pipe. */
+
+ if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
+ {
+ continue;
+ }
+
+ if( io->fd > 2 )
+ {
+ /* Make sure the fd used by this redirection is not used by e.g. a pipe. */
// free_fd(io_chain, io->fd );
// PCA I don't think we need to worry about this. fd redirection is pretty uncommon anyways.
- }
+ }
switch (io->io_mode)
{
case IO_CLOSE:
@@ -459,141 +459,141 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
err = posix_spawn_file_actions_addclose(actions, io->fd);
break;
}
-
+
case IO_FILE:
{
- if (! err)
+ if (! err)
err = posix_spawn_file_actions_addopen(actions, io->fd, io->filename_cstr, io->param2.flags /* mode */, OPEN_MASK);
break;
}
-
+
case IO_FD:
{
if (! err)
err = posix_spawn_file_actions_adddup2(actions, io->param1.old_fd /* from */, io->fd /* to */);
break;
}
-
- case IO_BUFFER:
- case IO_PIPE:
- {
+
+ case IO_BUFFER:
+ case IO_PIPE:
+ {
unsigned int write_pipe_idx = (io->is_input ? 0 : 1);
int from_fd = io->param1.pipe_fd[write_pipe_idx];
int to_fd = io->fd;
if (! err)
err = posix_spawn_file_actions_adddup2(actions, from_fd, to_fd);
-
- if( write_pipe_idx > 0 )
- {
- if (! err)
+
+ if( write_pipe_idx > 0 )
+ {
+ if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]);
if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[1]);
- }
- else
- {
- if (! err)
+ }
+ else
+ {
+ if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]);
- }
+ }
break;
}
}
}
-
+
/* Clean up on error */
if (err) {
posix_spawnattr_destroy(attr);
posix_spawn_file_actions_destroy(actions);
}
-
+
return ! err;
}
#endif //FISH_USE_POSIX_SPAWN
void safe_report_exec_error(int err, const char *actual_cmd, char **argv, char **envv)
{
- debug_safe( 0, "Failed to execute process '%s'. Reason:", actual_cmd );
-
- switch( err )
- {
-
- case E2BIG:
- {
- char sz1[128], sz2[128];
-
- long arg_max = -1;
-
- size_t sz = 0;
- char **p;
- for(p=argv; *p; p++)
- {
- sz += strlen(*p)+1;
- }
-
- for(p=envv; *p; p++)
- {
- sz += strlen(*p)+1;
- }
-
+ debug_safe( 0, "Failed to execute process '%s'. Reason:", actual_cmd );
+
+ switch( err )
+ {
+
+ case E2BIG:
+ {
+ char sz1[128], sz2[128];
+
+ long arg_max = -1;
+
+ size_t sz = 0;
+ char **p;
+ for(p=argv; *p; p++)
+ {
+ sz += strlen(*p)+1;
+ }
+
+ for(p=envv; *p; p++)
+ {
+ sz += strlen(*p)+1;
+ }
+
format_size_safe(sz1, sz);
- arg_max = sysconf( _SC_ARG_MAX );
-
- if( arg_max > 0 )
- {
+ arg_max = sysconf( _SC_ARG_MAX );
+
+ if( arg_max > 0 )
+ {
format_size_safe(sz2, sz);
debug_safe(0, "The total size of the argument and environment lists %s exceeds the operating system limit of %s.", sz1, sz2);
- }
- else
- {
- debug_safe( 0, "The total size of the argument and environment lists (%s) exceeds the operating system limit.", sz1);
- }
-
- debug_safe(0, "Try running the command again with fewer arguments.");
- break;
- }
-
- case ENOEXEC:
- {
+ }
+ else
+ {
+ debug_safe( 0, "The total size of the argument and environment lists (%s) exceeds the operating system limit.", sz1);
+ }
+
+ debug_safe(0, "Try running the command again with fewer arguments.");
+ break;
+ }
+
+ case ENOEXEC:
+ {
/* Hope strerror doesn't allocate... */
const char *err = strerror(errno);
debug_safe(0, "exec: %s", err);
-
- debug_safe(0, "The file '%s' is marked as an executable but could not be run by the operating system.", actual_cmd);
+
+ debug_safe(0, "The file '%s' is marked as an executable but could not be run by the operating system.", actual_cmd);
break;
- }
+ }
- case ENOENT:
- {
+ case ENOENT:
+ {
/* ENOENT is returned by exec() when the path fails, but also returned by posix_spawn if an open file action fails. These cases appear to be impossible to distinguish. We address this by not using posix_spawn for file redirections, so all the ENOENTs we find must be errors from exec(). */
char interpreter_buff[128] = {}, *interpreter;
interpreter = get_interpreter(actual_cmd, interpreter_buff, sizeof interpreter_buff);
- if( interpreter && 0 != access( interpreter, X_OK ) )
- {
- debug_safe(0, "The file '%s' specified the interpreter '%s', which is not an executable command.", actual_cmd, interpreter );
- }
- else
- {
- debug_safe(0, "The file '%s' does not exist or could not be executed.", actual_cmd);
- }
+ if( interpreter && 0 != access( interpreter, X_OK ) )
+ {
+ debug_safe(0, "The file '%s' specified the interpreter '%s', which is not an executable command.", actual_cmd, interpreter );
+ }
+ else
+ {
+ debug_safe(0, "The file '%s' does not exist or could not be executed.", actual_cmd);
+ }
break;
- }
+ }
- case ENOMEM:
- {
- debug_safe(0, "Out of memory");
+ case ENOMEM:
+ {
+ debug_safe(0, "Out of memory");
break;
- }
+ }
- default:
- {
+ default:
+ {
/* Hope strerror doesn't allocate... */
const char *err = strerror(errno);
debug_safe(0, "exec: %s", err);
-
- // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
+
+ // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
break;
- }
- }
+ }
+ }
}
diff --git a/postfork.h b/postfork.h
index 9acd4c86..6b085764 100644
--- a/postfork.h
+++ b/postfork.h
@@ -1,6 +1,6 @@
/** \file postfork.h
- Functions that we may safely call after fork(), of which there are very few. In particular we cannot allocate memory, since we're insane enough to call fork from a multithreaded process.
+ Functions that we may safely call after fork(), of which there are very few. In particular we cannot allocate memory, since we're insane enough to call fork from a multithreaded process.
*/
#ifndef FISH_POSTFORK_H
@@ -38,7 +38,7 @@
exit. The parent process may safely ignore the exit status of this
call.
- Returns 0 on sucess, -1 on failiure.
+ Returns 0 on sucess, -1 on failiure.
*/
int set_child_group( job_t *j, process_t *p, int print_errors );
diff --git a/print_help.cpp b/print_help.cpp
index 18a0f965..3bb17835 100644
--- a/print_help.cpp
+++ b/print_help.cpp
@@ -1,6 +1,6 @@
/** \file print_help.c
- Print help message for the specified command
+ Print help message for the specified command
*/
#include <stdlib.h>
@@ -19,16 +19,16 @@ ssize_t write_loop(int fd, const char *buff, size_t count);
void print_help( const char *c, int fd )
{
- char cmd[ CMD_LEN];
- int printed = snprintf( cmd, CMD_LEN, "fish -c '__fish_print_help %s >&%d'", c, fd );
-
- if( printed < CMD_LEN )
- {
- if( (system( cmd ) == -1) )
- {
- write_loop(2, HELP_ERR, strlen(HELP_ERR));
- }
-
- }
-
+ char cmd[ CMD_LEN];
+ int printed = snprintf( cmd, CMD_LEN, "fish -c '__fish_print_help %s >&%d'", c, fd );
+
+ if( printed < CMD_LEN )
+ {
+ if( (system( cmd ) == -1) )
+ {
+ write_loop(2, HELP_ERR, strlen(HELP_ERR));
+ }
+
+ }
+
}
diff --git a/print_help.h b/print_help.h
index 1020ca75..69f6578c 100644
--- a/print_help.h
+++ b/print_help.h
@@ -1,13 +1,13 @@
/** \file print_help.h
- Print help message for the specified command
+ Print help message for the specified command
*/
#ifndef FISH_PRINT_HELP_H
#define FISH_PRINT_HELP_H
-/**
- Print help message for the specified command
+/**
+ Print help message for the specified command
*/
void print_help( const char *cmd, int fd );
diff --git a/proc.cpp b/proc.cpp
index deeb0ed8..0ba13c6c 100644
--- a/proc.cpp
+++ b/proc.cpp
@@ -7,7 +7,7 @@ will call proc to create representations of the running jobs as
needed.
Some of the code in this file is based on code from the Glibc manual.
-
+
*/
#include "config.h"
@@ -75,7 +75,7 @@ Some of the code in this file is based on code from the Glibc manual.
#include "output.h"
/**
- Size of message buffer
+ Size of message buffer
*/
#define MESS_SIZE 256
@@ -84,13 +84,13 @@ Some of the code in this file is based on code from the Glibc manual.
*/
#define BUFFER_SIZE 4096
-/**
- Status of last process to exit
+/**
+ Status of last process to exit
*/
static int last_status=0;
/**
- Signal flag
+ Signal flag
*/
static sig_atomic_t got_signal=0;
@@ -156,13 +156,13 @@ static std::vector<int> interactive_stack;
void proc_init()
{
- proc_push_interactive( 0 );
+ proc_push_interactive( 0 );
event.arguments.reset(new wcstring_list_t);
}
/**
- Remove job from list of jobs
+ Remove job from list of jobs
*/
static int job_remove( job_t *j )
{
@@ -183,7 +183,7 @@ void job_promote(job_t *job)
*/
void job_free( job_t * j )
{
- job_remove( j );
+ job_remove( j );
delete j;
}
@@ -191,22 +191,22 @@ void proc_destroy()
{
event.arguments.reset(NULL);
job_list_t &jobs = parser_t::principal_parser().job_list();
- while( ! jobs.empty() )
- {
- job_t *job = jobs.front();
- debug( 2, L"freeing leaked job %ls", job->command_wcstr() );
- job_free( job );
- }
+ while( ! jobs.empty() )
+ {
+ job_t *job = jobs.front();
+ debug( 2, L"freeing leaked job %ls", job->command_wcstr() );
+ job_free( job );
+ }
}
void proc_set_last_status( int s )
{
- last_status = s;
+ last_status = s;
}
int proc_get_last_status()
{
- return last_status;
+ return last_status;
}
/* Basic thread safe job IDs. The vector consumed_job_ids has a true value wherever the job ID corresponding to that slot is in use. The job ID corresponding to slot 0 is 1. */
@@ -216,7 +216,7 @@ static std::vector<bool> consumed_job_ids;
job_id_t acquire_job_id(void)
{
scoped_lock lock(job_id_lock);
-
+
/* Find the index of the first 0 slot */
std::vector<bool>::iterator slot = std::find(consumed_job_ids.begin(), consumed_job_ids.end(), false);
if (slot != consumed_job_ids.end())
@@ -238,11 +238,11 @@ void release_job_id(job_id_t jid)
assert(jid > 0);
scoped_lock lock(job_id_lock);
size_t slot = (size_t)(jid - 1), count = consumed_job_ids.size();
-
+
/* Make sure this slot is within our vector and is currently set to consumed */
assert(slot < count);
assert(consumed_job_ids.at(slot) == true);
-
+
/* Clear it and then resize the vector to eliminate unused trailing job IDs */
consumed_job_ids.at(slot) = false;
while (count--) {
@@ -265,127 +265,127 @@ job_t *job_get_from_pid( int pid )
}
-/*
- Return true if all processes in the job have stopped or completed.
+/*
+ Return true if all processes in the job have stopped or completed.
\param j the job to test
*/
int job_is_stopped( const job_t *j )
{
- process_t *p;
-
- for (p = j->first_process; p; p = p->next)
- {
- if (!p->completed && !p->stopped)
- {
- return 0;
- }
- }
- return 1;
+ process_t *p;
+
+ for (p = j->first_process; p; p = p->next)
+ {
+ if (!p->completed && !p->stopped)
+ {
+ return 0;
+ }
+ }
+ return 1;
}
-/*
- Return true if the last processes in the job has completed.
+/*
+ Return true if the last processes in the job has completed.
\param j the job to test
*/
int job_is_completed( const job_t *j )
{
- process_t *p;
- assert(j->first_process != NULL);
- for (p = j->first_process; p->next; p = p->next)
- ;
-
- return p->completed;
-
+ process_t *p;
+ assert(j->first_process != NULL);
+ for (p = j->first_process; p->next; p = p->next)
+ ;
+
+ return p->completed;
+
}
void job_set_flag( job_t *j, int flag, int set )
{
- if( set )
- j->flags |= flag;
- else
- j->flags = j->flags & ((unsigned int)(-1) ^ flag);
+ if( set )
+ j->flags |= flag;
+ else
+ j->flags = j->flags & ((unsigned int)(-1) ^ flag);
}
int job_get_flag( const job_t *j, int flag )
{
- return j->flags&flag?1:0;
+ return j->flags&flag?1:0;
}
int job_signal( job_t *j, int signal )
-{
- pid_t my_pid = getpid();
- int res = 0;
-
- if( j->pgid != my_pid )
- {
- res = killpg( j->pgid, SIGHUP );
- }
- else
- {
- process_t *p;
-
- for( p = j->first_process; p; p=p->next )
- {
- if( ! p->completed )
- {
- if( p->pid )
- {
- if( kill( p->pid, SIGHUP ) )
- {
- res = -1;
- break;
- }
- }
- }
- }
-
- }
-
- return res;
+{
+ pid_t my_pid = getpid();
+ int res = 0;
+
+ if( j->pgid != my_pid )
+ {
+ res = killpg( j->pgid, SIGHUP );
+ }
+ else
+ {
+ process_t *p;
+
+ for( p = j->first_process; p; p=p->next )
+ {
+ if( ! p->completed )
+ {
+ if( p->pid )
+ {
+ if( kill( p->pid, SIGHUP ) )
+ {
+ res = -1;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ return res;
}
/**
Store the status of the process pid that was returned by waitpid.
- Return 0 if all went well, nonzero otherwise.
+ Return 0 if all went well, nonzero otherwise.
*/
static void mark_process_status( const job_t *j,
- process_t *p,
- int status )
+ process_t *p,
+ int status )
{
-// debug( 0, L"Process %ls %ls", p->argv[0], WIFSTOPPED (status)?L"stopped":(WIFEXITED( status )?L"exited":(WIFSIGNALED( status )?L"signaled to exit":L"BLARGH")) );
- p->status = status;
-
- if (WIFSTOPPED (status))
- {
- p->stopped = 1;
- }
- else if (WIFSIGNALED(status) || WIFEXITED(status))
- {
- p->completed = 1;
- }
- else
- {
- ssize_t ignore;
-
- /* This should never be reached */
- p->completed = 1;
-
- char mess[MESS_SIZE];
- snprintf( mess,
- MESS_SIZE,
- "Process %ld exited abnormally\n",
- (long) p->pid );
- /*
- If write fails, do nothing. We're in a signal handlers error
- handler. If things aren't working properly, it's safer to
- give up.
- */
- ignore = write( 2, mess, strlen(mess) );
- }
+// debug( 0, L"Process %ls %ls", p->argv[0], WIFSTOPPED (status)?L"stopped":(WIFEXITED( status )?L"exited":(WIFSIGNALED( status )?L"signaled to exit":L"BLARGH")) );
+ p->status = status;
+
+ if (WIFSTOPPED (status))
+ {
+ p->stopped = 1;
+ }
+ else if (WIFSIGNALED(status) || WIFEXITED(status))
+ {
+ p->completed = 1;
+ }
+ else
+ {
+ ssize_t ignore;
+
+ /* This should never be reached */
+ p->completed = 1;
+
+ char mess[MESS_SIZE];
+ snprintf( mess,
+ MESS_SIZE,
+ "Process %ld exited abnormally\n",
+ (long) p->pid );
+ /*
+ If write fails, do nothing. We're in a signal handlers error
+ handler. If things aren't working properly, it's safer to
+ give up.
+ */
+ ignore = write( 2, mess, strlen(mess) );
+ }
}
void job_mark_process_as_failed( const job_t *job, process_t *p )
@@ -404,97 +404,97 @@ void job_mark_process_as_failed( const job_t *job, process_t *p )
*/
static void handle_child_status( pid_t pid, int status )
{
- bool found_proc = false;
- const job_t *j=0;
- process_t *p=0;
-// char mess[MESS_SIZE];
- /*
- snprintf( mess,
- MESS_SIZE,
- "Process %d\n",
- (int) pid );
- write( 2, mess, strlen(mess ));
- */
+ bool found_proc = false;
+ const job_t *j=0;
+ process_t *p=0;
+// char mess[MESS_SIZE];
+ /*
+ snprintf( mess,
+ MESS_SIZE,
+ "Process %d\n",
+ (int) pid );
+ write( 2, mess, strlen(mess ));
+ */
job_iterator_t jobs;
- while (! found_proc && (j = jobs.next()))
- {
- process_t *prev=0;
- for( p=j->first_process; p; p=p->next )
- {
- if( pid == p->pid )
- {
-/* snprintf( mess,
+ while (! found_proc && (j = jobs.next()))
+ {
+ process_t *prev=0;
+ for( p=j->first_process; p; p=p->next )
+ {
+ if( pid == p->pid )
+ {
+/* snprintf( mess,
MESS_SIZE,
"Process %d is %ls from job %ls\n",
(int) pid, p->actual_cmd, j->command );
write( 2, mess, strlen(mess ));
-*/
-
- mark_process_status ( j, p, status);
- if( p->completed && prev != 0 )
- {
- if( !prev->completed && prev->pid)
- {
- /* snprintf( mess,
- MESS_SIZE,
- "Kill previously uncompleted process %ls (%d)\n",
- prev->actual_cmd,
- prev->pid );
- write( 2, mess, strlen(mess ));
- */
- kill(prev->pid,SIGPIPE);
- }
- }
- found_proc = true;
- break;
- }
- prev = p;
- }
- }
-
-
- if( WIFSIGNALED( status ) &&
- ( WTERMSIG(status)==SIGINT ||
- WTERMSIG(status)==SIGQUIT ) )
- {
- if( !is_interactive_session )
- {
- struct sigaction act;
- sigemptyset( & act.sa_mask );
- act.sa_flags=0;
- act.sa_handler=SIG_DFL;
- sigaction( SIGINT, &act, 0 );
- sigaction( SIGQUIT, &act, 0 );
- kill( getpid(), WTERMSIG(status) );
- }
- else
- {
+*/
+
+ mark_process_status ( j, p, status);
+ if( p->completed && prev != 0 )
+ {
+ if( !prev->completed && prev->pid)
+ {
+ /* snprintf( mess,
+ MESS_SIZE,
+ "Kill previously uncompleted process %ls (%d)\n",
+ prev->actual_cmd,
+ prev->pid );
+ write( 2, mess, strlen(mess ));
+ */
+ kill(prev->pid,SIGPIPE);
+ }
+ }
+ found_proc = true;
+ break;
+ }
+ prev = p;
+ }
+ }
+
+
+ if( WIFSIGNALED( status ) &&
+ ( WTERMSIG(status)==SIGINT ||
+ WTERMSIG(status)==SIGQUIT ) )
+ {
+ if( !is_interactive_session )
+ {
+ struct sigaction act;
+ sigemptyset( & act.sa_mask );
+ act.sa_flags=0;
+ act.sa_handler=SIG_DFL;
+ sigaction( SIGINT, &act, 0 );
+ sigaction( SIGQUIT, &act, 0 );
+ kill( getpid(), WTERMSIG(status) );
+ }
+ else
+ {
/* In an interactive session, tell the principal parser to skip all blocks we're executing so control-C returns control to the user. */
- if( p && found_proc )
- {
+ if( p && found_proc )
+ {
parser_t::skip_all_blocks();
- }
- }
- }
-
- if( !found_proc )
- {
- /*
- A child we lost track of?
-
- There have been bugs in both subshell handling and in
- builtin handling that have caused this previously...
- */
-/* snprintf( mess,
+ }
+ }
+ }
+
+ if( !found_proc )
+ {
+ /*
+ A child we lost track of?
+
+ There have been bugs in both subshell handling and in
+ builtin handling that have caused this previously...
+ */
+/* snprintf( mess,
MESS_SIZE,
"Process %d not found by %d\n",
(int) pid, (int)getpid() );
write( 2, mess, strlen(mess ));
*/
- }
- return;
+ }
+ return;
}
process_t::process_t() :
@@ -516,7 +516,7 @@ process_t::process_t() :
#endif
{
}
-
+
process_t::~process_t()
{
if (this->next != NULL)
@@ -534,7 +534,7 @@ job_t::job_t(job_id_t jobid) :
flags(0)
{
}
-
+
job_t::~job_t()
{
if (first_process != NULL)
@@ -546,191 +546,191 @@ job_t::~job_t()
/* This is called from a signal handler */
void job_handle_signal ( int signal, siginfo_t *info, void *con )
{
-
- int status;
- pid_t pid;
- int errno_old = errno;
-
- got_signal = 1;
-
-// write( 2, "got signal\n", 11 );
-
- while(1)
- {
- switch(pid=waitpid( -1,&status,WUNTRACED|WNOHANG ))
- {
- case 0:
- case -1:
- {
- errno=errno_old;
- return;
- }
- default:
-
- handle_child_status( pid, status );
- break;
- }
- }
- kill( 0, SIGIO );
- errno=errno_old;
+
+ int status;
+ pid_t pid;
+ int errno_old = errno;
+
+ got_signal = 1;
+
+// write( 2, "got signal\n", 11 );
+
+ while(1)
+ {
+ switch(pid=waitpid( -1,&status,WUNTRACED|WNOHANG ))
+ {
+ case 0:
+ case -1:
+ {
+ errno=errno_old;
+ return;
+ }
+ default:
+
+ handle_child_status( pid, status );
+ break;
+ }
+ }
+ kill( 0, SIGIO );
+ errno=errno_old;
}
-/**
- Format information about job status for the user to look at.
+/**
+ Format information about job status for the user to look at.
- \param j the job to test
- \param status a string description of the job exit type
+ \param j the job to test
+ \param status a string description of the job exit type
*/
static void format_job_info( const job_t *j, const wchar_t *status )
{
- fwprintf (stdout, L"\r" );
- fwprintf (stdout, _( L"Job %d, \'%ls\' has %ls" ), j->job_id, j->command_wcstr(), status);
- fflush( stdout );
- tputs(clr_eol,1,&writeb);
- fwprintf (stdout, L"\n" );
+ fwprintf (stdout, L"\r" );
+ fwprintf (stdout, _( L"Job %d, \'%ls\' has %ls" ), j->job_id, j->command_wcstr(), status);
+ fflush( stdout );
+ tputs(clr_eol,1,&writeb);
+ fwprintf (stdout, L"\n" );
}
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status )
{
-
- event.type=type;
- event.param1.pid = pid;
-
+
+ event.type=type;
+ event.param1.pid = pid;
+
event.arguments->push_back(msg);
event.arguments->push_back(to_string<int>(pid));
event.arguments->push_back(to_string<int>(status));
- event_fire( &event );
+ event_fire( &event );
event.arguments->resize(0);
-}
+}
int job_reap( bool interactive )
{
ASSERT_IS_MAIN_THREAD();
- job_t *jnext;
- int found=0;
-
- static int locked = 0;
-
- locked++;
-
- /*
- job_read may fire an event handler, we do not want to call
- ourselves recursively (to avoid infinite recursion).
- */
- if( locked>1 )
- return 0;
-
+ job_t *jnext;
+ int found=0;
+
+ static int locked = 0;
+
+ locked++;
+
+ /*
+ job_read may fire an event handler, we do not want to call
+ ourselves recursively (to avoid infinite recursion).
+ */
+ if( locked>1 )
+ return 0;
+
job_iterator_t jobs;
jnext = jobs.next();
- while (jnext)
+ while (jnext)
{
job_t *j = jnext;
jnext = jobs.next();
- process_t *p;
-
- /*
- If we are reaping only jobs who do not need status messages
- sent to the console, do not consider reaping jobs that need
- status messages
- */
- if( (!job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) && (!interactive) && (!job_get_flag( j, JOB_FOREGROUND )))
- {
- continue;
- }
-
- for( p=j->first_process; p; p=p->next )
- {
- int s;
- if( !p->completed )
- continue;
-
- if( !p->pid )
- continue;
-
- s = p->status;
-
- proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );
-
- if( WIFSIGNALED(s) )
- {
- /*
- Ignore signal SIGPIPE.We issue it ourselves to the pipe
- writer when the pipe reader dies.
- */
- if( WTERMSIG(s) != SIGPIPE )
- {
- int proc_is_job = ((p==j->first_process) && (p->next == 0));
- if( proc_is_job )
- job_set_flag( j, JOB_NOTIFIED, 1 );
- if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
- {
- if( proc_is_job )
- fwprintf( stdout,
- _( L"%ls: Job %d, \'%ls\' terminated by signal %ls (%ls)" ),
- program_name,
- j->job_id,
- j->command_wcstr(),
- sig2wcs(WTERMSIG(p->status)),
- signal_get_desc( WTERMSIG(p->status) ) );
- else
- fwprintf( stdout,
- _( L"%ls: Process %d, \'%ls\' from job %d, \'%ls\' terminated by signal %ls (%ls)" ),
- program_name,
- p->pid,
- p->argv0(),
- j->job_id,
- j->command_wcstr(),
- sig2wcs(WTERMSIG(p->status)),
- signal_get_desc( WTERMSIG(p->status) ) );
- tputs(clr_eol,1,&writeb);
- fwprintf (stdout, L"\n" );
- found=1;
- }
-
- /*
- Clear status so it is not reported more than once
- */
- p->status = 0;
- }
- }
- }
-
- /*
- If all processes have completed, tell the user the job has
- completed and delete it from the active job list.
- */
- if( job_is_completed( j ) )
- {
- if( !job_get_flag( j, JOB_FOREGROUND) && !job_get_flag( j, JOB_NOTIFIED ) && !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
- {
- format_job_info( j, _( L"ended" ) );
- found=1;
- }
- proc_fire_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 );
- proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );
-
- job_free(j);
- }
- else if( job_is_stopped( j ) && !job_get_flag( j, JOB_NOTIFIED ) )
- {
- /*
- Notify the user about newly stopped jobs.
- */
- if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
- {
- format_job_info( j, _( L"stopped" ) );
- found=1;
- }
- job_set_flag( j, JOB_NOTIFIED, 1 );
- }
- }
-
- if( found )
- fflush( stdout );
-
- locked = 0;
-
- return found;
+ process_t *p;
+
+ /*
+ If we are reaping only jobs who do not need status messages
+ sent to the console, do not consider reaping jobs that need
+ status messages
+ */
+ if( (!job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) && (!interactive) && (!job_get_flag( j, JOB_FOREGROUND )))
+ {
+ continue;
+ }
+
+ for( p=j->first_process; p; p=p->next )
+ {
+ int s;
+ if( !p->completed )
+ continue;
+
+ if( !p->pid )
+ continue;
+
+ s = p->status;
+
+ proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );
+
+ if( WIFSIGNALED(s) )
+ {
+ /*
+ Ignore signal SIGPIPE.We issue it ourselves to the pipe
+ writer when the pipe reader dies.
+ */
+ if( WTERMSIG(s) != SIGPIPE )
+ {
+ int proc_is_job = ((p==j->first_process) && (p->next == 0));
+ if( proc_is_job )
+ job_set_flag( j, JOB_NOTIFIED, 1 );
+ if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
+ {
+ if( proc_is_job )
+ fwprintf( stdout,
+ _( L"%ls: Job %d, \'%ls\' terminated by signal %ls (%ls)" ),
+ program_name,
+ j->job_id,
+ j->command_wcstr(),
+ sig2wcs(WTERMSIG(p->status)),
+ signal_get_desc( WTERMSIG(p->status) ) );
+ else
+ fwprintf( stdout,
+ _( L"%ls: Process %d, \'%ls\' from job %d, \'%ls\' terminated by signal %ls (%ls)" ),
+ program_name,
+ p->pid,
+ p->argv0(),
+ j->job_id,
+ j->command_wcstr(),
+ sig2wcs(WTERMSIG(p->status)),
+ signal_get_desc( WTERMSIG(p->status) ) );
+ tputs(clr_eol,1,&writeb);
+ fwprintf (stdout, L"\n" );
+ found=1;
+ }
+
+ /*
+ Clear status so it is not reported more than once
+ */
+ p->status = 0;
+ }
+ }
+ }
+
+ /*
+ If all processes have completed, tell the user the job has
+ completed and delete it from the active job list.
+ */
+ if( job_is_completed( j ) )
+ {
+ if( !job_get_flag( j, JOB_FOREGROUND) && !job_get_flag( j, JOB_NOTIFIED ) && !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
+ {
+ format_job_info( j, _( L"ended" ) );
+ found=1;
+ }
+ proc_fire_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 );
+ proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );
+
+ job_free(j);
+ }
+ else if( job_is_stopped( j ) && !job_get_flag( j, JOB_NOTIFIED ) )
+ {
+ /*
+ Notify the user about newly stopped jobs.
+ */
+ if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
+ {
+ format_job_info( j, _( L"stopped" ) );
+ found=1;
+ }
+ job_set_flag( j, JOB_NOTIFIED, 1 );
+ }
+ }
+
+ if( found )
+ fflush( stdout );
+
+ locked = 0;
+
+ return found;
}
@@ -746,83 +746,83 @@ int job_reap( bool interactive )
*/
unsigned long proc_get_jiffies( process_t *p )
{
- wchar_t fn[FN_SIZE];
-
- char state;
- int pid, ppid, pgrp,
- session, tty_nr, tpgid,
- exit_signal, processor;
-
- long int cutime, cstime, priority,
- nice, placeholder, itrealvalue,
- rss;
- unsigned long int flags, minflt, cminflt,
- majflt, cmajflt, utime,
- stime, starttime, vsize,
- rlim, startcode, endcode,
- startstack, kstkesp, kstkeip,
- signal, blocked, sigignore,
- sigcatch, wchan, nswap, cnswap;
- char comm[1024];
-
- if( p->pid <= 0 )
- return 0;
-
- swprintf( fn, FN_SIZE, L"/proc/%d/stat", p->pid );
-
- FILE *f = wfopen( fn, "r" );
- if( !f )
- return 0;
-
- int count = fscanf( f,
- "%d %s %c "
- "%d %d %d "
- "%d %d %lu "
-
- "%lu %lu %lu "
- "%lu %lu %lu "
- "%ld %ld %ld "
-
- "%ld %ld %ld "
- "%lu %lu %ld "
- "%lu %lu %lu "
-
- "%lu %lu %lu "
- "%lu %lu %lu "
- "%lu %lu %lu "
-
- "%lu %d %d ",
-
- &pid, comm, &state,
- &ppid, &pgrp, &session,
- &tty_nr, &tpgid, &flags,
-
- &minflt, &cminflt, &majflt,
- &cmajflt, &utime, &stime,
- &cutime, &cstime, &priority,
-
- &nice, &placeholder, &itrealvalue,
- &starttime, &vsize, &rss,
- &rlim, &startcode, &endcode,
-
- &startstack, &kstkesp, &kstkeip,
- &signal, &blocked, &sigignore,
- &sigcatch, &wchan, &nswap,
-
- &cnswap, &exit_signal, &processor
- );
-
- if( count < 17 )
- {
- return 0;
- }
-
- /*
- Don't need to check exit status of fclose on read-only streams
- */
- fclose( f );
- return utime+stime+cutime+cstime;
-
+ wchar_t fn[FN_SIZE];
+
+ char state;
+ int pid, ppid, pgrp,
+ session, tty_nr, tpgid,
+ exit_signal, processor;
+
+ long int cutime, cstime, priority,
+ nice, placeholder, itrealvalue,
+ rss;
+ unsigned long int flags, minflt, cminflt,
+ majflt, cmajflt, utime,
+ stime, starttime, vsize,
+ rlim, startcode, endcode,
+ startstack, kstkesp, kstkeip,
+ signal, blocked, sigignore,
+ sigcatch, wchan, nswap, cnswap;
+ char comm[1024];
+
+ if( p->pid <= 0 )
+ return 0;
+
+ swprintf( fn, FN_SIZE, L"/proc/%d/stat", p->pid );
+
+ FILE *f = wfopen( fn, "r" );
+ if( !f )
+ return 0;
+
+ int count = fscanf( f,
+ "%d %s %c "
+ "%d %d %d "
+ "%d %d %lu "
+
+ "%lu %lu %lu "
+ "%lu %lu %lu "
+ "%ld %ld %ld "
+
+ "%ld %ld %ld "
+ "%lu %lu %ld "
+ "%lu %lu %lu "
+
+ "%lu %lu %lu "
+ "%lu %lu %lu "
+ "%lu %lu %lu "
+
+ "%lu %d %d ",
+
+ &pid, comm, &state,
+ &ppid, &pgrp, &session,
+ &tty_nr, &tpgid, &flags,
+
+ &minflt, &cminflt, &majflt,
+ &cmajflt, &utime, &stime,
+ &cutime, &cstime, &priority,
+
+ &nice, &placeholder, &itrealvalue,
+ &starttime, &vsize, &rss,
+ &rlim, &startcode, &endcode,
+
+ &startstack, &kstkesp, &kstkeip,
+ &signal, &blocked, &sigignore,
+ &sigcatch, &wchan, &nswap,
+
+ &cnswap, &exit_signal, &processor
+ );
+
+ if( count < 17 )
+ {
+ return 0;
+ }
+
+ /*
+ Don't need to check exit status of fclose on read-only streams
+ */
+ fclose( f );
+ return utime+stime+cutime+cstime;
+
}
/**
@@ -830,18 +830,18 @@ unsigned long proc_get_jiffies( process_t *p )
*/
void proc_update_jiffies()
{
- job_t* job;
- process_t *p;
- job_iterator_t j;
-
- for( job = j.next(); job; job = j.next() )
- {
- for( p=job->first_process; p; p=p->next )
- {
- gettimeofday( &p->last_time, 0 );
- p->last_jiffies = proc_get_jiffies( p );
- }
- }
+ job_t* job;
+ process_t *p;
+ job_iterator_t j;
+
+ for( job = j.next(); job; job = j.next() )
+ {
+ for( p=job->first_process; p; p=p->next )
+ {
+ gettimeofday( &p->last_time, 0 );
+ p->last_jiffies = proc_get_jiffies( p );
+ }
+ }
}
@@ -849,103 +849,103 @@ void proc_update_jiffies()
/**
Check if there are buffers associated with the job, and select on
- them for a while if available.
-
+ them for a while if available.
+
\param j the job to test
\return 1 if buffers were avaialble, zero otherwise
*/
static int select_try( job_t *j )
{
- fd_set fds;
- int maxfd=-1;
+ fd_set fds;
+ int maxfd=-1;
+
+ FD_ZERO(&fds);
- FD_ZERO(&fds);
-
for (size_t idx = 0; idx < j->io.size(); idx++)
- {
+ {
const io_data_t *d = j->io.at(idx);
- if( d->io_mode == IO_BUFFER )
- {
- int fd = d->param1.pipe_fd[0];
-// fwprintf( stderr, L"fd %d on job %ls\n", fd, j->command );
- FD_SET( fd, &fds );
- maxfd = maxi(maxfd, fd);
- debug( 3, L"select_try on %d\n", fd );
- }
- }
-
- if( maxfd >= 0 )
- {
- int retval;
- struct timeval tv;
-
- tv.tv_sec=0;
- tv.tv_usec=10000;
-
- retval =select( maxfd+1, &fds, 0, 0, &tv );
- return retval > 0;
- }
-
- return -1;
+ if( d->io_mode == IO_BUFFER )
+ {
+ int fd = d->param1.pipe_fd[0];
+// fwprintf( stderr, L"fd %d on job %ls\n", fd, j->command );
+ FD_SET( fd, &fds );
+ maxfd = maxi(maxfd, fd);
+ debug( 3, L"select_try on %d\n", fd );
+ }
+ }
+
+ if( maxfd >= 0 )
+ {
+ int retval;
+ struct timeval tv;
+
+ tv.tv_sec=0;
+ tv.tv_usec=10000;
+
+ retval =select( maxfd+1, &fds, 0, 0, &tv );
+ return retval > 0;
+ }
+
+ return -1;
}
/**
- Read from descriptors until they are empty.
+ Read from descriptors until they are empty.
\param j the job to test
*/
static void read_try( job_t *j )
{
- io_data_t *buff=NULL;
+ io_data_t *buff=NULL;
- /*
- Find the last buffer, which is the one we want to read from
- */
+ /*
+ Find the last buffer, which is the one we want to read from
+ */
for (size_t idx = 0; idx < j->io.size(); idx++)
- {
+ {
io_data_t *d = j->io.at(idx);
- if( d->io_mode == IO_BUFFER )
- {
- buff=d;
- }
- }
-
- if( buff )
- {
- debug( 3, L"proc::read_try('%ls')\n", j->command_wcstr() );
- while(1)
- {
- char b[BUFFER_SIZE];
- long l;
-
- l=read_blocked( buff->param1.pipe_fd[0],
- b, BUFFER_SIZE );
- if( l==0 )
- {
- break;
- }
- else if( l<0 )
- {
- if( errno != EAGAIN )
- {
- debug( 1,
- _( L"An error occured while reading output from code block" ) );
- wperror( L"read_try" );
- }
- break;
- }
- else
- {
+ if( d->io_mode == IO_BUFFER )
+ {
+ buff=d;
+ }
+ }
+
+ if( buff )
+ {
+ debug( 3, L"proc::read_try('%ls')\n", j->command_wcstr() );
+ while(1)
+ {
+ char b[BUFFER_SIZE];
+ long l;
+
+ l=read_blocked( buff->param1.pipe_fd[0],
+ b, BUFFER_SIZE );
+ if( l==0 )
+ {
+ break;
+ }
+ else if( l<0 )
+ {
+ if( errno != EAGAIN )
+ {
+ debug( 1,
+ _( L"An error occured while reading output from code block" ) );
+ wperror( L"read_try" );
+ }
+ break;
+ }
+ else
+ {
buff->out_buffer_append(b, l);
- }
- }
- }
+ }
+ }
+ }
}
/**
- Give ownership of the terminal to the specified job.
+ Give ownership of the terminal to the specified job.
\param j The job to give the terminal to.
@@ -955,363 +955,363 @@ static void read_try( job_t *j )
*/
static int terminal_give_to_job( job_t *j, int cont )
{
-
- if( tcsetpgrp (0, j->pgid) )
- {
- debug( 1,
- _( L"Could not send job %d ('%ls') to foreground" ),
- j->job_id,
- j->command_wcstr() );
- wperror( L"tcsetpgrp" );
- return 0;
- }
-
- if( cont )
- {
- if( tcsetattr (0, TCSADRAIN, &j->tmodes))
- {
- debug( 1,
- _( L"Could not send job %d ('%ls') to foreground" ),
- j->job_id,
- j->command_wcstr() );
- wperror( L"tcsetattr" );
- return 0;
- }
- }
- return 1;
+
+ if( tcsetpgrp (0, j->pgid) )
+ {
+ debug( 1,
+ _( L"Could not send job %d ('%ls') to foreground" ),
+ j->job_id,
+ j->command_wcstr() );
+ wperror( L"tcsetpgrp" );
+ return 0;
+ }
+
+ if( cont )
+ {
+ if( tcsetattr (0, TCSADRAIN, &j->tmodes))
+ {
+ debug( 1,
+ _( L"Could not send job %d ('%ls') to foreground" ),
+ j->job_id,
+ j->command_wcstr() );
+ wperror( L"tcsetattr" );
+ return 0;
+ }
+ }
+ return 1;
}
/**
Returns contol of the terminal to the shell, and saves the terminal
attribute state to the job, so that we can restore the terminal
- ownership to the job at a later time .
+ ownership to the job at a later time .
*/
static int terminal_return_from_job( job_t *j)
{
-
- if( tcsetpgrp (0, getpgrp()) )
- {
- debug( 1, _( L"Could not return shell to foreground" ) );
- wperror( L"tcsetpgrp" );
- return 0;
- }
-
- /*
- Save jobs terminal modes.
- */
- if( tcgetattr (0, &j->tmodes) )
- {
- debug( 1, _( L"Could not return shell to foreground" ) );
- wperror( L"tcgetattr" );
- return 0;
- }
-
+
+ if( tcsetpgrp (0, getpgrp()) )
+ {
+ debug( 1, _( L"Could not return shell to foreground" ) );
+ wperror( L"tcsetpgrp" );
+ return 0;
+ }
+
+ /*
+ Save jobs terminal modes.
+ */
+ if( tcgetattr (0, &j->tmodes) )
+ {
+ debug( 1, _( L"Could not return shell to foreground" ) );
+ wperror( L"tcgetattr" );
+ return 0;
+ }
+
/* Disabling this per https://github.com/adityagodbole/fish-shell/commit/9d229cd18c3e5c25a8bd37e9ddd3b67ddc2d1b72
On Linux, 'cd . ; ftp' prevents you from typing into the ftp prompt
See https://github.com/fish-shell/fish-shell/issues/121
*/
#if 0
- /*
- Restore the shell's terminal modes.
- */
- if( tcsetattr (0, TCSADRAIN, &shell_modes))
- {
- debug( 1, _( L"Could not return shell to foreground" ) );
- wperror( L"tcsetattr" );
- return 0;
- }
+ /*
+ Restore the shell's terminal modes.
+ */
+ if( tcsetattr (0, TCSADRAIN, &shell_modes))
+ {
+ debug( 1, _( L"Could not return shell to foreground" ) );
+ wperror( L"tcsetattr" );
+ return 0;
+ }
#endif
- return 1;
+ return 1;
}
void job_continue (job_t *j, int cont)
{
- /*
- Put job first in the job list
- */
+ /*
+ Put job first in the job list
+ */
job_promote(j);
- job_set_flag( j, JOB_NOTIFIED, 0 );
-
- CHECK_BLOCK();
-
- debug( 4,
- L"Continue job %d, gid %d (%ls), %ls, %ls",
- j->job_id,
- j->pgid,
- j->command_wcstr(),
- job_is_completed( j )?L"COMPLETED":L"UNCOMPLETED",
- is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE" );
-
- if( !job_is_completed( j ) )
- {
- if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
- {
- /* Put the job into the foreground. */
- int ok;
-
- signal_block();
-
- ok = terminal_give_to_job( j, cont );
-
- signal_unblock();
-
- if( !ok )
- return;
-
- }
-
- /*
- Send the job a continue signal, if necessary.
- */
- if( cont )
- {
- process_t *p;
-
- for( p=j->first_process; p; p=p->next )
- p->stopped=0;
-
- if( job_get_flag( j, JOB_CONTROL ) )
- {
- if( killpg( j->pgid, SIGCONT ) )
- {
- wperror( L"killpg (SIGCONT)" );
- return;
- }
- }
- else
- {
- for( p=j->first_process; p; p=p->next )
- {
- if (kill ( p->pid, SIGCONT) < 0)
- {
- wperror (L"kill (SIGCONT)");
- return;
- }
- }
- }
- }
-
- if( job_get_flag( j, JOB_FOREGROUND ) )
- {
- int quit = 0;
-
- /*
- Wait for job to report. Looks a bit ugly because it has to
- handle the possibility that a signal is dispatched while
- running job_is_stopped().
- */
- while( !quit )
- {
- do
- {
- got_signal = 0;
- quit = job_is_stopped( j ) || job_is_completed( j );
- }
- while (got_signal && !quit);
-
- if( !quit )
- {
-
-// debug( 1, L"select_try()" );
- switch( select_try(j) )
- {
- case 1:
- {
- read_try( j );
- break;
- }
-
- case -1:
- {
- /*
- If there is no funky IO magic, we can use
- waitpid instead of handling child deaths
- through signals. This gives a rather large
- speed boost (A factor 3 startup time
- improvement on my 300 MHz machine) on
- short-lived jobs.
- */
- int status;
- pid_t pid = waitpid(-1, &status, WUNTRACED );
- if( pid > 0 )
- {
- handle_child_status( pid, status );
- }
- else
- {
- /*
- This probably means we got a
- signal. A signal might mean that the
- terminal emulator sent us a hup
- signal to tell is to close. If so,
- we should exit.
- */
- if( reader_exit_forced() )
- {
- quit = 1;
- }
-
- }
- break;
- }
-
- }
- }
- }
- }
- }
-
- if( job_get_flag( j, JOB_FOREGROUND ) )
- {
-
- if( job_is_completed( j ))
- {
-
- // It's possible that the job will produce output and exit before we've even read from it.
- // We'll eventually read the output, but it may be after we've executed subsequent calls
- // This is why my prompt colors kept getting screwed up - the builtin echo calls
- // were sometimes having their output combined with the set_color calls in the wrong order!
- read_try(j);
-
-
- process_t *p = j->first_process;
- while( p->next )
- p = p->next;
-
- if( WIFEXITED( p->status ) || WIFSIGNALED(p->status))
- {
- /*
- Mark process status only if we are in the foreground
- and the last process in a pipe, and it is not a short circuted builtin
- */
- if( p->pid )
- {
- int status = proc_format_status(p->status);
- //wprintf(L"setting status %d for %ls\n", job_get_flag( j, JOB_NEGATE )?!status:status, j->command);
- proc_set_last_status( job_get_flag( j, JOB_NEGATE )?!status:status);
- }
- }
- }
- /*
- Put the shell back in the foreground.
- */
- if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
- {
- int ok;
-
- signal_block();
-
- ok = terminal_return_from_job( j );
-
- signal_unblock();
-
- if( !ok )
- return;
-
- }
- }
-
+ job_set_flag( j, JOB_NOTIFIED, 0 );
+
+ CHECK_BLOCK();
+
+ debug( 4,
+ L"Continue job %d, gid %d (%ls), %ls, %ls",
+ j->job_id,
+ j->pgid,
+ j->command_wcstr(),
+ job_is_completed( j )?L"COMPLETED":L"UNCOMPLETED",
+ is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE" );
+
+ if( !job_is_completed( j ) )
+ {
+ if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
+ {
+ /* Put the job into the foreground. */
+ int ok;
+
+ signal_block();
+
+ ok = terminal_give_to_job( j, cont );
+
+ signal_unblock();
+
+ if( !ok )
+ return;
+
+ }
+
+ /*
+ Send the job a continue signal, if necessary.
+ */
+ if( cont )
+ {
+ process_t *p;
+
+ for( p=j->first_process; p; p=p->next )
+ p->stopped=0;
+
+ if( job_get_flag( j, JOB_CONTROL ) )
+ {
+ if( killpg( j->pgid, SIGCONT ) )
+ {
+ wperror( L"killpg (SIGCONT)" );
+ return;
+ }
+ }
+ else
+ {
+ for( p=j->first_process; p; p=p->next )
+ {
+ if (kill ( p->pid, SIGCONT) < 0)
+ {
+ wperror (L"kill (SIGCONT)");
+ return;
+ }
+ }
+ }
+ }
+
+ if( job_get_flag( j, JOB_FOREGROUND ) )
+ {
+ int quit = 0;
+
+ /*
+ Wait for job to report. Looks a bit ugly because it has to
+ handle the possibility that a signal is dispatched while
+ running job_is_stopped().
+ */
+ while( !quit )
+ {
+ do
+ {
+ got_signal = 0;
+ quit = job_is_stopped( j ) || job_is_completed( j );
+ }
+ while (got_signal && !quit);
+
+ if( !quit )
+ {
+
+// debug( 1, L"select_try()" );
+ switch( select_try(j) )
+ {
+ case 1:
+ {
+ read_try( j );
+ break;
+ }
+
+ case -1:
+ {
+ /*
+ If there is no funky IO magic, we can use
+ waitpid instead of handling child deaths
+ through signals. This gives a rather large
+ speed boost (A factor 3 startup time
+ improvement on my 300 MHz machine) on
+ short-lived jobs.
+ */
+ int status;
+ pid_t pid = waitpid(-1, &status, WUNTRACED );
+ if( pid > 0 )
+ {
+ handle_child_status( pid, status );
+ }
+ else
+ {
+ /*
+ This probably means we got a
+ signal. A signal might mean that the
+ terminal emulator sent us a hup
+ signal to tell is to close. If so,
+ we should exit.
+ */
+ if( reader_exit_forced() )
+ {
+ quit = 1;
+ }
+
+ }
+ break;
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ if( job_get_flag( j, JOB_FOREGROUND ) )
+ {
+
+ if( job_is_completed( j ))
+ {
+
+ // It's possible that the job will produce output and exit before we've even read from it.
+ // We'll eventually read the output, but it may be after we've executed subsequent calls
+ // This is why my prompt colors kept getting screwed up - the builtin echo calls
+ // were sometimes having their output combined with the set_color calls in the wrong order!
+ read_try(j);
+
+
+ process_t *p = j->first_process;
+ while( p->next )
+ p = p->next;
+
+ if( WIFEXITED( p->status ) || WIFSIGNALED(p->status))
+ {
+ /*
+ Mark process status only if we are in the foreground
+ and the last process in a pipe, and it is not a short circuted builtin
+ */
+ if( p->pid )
+ {
+ int status = proc_format_status(p->status);
+ //wprintf(L"setting status %d for %ls\n", job_get_flag( j, JOB_NEGATE )?!status:status, j->command);
+ proc_set_last_status( job_get_flag( j, JOB_NEGATE )?!status:status);
+ }
+ }
+ }
+ /*
+ Put the shell back in the foreground.
+ */
+ if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
+ {
+ int ok;
+
+ signal_block();
+
+ ok = terminal_return_from_job( j );
+
+ signal_unblock();
+
+ if( !ok )
+ return;
+
+ }
+ }
+
}
-int proc_format_status(int status)
+int proc_format_status(int status)
{
- if( WIFSIGNALED( status ) )
- {
- return 128+WTERMSIG(status);
- }
- else if( WIFEXITED( status ) )
- {
- return WEXITSTATUS(status);
- }
- return status;
-
+ if( WIFSIGNALED( status ) )
+ {
+ return 128+WTERMSIG(status);
+ }
+ else if( WIFEXITED( status ) )
+ {
+ return WEXITSTATUS(status);
+ }
+ return status;
+
}
void proc_sanity_check()
{
- job_t *j;
- job_t *fg_job=0;
-
+ job_t *j;
+ job_t *fg_job=0;
+
job_iterator_t jobs;
while ((j = jobs.next()))
- {
- process_t *p;
-
- if( !job_get_flag( j, JOB_CONSTRUCTED ) )
- continue;
-
-
- validate_pointer( j->first_process,
- _( L"Process list pointer" ),
- 0 );
-
- /*
- More than one foreground job?
- */
- if( job_get_flag( j, JOB_FOREGROUND ) && !(job_is_stopped(j) || job_is_completed(j) ) )
- {
- if( fg_job != 0 )
- {
- debug( 0,
- _( L"More than one job in foreground: job 1: '%ls' job 2: '%ls'"),
- fg_job->command_wcstr(),
- j->command_wcstr() );
- sanity_lose();
- }
- fg_job = j;
- }
-
- p = j->first_process;
- while( p )
- {
- 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 );
-
- if ( (p->stopped & (~0x00000001)) != 0 )
- {
- debug( 0,
- _( L"Job '%ls', process '%ls' has inconsistent state \'stopped\'=%d" ),
- j->command_wcstr(),
- p->argv0(),
- p->stopped );
- sanity_lose();
- }
-
- if ( (p->completed & (~0x00000001)) != 0 )
- {
- debug( 0,
- _( L"Job '%ls', process '%ls' has inconsistent state \'completed\'=%d" ),
- j->command_wcstr(),
- p->argv0(),
- p->completed );
- sanity_lose();
- }
-
- p=p->next;
- }
-
- }
+ {
+ process_t *p;
+
+ if( !job_get_flag( j, JOB_CONSTRUCTED ) )
+ continue;
+
+
+ validate_pointer( j->first_process,
+ _( L"Process list pointer" ),
+ 0 );
+
+ /*
+ More than one foreground job?
+ */
+ if( job_get_flag( j, JOB_FOREGROUND ) && !(job_is_stopped(j) || job_is_completed(j) ) )
+ {
+ if( fg_job != 0 )
+ {
+ debug( 0,
+ _( L"More than one job in foreground: job 1: '%ls' job 2: '%ls'"),
+ fg_job->command_wcstr(),
+ j->command_wcstr() );
+ sanity_lose();
+ }
+ fg_job = j;
+ }
+
+ p = j->first_process;
+ while( p )
+ {
+ 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 );
+
+ if ( (p->stopped & (~0x00000001)) != 0 )
+ {
+ debug( 0,
+ _( L"Job '%ls', process '%ls' has inconsistent state \'stopped\'=%d" ),
+ j->command_wcstr(),
+ p->argv0(),
+ p->stopped );
+ sanity_lose();
+ }
+
+ if ( (p->completed & (~0x00000001)) != 0 )
+ {
+ debug( 0,
+ _( L"Job '%ls', process '%ls' has inconsistent state \'completed\'=%d" ),
+ j->command_wcstr(),
+ p->argv0(),
+ p->completed );
+ sanity_lose();
+ }
+
+ p=p->next;
+ }
+
+ }
}
void proc_push_interactive( int value )
{
ASSERT_IS_MAIN_THREAD();
- int old = is_interactive;
+ int old = is_interactive;
interactive_stack.push_back(is_interactive);
- is_interactive = value;
- if( old != value )
- signal_set_handlers();
+ is_interactive = value;
+ if( old != value )
+ signal_set_handlers();
}
void proc_pop_interactive()
{
ASSERT_IS_MAIN_THREAD();
- int old = is_interactive;
- is_interactive= interactive_stack.back();
+ int old = is_interactive;
+ is_interactive= interactive_stack.back();
interactive_stack.pop_back();
- if( is_interactive != old )
- signal_set_handlers();
+ if( is_interactive != old )
+ signal_set_handlers();
}
diff --git a/proc.h b/proc.h
index 6feb9afe..2038f969 100644
--- a/proc.h
+++ b/proc.h
@@ -1,11 +1,11 @@
-/** \file proc.h
+/** \file proc.h
Prototypes for utilities for keeping track of jobs, processes and subshells, as
- well as signal handling functions for tracking children. These
- functions do not themselves launch new processes, the exec library
- will call proc to create representations of the running jobs as
- needed.
-
+ well as signal handling functions for tracking children. These
+ functions do not themselves launch new processes, the exec library
+ will call proc to create representations of the running jobs as
+ needed.
+
*/
#ifndef FISH_PROC_H
@@ -56,194 +56,194 @@
*/
enum
{
- /**
- A regular external command
- */
- EXTERNAL,
- /**
- A builtin command
- */
- INTERNAL_BUILTIN,
- /**
- A shellscript function
- */
- INTERNAL_FUNCTION,
- /**
- A block of commands
- */
- INTERNAL_BLOCK,
- /**
- The exec builtin
- */
- INTERNAL_EXEC,
- /**
- A buffer
- */
- INTERNAL_BUFFER,
-
+ /**
+ A regular external command
+ */
+ EXTERNAL,
+ /**
+ A builtin command
+ */
+ INTERNAL_BUILTIN,
+ /**
+ A shellscript function
+ */
+ INTERNAL_FUNCTION,
+ /**
+ A block of commands
+ */
+ INTERNAL_BLOCK,
+ /**
+ The exec builtin
+ */
+ INTERNAL_EXEC,
+ /**
+ A buffer
+ */
+ INTERNAL_BUFFER,
+
}
- ;
+ ;
enum
{
- JOB_CONTROL_ALL,
- JOB_CONTROL_INTERACTIVE,
- JOB_CONTROL_NONE,
+ JOB_CONTROL_ALL,
+ JOB_CONTROL_INTERACTIVE,
+ JOB_CONTROL_NONE,
}
- ;
+ ;
-/**
- A structure representing a single fish process. Contains variables
- for tracking process state and the process argument
- list. Actually, a fish process can be either a regular externa
- lrocess, an internal builtin which may or may not spawn a fake IO
- process during execution, a shellscript function or a block of
- commands to be evaluated by calling eval. Lastly, this process can
- be the result of an exec command. The role of this process_t is
- determined by the type field, which can be one of EXTERNAL,
- INTERNAL_BUILTIN, INTERNAL_FUNCTION, INTERNAL_BLOCK and
- INTERNAL_EXEC, INTERNAL_BUFFER
+/**
+ A structure representing a single fish process. Contains variables
+ for tracking process state and the process argument
+ list. Actually, a fish process can be either a regular externa
+ lrocess, an internal builtin which may or may not spawn a fake IO
+ process during execution, a shellscript function or a block of
+ commands to be evaluated by calling eval. Lastly, this process can
+ be the result of an exec command. The role of this process_t is
+ determined by the type field, which can be one of EXTERNAL,
+ INTERNAL_BUILTIN, INTERNAL_FUNCTION, INTERNAL_BLOCK and
+ INTERNAL_EXEC, INTERNAL_BUFFER
- The process_t contains information on how the process should be
- started, such as command name and arguments, as well as runtime
- information on the status of the actual physical process which
- represents it. Shellscript functions, builtins and blocks of code
- may all need to spawn an external process that handles the piping
- and redirecting of IO for them.
+ The process_t contains information on how the process should be
+ started, such as command name and arguments, as well as runtime
+ information on the status of the actual physical process which
+ represents it. Shellscript functions, builtins and blocks of code
+ may all need to spawn an external process that handles the piping
+ and redirecting of IO for them.
- If the process is of type EXTERNAL or INTERNAL_EXEC, argv is the
- argument array and actual_cmd is the absolute path of the command
- to execute.
+ If the process is of type EXTERNAL or INTERNAL_EXEC, argv is the
+ argument array and actual_cmd is the absolute path of the command
+ to execute.
- If the process is of type INTERNAL_BUILTIN, argv is the argument
- vector, and argv[0] is the name of the builtin command.
+ If the process is of type INTERNAL_BUILTIN, argv is the argument
+ vector, and argv[0] is the name of the builtin command.
- If the process is of type INTERNAL_FUNCTION, argv is the argument
- vector, and argv[0] is the name of the shellscript function.
+ If the process is of type INTERNAL_FUNCTION, argv is the argument
+ vector, and argv[0] is the name of the shellscript function.
- If the process is of type INTERNAL_BLOCK, argv has exactly one
- element, which is the block of commands to execute.
+ If the process is of type INTERNAL_BLOCK, argv has exactly one
+ element, which is the block of commands to execute.
*/
class process_t
{
private:
-
+
null_terminated_array_t<wchar_t> argv_array;
-
+
/* narrow copy of argv0 so we don't have to convert after fork */
narrow_string_rep_t argv0_narrow;
/* No copying */
process_t(const process_t &rhs);
void operator=(const process_t &rhs);
-
+
public:
-
+
process_t();
-
+
~process_t();
-
- /**
- Type of process. Can be one of \c EXTERNAL, \c
- INTERNAL_BUILTIN, \c INTERNAL_FUNCTION, \c INTERNAL_BLOCK,
- INTERNAL_EXEC, or INTERNAL_BUFFER
- */
- int type;
-
-
+
+ /**
+ Type of process. Can be one of \c EXTERNAL, \c
+ INTERNAL_BUILTIN, \c INTERNAL_FUNCTION, \c INTERNAL_BLOCK,
+ INTERNAL_EXEC, or INTERNAL_BUFFER
+ */
+ int type;
+
+
/** Sets argv */
void set_argv(const wcstring_list_t &argv) {
argv_array.set(argv);
argv0_narrow.set(argv.empty() ? L"" : argv[0]);
}
-
+
/** Returns argv */
const wchar_t * const *get_argv(void) const { return argv_array.get(); }
const null_terminated_array_t<wchar_t> &get_argv_array(void) const { return argv_array; }
-
+
/** Returns argv[idx] */
const wchar_t *argv(size_t idx) const {
const wchar_t * const *argv = argv_array.get();
assert(argv != NULL);
return argv[idx];
}
-
+
/** Returns argv[0], or NULL */
const wchar_t *argv0(void) const {
const wchar_t * const *argv = argv_array.get();
return argv ? argv[0] : NULL;
}
-
+
/** Returns argv[0] as a char * */
const char *argv0_cstr(void) const {
return argv0_narrow.get();
}
- /** actual command to pass to exec in case of EXTERNAL or INTERNAL_EXEC. */
- wcstring actual_cmd;
+ /** actual command to pass to exec in case of EXTERNAL or INTERNAL_EXEC. */
+ wcstring actual_cmd;
- /** process ID */
- pid_t pid;
+ /** process ID */
+ pid_t pid;
- /** File descriptor that pipe output should bind to */
- int pipe_write_fd;
+ /** File descriptor that pipe output should bind to */
+ int pipe_write_fd;
- /** File descriptor that the _next_ process pipe input should bind to */
- int pipe_read_fd;
+ /** File descriptor that the _next_ process pipe input should bind to */
+ int pipe_read_fd;
- /** true if process has completed */
- volatile int completed;
+ /** true if process has completed */
+ volatile int completed;
- /** true if process has stopped */
- volatile int stopped;
+ /** true if process has stopped */
+ volatile int stopped;
- /** reported status value */
- volatile int status;
+ /** reported status value */
+ volatile int status;
- /** Special flag to tell the evaluation function for count to print the help information */
- int count_help_magic;
+ /** Special flag to tell the evaluation function for count to print the help information */
+ int count_help_magic;
- /** Next process in pipeline. We own this and we are responsible for deleting it. */
- process_t *next;
+ /** Next process in pipeline. We own this and we are responsible for deleting it. */
+ process_t *next;
#ifdef HAVE__PROC_SELF_STAT
- /** Last time of cpu time check */
- struct timeval last_time;
- /** Number of jiffies spent in process at last cpu time check */
- unsigned long last_jiffies;
+ /** Last time of cpu time check */
+ struct timeval last_time;
+ /** Number of jiffies spent in process at last cpu time check */
+ unsigned long last_jiffies;
#endif
};
-/* Constants for the flag variable in the job struct */
+/* Constants for the flag variable in the job struct */
enum {
/** true if user was told about stopped job */
JOB_NOTIFIED = 1 << 0,
-
+
/** Whether this job is in the foreground */
JOB_FOREGROUND = 1 << 1,
-
+
/**
- Whether the specified job is completely constructed,
- i.e. completely parsed, and every process in the job has been
- forked, etc.
+ Whether the specified job is completely constructed,
+ i.e. completely parsed, and every process in the job has been
+ forked, etc.
*/
JOB_CONSTRUCTED = 1 << 2,
-
+
/** Whether the specified job is a part of a subshell, event handler or some other form of special job that should not be reported */
JOB_SKIP_NOTIFICATION = 1 << 3,
/** Should the exit status be negated? This flag can only be set by the not builtin. */
JOB_NEGATE = 1 << 4,
-
+
/** Should the exit status be used to reevaluate the condition in an if block? This is only used by elseif and is a big hack. */
JOB_ELSEIF = 1 << 5,
-
+
/** This flag is set to one on wildcard expansion errors. It means that the current command should not be executed */
JOB_WILDCARD_ERROR = 1 << 6,
-
+
/** Skip executing this job. This flag is set by the short-circut builtins, i.e. and and or */
JOB_SKIP = 1 << 7,
-
+
/** Whether the job is under job control */
JOB_CONTROL = 1 << 8,
@@ -251,7 +251,7 @@ enum {
JOB_TERMINAL = 1 << 9
};
-/**
+/**
A struct represeting a job. A job is basically a pipeline of one
or more processes and a couple of flags.
*/
@@ -261,105 +261,105 @@ void release_job_id(job_id_t jobid);
class job_t
{
- /**
- The original command which led to the creation of this
- job. It is used for displaying messages about job status
- on the terminal.
- */
- wcstring command_str;
-
+ /**
+ The original command which led to the creation of this
+ job. It is used for displaying messages about job status
+ on the terminal.
+ */
+ wcstring command_str;
+
/* narrow copy so we don't have to convert after fork */
narrow_string_rep_t command_narrow;
-
+
/* No copying */
job_t(const job_t &rhs);
void operator=(const job_t &);
-
+
public:
-
+
job_t(job_id_t jobid);
~job_t();
-
+
/** Returns whether the command is 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_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_str = cmd;
command_narrow.set(cmd);
}
-
- /**
- A linked list of all the processes in this job. We are responsible for deleting this when we are deallocated.
- */
- process_t *first_process;
-
- /**
- process group ID for the process group that this job is
- running in.
- */
- pid_t pgid;
-
- /**
- The saved terminal modes of this job. This needs to be
- saved so that we can restore the terminal to the same
- state after temporarily taking control over the terminal
- when a job stops.
- */
- struct termios tmodes;
-
- /**
- The job id of the job. This is a small integer that is a
- unique identifier of the job within this shell, and is
- used e.g. in process expansion.
- */
- const job_id_t job_id;
-
- /** List of all IO redirections for this job. */
- io_chain_t io;
-
- /**
- Bitset containing information about the job. A combination of the JOB_* constants.
- */
- unsigned int flags;
+
+ /**
+ A linked list of all the processes in this job. We are responsible for deleting this when we are deallocated.
+ */
+ process_t *first_process;
+
+ /**
+ process group ID for the process group that this job is
+ running in.
+ */
+ pid_t pgid;
+
+ /**
+ The saved terminal modes of this job. This needs to be
+ saved so that we can restore the terminal to the same
+ state after temporarily taking control over the terminal
+ when a job stops.
+ */
+ struct termios tmodes;
+
+ /**
+ The job id of the job. This is a small integer that is a
+ unique identifier of the job within this shell, and is
+ used e.g. in process expansion.
+ */
+ const job_id_t job_id;
+
+ /** List of all IO redirections for this job. */
+ io_chain_t io;
+
+ /**
+ Bitset containing information about the job. A combination of the JOB_* constants.
+ */
+ unsigned int flags;
};
-/**
- Whether we are running a subshell command
+/**
+ Whether we are running a subshell command
*/
extern int is_subshell;
-/**
- Whether we are running a block of commands
+/**
+ Whether we are running a block of commands
*/
extern int is_block;
-/**
- Whether we are reading from the keyboard right now
+/**
+ Whether we are reading from the keyboard right now
*/
int get_is_interactive(void);
-/**
- Whether this shell is attached to the keyboard at all
+/**
+ Whether this shell is attached to the keyboard at all
*/
extern int is_interactive_session;
-/**
- Whether we are a login shell
+/**
+ Whether we are a login shell
*/
extern int is_login;
-/**
- Whether we are running an event handler
+/**
+ Whether we are running an event handler
*/
extern int is_event;
@@ -375,9 +375,9 @@ class job_iterator_t {
job_list_t * const job_list;
job_list_t::iterator current, end;
public:
-
+
void reset(void);
-
+
job_t *next() {
job_t *job = NULL;
if (current != end) {
@@ -386,7 +386,7 @@ class job_iterator_t {
}
return job;
}
-
+
job_iterator_t(job_list_t &jobs);
job_iterator_t();
};
@@ -471,7 +471,7 @@ job_t *job_get(job_id_t id);
job_t *job_get_from_pid(int pid);
/**
- Tests if the job is stopped
+ Tests if the job is stopped
*/
int job_is_stopped( const job_t *j );
diff --git a/reader.cpp b/reader.cpp
index 4102aa28..3c19557b 100644
--- a/reader.cpp
+++ b/reader.cpp
@@ -194,129 +194,129 @@ typedef int color_t;
class reader_data_t
{
public:
-
- /** String containing the whole current commandline */
- wcstring command_line;
-
+
+ /** String containing the whole current commandline */
+ wcstring command_line;
+
/** String containing the autosuggestion */
wcstring autosuggestion;
/** When backspacing, we suppress autosuggestions */
bool suppress_autosuggestion;
- /** The representation of the current screen contents */
- screen_t screen;
-
+ /** The representation of the current screen contents */
+ screen_t screen;
+
/** The history */
history_t *history;
- /**
- String containing the current search item
- */
- wcstring search_buff;
+ /**
+ String containing the current search item
+ */
+ wcstring search_buff;
/* History search */
history_search_t history_search;
- /**
- Saved position used by token history search
- */
- int token_history_pos;
+ /**
+ Saved position used by token history search
+ */
+ int token_history_pos;
- /**
- Saved search string for token history search. Not handled by command_line_changed.
- */
- wcstring token_history_buff;
+ /**
+ Saved search string for token history search. Not handled by command_line_changed.
+ */
+ wcstring token_history_buff;
- /**
- List for storing previous search results. Used to avoid duplicates.
- */
- wcstring_list_t search_prev;
+ /**
+ List for storing previous search results. Used to avoid duplicates.
+ */
+ wcstring_list_t search_prev;
+
+ /** The current position in search_prev */
+ size_t search_pos;
- /** The current position in search_prev */
- size_t search_pos;
-
/** Length of the command */
size_t command_length() const { return command_line.size(); }
-
+
/** Do what we need to do whenever our command line changes */
void command_line_changed(void);
- /** The current position of the cursor in buff. */
- size_t buff_pos;
+ /** The current position of the cursor in buff. */
+ size_t buff_pos;
- /** Name of the current application */
- wcstring app_name;
+ /** Name of the current application */
+ wcstring app_name;
- /** The prompt commands */
- wcstring left_prompt;
+ /** The prompt commands */
+ wcstring left_prompt;
wcstring right_prompt;
- /** The output of the last evaluation of the prompt command */
- wcstring left_prompt_buff;
-
- /** The output of the last evaluation of the right prompt command */
- wcstring right_prompt_buff;
-
- /**
- Color is the syntax highlighting for buff. The format is that
- color[i] is the classification (according to the enum in
- highlight.h) of buff[i].
- */
+ /** The output of the last evaluation of the prompt command */
+ wcstring left_prompt_buff;
+
+ /** The output of the last evaluation of the right prompt command */
+ wcstring right_prompt_buff;
+
+ /**
+ Color is the syntax highlighting for buff. The format is that
+ color[i] is the classification (according to the enum in
+ highlight.h) of buff[i].
+ */
std::vector<color_t> colors;
- /** An array defining the block level at each character. */
- std::vector<int> indents;
+ /** An array defining the block level at each character. */
+ std::vector<int> indents;
- /**
- Function for tab completion
- */
+ /**
+ Function for tab completion
+ */
complete_function_t complete_func;
- /**
- Function for syntax highlighting
- */
- highlight_function_t highlight_function;
-
- /**
- Function for testing if the string can be returned
- */
- int (*test_func)( const wchar_t * );
-
- /**
- When this is true, the reader will exit
- */
- bool end_loop;
-
- /**
- If this is true, exit reader even if there are running
- jobs. This happens if we press e.g. ^D twice.
- */
- bool prev_end_loop;
-
- /** The current contents of the top item in the kill ring. */
- wcstring kill_item;
-
- /**
- Pointer to previous reader_data
- */
- reader_data_t *next;
-
- /**
- This variable keeps state on if we are in search mode, and
- if yes, what mode
- */
- int search_mode;
-
- /**
- Keep track of whether any internal code has done something
- which is known to require a repaint.
- */
- bool repaint_needed;
-
+ /**
+ Function for syntax highlighting
+ */
+ highlight_function_t highlight_function;
+
+ /**
+ Function for testing if the string can be returned
+ */
+ int (*test_func)( const wchar_t * );
+
+ /**
+ When this is true, the reader will exit
+ */
+ bool end_loop;
+
+ /**
+ If this is true, exit reader even if there are running
+ jobs. This happens if we press e.g. ^D twice.
+ */
+ bool prev_end_loop;
+
+ /** The current contents of the top item in the kill ring. */
+ wcstring kill_item;
+
+ /**
+ Pointer to previous reader_data
+ */
+ reader_data_t *next;
+
+ /**
+ This variable keeps state on if we are in search mode, and
+ if yes, what mode
+ */
+ int search_mode;
+
+ /**
+ Keep track of whether any internal code has done something
+ which is known to require a repaint.
+ */
+ bool repaint_needed;
+
/** Whether the a screen reset is needed after a repaint. */
bool screen_reset_needed;
-
+
/** Constructor */
reader_data_t() :
suppress_autosuggestion(0),
@@ -392,22 +392,22 @@ static int exit_forced;
*/
static void term_donate()
{
- set_color(rgb_color_t::normal(), rgb_color_t::normal());
+ set_color(rgb_color_t::normal(), rgb_color_t::normal());
- while( 1 )
- {
- if( tcsetattr(0,TCSANOW,&saved_modes) )
- {
- if( errno != EINTR )
- {
- debug( 1, _( L"Could not set terminal mode for new job" ) );
- wperror( L"tcsetattr" );
- break;
- }
- }
- else
- break;
- }
+ while( 1 )
+ {
+ if( tcsetattr(0,TCSANOW,&saved_modes) )
+ {
+ if( errno != EINTR )
+ {
+ debug( 1, _( L"Could not set terminal mode for new job" ) );
+ wperror( L"tcsetattr" );
+ break;
+ }
+ }
+ else
+ break;
+ }
}
@@ -418,28 +418,28 @@ static void term_donate()
static void term_steal()
{
- while( 1 )
- {
- if( tcsetattr(0,TCSANOW,&shell_modes) )
- {
- if( errno != EINTR )
- {
- debug( 1, _( L"Could not set terminal mode for shell" ) );
- wperror( L"tcsetattr" );
- break;
- }
- }
- else
- break;
- }
+ while( 1 )
+ {
+ if( tcsetattr(0,TCSANOW,&shell_modes) )
+ {
+ if( errno != EINTR )
+ {
+ debug( 1, _( L"Could not set terminal mode for shell" ) );
+ wperror( L"tcsetattr" );
+ break;
+ }
+ }
+ else
+ break;
+ }
- common_handle_winch(0 );
+ common_handle_winch(0 );
}
int reader_exit_forced()
{
- return exit_forced;
+ return exit_forced;
}
/**
@@ -451,16 +451,16 @@ int reader_exit_forced()
static void reader_repaint()
{
//Update the indentation
- parser_t::principal_parser().test( data->command_line.c_str(), &data->indents[0], 0, 0 );
-
+ parser_t::principal_parser().test( data->command_line.c_str(), &data->indents[0], 0, 0 );
+
wcstring full_line = (data->autosuggestion.empty() ? data->command_line : data->autosuggestion);
size_t len = full_line.size();
if (len < 1)
len = 1;
-
+
std::vector<color_t> colors = data->colors;
colors.resize(len, HIGHLIGHT_AUTOSUGGESTION);
-
+
std::vector<int> indents = data->indents;
indents.resize(len);
@@ -473,7 +473,7 @@ static void reader_repaint()
&indents[0],
data->buff_pos);
- data->repaint_needed = false;
+ data->repaint_needed = false;
}
/**
@@ -482,53 +482,53 @@ static void reader_repaint()
static void reader_kill( size_t begin_idx, size_t length, int mode, int newv )
{
const wchar_t *begin = data->command_line.c_str() + begin_idx;
- if( newv )
- {
+ if( newv )
+ {
data->kill_item = wcstring(begin, length);
- kill_add(data->kill_item);
- }
- else
- {
+ kill_add(data->kill_item);
+ }
+ else
+ {
wcstring old = data->kill_item;
- if( mode == KILL_APPEND )
- {
+ if( mode == KILL_APPEND )
+ {
data->kill_item.append(begin, length);
- }
- else
- {
+ }
+ else
+ {
data->kill_item = wcstring(begin, length);
data->kill_item.append(old);
- }
+ }
+
-
- kill_replace( old, data->kill_item );
- }
+ kill_replace( old, data->kill_item );
+ }
- if( data->buff_pos > begin_idx ) {
+ if( data->buff_pos > begin_idx ) {
/* Move the buff position back by the number of characters we deleted, but don't go past buff_pos */
size_t backtrack = mini(data->buff_pos - begin_idx, length);
data->buff_pos -= backtrack;
- }
-
+ }
+
data->command_line.erase(begin_idx, length);
data->command_line_changed();
-
- reader_super_highlight_me_plenty( data->buff_pos );
- reader_repaint();
-
+
+ reader_super_highlight_me_plenty( data->buff_pos );
+ reader_repaint();
+
}
/* This is called from a signal handler! */
void reader_handle_int( int sig )
{
- if( !is_interactive_read )
- {
+ if( !is_interactive_read )
+ {
parser_t::skip_all_blocks();
- }
-
- interrupted = 1;
-
+ }
+
+ interrupted = 1;
+
}
const wchar_t *reader_current_filename()
@@ -548,7 +548,7 @@ void reader_push_current_filename( const wchar_t *fn )
void reader_pop_current_filename()
{
ASSERT_IS_MAIN_THREAD();
- current_filename.pop();
+ current_filename.pop();
}
@@ -556,13 +556,13 @@ void reader_pop_current_filename()
void reader_data_t::command_line_changed() {
ASSERT_IS_MAIN_THREAD();
size_t len = command_length();
-
+
/* When we grow colors, propagate the last color (if any), under the assumption that usually it will be correct. If it is, it avoids a repaint. */
color_t last_color = colors.empty() ? color_t() : colors.back();
colors.resize(len, last_color);
-
+
indents.resize(len);
-
+
/* Update the gen count */
s_generation_count++;
}
@@ -571,84 +571,84 @@ void reader_data_t::command_line_changed() {
/** Remove any duplicate completions in the list. This relies on the list first beeing sorted. */
static void remove_duplicates(std::vector<completion_t> &l)
{
- l.erase(std::unique( l.begin(), l.end()), l.end());
+ l.erase(std::unique( l.begin(), l.end()), l.end());
}
int reader_interrupted()
{
- int res=interrupted;
- if( res )
- interrupted=0;
- return res;
+ int res=interrupted;
+ if( res )
+ interrupted=0;
+ return res;
}
void reader_write_title()
{
- const wchar_t *title;
- const env_var_t term_str = env_get_string( L"TERM" );
-
- /*
- This is a pretty lame heuristic for detecting terminals that do
- not support setting the title. If we recognise the terminal name
- as that of a virtual terminal, we assume it supports setting the
- title. If we recognise it as that of a console, we assume it
- does not support setting the title. Otherwise we check the
- ttyname and see if we belive it is a virtual terminal.
-
- One situation in which this breaks down is with screen, since
- screen supports setting the terminal title if the underlying
- terminal does so, but will print garbage on terminals that
- don't. Since we can't see the underlying terminal below screen
- there is no way to fix this.
- */
- if ( term_str.missing() )
- return;
-
- const wchar_t *term = term_str.c_str();
+ const wchar_t *title;
+ const env_var_t term_str = env_get_string( L"TERM" );
+
+ /*
+ This is a pretty lame heuristic for detecting terminals that do
+ not support setting the title. If we recognise the terminal name
+ as that of a virtual terminal, we assume it supports setting the
+ title. If we recognise it as that of a console, we assume it
+ does not support setting the title. Otherwise we check the
+ ttyname and see if we belive it is a virtual terminal.
+
+ One situation in which this breaks down is with screen, since
+ screen supports setting the terminal title if the underlying
+ terminal does so, but will print garbage on terminals that
+ don't. Since we can't see the underlying terminal below screen
+ there is no way to fix this.
+ */
+ if ( term_str.missing() )
+ return;
+
+ const wchar_t *term = term_str.c_str();
bool recognized = false;
recognized = recognized || contains( term, L"xterm", L"screen", L"nxterm", L"rxvt" );
recognized = recognized || ! wcsncmp(term, L"xterm-", wcslen(L"xterm-"));
recognized = recognized || ! wcsncmp(term, L"screen-", wcslen(L"screen-"));
- if( ! recognized )
- {
- char *n = ttyname( STDIN_FILENO );
+ if( ! recognized )
+ {
+ char *n = ttyname( STDIN_FILENO );
+
+
+ if( contains( term, L"linux" ) )
+ {
+ return;
+ }
+ if( strstr( n, "tty" ) || strstr( n, "/vc/") )
+ return;
- if( contains( term, L"linux" ) )
- {
- return;
- }
- if( strstr( n, "tty" ) || strstr( n, "/vc/") )
- return;
-
-
- }
+ }
- title = function_exists( L"fish_title" )?L"fish_title":DEFAULT_TITLE;
+ title = function_exists( L"fish_title" )?L"fish_title":DEFAULT_TITLE;
- if( wcslen( title ) ==0 )
- return;
+ if( wcslen( title ) ==0 )
+ return;
wcstring_list_t lst;
- proc_push_interactive(0);
- if( exec_subshell( title, lst ) != -1 )
- {
- size_t i;
- if( lst.size() > 0 )
- {
- writestr( L"\x1b]0;" );
- for( i=0; i<lst.size(); i++ )
- {
- writestr( lst.at(i).c_str() );
- }
- writestr( L"\7" );
- }
- }
- proc_pop_interactive();
- set_color( rgb_color_t::reset(), rgb_color_t::reset() );
+ proc_push_interactive(0);
+ if( exec_subshell( title, lst ) != -1 )
+ {
+ size_t i;
+ if( lst.size() > 0 )
+ {
+ writestr( L"\x1b]0;" );
+ for( i=0; i<lst.size(); i++ )
+ {
+ writestr( lst.at(i).c_str() );
+ }
+ writestr( L"\7" );
+ }
+ }
+ proc_pop_interactive();
+ set_color( rgb_color_t::reset(), rgb_color_t::reset() );
}
/**
@@ -659,12 +659,12 @@ static void exec_prompt()
/* Clear existing prompts */
data->left_prompt_buff.clear();
data->right_prompt_buff.clear();
-
+
/* If we have any prompts, they must be run non-interactively */
if (data->left_prompt.size() || data->right_prompt.size())
{
proc_push_interactive( 0 );
-
+
if (data->left_prompt.size())
{
wcstring_list_t prompt_list;
@@ -677,7 +677,7 @@ static void exec_prompt()
}
}
}
-
+
if (data->right_prompt.size())
{
wcstring_list_t prompt_list;
@@ -690,34 +690,34 @@ static void exec_prompt()
}
}
}
-
+
proc_pop_interactive();
}
-
+
/* Write the screen title */
- reader_write_title();
+ reader_write_title();
}
void reader_init()
{
- tcgetattr(0,&shell_modes); /* get the current terminal modes */
- memcpy( &saved_modes,
- &shell_modes,
- sizeof(saved_modes)); /* save a copy so we can reset the terminal later */
-
- shell_modes.c_lflag &= ~ICANON; /* turn off canonical mode */
- shell_modes.c_lflag &= ~ECHO; /* turn off echo mode */
+ tcgetattr(0,&shell_modes); /* get the current terminal modes */
+ memcpy( &saved_modes,
+ &shell_modes,
+ sizeof(saved_modes)); /* save a copy so we can reset the terminal later */
+
+ shell_modes.c_lflag &= ~ICANON; /* turn off canonical mode */
+ shell_modes.c_lflag &= ~ECHO; /* turn off echo mode */
shell_modes.c_cc[VMIN]=1;
shell_modes.c_cc[VTIME]=0;
-
+
// PCA disable VDSUSP (typically control-Y), which is a funny job control
// function available only on OS X and BSD systems
// This lets us use control-Y for yank instead
#ifdef VDSUSP
- shell_modes.c_cc[VDSUSP] = _POSIX_VDISABLE;
+ shell_modes.c_cc[VDSUSP] = _POSIX_VDISABLE;
#endif
-
+
/* Repaint if necessary before each byte is read. This lets us react immediately to universal variable color changes. */
input_common_set_poll_callback(reader_repaint_if_needed);
}
@@ -725,25 +725,25 @@ void reader_init()
void reader_destroy()
{
- tcsetattr(0, TCSANOW, &saved_modes);
+ tcsetattr(0, TCSANOW, &saved_modes);
}
void reader_exit( int do_exit, int forced )
{
- if( data )
- data->end_loop=do_exit;
- end_loop=do_exit;
- if( forced )
- exit_forced = 1;
-
+ if( data )
+ data->end_loop=do_exit;
+ end_loop=do_exit;
+ if( forced )
+ exit_forced = 1;
+
}
void reader_repaint_needed()
{
- if (data) {
- data->repaint_needed = true;
- }
+ if (data) {
+ data->repaint_needed = true;
+ }
}
void reader_repaint_if_needed() {
@@ -759,10 +759,10 @@ void reader_repaint_if_needed() {
}
void reader_react_to_color_change() {
- if (data) {
+ if (data) {
data->repaint_needed = true;
data->screen_reset_needed = true;
- }
+ }
}
@@ -773,22 +773,22 @@ void reader_react_to_color_change() {
static void remove_backward()
{
- if( data->buff_pos <= 0 )
- return;
-
+ if( data->buff_pos <= 0 )
+ return;
+
/* Fake composed character sequences by continuning to delete until we delete a character of width at least 1. */
int width;
do {
data->buff_pos -= 1;
width = fish_wcwidth(data->command_line.at(data->buff_pos));
- data->command_line.erase(data->buff_pos, 1);
+ data->command_line.erase(data->buff_pos, 1);
} while (width == 0 && data->buff_pos > 0);
data->command_line_changed();
data->suppress_autosuggestion = true;
- reader_super_highlight_me_plenty( data->buff_pos );
+ reader_super_highlight_me_plenty( data->buff_pos );
- reader_repaint();
+ reader_repaint();
}
@@ -802,18 +802,18 @@ static int insert_string(const wcstring &str)
size_t len = str.size();
if (len == 0)
return 0;
-
+
data->command_line.insert(data->buff_pos, str);
data->buff_pos += len;
data->command_line_changed();
data->suppress_autosuggestion = false;
-
- /* Syntax highlight. Note we must have that buff_pos > 0 because we just added something nonzero to its length */
+
+ /* Syntax highlight. Note we must have that buff_pos > 0 because we just added something nonzero to its length */
assert(data->buff_pos > 0);
- reader_super_highlight_me_plenty( data->buff_pos-1 );
-
- reader_repaint();
- return 1;
+ reader_super_highlight_me_plenty( data->buff_pos-1 );
+
+ reader_repaint();
+ return 1;
}
@@ -823,7 +823,7 @@ static int insert_string(const wcstring &str)
*/
static int insert_char( wchar_t c )
{
- return insert_string(wcstring(&c, 1));
+ return insert_string(wcstring(&c, 1));
}
@@ -832,10 +832,10 @@ static int insert_char( wchar_t c )
*/
static size_t comp_len( const wchar_t *a, const wchar_t *b )
{
- size_t i;
- for( i=0; a[i] != L'\0' && b[i] != L'\0' && a[i]==b[i]; i++ )
- ;
- return i;
+ size_t i;
+ for( i=0; a[i] != L'\0' && b[i] != L'\0' && a[i]==b[i]; i++ )
+ ;
+ return i;
}
/**
@@ -843,10 +843,10 @@ static size_t comp_len( const wchar_t *a, const wchar_t *b )
*/
static size_t comp_ilen( const wchar_t *a, const wchar_t *b )
{
- size_t i;
- for( i=0; a[i] != L'\0' && b[i] != L'\0' && towlower(a[i])==towlower(b[i]); i++ )
- ;
- return i;
+ size_t i;
+ for( i=0; a[i] != L'\0' && b[i] != L'\0' && towlower(a[i])==towlower(b[i]); i++ )
+ ;
+ return i;
}
@@ -863,71 +863,71 @@ static size_t comp_ilen( const wchar_t *a, const wchar_t *b )
static wcstring completion_apply_to_command_line(const wcstring &val_str, int flags, const wcstring &command_line, size_t *inout_cursor_pos)
{
const wchar_t *val = val_str.c_str();
- bool add_space = !(flags & COMPLETE_NO_SPACE);
- bool do_replace = !!(flags & COMPLETE_NO_CASE);
- bool do_escape = !(flags & COMPLETE_DONT_ESCAPE);
+ bool add_space = !(flags & COMPLETE_NO_SPACE);
+ bool do_replace = !!(flags & COMPLETE_NO_CASE);
+ bool do_escape = !(flags & COMPLETE_DONT_ESCAPE);
const size_t cursor_pos = *inout_cursor_pos;
-
- // debug( 0, L"Insert completion %ls with flags %d", val, flags);
-
- if( do_replace )
- {
-
- size_t move_cursor;
- const wchar_t *begin, *end;
- wchar_t *escaped;
-
+
+ // debug( 0, L"Insert completion %ls with flags %d", val, flags);
+
+ if( do_replace )
+ {
+
+ size_t move_cursor;
+ const wchar_t *begin, *end;
+ wchar_t *escaped;
+
const wchar_t *buff = command_line.c_str();
- parse_util_token_extent( buff, cursor_pos, &begin, 0, 0, 0 );
- end = buff + cursor_pos;
-
- wcstring sb(buff, begin - buff);
-
- if( do_escape )
- {
- escaped = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
- sb.append( escaped );
- move_cursor = wcslen(escaped);
- free( escaped );
- }
- else
- {
- sb.append( val );
- move_cursor = wcslen(val);
- }
-
-
- if( add_space )
- {
- sb.append( L" " );
- move_cursor += 1;
- }
- sb.append( end );
-
+ parse_util_token_extent( buff, cursor_pos, &begin, 0, 0, 0 );
+ end = buff + cursor_pos;
+
+ wcstring sb(buff, begin - buff);
+
+ if( do_escape )
+ {
+ escaped = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
+ sb.append( escaped );
+ move_cursor = wcslen(escaped);
+ free( escaped );
+ }
+ else
+ {
+ sb.append( val );
+ move_cursor = wcslen(val);
+ }
+
+
+ if( add_space )
+ {
+ sb.append( L" " );
+ move_cursor += 1;
+ }
+ sb.append( end );
+
size_t new_cursor_pos = (begin - buff) + move_cursor;
*inout_cursor_pos = new_cursor_pos;
return sb;
- }
- else
- {
+ }
+ else
+ {
wchar_t quote = L'\0';
wcstring replaced;
- if( do_escape )
- {
+ if( do_escape )
+ {
parse_util_get_parameter_info(command_line, cursor_pos, &quote, NULL, NULL);
replaced = parse_util_escape_string_with_quote(val_str, quote);
- }
- else
- {
- replaced = val;
- }
-
+ }
+ else
+ {
+ replaced = val;
+ }
+
wcstring result = command_line;
result.insert(cursor_pos, replaced);
size_t new_cursor_pos = cursor_pos + replaced.size();
if (add_space)
{
- if (quote && (command_line.c_str()[cursor_pos] != quote))
+ if (quote && (command_line.c_str()[cursor_pos] != quote))
{
/* This is a quoted parameter, first print a quote */
result.insert(new_cursor_pos++, wcstring(&quote, 1));
@@ -936,7 +936,7 @@ static wcstring completion_apply_to_command_line(const wcstring &val_str, int fl
}
*inout_cursor_pos = new_cursor_pos;
return result;
- }
+ }
}
/**
@@ -953,7 +953,7 @@ static void completion_insert( const wchar_t *val, int flags )
size_t cursor = data->buff_pos;
wcstring new_command_line = completion_apply_to_command_line(val, flags, data->command_line, &cursor);
reader_set_buffer(new_command_line, cursor);
-
+
/* Since we just inserted a completion, don't immediately do a new autosuggestion */
data->suppress_autosuggestion = true;
}
@@ -963,7 +963,7 @@ static void completion_insert( const wchar_t *val, int flags )
fish_pager outputs any text, it is inserted into the input
backbuffer.
- \param prefix the string to display before every completion.
+ \param prefix the string to display before every completion.
\param is_quoted should be set if the argument is quoted. This will change the display style.
\param comp the list of completions to display
*/
@@ -971,74 +971,74 @@ static void completion_insert( const wchar_t *val, int flags )
static void run_pager( const wcstring &prefix, int is_quoted, const std::vector<completion_t> &comp )
{
wcstring msg;
- wcstring prefix_esc;
- char *foo;
-
- wchar_t *escaped_separator;
- int has_case_sensitive=0;
-
- if (prefix.empty())
- {
- prefix_esc = L"\"\"";
- }
- else
- {
- prefix_esc = escape_string(prefix, 1);
- }
-
+ wcstring prefix_esc;
+ char *foo;
+
+ wchar_t *escaped_separator;
+ int has_case_sensitive=0;
+
+ if (prefix.empty())
+ {
+ prefix_esc = L"\"\"";
+ }
+ else
+ {
+ prefix_esc = escape_string(prefix, 1);
+ }
+
wcstring cmd = format_string(L"fish_pager -c 3 -r 4 %ls -p %ls",
// L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./fish_pager %d %ls",
is_quoted?L"-q":L"",
prefix_esc.c_str() );
-
+
io_data_t *in = io_buffer_create(true);
- in->fd = 3;
-
- escaped_separator = escape( COMPLETE_SEP_STR, 1);
-
- for( size_t i=0; i< comp.size(); i++ )
- {
- const completion_t &el = comp.at( i );
- has_case_sensitive |= !(el.flags & COMPLETE_NO_CASE );
- }
-
- for( size_t i=0; i< comp.size(); i++ )
- {
-
- long base_len=-1;
- const completion_t &el = comp.at( i );
-
- wcstring completion_text;
- wcstring description_text;
-
- if( has_case_sensitive && (el.flags & COMPLETE_NO_CASE ))
- {
- continue;
- }
-
- // Note that an empty completion is perfectly sensible here, e.g. tab-completing 'foo' with a file called 'foo' and another called 'foobar'
- if( el.flags & COMPLETE_NO_CASE )
- {
- if( base_len == -1 )
+ in->fd = 3;
+
+ escaped_separator = escape( COMPLETE_SEP_STR, 1);
+
+ for( size_t i=0; i< comp.size(); i++ )
+ {
+ const completion_t &el = comp.at( i );
+ has_case_sensitive |= !(el.flags & COMPLETE_NO_CASE );
+ }
+
+ for( size_t i=0; i< comp.size(); i++ )
+ {
+
+ long base_len=-1;
+ const completion_t &el = comp.at( i );
+
+ wcstring completion_text;
+ wcstring description_text;
+
+ if( has_case_sensitive && (el.flags & COMPLETE_NO_CASE ))
+ {
+ continue;
+ }
+
+ // Note that an empty completion is perfectly sensible here, e.g. tab-completing 'foo' with a file called 'foo' and another called 'foobar'
+ if( el.flags & COMPLETE_NO_CASE )
+ {
+ if( base_len == -1 )
{
const wchar_t *begin, *buff = data->command_line.c_str();
-
+
parse_util_token_extent( buff, data->buff_pos, &begin, 0, 0, 0 );
base_len = data->buff_pos - (begin-buff);
}
-
- completion_text = escape_string( el.completion.c_str() + base_len, ESCAPE_ALL | ESCAPE_NO_QUOTED );
- }
- else
+
+ completion_text = escape_string( el.completion.c_str() + base_len, ESCAPE_ALL | ESCAPE_NO_QUOTED );
+ }
+ else
{
- completion_text = escape_string( el.completion, ESCAPE_ALL | ESCAPE_NO_QUOTED );
+ completion_text = escape_string( el.completion, ESCAPE_ALL | ESCAPE_NO_QUOTED );
}
-
-
- if( ! el.description.empty() )
- {
- description_text = escape_string( el.description, true );
- }
+
+
+ if( ! el.description.empty() )
+ {
+ description_text = escape_string( el.description, true );
+ }
/* It's possible (even common) to have an empty completion with no description. An example would be completing 'foo' with extant files 'foo' and 'foobar'. But fish_pager ignores blank lines. So if our completion text is empty, always include a description, even if it's empty.
*/
@@ -1052,44 +1052,44 @@ static void run_pager( const wcstring &prefix, int is_quoted, const std::vector<
msg.push_back(L'\n');
}
- free( escaped_separator );
-
- foo = wcs2str(msg.c_str());
- in->out_buffer_append(foo, strlen(foo) );
- free( foo );
-
- term_donate();
-
- io_data_t *out = io_buffer_create( false );
- out->fd = 4;
-
+ free( escaped_separator );
+
+ foo = wcs2str(msg.c_str());
+ in->out_buffer_append(foo, strlen(foo) );
+ free( foo );
+
+ term_donate();
+
+ io_data_t *out = io_buffer_create( false );
+ out->fd = 4;
+
parser_t &parser = parser_t::principal_parser();
io_chain_t io_chain;
io_chain.push_back(out);
io_chain.push_back(in);
- parser.eval( cmd, io_chain, TOP);
- term_steal();
+ parser.eval( cmd, io_chain, TOP);
+ term_steal();
- io_buffer_read( out );
+ io_buffer_read( out );
- int nil=0;
+ int nil=0;
out->out_buffer_append((char *)&nil, 1);
- wchar_t *tmp;
- wchar_t *str = str2wcs(out->out_buffer_ptr());
+ wchar_t *tmp;
+ wchar_t *str = str2wcs(out->out_buffer_ptr());
- if( str )
- {
- for( tmp = str + wcslen(str)-1; tmp >= str; tmp-- )
- {
- input_unreadch( *tmp );
- }
- free( str );
- }
+ if( str )
+ {
+ for( tmp = str + wcslen(str)-1; tmp >= str; tmp-- )
+ {
+ input_unreadch( *tmp );
+ }
+ free( str );
+ }
- io_buffer_destroy( out);
- io_buffer_destroy( in);
+ io_buffer_destroy( out);
+ io_buffer_destroy( in);
}
struct autosuggestion_context_t {
@@ -1102,10 +1102,10 @@ struct autosuggestion_context_t {
const env_vars_snapshot_t vars;
wcstring_list_t commands_to_load;
const unsigned int generation_count;
-
+
// don't reload more than once
bool has_tried_reloading;
-
+
autosuggestion_context_t(history_t *history, const wcstring &term, size_t pos) :
search_string(term),
cursor_pos(pos),
@@ -1117,28 +1117,28 @@ struct autosuggestion_context_t {
has_tried_reloading(false)
{
}
-
+
/* The function run in the background thread to determine an autosuggestion */
int threaded_autosuggest(void) {
ASSERT_IS_BACKGROUND_THREAD();
-
+
/* If the main thread has moved on, skip all the work */
if (generation_count != s_generation_count) {
return 0;
}
-
+
/* Let's make sure we aren't using the empty string */
if (search_string.empty()) {
return 0;
}
-
+
while (searcher.go_backwards()) {
history_item_t item = searcher.current_item();
-
+
/* Skip items with newlines because they make terrible autosuggestions */
if (item.str().find('\n') != wcstring::npos)
continue;
-
+
if (autosuggest_validate_from_history(item, detector, working_directory, vars)) {
/* The command autosuggestion was handled specially, so we're done */
this->autosuggestion = searcher.current_string();
@@ -1146,14 +1146,14 @@ struct autosuggestion_context_t {
}
}
-
+
/* Try handling a special command like cd */
wcstring special_suggestion;
if (autosuggest_suggest_special(search_string, working_directory, special_suggestion)) {
this->autosuggestion = special_suggestion;
return 1;
}
-
+
// Here we do something a little funny
// If the line ends with a space, and the cursor is not at the end,
// don't use completion autosuggestions. It ends up being pretty weird seeing stuff get spammed on the right
@@ -1176,7 +1176,7 @@ struct autosuggestion_context_t {
this->autosuggestion = completion_apply_to_command_line(comp.completion.c_str(), comp.flags, this->search_string, &cursor);
return 1;
}
-
+
return 0;
}
};
@@ -1198,7 +1198,7 @@ static void autosuggest_completed(autosuggestion_context_t *ctx, int result) {
/* Extract the commands to load */
wcstring_list_t commands_to_load;
ctx->commands_to_load.swap(commands_to_load);
-
+
/* If we have autosuggestions to load, load them and try again */
if (! result && ! commands_to_load.empty() && ! ctx->has_tried_reloading)
{
@@ -1210,7 +1210,7 @@ static void autosuggest_completed(autosuggestion_context_t *ctx, int result) {
iothread_perform(threaded_autosuggest, autosuggest_completed, ctx);
return;
}
-
+
if (result &&
can_autosuggest() &&
ctx->search_string == data->command_line &&
@@ -1263,22 +1263,22 @@ static void accept_autosuggestion(void) {
*/
static void reader_flash()
{
- struct timespec pollint;
+ struct timespec pollint;
+
+ for( size_t i=0; i<data->buff_pos; i++ )
+ {
+ data->colors.at(i) = HIGHLIGHT_SEARCH_MATCH<<16;
+ }
- for( size_t i=0; i<data->buff_pos; i++ )
- {
- data->colors.at(i) = HIGHLIGHT_SEARCH_MATCH<<16;
- }
-
- reader_repaint();
-
- pollint.tv_sec = 0;
- pollint.tv_nsec = 100 * 1000000;
- nanosleep( &pollint, NULL );
+ reader_repaint();
- reader_super_highlight_me_plenty( data->buff_pos );
-
- reader_repaint();
+ pollint.tv_sec = 0;
+ pollint.tv_nsec = 100 * 1000000;
+ nanosleep( &pollint, NULL );
+
+ reader_super_highlight_me_plenty( data->buff_pos );
+
+ reader_repaint();
}
/**
@@ -1299,23 +1299,23 @@ static void reader_flash()
static bool reader_can_replace( const wcstring &in, int flags )
{
- const wchar_t * str = in.c_str();
+ const wchar_t * str = in.c_str();
- if( flags & COMPLETE_DONT_ESCAPE )
- {
- return true;
- }
- /*
- Test characters that have a special meaning in any character position
- */
- while( *str )
- {
- if( wcschr( REPLACE_UNCLEAN, *str ) )
- return false;
- str++;
- }
+ if( flags & COMPLETE_DONT_ESCAPE )
+ {
+ return true;
+ }
+ /*
+ Test characters that have a special meaning in any character position
+ */
+ while( *str )
+ {
+ if( wcschr( REPLACE_UNCLEAN, *str ) )
+ return false;
+ str++;
+ }
- return true;
+ return true;
}
/* Compare two completions, except make the case insensitive comes larger than everyone (so they come last) */
@@ -1350,14 +1350,14 @@ static const completion_t *cycle_competions(const std::vector<completion_t> &com
{
/* Bump the index */
idx = (idx + 1) % size;
-
+
/* Bail if we've looped */
if (idx == start_idx)
break;
-
+
/* Get the completion */
const completion_t &c = comp.at(idx);
-
+
/* Try this completion */
if (! c.is_case_insensitive() || reader_can_replace(command_line, c.flags))
{
@@ -1366,14 +1366,14 @@ static const completion_t *cycle_competions(const std::vector<completion_t> &com
break;
}
}
-
+
*inout_idx = idx;
return result;
}
/**
Handle the list of completions. This means the following:
-
+
- If the list is empty, flash the terminal.
- If the list contains one element, write the whole element, and if
the element does not end on a '/', '@', ':', or a '=', also write a trailing
@@ -1382,199 +1382,199 @@ static const completion_t *cycle_competions(const std::vector<completion_t> &com
the prefix.
- If the list contains multiple elements without.
a common prefix, call run_pager to display a list of completions. Depending on terminal size and the length of the list, run_pager may either show less than a screenfull and exit or use an interactive pager to allow the user to scroll through the completions.
-
+
\param comp the list of completion strings
-
+
Return true if we inserted text into the command line, false if we did not.
*/
static bool handle_completions( const std::vector<completion_t> &comp )
{
- wchar_t *base = NULL;
- size_t len = 0;
- bool done = false;
+ wchar_t *base = NULL;
+ size_t len = 0;
+ bool done = false;
bool success = false;
- int count = 0;
- int flags=0;
- const wchar_t *begin, *end, *buff = data->command_line.c_str();
-
- parse_util_token_extent( buff, data->buff_pos, &begin, 0, 0, 0 );
- end = buff+data->buff_pos;
-
+ int count = 0;
+ int flags=0;
+ const wchar_t *begin, *end, *buff = data->command_line.c_str();
+
+ parse_util_token_extent( buff, data->buff_pos, &begin, 0, 0, 0 );
+ end = buff+data->buff_pos;
+
const wcstring tok(begin, end - begin);
-
- /*
- Check trivial cases
- */
- switch(comp.size())
- {
- /* No suitable completions found, flash screen and return */
- case 0:
- {
- reader_flash();
- done = true;
+
+ /*
+ Check trivial cases
+ */
+ switch(comp.size())
+ {
+ /* No suitable completions found, flash screen and return */
+ case 0:
+ {
+ reader_flash();
+ done = true;
success = false;
- break;
- }
-
- /* Exactly one suitable completion found - insert it */
- case 1:
- {
-
- const completion_t &c = comp.at( 0 );
-
- /*
- If this is a replacement completion, check
- that we know how to replace it, e.g. that
- the token doesn't contain evil operators
- like {}
- */
- if( ! c.is_case_insensitive() || reader_can_replace( tok, c.flags ) )
- {
- completion_insert( c.completion.c_str(), c.flags );
- }
- done = true;
- success = true;
- break;
- }
- }
-
-
- if( !done )
- {
- /* Try to find something to insert with the correct case */
- for( size_t i=0; i< comp.size() ; i++ )
- {
- const completion_t &c = comp.at( i );
-
- /* Ignore case insensitive completions for now */
- if( c.is_case_insensitive() )
- continue;
-
- count++;
-
- if( base )
- {
- size_t new_len = comp_len( base, c.completion.c_str() );
+ break;
+ }
+
+ /* Exactly one suitable completion found - insert it */
+ case 1:
+ {
+
+ const completion_t &c = comp.at( 0 );
+
+ /*
+ If this is a replacement completion, check
+ that we know how to replace it, e.g. that
+ the token doesn't contain evil operators
+ like {}
+ */
+ if( ! c.is_case_insensitive() || reader_can_replace( tok, c.flags ) )
+ {
+ completion_insert( c.completion.c_str(), c.flags );
+ }
+ done = true;
+ success = true;
+ break;
+ }
+ }
+
+
+ if( !done )
+ {
+ /* Try to find something to insert with the correct case */
+ for( size_t i=0; i< comp.size() ; i++ )
+ {
+ const completion_t &c = comp.at( i );
+
+ /* Ignore case insensitive completions for now */
+ if( c.is_case_insensitive() )
+ continue;
+
+ count++;
+
+ if( base )
+ {
+ size_t new_len = comp_len( base, c.completion.c_str() );
len = mini(new_len, len);
- }
- else
- {
- base = wcsdup( c.completion.c_str() );
- len = wcslen( base );
- flags = c.flags;
- }
- }
-
- /* If we found something to insert, do it. */
- if( len > 0 )
- {
- if( count > 1 )
- flags = flags | COMPLETE_NO_SPACE;
-
- base[len]=L'\0';
- completion_insert(base, flags);
- done = true;
+ }
+ else
+ {
+ base = wcsdup( c.completion.c_str() );
+ len = wcslen( base );
+ flags = c.flags;
+ }
+ }
+
+ /* If we found something to insert, do it. */
+ if( len > 0 )
+ {
+ if( count > 1 )
+ flags = flags | COMPLETE_NO_SPACE;
+
+ base[len]=L'\0';
+ completion_insert(base, flags);
+ done = true;
success = true;
- }
- }
-
-
-
- if( !done && base == NULL )
- {
- /* Try to find something to insert ignoring case */
- if( begin )
- {
- size_t offset = tok.size();
-
- count = 0;
-
- for( size_t i=0; i< comp.size(); i++ )
- {
- const completion_t &c = comp.at( i );
-
- if( ! c.is_case_insensitive() )
- continue;
-
- if( !reader_can_replace( tok, c.flags ) )
- {
- len=0;
- break;
- }
-
- count++;
-
- if( base )
- {
- size_t new_len = offset + comp_ilen( base+offset, c.completion.c_str()+offset );
- len = new_len < len ? new_len: len;
- }
- else
- {
- base = wcsdup( c.completion.c_str() );
- len = wcslen( base );
- flags = c.flags;
-
- }
- }
-
- if( len > offset )
- {
- if( count > 1 )
- flags = flags | COMPLETE_NO_SPACE;
-
- base[len]=L'\0';
- completion_insert( base, flags );
- done = 1;
+ }
+ }
+
+
+
+ if( !done && base == NULL )
+ {
+ /* Try to find something to insert ignoring case */
+ if( begin )
+ {
+ size_t offset = tok.size();
+
+ count = 0;
+
+ for( size_t i=0; i< comp.size(); i++ )
+ {
+ const completion_t &c = comp.at( i );
+
+ if( ! c.is_case_insensitive() )
+ continue;
+
+ if( !reader_can_replace( tok, c.flags ) )
+ {
+ len=0;
+ break;
+ }
+
+ count++;
+
+ if( base )
+ {
+ size_t new_len = offset + comp_ilen( base+offset, c.completion.c_str()+offset );
+ len = new_len < len ? new_len: len;
+ }
+ else
+ {
+ base = wcsdup( c.completion.c_str() );
+ len = wcslen( base );
+ flags = c.flags;
+
+ }
+ }
+
+ if( len > offset )
+ {
+ if( count > 1 )
+ flags = flags | COMPLETE_NO_SPACE;
+
+ base[len]=L'\0';
+ completion_insert( base, flags );
+ done = 1;
success = true;
- }
-
- }
- }
-
- free( base );
-
- if( !done )
- {
- /*
- There is no common prefix in the completions, and show_list
- is true, so we print the list
- */
- size_t len, prefix_start = 0;
- wcstring prefix;
- parse_util_get_parameter_info(data->command_line, data->buff_pos, NULL, &prefix_start, NULL);
-
- assert(data->buff_pos >= prefix_start);
- len = data->buff_pos - prefix_start;
-
- if( len <= PREFIX_MAX_LEN )
+ }
+
+ }
+ }
+
+ free( base );
+
+ if( !done )
+ {
+ /*
+ There is no common prefix in the completions, and show_list
+ is true, so we print the list
+ */
+ size_t len, prefix_start = 0;
+ wcstring prefix;
+ parse_util_get_parameter_info(data->command_line, data->buff_pos, NULL, &prefix_start, NULL);
+
+ assert(data->buff_pos >= prefix_start);
+ len = data->buff_pos - prefix_start;
+
+ if( len <= PREFIX_MAX_LEN )
{
prefix.append(data->command_line, prefix_start, len);
- }
- else
- {
+ }
+ else
+ {
// append just the end of the string
prefix = wcstring(&ellipsis_char, 1);
- prefix.append(data->command_line, prefix_start + len - PREFIX_MAX_LEN - 1, wcstring::npos);
+ prefix.append(data->command_line, prefix_start + len - PREFIX_MAX_LEN - 1, wcstring::npos);
}
- {
- int is_quoted;
-
- wchar_t quote;
- parse_util_get_parameter_info(data->command_line, data->buff_pos, &quote, NULL, NULL);
- is_quoted = (quote != L'\0');
-
- write_loop(1, "\n", 1 );
-
- run_pager( prefix, is_quoted, comp );
- }
- s_reset( &data->screen, true);
- reader_repaint();
+ {
+ int is_quoted;
+
+ wchar_t quote;
+ parse_util_get_parameter_info(data->command_line, data->buff_pos, &quote, NULL, NULL);
+ is_quoted = (quote != L'\0');
+
+ write_loop(1, "\n", 1 );
+
+ run_pager( prefix, is_quoted, comp );
+ }
+ s_reset( &data->screen, true);
+ reader_repaint();
success = false;
- }
- return success;
+ }
+ return success;
}
@@ -1583,101 +1583,101 @@ static bool handle_completions( const std::vector<completion_t> &comp )
*/
static void reader_interactive_init()
{
- /* See if we are running interactively. */
- pid_t shell_pgid;
-
- input_init();
- kill_init();
- shell_pgid = getpgrp ();
-
- /*
- This should enable job control on fish, even if our parent process did
- not enable it for us.
- */
-
- /*
- Check if we are in control of the terminal, so that we don't do
- semi-expensive things like reset signal handlers unless we
- really have to, which we often don't.
- */
- if (tcgetpgrp( 0 ) != shell_pgid)
- {
- int block_count = 0;
- int i;
-
- /*
- Bummer, we are not in control of the terminal. Stop until
- parent has given us control of it. Stopping in fish is a bit
- of a challange, what with all the signal fidgeting, we need
- to reset a bunch of signal state, making this coda a but
- unobvious.
-
- In theory, reseting signal handlers could cause us to miss
- signal deliveries. In practice, this code should only be run
- suring startup, when we're not waiting for any signals.
- */
- while (signal_is_blocked())
- {
- signal_unblock();
- block_count++;
- }
- signal_reset_handlers();
-
- /*
- Ok, signal handlers are taken out of the picture. Stop ourself in a loop
- until we are in control of the terminal.
- */
- while (tcgetpgrp( 0 ) != shell_pgid)
- {
- killpg( shell_pgid, SIGTTIN);
- }
-
- signal_set_handlers();
-
- for( i=0; i<block_count; i++ )
- {
- signal_block();
- }
-
- }
-
-
- /* Put ourselves in our own process group. */
- shell_pgid = getpid ();
- if( getpgrp() != shell_pgid )
- {
- if (setpgid (shell_pgid, shell_pgid) < 0)
- {
- debug( 1,
- _( L"Couldn't put the shell in its own process group" ));
- wperror( L"setpgid" );
- exit (1);
- }
- }
-
- /* Grab control of the terminal. */
- if( tcsetpgrp (STDIN_FILENO, shell_pgid) )
- {
- debug( 1,
- _( L"Couldn't grab control of terminal" ) );
- wperror( L"tcsetpgrp" );
- exit_without_destructors(1);
- }
-
- common_handle_winch(0);
+ /* See if we are running interactively. */
+ pid_t shell_pgid;
+
+ input_init();
+ kill_init();
+ shell_pgid = getpgrp ();
+
+ /*
+ This should enable job control on fish, even if our parent process did
+ not enable it for us.
+ */
+
+ /*
+ Check if we are in control of the terminal, so that we don't do
+ semi-expensive things like reset signal handlers unless we
+ really have to, which we often don't.
+ */
+ if (tcgetpgrp( 0 ) != shell_pgid)
+ {
+ int block_count = 0;
+ int i;
+
+ /*
+ Bummer, we are not in control of the terminal. Stop until
+ parent has given us control of it. Stopping in fish is a bit
+ of a challange, what with all the signal fidgeting, we need
+ to reset a bunch of signal state, making this coda a but
+ unobvious.
+
+ In theory, reseting signal handlers could cause us to miss
+ signal deliveries. In practice, this code should only be run
+ suring startup, when we're not waiting for any signals.
+ */
+ while (signal_is_blocked())
+ {
+ signal_unblock();
+ block_count++;
+ }
+ signal_reset_handlers();
+
+ /*
+ Ok, signal handlers are taken out of the picture. Stop ourself in a loop
+ until we are in control of the terminal.
+ */
+ while (tcgetpgrp( 0 ) != shell_pgid)
+ {
+ killpg( shell_pgid, SIGTTIN);
+ }
+
+ signal_set_handlers();
+
+ for( i=0; i<block_count; i++ )
+ {
+ signal_block();
+ }
+
+ }
+
+
+ /* Put ourselves in our own process group. */
+ shell_pgid = getpid ();
+ if( getpgrp() != shell_pgid )
+ {
+ if (setpgid (shell_pgid, shell_pgid) < 0)
+ {
+ debug( 1,
+ _( L"Couldn't put the shell in its own process group" ));
+ wperror( L"setpgid" );
+ exit (1);
+ }
+ }
+
+ /* Grab control of the terminal. */
+ if( tcsetpgrp (STDIN_FILENO, shell_pgid) )
+ {
+ debug( 1,
+ _( L"Couldn't grab control of terminal" ) );
+ wperror( L"tcsetpgrp" );
+ exit_without_destructors(1);
+ }
+
+ common_handle_winch(0);
if( tcsetattr(0,TCSANOW,&shell_modes)) /* set the new modes */
{
wperror(L"tcsetattr");
}
- /*
- We need to know our own pid so we'll later know if we are a
- fork
- */
- original_pid = getpid();
+ /*
+ We need to know our own pid so we'll later know if we are a
+ fork
+ */
+ original_pid = getpid();
- env_set( L"_", L"fish", ENV_GLOBAL );
+ env_set( L"_", L"fish", ENV_GLOBAL );
}
/**
@@ -1685,30 +1685,30 @@ static void reader_interactive_init()
*/
static void reader_interactive_destroy()
{
- kill_destroy();
- writestr( L"\n" );
- set_color( rgb_color_t::reset(), rgb_color_t::reset() );
- input_destroy();
+ kill_destroy();
+ writestr( L"\n" );
+ set_color( rgb_color_t::reset(), rgb_color_t::reset() );
+ input_destroy();
}
void reader_sanity_check()
{
- if( get_is_interactive())
- {
- if( !data )
- sanity_lose();
+ if( get_is_interactive())
+ {
+ if( !data )
+ sanity_lose();
+
+ if(!( data->buff_pos <= data->command_length() ))
+ sanity_lose();
- if(!( data->buff_pos <= data->command_length() ))
- sanity_lose();
-
if (data->colors.size() != data->command_length())
sanity_lose();
-
+
if (data->indents.size() != data->command_length())
sanity_lose();
-
- }
+
+ }
}
/**
@@ -1727,22 +1727,22 @@ static void set_command_line_and_position( const wcstring &new_str, size_t pos )
void reader_replace_current_token( const wchar_t *new_token )
{
- const wchar_t *begin, *end;
- size_t new_pos;
+ const wchar_t *begin, *end;
+ size_t new_pos;
- /* Find current token */
+ /* Find current token */
const wchar_t *buff = data->command_line.c_str();
- parse_util_token_extent( (wchar_t *)buff, data->buff_pos, &begin, &end, 0, 0 );
+ parse_util_token_extent( (wchar_t *)buff, data->buff_pos, &begin, &end, 0, 0 );
- if( !begin || !end )
- return;
+ if( !begin || !end )
+ return;
- /* Make new string */
+ /* Make new string */
wcstring new_buff(buff, begin - buff);
new_buff.append(new_token);
new_buff.append(end);
- new_pos = (begin-buff) + wcslen(new_token);
-
+ new_pos = (begin-buff) + wcslen(new_token);
+
set_command_line_and_position(new_buff, new_pos);
}
@@ -1752,21 +1752,21 @@ void reader_replace_current_token( const wchar_t *new_token )
*/
static void reset_token_history()
{
- const wchar_t *begin, *end;
+ const wchar_t *begin, *end;
const wchar_t *buff = data->command_line.c_str();
- parse_util_token_extent( (wchar_t *)buff, data->buff_pos, &begin, &end, 0, 0 );
-
- data->search_buff.clear();
- if( begin )
- {
+ parse_util_token_extent( (wchar_t *)buff, data->buff_pos, &begin, &end, 0, 0 );
+
+ data->search_buff.clear();
+ if( begin )
+ {
data->search_buff.append(begin, end - begin);
- }
+ }
- data->token_history_pos = -1;
- data->search_pos=0;
+ data->token_history_pos = -1;
+ data->search_pos=0;
data->search_prev.clear();
data->search_prev.push_back(data->search_buff);
-
+
data->history_search = history_search_t(*data->history, data->search_buff, HISTORY_SEARCH_TYPE_CONTAINS);
}
@@ -1782,128 +1782,128 @@ static void handle_token_history( int forward, int reset )
/* Paranoia */
if (! data)
return;
-
- const wchar_t *str=0;
- long current_pos;
- tokenizer tok;
-
- if( reset )
- {
- /*
- Start a new token search using the current token
- */
- reset_token_history();
-
- }
-
-
- current_pos = data->token_history_pos;
-
- if( forward || data->search_pos + 1 < data->search_prev.size() )
- {
- if( forward )
- {
- if( data->search_pos > 0 )
- {
- data->search_pos--;
- }
+
+ const wchar_t *str=0;
+ long current_pos;
+ tokenizer tok;
+
+ if( reset )
+ {
+ /*
+ Start a new token search using the current token
+ */
+ reset_token_history();
+
+ }
+
+
+ current_pos = data->token_history_pos;
+
+ if( forward || data->search_pos + 1 < data->search_prev.size() )
+ {
+ if( forward )
+ {
+ if( data->search_pos > 0 )
+ {
+ data->search_pos--;
+ }
str = data->search_prev.at(data->search_pos).c_str();
- }
- else
- {
- data->search_pos++;
+ }
+ else
+ {
+ data->search_pos++;
str = data->search_prev.at(data->search_pos).c_str();
- }
-
- reader_replace_current_token( str );
- reader_super_highlight_me_plenty( data->buff_pos );
- reader_repaint();
- }
- else
- {
- if( current_pos == -1 )
- {
+ }
+
+ reader_replace_current_token( str );
+ reader_super_highlight_me_plenty( data->buff_pos );
+ reader_repaint();
+ }
+ else
+ {
+ if( current_pos == -1 )
+ {
data->token_history_buff.clear();
-
- /*
- Search for previous item that contains this substring
- */
+
+ /*
+ Search for previous item that contains this substring
+ */
if (data->history_search.go_backwards()) {
wcstring item = data->history_search.current_string();
data->token_history_buff = data->history_search.current_string();
}
- current_pos = data->token_history_buff.size();
-
- }
-
- if( data->token_history_buff.empty() )
- {
- /*
- We have reached the end of the history - check if the
- history already contains the search string itself, if so
- return, otherwise add it.
- */
-
- const wcstring &last = data->search_prev.back();
- if (data->search_buff != last)
- {
- str = wcsdup( data->search_buff.c_str() );
- }
- else
- {
- return;
- }
- }
- else
- {
-
- //debug( 3, L"new '%ls'", data->token_history_buff.c_str() );
-
- for( tok_init( &tok, data->token_history_buff.c_str(), TOK_ACCEPT_UNFINISHED );
- tok_has_next( &tok);
- tok_next( &tok ))
- {
- switch( tok_last_type( &tok ) )
- {
- case TOK_STRING:
- {
- if( wcsstr( tok_last( &tok ), data->search_buff.c_str() ) )
- {
- //debug( 3, L"Found token at pos %d\n", tok_get_pos( &tok ) );
- if( tok_get_pos( &tok ) >= current_pos )
- {
- break;
- }
- //debug( 3, L"ok pos" );
+ current_pos = data->token_history_buff.size();
+
+ }
+
+ if( data->token_history_buff.empty() )
+ {
+ /*
+ We have reached the end of the history - check if the
+ history already contains the search string itself, if so
+ return, otherwise add it.
+ */
+
+ const wcstring &last = data->search_prev.back();
+ if (data->search_buff != last)
+ {
+ str = wcsdup( data->search_buff.c_str() );
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+
+ //debug( 3, L"new '%ls'", data->token_history_buff.c_str() );
+
+ for( tok_init( &tok, data->token_history_buff.c_str(), TOK_ACCEPT_UNFINISHED );
+ tok_has_next( &tok);
+ tok_next( &tok ))
+ {
+ switch( tok_last_type( &tok ) )
+ {
+ case TOK_STRING:
+ {
+ if( wcsstr( tok_last( &tok ), data->search_buff.c_str() ) )
+ {
+ //debug( 3, L"Found token at pos %d\n", tok_get_pos( &tok ) );
+ if( tok_get_pos( &tok ) >= current_pos )
+ {
+ break;
+ }
+ //debug( 3, L"ok pos" );
const wcstring last_tok = tok_last( &tok );
if (find(data->search_prev.begin(), data->search_prev.end(), last_tok) == data->search_prev.end()) {
- data->token_history_pos = tok_get_pos( &tok );
- str = wcsdup(tok_last( &tok ));
- }
-
- }
- }
- }
- }
-
- tok_destroy( &tok );
- }
-
- if( str )
- {
- reader_replace_current_token( str );
- reader_super_highlight_me_plenty( data->buff_pos );
- reader_repaint();
+ data->token_history_pos = tok_get_pos( &tok );
+ str = wcsdup(tok_last( &tok ));
+ }
+
+ }
+ }
+ }
+ }
+
+ tok_destroy( &tok );
+ }
+
+ if( str )
+ {
+ reader_replace_current_token( str );
+ reader_super_highlight_me_plenty( data->buff_pos );
+ reader_repaint();
data->search_pos = data->search_prev.size();
data->search_prev.push_back(str);
- }
- else if( ! reader_interrupted() )
- {
- data->token_history_pos=-1;
- handle_token_history( 0, 0 );
- }
- }
+ }
+ else if( ! reader_interrupted() )
+ {
+ data->token_history_pos=-1;
+ handle_token_history( 0, 0 );
+ }
+ }
}
/* Our state machine that implements "one word" movement or erasure. */
@@ -1915,13 +1915,13 @@ class move_word_state_machine_t
s_alphanumeric_or_punctuation_except_slash,
s_end
} state;
-
+
public:
-
+
move_word_state_machine_t() : state(s_whitespace)
{
}
-
+
bool consume_char(wchar_t c)
{
/* Note fall-through in all of these! */
@@ -1931,20 +1931,20 @@ class move_word_state_machine_t
if (iswspace(c))
return true;
state = s_punctuation;
-
+
case s_punctuation:
if (iswpunct(c))
return true;
state = s_alphanumeric_or_punctuation_except_slash;
-
+
case s_alphanumeric_or_punctuation_except_slash:
if (c != L'/' && (iswalnum(c) || iswpunct(c)))
return true;
state = s_end;
-
+
case s_end:
default:
- return false;
+ return false;
}
}
};
@@ -1957,13 +1957,13 @@ class move_word_state_machine_t
\param dir Direction to move/erase. 0 means move left, 1 means move right.
\param erase Whether to erase the characters along the way or only move past them.
\param new if the new kill item should be appended to the previous kill item or not.
-
+
The regex we implement:
-
+
WHITESPACE*
PUNCTUATION*
ALPHANUMERIC_OR_PUNCTUATION_EXCEPT_SLASH*
-
+
Interesting test case:
/foo/bar/baz/ -> /foo/bar/ -> /foo/ -> /
echo --foo --bar -> echo --foo -> echo
@@ -1975,26 +1975,26 @@ enum move_word_dir_t {
static void move_word( bool move_right, bool erase, bool newv )
{
const size_t start_buff_pos = data->buff_pos;
- size_t end_buff_pos = data->buff_pos; //this is the last character we delete; we always delete at least one character
+ size_t end_buff_pos = data->buff_pos; //this is the last character we delete; we always delete at least one character
- /* Return if we are already at the edge */
+ /* Return if we are already at the edge */
const size_t boundary = move_right ? data->command_length() : 0;
if (data->buff_pos == boundary)
return;
-
- /*
- If we are beyond the last character and moving left, start by
- moving one step, since otherwise we'll start on the \0, which
- should be ignored.
- */
- if (! move_right && (end_buff_pos == data->command_length()) )
- {
- if( !end_buff_pos )
- return;
-
- end_buff_pos--;
- }
-
+
+ /*
+ If we are beyond the last character and moving left, start by
+ moving one step, since otherwise we'll start on the \0, which
+ should be ignored.
+ */
+ if (! move_right && (end_buff_pos == data->command_length()) )
+ {
+ if( !end_buff_pos )
+ return;
+
+ end_buff_pos--;
+ }
+
const wchar_t * const command_line = data->command_line.c_str();
move_word_state_machine_t state;
const size_t last_valid_end_buff_pos = (move_right ? data->command_length() - 1 : 0);
@@ -2007,132 +2007,132 @@ static void move_word( bool move_right, bool erase, bool newv )
end_buff_pos = next_buff_pos;
}
- if( erase )
- {
+ if( erase )
+ {
size_t start_idx = mini(start_buff_pos, end_buff_pos); //first char to delete
size_t end_idx = maxi(start_buff_pos, end_buff_pos); //last char to delete
-
+
// Don't try to delete past the end
end_idx = mini(end_idx, data->command_length() - 1);
-
+
// Don't autosuggest after a kill
data->suppress_autosuggestion = true;
-
- reader_kill( start_idx, end_idx - start_idx + 1, move_right?KILL_APPEND:KILL_PREPEND, newv );
- }
- else
- {
- data->buff_pos = move_right ? end_buff_pos + 1 : end_buff_pos;
- reader_repaint();
- }
+
+ reader_kill( start_idx, end_idx - start_idx + 1, move_right?KILL_APPEND:KILL_PREPEND, newv );
+ }
+ else
+ {
+ data->buff_pos = move_right ? end_buff_pos + 1 : end_buff_pos;
+ reader_repaint();
+ }
}
const wchar_t *reader_get_buffer(void)
{
ASSERT_IS_MAIN_THREAD();
- return data?data->command_line.c_str():NULL;
+ return data?data->command_line.c_str():NULL;
}
history_t *reader_get_history(void) {
ASSERT_IS_MAIN_THREAD();
- return data ? data->history : NULL;
+ return data ? data->history : NULL;
}
void reader_set_buffer( const wcstring &b, size_t pos )
{
- if( !data )
- return;
+ if( !data )
+ return;
/* Callers like to pass us pointers into ourselves, so be careful! I don't know if we can use operator= with a pointer to our interior, so use an intermediate. */
- size_t command_line_len = b.size();
+ size_t command_line_len = b.size();
data->command_line = b;
data->command_line_changed();
/* Don't set a position past the command line length */
if (pos > command_line_len)
pos = command_line_len;
-
+
data->buff_pos = pos;
- data->search_mode = NO_SEARCH;
- data->search_buff.clear();
- data->history_search.go_to_end();
+ data->search_mode = NO_SEARCH;
+ data->search_buff.clear();
+ data->history_search.go_to_end();
- reader_super_highlight_me_plenty( data->buff_pos );
- reader_repaint_needed();
+ reader_super_highlight_me_plenty( data->buff_pos );
+ reader_repaint_needed();
}
size_t reader_get_cursor_pos()
{
- if( !data )
- return (size_t)(-1);
+ if( !data )
+ return (size_t)(-1);
- return data->buff_pos;
+ return data->buff_pos;
}
#define ENV_CMD_DURATION L"CMD_DURATION"
void set_env_cmd_duration(struct timeval *after, struct timeval *before)
{
- time_t secs = after->tv_sec - before->tv_sec;
- suseconds_t usecs = after->tv_usec - before->tv_usec;
- wchar_t buf[16];
-
- if (after->tv_usec < before->tv_usec) {
- usecs += 1000000;
- secs -= 1;
- }
-
- if (secs < 1) {
- env_remove( ENV_CMD_DURATION, 0 );
- } else {
- if (secs < 10) { // 10 secs
- swprintf(buf, 16, L"%lu.%02us", secs, usecs / 10000);
- } else if (secs < 60) { // 1 min
- swprintf(buf, 16, L"%lu.%01us", secs, usecs / 100000);
- } else if (secs < 600) { // 10 mins
- swprintf(buf, 16, L"%lum %lu.%01us", secs / 60, secs % 60, usecs / 100000);
- } else if (secs < 5400) { // 1.5 hours
- swprintf(buf, 16, L"%lum %lus", secs / 60, secs % 60);
- } else {
- swprintf(buf, 16, L"%.1fh", secs / 3600.0);
- }
- env_set( ENV_CMD_DURATION, buf, ENV_EXPORT );
- }
+ time_t secs = after->tv_sec - before->tv_sec;
+ suseconds_t usecs = after->tv_usec - before->tv_usec;
+ wchar_t buf[16];
+
+ if (after->tv_usec < before->tv_usec) {
+ usecs += 1000000;
+ secs -= 1;
+ }
+
+ if (secs < 1) {
+ env_remove( ENV_CMD_DURATION, 0 );
+ } else {
+ if (secs < 10) { // 10 secs
+ swprintf(buf, 16, L"%lu.%02us", secs, usecs / 10000);
+ } else if (secs < 60) { // 1 min
+ swprintf(buf, 16, L"%lu.%01us", secs, usecs / 100000);
+ } else if (secs < 600) { // 10 mins
+ swprintf(buf, 16, L"%lum %lu.%01us", secs / 60, secs % 60, usecs / 100000);
+ } else if (secs < 5400) { // 1.5 hours
+ swprintf(buf, 16, L"%lum %lus", secs / 60, secs % 60);
+ } else {
+ swprintf(buf, 16, L"%.1fh", secs / 3600.0);
+ }
+ env_set( ENV_CMD_DURATION, buf, ENV_EXPORT );
+ }
}
void reader_run_command( parser_t &parser, const wchar_t *cmd )
{
- wchar_t *ft;
- struct timeval time_before, time_after;
+ wchar_t *ft;
+ struct timeval time_before, time_after;
- ft= tok_first( cmd );
+ ft= tok_first( cmd );
- if( ft != 0 )
- env_set( L"_", ft, ENV_GLOBAL );
- free(ft);
+ if( ft != 0 )
+ env_set( L"_", ft, ENV_GLOBAL );
+ free(ft);
- reader_write_title();
+ reader_write_title();
- term_donate();
+ term_donate();
- gettimeofday(&time_before, NULL);
+ gettimeofday(&time_before, NULL);
- parser.eval( cmd, io_chain_t(), TOP );
- job_reap( 1 );
+ parser.eval( cmd, io_chain_t(), TOP );
+ job_reap( 1 );
- gettimeofday(&time_after, NULL);
- set_env_cmd_duration(&time_after, &time_before);
+ gettimeofday(&time_after, NULL);
+ set_env_cmd_duration(&time_after, &time_before);
- term_steal();
+ term_steal();
- env_set( L"_", program_name, ENV_GLOBAL );
+ env_set( L"_", program_name, ENV_GLOBAL );
#ifdef HAVE__PROC_SELF_STAT
- proc_update_jiffies();
+ proc_update_jiffies();
#endif
@@ -2141,16 +2141,16 @@ void reader_run_command( parser_t &parser, const wchar_t *cmd )
int reader_shell_test( const wchar_t *b )
{
- int res = parser_t::principal_parser().test( b, 0, 0, 0 );
-
- if( res & PARSER_TEST_ERROR )
- {
- wcstring sb;
+ int res = parser_t::principal_parser().test( b, 0, 0, 0 );
+
+ if( res & PARSER_TEST_ERROR )
+ {
+ wcstring sb;
- const int tmp[1] = {0};
- const int tmp2[1] = {0};
+ const int tmp[1] = {0};
+ const int tmp2[1] = {0};
const wcstring empty;
-
+
s_write( &data->screen,
empty,
empty,
@@ -2159,12 +2159,12 @@ int reader_shell_test( const wchar_t *b )
tmp,
tmp2,
0);
-
-
- parser_t::principal_parser().test( b, 0, &sb, L"fish" );
- fwprintf( stderr, L"%ls", sb.c_str() );
- }
- return res;
+
+
+ parser_t::principal_parser().test( b, 0, &sb, L"fish" );
+ fwprintf( stderr, L"%ls", sb.c_str() );
+ }
+ return res;
}
/**
@@ -2174,58 +2174,58 @@ int reader_shell_test( const wchar_t *b )
*/
static int default_test( const wchar_t *b )
{
- return 0;
+ return 0;
}
void reader_push( const wchar_t *name )
{
reader_data_t *n = new reader_data_t();
-
+
n->history = & history_t::history_with_name(name);
- n->app_name = name;
- n->next = data;
+ n->app_name = name;
+ n->next = data;
- data=n;
+ data=n;
- data->command_line_changed();
+ data->command_line_changed();
- if( data->next == 0 )
- {
- reader_interactive_init();
- }
+ if( data->next == 0 )
+ {
+ reader_interactive_init();
+ }
- exec_prompt();
- reader_set_highlight_function( &highlight_universal );
- reader_set_test_function( &default_test );
- reader_set_left_prompt( L"" );
+ exec_prompt();
+ reader_set_highlight_function( &highlight_universal );
+ reader_set_test_function( &default_test );
+ reader_set_left_prompt( L"" );
}
void reader_pop()
{
- reader_data_t *n = data;
+ reader_data_t *n = data;
- if( data == 0 )
- {
- debug( 0, _( L"Pop null reader block" ) );
- sanity_lose();
- return;
- }
+ if( data == 0 )
+ {
+ debug( 0, _( L"Pop null reader block" ) );
+ sanity_lose();
+ return;
+ }
+
+ data=data->next;
- data=data->next;
-
/* Invoke the destructor to balance our new */
delete n;
- if( data == 0 )
- {
- reader_interactive_destroy();
- }
- else
- {
- end_loop = 0;
- //history_set_mode( data->app_name.c_str() );
- s_reset( &data->screen, true);
- }
+ if( data == 0 )
+ {
+ reader_interactive_destroy();
+ }
+ else
+ {
+ end_loop = 0;
+ //history_set_mode( data->app_name.c_str() );
+ s_reset( &data->screen, true);
+ }
}
void reader_set_left_prompt( const wcstring &new_prompt )
@@ -2240,17 +2240,17 @@ void reader_set_right_prompt(const wcstring &new_prompt)
void reader_set_complete_function( complete_function_t f )
{
- data->complete_func = f;
+ data->complete_func = f;
}
void reader_set_highlight_function( highlight_function_t func )
{
- data->highlight_function = func;
+ data->highlight_function = func;
}
void reader_set_test_function( int (*f)( const wchar_t * ) )
{
- data->test_func = f;
+ data->test_func = f;
}
void reader_import_history_if_necessary(void)
@@ -2276,26 +2276,26 @@ void reader_import_history_if_necessary(void)
class background_highlight_context_t {
public:
/** The string to highlight */
- const wcstring string_to_highlight;
-
- /** Color buffer */
- std::vector<color_t> colors;
-
- /** The position to use for bracket matching */
- const size_t match_highlight_pos;
-
- /** Function for syntax highlighting */
- const highlight_function_t highlight_function;
-
+ const wcstring string_to_highlight;
+
+ /** Color buffer */
+ std::vector<color_t> colors;
+
+ /** The position to use for bracket matching */
+ const size_t match_highlight_pos;
+
+ /** Function for syntax highlighting */
+ const highlight_function_t highlight_function;
+
/** Environment variables */
const env_vars_snapshot_t vars;
/** When the request was made */
const double when;
-
+
/** Gen count at the time the request was made */
const unsigned int generation_count;
-
+
background_highlight_context_t(const wcstring &pbuff, size_t phighlight_pos, highlight_function_t phighlight_func) :
string_to_highlight(pbuff),
colors(pbuff.size(), 0),
@@ -2306,7 +2306,7 @@ public:
generation_count(s_generation_count)
{
}
-
+
int threaded_highlight() {
if (generation_count != s_generation_count)
{
@@ -2323,41 +2323,41 @@ public:
/* Called to set the highlight flag for search results */
static void highlight_search(void) {
- if( ! data->search_buff.empty() && ! data->history_search.is_at_end())
- {
+ if( ! data->search_buff.empty() && ! data->history_search.is_at_end())
+ {
const wchar_t *buff = data->command_line.c_str();
- const wchar_t *match = wcsstr( buff, data->search_buff.c_str() );
- if( match )
- {
- size_t start = match-buff;
- size_t i, count = data->search_buff.size();
- for( i=0; i<count; i++ )
- {
- data->colors.at(start+i) |= HIGHLIGHT_SEARCH_MATCH<<16;
- }
- }
- }
+ const wchar_t *match = wcsstr( buff, data->search_buff.c_str() );
+ if( match )
+ {
+ size_t start = match-buff;
+ size_t i, count = data->search_buff.size();
+ for( i=0; i<count; i++ )
+ {
+ data->colors.at(start+i) |= HIGHLIGHT_SEARCH_MATCH<<16;
+ }
+ }
+ }
}
static void highlight_complete(background_highlight_context_t *ctx, int result) {
ASSERT_IS_MAIN_THREAD();
- if (ctx->string_to_highlight == data->command_line) {
- /* The data hasn't changed, so swap in our colors. The colors may not have changed, so do nothing if they have not. */
+ if (ctx->string_to_highlight == data->command_line) {
+ /* The data hasn't changed, so swap in our colors. The colors may not have changed, so do nothing if they have not. */
assert(ctx->colors.size() == data->command_length());
if (data->colors != ctx->colors)
{
data->colors.swap(ctx->colors);
-
+
//data->repaint_needed = 1;
//s_reset( &data->screen, 1 );
-
+
sanity_check();
highlight_search();
reader_repaint();
}
- }
-
- /* Free our context */
+ }
+
+ /* Free our context */
delete ctx;
}
@@ -2378,11 +2378,11 @@ static int threaded_highlight(background_highlight_context_t *ctx) {
static void reader_super_highlight_me_plenty( size_t match_highlight_pos )
{
reader_sanity_check();
-
- background_highlight_context_t *ctx = new background_highlight_context_t(data->command_line, match_highlight_pos, data->highlight_function);
- iothread_perform(threaded_highlight, highlight_complete, ctx);
+
+ background_highlight_context_t *ctx = new background_highlight_context_t(data->command_line, match_highlight_pos, data->highlight_function);
+ iothread_perform(threaded_highlight, highlight_complete, ctx);
highlight_search();
-
+
/* Here's a hack. Check to see if our autosuggestion still applies; if so, don't recompute it. Since the autosuggestion computation is asynchronous, this avoids "flashing" as you type into the autosuggestion. */
const wcstring &cmd = data->command_line, &suggest = data->autosuggestion;
if (can_autosuggest() && ! suggest.empty() && string_prefixes_string_case_insensitive(cmd, suggest)) {
@@ -2395,10 +2395,10 @@ static void reader_super_highlight_me_plenty( size_t match_highlight_pos )
int exit_status()
{
- if( get_is_interactive() )
- return job_list_is_empty() && data->end_loop;
- else
- return end_loop;
+ if( get_is_interactive() )
+ return job_list_is_empty() && data->end_loop;
+ else
+ return end_loop;
}
/**
@@ -2409,63 +2409,63 @@ int exit_status()
static void handle_end_loop()
{
- job_t *j;
- int job_count=0;
- int is_breakpoint=0;
- block_t *b;
- parser_t &parser = parser_t::principal_parser();
-
- for( b = parser.current_block;
- b;
- b = b->outer )
- {
- if( b->type() == BREAKPOINT )
- {
- is_breakpoint = 1;
- break;
- }
- }
-
+ job_t *j;
+ int job_count=0;
+ int is_breakpoint=0;
+ block_t *b;
+ parser_t &parser = parser_t::principal_parser();
+
+ for( b = parser.current_block;
+ b;
+ b = b->outer )
+ {
+ if( b->type() == BREAKPOINT )
+ {
+ is_breakpoint = 1;
+ break;
+ }
+ }
+
job_iterator_t jobs;
while ((j = jobs.next()))
- {
- if( !job_is_completed(j) )
- {
- job_count++;
- break;
- }
- }
-
- if( !reader_exit_forced() && !data->prev_end_loop && job_count && !is_breakpoint )
- {
- writestr(_( L"There are stopped jobs. A second attempt to exit will enforce their termination.\n" ));
-
- reader_exit( 0, 0 );
- data->prev_end_loop=1;
- }
- else
- {
+ {
+ if( !job_is_completed(j) )
+ {
+ job_count++;
+ break;
+ }
+ }
+
+ if( !reader_exit_forced() && !data->prev_end_loop && job_count && !is_breakpoint )
+ {
+ writestr(_( L"There are stopped jobs. A second attempt to exit will enforce their termination.\n" ));
+
+ reader_exit( 0, 0 );
+ data->prev_end_loop=1;
+ }
+ else
+ {
/* PCA: we used to only hangup jobs if stdin was closed. This prevented child processes from exiting. It's unclear to my why it matters if stdin is closed, but it seems to me if we're forcing an exit, we definitely want to hang up our processes.
-
+
See https://github.com/fish-shell/fish-shell/issues/138
*/
- if( reader_exit_forced() || !isatty(0) )
- {
- /*
- We already know that stdin is a tty since we're
- in interactive mode. If isatty returns false, it
- means stdin must have been closed.
- */
- job_iterator_t jobs;
- while ((j = jobs.next()))
- {
- if( ! job_is_completed( j ) )
- {
- job_signal( j, SIGHUP );
- }
- }
- }
- }
+ if( reader_exit_forced() || !isatty(0) )
+ {
+ /*
+ We already know that stdin is a tty since we're
+ in interactive mode. If isatty returns false, it
+ means stdin must have been closed.
+ */
+ job_iterator_t jobs;
+ while ((j = jobs.next()))
+ {
+ if( ! job_is_completed( j ) )
+ {
+ job_signal( j, SIGHUP );
+ }
+ }
+ }
+ }
}
@@ -2476,69 +2476,69 @@ static void handle_end_loop()
*/
static int read_i()
{
- reader_push(L"fish");
- reader_set_complete_function( &complete );
- reader_set_highlight_function( &highlight_shell );
- reader_set_test_function( &reader_shell_test );
+ reader_push(L"fish");
+ reader_set_complete_function( &complete );
+ reader_set_highlight_function( &highlight_shell );
+ reader_set_test_function( &reader_shell_test );
reader_import_history_if_necessary();
-
- parser_t &parser = parser_t::principal_parser();
-
- data->prev_end_loop=0;
-
- while( (!data->end_loop) && (!sanity_check()) )
- {
- const wchar_t *tmp;
-
- event_fire_generic(L"fish_prompt");
- if( function_exists( LEFT_PROMPT_FUNCTION_NAME ) )
- reader_set_left_prompt( LEFT_PROMPT_FUNCTION_NAME );
- else
- reader_set_left_prompt( DEFAULT_PROMPT );
-
- if( function_exists( RIGHT_PROMPT_FUNCTION_NAME ) )
- reader_set_right_prompt( RIGHT_PROMPT_FUNCTION_NAME );
- else
- reader_set_right_prompt( L"" );
-
-
- /*
- Put buff in temporary string and clear buff, so
- that we can handle a call to reader_set_buffer
- during evaluation.
- */
-
-
- tmp = reader_readline();
-
-
- if( data->end_loop)
- {
- handle_end_loop();
- }
- else if( tmp )
- {
- tmp = wcsdup( tmp );
-
- data->buff_pos=0;
+
+ parser_t &parser = parser_t::principal_parser();
+
+ data->prev_end_loop=0;
+
+ while( (!data->end_loop) && (!sanity_check()) )
+ {
+ const wchar_t *tmp;
+
+ event_fire_generic(L"fish_prompt");
+ if( function_exists( LEFT_PROMPT_FUNCTION_NAME ) )
+ reader_set_left_prompt( LEFT_PROMPT_FUNCTION_NAME );
+ else
+ reader_set_left_prompt( DEFAULT_PROMPT );
+
+ if( function_exists( RIGHT_PROMPT_FUNCTION_NAME ) )
+ reader_set_right_prompt( RIGHT_PROMPT_FUNCTION_NAME );
+ else
+ reader_set_right_prompt( L"" );
+
+
+ /*
+ Put buff in temporary string and clear buff, so
+ that we can handle a call to reader_set_buffer
+ during evaluation.
+ */
+
+
+ tmp = reader_readline();
+
+
+ if( data->end_loop)
+ {
+ handle_end_loop();
+ }
+ else if( tmp )
+ {
+ tmp = wcsdup( tmp );
+
+ data->buff_pos=0;
data->command_line.clear();
data->command_line_changed();
- reader_run_command( parser, tmp );
- free( (void *)tmp );
- if( data->end_loop)
- {
- handle_end_loop();
- }
- else
- {
- data->prev_end_loop=0;
- }
- }
-
-
- }
- reader_pop();
- return 0;
+ reader_run_command( parser, tmp );
+ free( (void *)tmp );
+ if( data->end_loop)
+ {
+ handle_end_loop();
+ }
+ else
+ {
+ data->prev_end_loop=0;
+ }
+ }
+
+
+ }
+ reader_pop();
+ return 0;
}
/**
@@ -2547,10 +2547,10 @@ static int read_i()
*/
static int can_read( int fd )
{
- struct timeval can_read_timeout = { 0, 0 };
- fd_set fds;
+ struct timeval can_read_timeout = { 0, 0 };
+ fd_set fds;
- FD_ZERO(&fds);
+ FD_ZERO(&fds);
FD_SET(fd, &fds);
return select(fd + 1, &fds, 0, 0, &can_read_timeout) == 1;
}
@@ -2561,7 +2561,7 @@ static int can_read( int fd )
*/
static int wchar_private( wchar_t c )
{
- return ( (c >= 0xe000) && (c <= 0xf8ff ) );
+ return ( (c >= 0xe000) && (c <= 0xf8ff ) );
}
/**
@@ -2570,191 +2570,191 @@ static int wchar_private( wchar_t c )
*/
static bool is_backslashed( const wchar_t *str, size_t pos )
{
- size_t count = 0;
- size_t idx = pos;
- while (idx--)
- {
- if( str[idx] != L'\\' )
- break;
-
- count++;
- }
+ size_t count = 0;
+ size_t idx = pos;
+ while (idx--)
+ {
+ if( str[idx] != L'\\' )
+ break;
- return (count % 2) == 1;
+ count++;
+ }
+
+ return (count % 2) == 1;
}
const wchar_t *reader_readline()
{
-
- wint_t c;
- int last_char=0;
+
+ wint_t c;
+ int last_char=0;
size_t yank_len=0;
- const wchar_t *yank_str;
- bool comp_empty = true;
- std::vector<completion_t> comp;
- int finished=0;
- struct termios old_modes;
+ const wchar_t *yank_str;
+ bool comp_empty = true;
+ std::vector<completion_t> comp;
+ int finished=0;
+ struct termios old_modes;
/* The cycle index in our completion list */
size_t completion_cycle_idx = (size_t)(-1);
-
+
/* The command line before completion */
wcstring cycle_command_line;
size_t cycle_cursor_pos;
-
- data->search_buff.clear();
- data->search_mode = NO_SEARCH;
-
-
- exec_prompt();
-
- reader_super_highlight_me_plenty( data->buff_pos );
- s_reset( &data->screen, true);
- reader_repaint();
-
- /*
+
+ data->search_buff.clear();
+ data->search_mode = NO_SEARCH;
+
+
+ exec_prompt();
+
+ reader_super_highlight_me_plenty( data->buff_pos );
+ s_reset( &data->screen, true);
+ reader_repaint();
+
+ /*
get the current terminal modes. These will be restored when the
function returns.
*/
- tcgetattr(0,&old_modes);
- /* set the new modes */
- if( tcsetattr(0,TCSANOW,&shell_modes))
- {
- wperror(L"tcsetattr");
- }
-
- while( !finished && !data->end_loop)
- {
- /*
+ tcgetattr(0,&old_modes);
+ /* set the new modes */
+ if( tcsetattr(0,TCSANOW,&shell_modes))
+ {
+ wperror(L"tcsetattr");
+ }
+
+ while( !finished && !data->end_loop)
+ {
+ /*
Sometimes strange input sequences seem to generate a zero
byte. I believe these simply mean a character was pressed
but it should be ignored. (Example: Trying to add a tilde
(~) to digit)
*/
- while( 1 )
- {
- int was_interactive_read = is_interactive_read;
- is_interactive_read = 1;
- c=input_readch();
- is_interactive_read = was_interactive_read;
-
- if( ( (!wchar_private(c))) && (c>31) && (c != 127) )
- {
- if( can_read(0) )
- {
-
- wchar_t arr[READAHEAD_MAX+1];
- int i;
-
- memset( arr, 0, sizeof( arr ) );
- arr[0] = c;
-
- for( i=1; i<READAHEAD_MAX; i++ )
- {
-
- if( !can_read( 0 ) )
- {
- c = 0;
- break;
- }
- c = input_readch();
- if( (!wchar_private(c)) && (c>31) && (c != 127) )
- {
- arr[i]=c;
- c=0;
- }
- else
- break;
- }
-
- insert_string( arr );
-
- }
- }
-
- if( c != 0 )
- break;
- }
-
- if( last_char != R_YANK && last_char != R_YANK_POP )
- yank_len=0;
+ while( 1 )
+ {
+ int was_interactive_read = is_interactive_read;
+ is_interactive_read = 1;
+ c=input_readch();
+ is_interactive_read = was_interactive_read;
+
+ if( ( (!wchar_private(c))) && (c>31) && (c != 127) )
+ {
+ if( can_read(0) )
+ {
+
+ wchar_t arr[READAHEAD_MAX+1];
+ int i;
+
+ memset( arr, 0, sizeof( arr ) );
+ arr[0] = c;
+
+ for( i=1; i<READAHEAD_MAX; i++ )
+ {
+
+ if( !can_read( 0 ) )
+ {
+ c = 0;
+ break;
+ }
+ c = input_readch();
+ if( (!wchar_private(c)) && (c>31) && (c != 127) )
+ {
+ arr[i]=c;
+ c=0;
+ }
+ else
+ break;
+ }
+
+ insert_string( arr );
+
+ }
+ }
+
+ if( c != 0 )
+ break;
+ }
+
+ if( last_char != R_YANK && last_char != R_YANK_POP )
+ yank_len=0;
const wchar_t *buff = data->command_line.c_str();
- switch( c )
- {
-
+ switch( c )
+ {
+
/* go to beginning of line*/
- case R_BEGINNING_OF_LINE:
- {
- while( ( data->buff_pos>0 ) &&
+ case R_BEGINNING_OF_LINE:
+ {
+ while( ( data->buff_pos>0 ) &&
( buff[data->buff_pos-1] != L'\n' ) )
- {
- data->buff_pos--;
- }
-
- reader_repaint();
- break;
- }
-
- case R_END_OF_LINE:
- {
- while( buff[data->buff_pos] &&
+ {
+ data->buff_pos--;
+ }
+
+ reader_repaint();
+ break;
+ }
+
+ case R_END_OF_LINE:
+ {
+ while( buff[data->buff_pos] &&
buff[data->buff_pos] != L'\n' )
- {
- data->buff_pos++;
- }
-
- reader_repaint();
- break;
- }
-
-
- case R_BEGINNING_OF_BUFFER:
- {
- data->buff_pos = 0;
-
- reader_repaint();
- break;
- }
-
+ {
+ data->buff_pos++;
+ }
+
+ reader_repaint();
+ break;
+ }
+
+
+ case R_BEGINNING_OF_BUFFER:
+ {
+ data->buff_pos = 0;
+
+ reader_repaint();
+ break;
+ }
+
/* go to EOL*/
- case R_END_OF_BUFFER:
- {
- data->buff_pos = data->command_length();
-
- reader_repaint();
- break;
- }
-
- case R_NULL:
- {
- reader_repaint_if_needed();
- break;
- }
-
- case R_REPAINT:
- {
- exec_prompt();
- write_loop( 1, "\r", 1 );
- s_reset( &data->screen, false);
- reader_repaint();
- break;
- }
-
- case R_EOF:
- {
- exit_forced = 1;
- data->end_loop=1;
- break;
- }
-
+ case R_END_OF_BUFFER:
+ {
+ data->buff_pos = data->command_length();
+
+ reader_repaint();
+ break;
+ }
+
+ case R_NULL:
+ {
+ reader_repaint_if_needed();
+ break;
+ }
+
+ case R_REPAINT:
+ {
+ exec_prompt();
+ write_loop( 1, "\r", 1 );
+ s_reset( &data->screen, false);
+ reader_repaint();
+ break;
+ }
+
+ case R_EOF:
+ {
+ exit_forced = 1;
+ data->end_loop=1;
+ break;
+ }
+
/* complete */
- case R_COMPLETE:
- {
-
- if( !data->complete_func )
- break;
-
+ case R_COMPLETE:
+ {
+
+ if( !data->complete_func )
+ break;
+
if (! comp_empty && last_char == R_COMPLETE)
{
/* The user typed R_COMPLETE more than once in a row. Cycle through our available completions */
@@ -2764,541 +2764,541 @@ const wchar_t *reader_readline()
size_t cursor_pos = cycle_cursor_pos;
const wcstring new_cmd_line = completion_apply_to_command_line(next_comp->completion, next_comp->flags, cycle_command_line, &cursor_pos);
reader_set_buffer(new_cmd_line, cursor_pos);
-
+
/* Since we just inserted a completion, don't immediately do a new autosuggestion */
data->suppress_autosuggestion = true;
}
}
- else
- {
+ else
+ {
/* Either the user hit tab only once, or we had no visible completion list. */
- const wchar_t *begin, *end;
- const wchar_t *token_begin, *token_end;
+ const wchar_t *begin, *end;
+ const wchar_t *token_begin, *token_end;
const wchar_t *buff = data->command_line.c_str();
- long cursor_steps;
-
+ long cursor_steps;
+
/* Clear the completion list */
comp.clear();
-
- parse_util_cmdsubst_extent( buff, data->buff_pos, &begin, &end );
-
- parse_util_token_extent( begin, data->buff_pos - (begin-buff), &token_begin, &token_end, 0, 0 );
-
- cursor_steps = token_end - buff- data->buff_pos;
- data->buff_pos += cursor_steps;
- if( is_backslashed( buff, data->buff_pos ) )
- {
- remove_backward();
- }
-
- reader_repaint();
-
- size_t len = data->buff_pos - (begin-buff);
+
+ parse_util_cmdsubst_extent( buff, data->buff_pos, &begin, &end );
+
+ parse_util_token_extent( begin, data->buff_pos - (begin-buff), &token_begin, &token_end, 0, 0 );
+
+ cursor_steps = token_end - buff- data->buff_pos;
+ data->buff_pos += cursor_steps;
+ if( is_backslashed( buff, data->buff_pos ) )
+ {
+ remove_backward();
+ }
+
+ reader_repaint();
+
+ size_t len = data->buff_pos - (begin-buff);
const wcstring buffcpy = wcstring(begin, len);
-
- data->complete_func( buffcpy, comp, COMPLETE_DEFAULT, NULL);
-
- /* Munge our completions */
- sort(comp.begin(), comp.end());
- remove_duplicates( comp );
- prioritize_completions(comp);
-
- /* Record our cycle_command_line */
- cycle_command_line = data->command_line;
- cycle_cursor_pos = data->buff_pos;
-
- comp_empty = handle_completions( comp );
-
- /* Start the cycle at the beginning */
- completion_cycle_idx = (size_t)(-1);
- }
-
- break;
- }
-
+
+ data->complete_func( buffcpy, comp, COMPLETE_DEFAULT, NULL);
+
+ /* Munge our completions */
+ sort(comp.begin(), comp.end());
+ remove_duplicates( comp );
+ prioritize_completions(comp);
+
+ /* Record our cycle_command_line */
+ cycle_command_line = data->command_line;
+ cycle_cursor_pos = data->buff_pos;
+
+ comp_empty = handle_completions( comp );
+
+ /* Start the cycle at the beginning */
+ completion_cycle_idx = (size_t)(-1);
+ }
+
+ break;
+ }
+
/* kill */
- case R_KILL_LINE:
- {
+ case R_KILL_LINE:
+ {
const wchar_t *buff = data->command_line.c_str();
- const wchar_t *begin = &buff[data->buff_pos];
- const wchar_t *end = begin;
-
- while( *end && *end != L'\n' )
- end++;
-
- if( end==begin && *end )
- end++;
-
- size_t len = end-begin;
- if( len )
- {
- reader_kill( begin - buff, len, KILL_APPEND, last_char!=R_KILL_LINE );
- }
-
- break;
- }
-
- case R_BACKWARD_KILL_LINE:
- {
- if( data->buff_pos > 0 )
- {
+ const wchar_t *begin = &buff[data->buff_pos];
+ const wchar_t *end = begin;
+
+ while( *end && *end != L'\n' )
+ end++;
+
+ if( end==begin && *end )
+ end++;
+
+ size_t len = end-begin;
+ if( len )
+ {
+ reader_kill( begin - buff, len, KILL_APPEND, last_char!=R_KILL_LINE );
+ }
+
+ break;
+ }
+
+ case R_BACKWARD_KILL_LINE:
+ {
+ if( data->buff_pos > 0 )
+ {
const wchar_t *buff = data->command_line.c_str();
- const wchar_t *end = &buff[data->buff_pos];
- const wchar_t *begin = end;
-
- while( begin > buff && *begin != L'\n' )
- begin--;
-
- if( *begin == L'\n' )
- begin++;
-
- size_t len = maxi<size_t>( end-begin, 1 );
- begin = end - len;
-
- reader_kill( begin - buff, len, KILL_PREPEND, last_char!=R_BACKWARD_KILL_LINE );
-
- }
- break;
-
- }
-
- case R_KILL_WHOLE_LINE:
- {
+ const wchar_t *end = &buff[data->buff_pos];
+ const wchar_t *begin = end;
+
+ while( begin > buff && *begin != L'\n' )
+ begin--;
+
+ if( *begin == L'\n' )
+ begin++;
+
+ size_t len = maxi<size_t>( end-begin, 1 );
+ begin = end - len;
+
+ reader_kill( begin - buff, len, KILL_PREPEND, last_char!=R_BACKWARD_KILL_LINE );
+
+ }
+ break;
+
+ }
+
+ case R_KILL_WHOLE_LINE:
+ {
const wchar_t *buff = data->command_line.c_str();
- const wchar_t *end = &buff[data->buff_pos];
- const wchar_t *begin = end;
- size_t len;
-
- while( begin > buff && *begin != L'\n' )
- begin--;
-
- if( *begin == L'\n' )
- begin++;
-
- len = maxi<size_t>( end-begin, 0 );
- begin = end - len;
-
- while( *end && *end != L'\n' )
- end++;
-
- if( begin == end && *end )
- end++;
-
- len = end-begin;
-
- if( len )
- {
- reader_kill( begin - buff, len, KILL_APPEND, last_char!=R_KILL_WHOLE_LINE );
- }
-
- break;
- }
-
+ const wchar_t *end = &buff[data->buff_pos];
+ const wchar_t *begin = end;
+ size_t len;
+
+ while( begin > buff && *begin != L'\n' )
+ begin--;
+
+ if( *begin == L'\n' )
+ begin++;
+
+ len = maxi<size_t>( end-begin, 0 );
+ begin = end - len;
+
+ while( *end && *end != L'\n' )
+ end++;
+
+ if( begin == end && *end )
+ end++;
+
+ len = end-begin;
+
+ if( len )
+ {
+ reader_kill( begin - buff, len, KILL_APPEND, last_char!=R_KILL_WHOLE_LINE );
+ }
+
+ break;
+ }
+
/* yank*/
- case R_YANK:
- {
- yank_str = kill_yank();
- insert_string( yank_str );
- yank_len = wcslen( yank_str );
- break;
- }
-
+ case R_YANK:
+ {
+ yank_str = kill_yank();
+ insert_string( yank_str );
+ yank_len = wcslen( yank_str );
+ break;
+ }
+
/* rotate killring*/
- case R_YANK_POP:
- {
- if( yank_len )
- {
- for( size_t i=0; i<yank_len; i++ )
- remove_backward();
-
- yank_str = kill_yank_rotate();
- insert_string(yank_str);
- yank_len = wcslen(yank_str);
- }
- break;
- }
-
+ case R_YANK_POP:
+ {
+ if( yank_len )
+ {
+ for( size_t i=0; i<yank_len; i++ )
+ remove_backward();
+
+ yank_str = kill_yank_rotate();
+ insert_string(yank_str);
+ yank_len = wcslen(yank_str);
+ }
+ break;
+ }
+
/* Escape was pressed */
- case L'\x1b':
- {
- if( data->search_mode )
- {
- data->search_mode= NO_SEARCH;
-
- if( data->token_history_pos==-1 )
- {
- //history_reset();
+ case L'\x1b':
+ {
+ if( data->search_mode )
+ {
+ data->search_mode= NO_SEARCH;
+
+ if( data->token_history_pos==-1 )
+ {
+ //history_reset();
data->history_search.go_to_end();
- reader_set_buffer( data->search_buff.c_str(), data->search_buff.size() );
- }
- else
- {
- reader_replace_current_token( data->search_buff.c_str() );
- }
- data->search_buff.clear();
- reader_super_highlight_me_plenty( data->buff_pos );
- reader_repaint();
-
- }
-
- break;
- }
-
+ reader_set_buffer( data->search_buff.c_str(), data->search_buff.size() );
+ }
+ else
+ {
+ reader_replace_current_token( data->search_buff.c_str() );
+ }
+ data->search_buff.clear();
+ reader_super_highlight_me_plenty( data->buff_pos );
+ reader_repaint();
+
+ }
+
+ break;
+ }
+
/* delete backward*/
- case R_BACKWARD_DELETE_CHAR:
- {
- remove_backward();
- break;
- }
-
+ case R_BACKWARD_DELETE_CHAR:
+ {
+ remove_backward();
+ break;
+ }
+
/* delete forward*/
- case R_DELETE_CHAR:
- {
- /**
+ case R_DELETE_CHAR:
+ {
+ /**
Remove the current character in the character buffer and on the
screen using syntax highlighting, etc.
*/
- if( data->buff_pos < data->command_length() )
- {
- data->buff_pos++;
- remove_backward();
- }
- break;
- }
-
+ if( data->buff_pos < data->command_length() )
+ {
+ data->buff_pos++;
+ remove_backward();
+ }
+ break;
+ }
+
/*
Evaluate. If the current command is unfinished, or if
the charater is escaped using a backslash, insert a
newline
*/
- case R_EXECUTE:
- {
+ case R_EXECUTE:
+ {
/* Delete any autosuggestion */
data->autosuggestion.clear();
-
- /*
+
+ /*
Allow backslash-escaped newlines
*/
- if( is_backslashed( data->command_line.c_str(), data->buff_pos ) )
- {
- insert_char( '\n' );
- break;
- }
-
- switch( data->test_func( data->command_line.c_str() ) )
- {
-
- case 0:
- {
- /*
+ if( is_backslashed( data->command_line.c_str(), data->buff_pos ) )
+ {
+ insert_char( '\n' );
+ break;
+ }
+
+ switch( data->test_func( data->command_line.c_str() ) )
+ {
+
+ case 0:
+ {
+ /*
Finished commend, execute it
*/
- if( ! data->command_line.empty() )
- {
+ if( ! data->command_line.empty() )
+ {
if (data->history) {
data->history->add_with_file_detection(data->command_line);
}
- }
- finished=1;
- data->buff_pos=data->command_length();
- reader_repaint();
- break;
- }
-
+ }
+ finished=1;
+ data->buff_pos=data->command_length();
+ reader_repaint();
+ break;
+ }
+
/*
We are incomplete, continue editing
*/
- case PARSER_TEST_INCOMPLETE:
- {
- insert_char( '\n' );
- break;
- }
-
+ case PARSER_TEST_INCOMPLETE:
+ {
+ insert_char( '\n' );
+ break;
+ }
+
/*
Result must be some combination including an
error. The error message will already be
printed, all we need to do is repaint
*/
- default:
- {
- s_reset( &data->screen, true);
- reader_repaint();
- break;
- }
-
- }
-
- break;
- }
-
+ default:
+ {
+ s_reset( &data->screen, true);
+ reader_repaint();
+ break;
+ }
+
+ }
+
+ break;
+ }
+
/* History functions */
- case R_HISTORY_SEARCH_BACKWARD:
- case R_HISTORY_TOKEN_SEARCH_BACKWARD:
- case R_HISTORY_SEARCH_FORWARD:
- case R_HISTORY_TOKEN_SEARCH_FORWARD:
- {
- int reset = 0;
-
- if( data->search_mode == NO_SEARCH )
- {
- reset = 1;
- if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
+ case R_HISTORY_SEARCH_BACKWARD:
+ case R_HISTORY_TOKEN_SEARCH_BACKWARD:
+ case R_HISTORY_SEARCH_FORWARD:
+ case R_HISTORY_TOKEN_SEARCH_FORWARD:
+ {
+ int reset = 0;
+
+ if( data->search_mode == NO_SEARCH )
+ {
+ reset = 1;
+ if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
( c == R_HISTORY_SEARCH_FORWARD ) )
- {
- data->search_mode = LINE_SEARCH;
- }
- else
- {
- data->search_mode = TOKEN_SEARCH;
- }
-
+ {
+ data->search_mode = LINE_SEARCH;
+ }
+ else
+ {
+ data->search_mode = TOKEN_SEARCH;
+ }
+
data->search_buff.append(data->command_line);
data->history_search = history_search_t(*data->history, data->search_buff, HISTORY_SEARCH_TYPE_CONTAINS);
-
+
/* Skip the autosuggestion as history */
const wcstring &suggest = data->autosuggestion;
if (! suggest.empty()) {
data->history_search.skip_matches(wcstring_list_t(&suggest, 1 + &suggest));
}
- }
-
- switch( data->search_mode )
- {
-
- case LINE_SEARCH:
- {
- if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
+ }
+
+ switch( data->search_mode )
+ {
+
+ case LINE_SEARCH:
+ {
+ if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
( c == R_HISTORY_TOKEN_SEARCH_BACKWARD ) )
- {
- data->history_search.go_backwards();
- }
- else
- {
- if (! data->history_search.go_forwards()) {
+ {
+ data->history_search.go_backwards();
+ }
+ else
+ {
+ if (! data->history_search.go_forwards()) {
/* If you try to go forwards past the end, we just go to the end */
data->history_search.go_to_end();
}
- }
-
+ }
+
wcstring new_text;
if (data->history_search.is_at_end()) {
new_text = data->search_buff;
} else {
new_text = data->history_search.current_string();
}
- set_command_line_and_position(new_text, new_text.size());
-
- break;
- }
-
- case TOKEN_SEARCH:
- {
- if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
+ set_command_line_and_position(new_text, new_text.size());
+
+ break;
+ }
+
+ case TOKEN_SEARCH:
+ {
+ if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
( c == R_HISTORY_TOKEN_SEARCH_BACKWARD ) )
- {
- handle_token_history( SEARCH_BACKWARD, reset );
- }
- else
- {
- handle_token_history( SEARCH_FORWARD, reset );
- }
-
- break;
- }
-
- }
- break;
- }
-
-
+ {
+ handle_token_history( SEARCH_BACKWARD, reset );
+ }
+ else
+ {
+ handle_token_history( SEARCH_FORWARD, reset );
+ }
+
+ break;
+ }
+
+ }
+ break;
+ }
+
+
/* Move left*/
- case R_BACKWARD_CHAR:
- {
- if( data->buff_pos > 0 )
- {
- data->buff_pos--;
- reader_repaint();
- }
- break;
- }
-
+ case R_BACKWARD_CHAR:
+ {
+ if( data->buff_pos > 0 )
+ {
+ data->buff_pos--;
+ reader_repaint();
+ }
+ break;
+ }
+
/* Move right*/
- case R_FORWARD_CHAR:
- {
- if( data->buff_pos < data->command_length() )
- {
- data->buff_pos++;
- reader_repaint();
- } else {
+ case R_FORWARD_CHAR:
+ {
+ if( data->buff_pos < data->command_length() )
+ {
+ data->buff_pos++;
+ reader_repaint();
+ } else {
accept_autosuggestion();
}
- break;
- }
-
+ break;
+ }
+
/* kill one word left */
- case R_BACKWARD_KILL_WORD:
- {
- move_word(MOVE_DIR_LEFT, true /* erase */, last_char!=R_BACKWARD_KILL_WORD);
- break;
- }
-
+ case R_BACKWARD_KILL_WORD:
+ {
+ move_word(MOVE_DIR_LEFT, true /* erase */, last_char!=R_BACKWARD_KILL_WORD);
+ break;
+ }
+
/* kill one word right */
- case R_KILL_WORD:
- {
- move_word(MOVE_DIR_RIGHT, true /* erase */, last_char!=R_KILL_WORD);
- break;
- }
-
+ case R_KILL_WORD:
+ {
+ move_word(MOVE_DIR_RIGHT, true /* erase */, last_char!=R_KILL_WORD);
+ break;
+ }
+
/* move one word left*/
- case R_BACKWARD_WORD:
- {
- move_word(MOVE_DIR_LEFT, false /* do not erase */, false);
- break;
- }
-
+ case R_BACKWARD_WORD:
+ {
+ move_word(MOVE_DIR_LEFT, false /* do not erase */, false);
+ break;
+ }
+
/* move one word right*/
- case R_FORWARD_WORD:
- {
- move_word(MOVE_DIR_RIGHT, false /* do not erase */, false);
- break;
- }
-
- case R_BEGINNING_OF_HISTORY:
- {
+ case R_FORWARD_WORD:
+ {
+ move_word(MOVE_DIR_RIGHT, false /* do not erase */, false);
+ break;
+ }
+
+ case R_BEGINNING_OF_HISTORY:
+ {
data->history_search = history_search_t(*data->history, data->command_line, HISTORY_SEARCH_TYPE_PREFIX);
data->history_search.go_to_beginning();
if (! data->history_search.is_at_end()) {
wcstring new_text = data->history_search.current_string();
set_command_line_and_position(new_text, new_text.size());
}
-
- break;
- }
-
- case R_END_OF_HISTORY:
- {
- data->history_search.go_to_end();
- break;
- }
-
- case R_UP_LINE:
- case R_DOWN_LINE:
- {
- int line_old = parse_util_get_line_from_offset( data->command_line, data->buff_pos );
- int line_new;
-
- if( c == R_UP_LINE )
- line_new = line_old-1;
- else
- line_new = line_old+1;
-
- int line_count = parse_util_lineno( data->command_line.c_str(), data->command_length() )-1;
-
- if( line_new >= 0 && line_new <= line_count)
- {
- size_t base_pos_new;
- size_t base_pos_old;
-
- int indent_old;
- int indent_new;
- size_t line_offset_old;
- size_t total_offset_new;
-
- base_pos_new = parse_util_get_offset_from_line( data->command_line, line_new );
-
- base_pos_old = parse_util_get_offset_from_line( data->command_line, line_old );
-
- assert(base_pos_new != (size_t)(-1) && base_pos_old != (size_t)(-1));
- indent_old = data->indents.at(base_pos_old);
- indent_new = data->indents.at(base_pos_new);
-
- line_offset_old = data->buff_pos - parse_util_get_offset_from_line( data->command_line, line_old );
- total_offset_new = parse_util_get_offset( data->command_line, line_new, line_offset_old - 4*(indent_new-indent_old));
- data->buff_pos = total_offset_new;
- reader_repaint();
- }
-
- break;
- }
-
- case R_SUPPRESS_AUTOSUGGESTION:
- {
- data->suppress_autosuggestion = true;
- data->autosuggestion.clear();
- reader_repaint();
- break;
- }
-
- case R_ACCEPT_AUTOSUGGESTION:
- {
- accept_autosuggestion();
- break;
- }
-
+
+ break;
+ }
+
+ case R_END_OF_HISTORY:
+ {
+ data->history_search.go_to_end();
+ break;
+ }
+
+ case R_UP_LINE:
+ case R_DOWN_LINE:
+ {
+ int line_old = parse_util_get_line_from_offset( data->command_line, data->buff_pos );
+ int line_new;
+
+ if( c == R_UP_LINE )
+ line_new = line_old-1;
+ else
+ line_new = line_old+1;
+
+ int line_count = parse_util_lineno( data->command_line.c_str(), data->command_length() )-1;
+
+ if( line_new >= 0 && line_new <= line_count)
+ {
+ size_t base_pos_new;
+ size_t base_pos_old;
+
+ int indent_old;
+ int indent_new;
+ size_t line_offset_old;
+ size_t total_offset_new;
+
+ base_pos_new = parse_util_get_offset_from_line( data->command_line, line_new );
+
+ base_pos_old = parse_util_get_offset_from_line( data->command_line, line_old );
+
+ assert(base_pos_new != (size_t)(-1) && base_pos_old != (size_t)(-1));
+ indent_old = data->indents.at(base_pos_old);
+ indent_new = data->indents.at(base_pos_new);
+
+ line_offset_old = data->buff_pos - parse_util_get_offset_from_line( data->command_line, line_old );
+ total_offset_new = parse_util_get_offset( data->command_line, line_new, line_offset_old - 4*(indent_new-indent_old));
+ data->buff_pos = total_offset_new;
+ reader_repaint();
+ }
+
+ break;
+ }
+
+ case R_SUPPRESS_AUTOSUGGESTION:
+ {
+ data->suppress_autosuggestion = true;
+ data->autosuggestion.clear();
+ reader_repaint();
+ break;
+ }
+
+ case R_ACCEPT_AUTOSUGGESTION:
+ {
+ accept_autosuggestion();
+ break;
+ }
+
/* Other, if a normal character, we add it to the command */
- default:
- {
-
- if( (!wchar_private(c)) && (( (c>31) || (c==L'\n'))&& (c != 127)) )
- {
+ default:
+ {
+
+ if( (!wchar_private(c)) && (( (c>31) || (c==L'\n'))&& (c != 127)) )
+ {
/* Regular character */
- insert_char( c );
- }
- else
- {
- /*
+ insert_char( c );
+ }
+ else
+ {
+ /*
Low priority debug message. These can happen if
the user presses an unefined control
sequnece. No reason to report.
*/
- debug( 2, _( L"Unknown keybinding %d" ), c );
- }
- break;
- }
-
- }
-
- if( (c != R_HISTORY_SEARCH_BACKWARD) &&
+ debug( 2, _( L"Unknown keybinding %d" ), c );
+ }
+ break;
+ }
+
+ }
+
+ if( (c != R_HISTORY_SEARCH_BACKWARD) &&
(c != R_HISTORY_SEARCH_FORWARD) &&
(c != R_HISTORY_TOKEN_SEARCH_BACKWARD) &&
(c != R_HISTORY_TOKEN_SEARCH_FORWARD) &&
(c != R_NULL) )
- {
- data->search_mode = NO_SEARCH;
- data->search_buff.clear();
- data->history_search.go_to_end();
- data->token_history_pos=-1;
- }
-
- last_char = c;
- }
-
- writestr( L"\n" );
+ {
+ data->search_mode = NO_SEARCH;
+ data->search_buff.clear();
+ data->history_search.go_to_end();
+ data->token_history_pos=-1;
+ }
+
+ last_char = c;
+ }
+
+ writestr( L"\n" );
/*
if( comp )
halloc_free( comp );
*/
- if( !reader_exit_forced() )
- {
- if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
- {
- wperror(L"tcsetattr");
- }
-
- set_color( rgb_color_t::reset(), rgb_color_t::reset() );
- }
-
- return finished ? data->command_line.c_str() : 0;
+ if( !reader_exit_forced() )
+ {
+ if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
+ {
+ wperror(L"tcsetattr");
+ }
+
+ set_color( rgb_color_t::reset(), rgb_color_t::reset() );
+ }
+
+ return finished ? data->command_line.c_str() : 0;
}
int reader_search_mode()
{
- if( !data )
- {
- return -1;
- }
-
- return !!data->search_mode;
+ if( !data )
+ {
+ return -1;
+ }
+
+ return !!data->search_mode;
}
@@ -3310,123 +3310,123 @@ int reader_search_mode()
static int read_ni( int fd, const io_chain_t &io )
{
parser_t &parser = parser_t::principal_parser();
- FILE *in_stream;
- wchar_t *buff=0;
- std::vector<char> acc;
-
- int des = fd == 0 ? dup(0) : fd;
- int res=0;
-
- if (des == -1)
- {
- wperror( L"dup" );
- return 1;
- }
-
- in_stream = fdopen( des, "r" );
- if( in_stream != 0 )
- {
- wchar_t *str;
- size_t acc_used;
-
- while(!feof( in_stream ))
- {
- char buff[4096];
- size_t c = fread(buff, 1, 4096, in_stream);
-
- if( ferror( in_stream ) && ( errno != EINTR ) )
- {
- debug( 1,
- _( L"Error while reading from file descriptor" ) );
-
- /*
- Reset buffer on error. We won't evaluate incomplete files.
- */
- acc.clear();
- break;
-
- }
-
- acc.insert(acc.end(), buff, buff + c);
- }
+ FILE *in_stream;
+ wchar_t *buff=0;
+ std::vector<char> acc;
+
+ int des = fd == 0 ? dup(0) : fd;
+ int res=0;
+
+ if (des == -1)
+ {
+ wperror( L"dup" );
+ return 1;
+ }
+
+ in_stream = fdopen( des, "r" );
+ if( in_stream != 0 )
+ {
+ wchar_t *str;
+ size_t acc_used;
+
+ while(!feof( in_stream ))
+ {
+ char buff[4096];
+ size_t c = fread(buff, 1, 4096, in_stream);
+
+ if( ferror( in_stream ) && ( errno != EINTR ) )
+ {
+ debug( 1,
+ _( L"Error while reading from file descriptor" ) );
+
+ /*
+ Reset buffer on error. We won't evaluate incomplete files.
+ */
+ acc.clear();
+ break;
+
+ }
+
+ acc.insert(acc.end(), buff, buff + c);
+ }
acc.push_back(0);
- acc_used = acc.size();
- str = str2wcs(&acc.at(0));
+ acc_used = acc.size();
+ str = str2wcs(&acc.at(0));
acc.clear();
- if( fclose( in_stream ))
- {
- debug( 1,
- _( L"Error while closing input stream" ) );
- wperror( L"fclose" );
- res = 1;
- }
-
- if( str )
- {
- wcstring sb;
- if( ! parser.test( str, 0, &sb, L"fish" ) )
- {
- parser.eval( str, io, TOP );
- }
- else
- {
- fwprintf( stderr, L"%ls", sb.c_str() );
- res = 1;
- }
- free( str );
- }
- else
- {
- if( acc_used > 1 )
- {
- debug( 1,
- _( L"Could not convert input. Read %d bytes." ),
- acc_used-1 );
- }
- else
- {
- debug( 1,
- _( L"Could not read input stream" ) );
- }
- res=1;
- }
-
- }
- else
- {
- debug( 1,
- _( L"Error while opening input stream" ) );
- wperror( L"fdopen" );
- free( buff );
- res=1;
- }
- return res;
+ if( fclose( in_stream ))
+ {
+ debug( 1,
+ _( L"Error while closing input stream" ) );
+ wperror( L"fclose" );
+ res = 1;
+ }
+
+ if( str )
+ {
+ wcstring sb;
+ if( ! parser.test( str, 0, &sb, L"fish" ) )
+ {
+ parser.eval( str, io, TOP );
+ }
+ else
+ {
+ fwprintf( stderr, L"%ls", sb.c_str() );
+ res = 1;
+ }
+ free( str );
+ }
+ else
+ {
+ if( acc_used > 1 )
+ {
+ debug( 1,
+ _( L"Could not convert input. Read %d bytes." ),
+ acc_used-1 );
+ }
+ else
+ {
+ debug( 1,
+ _( L"Could not read input stream" ) );
+ }
+ res=1;
+ }
+
+ }
+ else
+ {
+ debug( 1,
+ _( L"Error while opening input stream" ) );
+ wperror( L"fdopen" );
+ free( buff );
+ res=1;
+ }
+ return res;
}
int reader_read( int fd, const io_chain_t &io )
{
- int res;
-
- /*
- If reader_read is called recursively through the '.' builtin, we
- need to preserve is_interactive. This, and signal handler setup
- is handled by proc_push_interactive/proc_pop_interactive.
- */
-
- int inter = ((fd == STDIN_FILENO) && isatty(STDIN_FILENO));
- proc_push_interactive( inter );
-
- res= get_is_interactive() ? read_i():read_ni( fd, io );
-
- /*
- If the exit command was called in a script, only exit the
- script, not the program.
- */
- if( data )
- data->end_loop = 0;
- end_loop = 0;
-
- proc_pop_interactive();
- return res;
+ int res;
+
+ /*
+ If reader_read is called recursively through the '.' builtin, we
+ need to preserve is_interactive. This, and signal handler setup
+ is handled by proc_push_interactive/proc_pop_interactive.
+ */
+
+ int inter = ((fd == STDIN_FILENO) && isatty(STDIN_FILENO));
+ proc_push_interactive( inter );
+
+ res= get_is_interactive() ? read_i():read_ni( fd, io );
+
+ /*
+ If the exit command was called in a script, only exit the
+ script, not the program.
+ */
+ if( data )
+ data->end_loop = 0;
+ end_loop = 0;
+
+ proc_pop_interactive();
+ return res;
}
diff --git a/reader.h b/reader.h
index 5ce99882..db8dfcb4 100644
--- a/reader.h
+++ b/reader.h
@@ -1,9 +1,9 @@
-/** \file reader.h
+/** \file reader.h
Prototypes for functions for reading data from stdin and passing
- to the parser. If stdin is a keyboard, it supplies a killring,
- history, syntax highlighting, tab-completion and various other
- features.
+ to the parser. If stdin is a keyboard, it supplies a killring,
+ history, syntax highlighting, tab-completion and various other
+ features.
*/
#ifndef FISH_READER_H
@@ -53,7 +53,7 @@ const wchar_t *reader_current_filename();
/**
Push a new filename on the stack of read files
-
+
\param fn The fileanme to push
*/
void reader_push_current_filename( const wchar_t *fn );
@@ -125,7 +125,7 @@ int reader_interrupted();
const wchar_t *reader_readline();
/**
- Push a new reader environment.
+ Push a new reader environment.
*/
void reader_push( const wchar_t *name );
@@ -135,7 +135,7 @@ void reader_push( const wchar_t *name );
void reader_pop();
/**
- Specify function to use for finding possible tab completions. The function must take these arguments:
+ Specify function to use for finding possible tab completions. The function must take these arguments:
- The command to be completed as a null terminated array of wchar_t
- An array_list_t in which completions will be inserted.
@@ -151,7 +151,7 @@ typedef void (*highlight_function_t)( const wcstring &, std::vector<int> &, size
/**
Specify function for syntax highlighting. The function must take these arguments:
-
+
- The command to be highlighted as a null terminated array of wchar_t
- The color code of each character as an array of ints
- The cursor position
@@ -178,7 +178,7 @@ void reader_set_left_prompt( const wcstring &prompt );
void reader_set_right_prompt( const wcstring &prompt );
/**
- Returns true if the shell is exiting, 0 otherwise.
+ Returns true if the shell is exiting, 0 otherwise.
*/
int exit_status();
diff --git a/sanity.cpp b/sanity.cpp
index 37e7e7e9..cbce3c82 100644
--- a/sanity.cpp
+++ b/sanity.cpp
@@ -1,5 +1,5 @@
/** \file sanity.c
- Functions for performing sanity checks on the program state
+ Functions for performing sanity checks on the program state
*/
#include "config.h"
@@ -34,43 +34,43 @@ static int insane;
void sanity_lose()
{
- debug( 0, _(L"Errors detected, shutting down. Break on sanity_lose() to debug.") );
- insane = 1;
+ debug( 0, _(L"Errors detected, shutting down. Break on sanity_lose() to debug.") );
+ insane = 1;
}
int sanity_check()
{
- if( !insane )
- if( get_is_interactive() )
- history_sanity_check();
- if( !insane )
- reader_sanity_check();
- if( !insane )
- kill_sanity_check();
- if( !insane )
- proc_sanity_check();
-
- return insane;
+ if( !insane )
+ if( get_is_interactive() )
+ history_sanity_check();
+ if( !insane )
+ reader_sanity_check();
+ if( !insane )
+ kill_sanity_check();
+ if( !insane )
+ proc_sanity_check();
+
+ return insane;
}
void validate_pointer( const void *ptr, const wchar_t *err, int null_ok )
{
-
- /*
- Test if the pointer data crosses a segment boundary.
- */
-
- if( (0x00000003l & (intptr_t)ptr) != 0 )
- {
- debug( 0, _(L"The pointer '%ls' is invalid"), err );
- sanity_lose();
- }
-
- if((!null_ok) && (ptr==0))
- {
- debug( 0, _(L"The pointer '%ls' is null"), err );
- sanity_lose();
- }
+
+ /*
+ Test if the pointer data crosses a segment boundary.
+ */
+
+ if( (0x00000003l & (intptr_t)ptr) != 0 )
+ {
+ debug( 0, _(L"The pointer '%ls' is invalid"), err );
+ sanity_lose();
+ }
+
+ if((!null_ok) && (ptr==0))
+ {
+ debug( 0, _(L"The pointer '%ls' is null"), err );
+ sanity_lose();
+ }
}
diff --git a/sanity.h b/sanity.h
index 0ca8cd2a..40b92dec 100644
--- a/sanity.h
+++ b/sanity.h
@@ -1,5 +1,5 @@
/** \file sanity.h
- Prototypes for functions for performing sanity checks on the program state
+ Prototypes for functions for performing sanity checks on the program state
*/
#ifndef FISH_SANITY_H
@@ -19,7 +19,7 @@ int sanity_check();
/**
Try and determine if ptr is a valid pointer. If not, loose sanity.
-
+
\param ptr The pointer to validate
\param err A description of what the pointer refers to, for use in error messages
\param null_ok Wheter the pointer is allowed to point to 0
diff --git a/screen.cpp b/screen.cpp
index 5caa3d01..80865c3f 100644
--- a/screen.cpp
+++ b/screen.cpp
@@ -78,14 +78,14 @@ static int s_writeb( char c );
class scoped_buffer_t {
data_buffer_t * const old_buff;
int (* const old_writer)(char);
-
+
public:
scoped_buffer_t(data_buffer_t *buff) : old_buff(s_writeb_buffer), old_writer(output_get_writer())
{
s_writeb_buffer = buff;
output_set_writer(s_writeb);
}
-
+
~scoped_buffer_t()
{
s_writeb_buffer = old_buff;
@@ -100,18 +100,18 @@ class scoped_buffer_t {
*/
static int try_sequence( const char *seq, const wchar_t *str )
{
- int i;
+ int i;
- for( i=0;; i++ )
- {
- if( !seq[i] )
- return i;
+ for( i=0;; i++ )
+ {
+ if( !seq[i] )
+ return i;
- if( seq[i] != str[i] )
- return 0;
- }
+ if( seq[i] != str[i] )
+ return 0;
+ }
- return 0;
+ return 0;
}
/**
@@ -120,32 +120,32 @@ static int try_sequence( const char *seq, const wchar_t *str )
*/
static size_t next_tab_stop( size_t in )
{
- /*
- Assume tab stops every 8 characters if undefined
- */
- size_t tab_width = (init_tabs > 0 ? (size_t)init_tabs : 8);
- return ( (in/tab_width)+1 )*tab_width;
+ /*
+ Assume tab stops every 8 characters if undefined
+ */
+ size_t tab_width = (init_tabs > 0 ? (size_t)init_tabs : 8);
+ return ( (in/tab_width)+1 )*tab_width;
}
// PCA for term256 support, let's just detect the escape codes directly
static int is_term256_escape(const wchar_t *str)
{
- // An escape code looks like this: \x1b[38;5;<num>m
- // or like this: \x1b[48;5;<num>m
-
+ // An escape code looks like this: \x1b[38;5;<num>m
+ // or like this: \x1b[48;5;<num>m
+
// parse out the required prefix
int len = try_sequence("\x1b[38;5;", str);
if (! len) len = try_sequence("\x1b[48;5;", str);
if (! len) return 0;
-
+
// now try parsing out a string of digits
// we need at least one
if (! iswdigit(str[len])) return 0;
while (iswdigit(str[len])) len++;
-
+
// look for the terminating m
if (str[len++] != L'm') return 0;
-
+
// success
return len;
}
@@ -164,39 +164,39 @@ static bool allow_soft_wrap(void)
*/
static size_t calc_prompt_width_and_lines( const wchar_t *prompt, size_t *out_prompt_lines )
{
- size_t res = 0;
- size_t j, k;
+ size_t res = 0;
+ size_t j, k;
*out_prompt_lines = 1;
-
- for( j=0; prompt[j]; j++ )
- {
- if( prompt[j] == L'\x1b' )
- {
- /*
+
+ for( j=0; prompt[j]; j++ )
+ {
+ if( prompt[j] == L'\x1b' )
+ {
+ /*
This is the start of an escape code. Try to guess it's width.
*/
- size_t p;
- int len=0;
- bool found = false;
-
- /*
+ size_t p;
+ int len=0;
+ bool found = false;
+
+ /*
Detect these terminfo color escapes with parameter
value 0..7, all of which don't move the cursor
*/
- char * const esc[] =
+ char * const esc[] =
{
set_a_foreground,
set_a_background,
set_foreground,
set_background,
}
- ;
-
- /*
+ ;
+
+ /*
Detect these semi-common terminfo escapes without any
parameter values, all of which don't move the cursor
*/
- char * const esc2[] =
+ char * const esc2[] =
{
enter_bold_mode,
exit_attribute_mode,
@@ -219,25 +219,25 @@ static size_t calc_prompt_width_and_lines( const wchar_t *prompt, size_t *out_pr
exit_standout_mode,
enter_secure_mode
}
- ;
-
- for( p=0; p < sizeof esc / sizeof *esc && !found; p++ )
- {
- if( !esc[p] )
- continue;
-
- for( k=0; k<8; k++ )
- {
- len = try_sequence( tparm(esc[p],k), &prompt[j] );
- if( len )
- {
- j += (len-1);
- found = true;
- break;
- }
- }
- }
-
+ ;
+
+ for( p=0; p < sizeof esc / sizeof *esc && !found; p++ )
+ {
+ if( !esc[p] )
+ continue;
+
+ for( k=0; k<8; k++ )
+ {
+ len = try_sequence( tparm(esc[p],k), &prompt[j] );
+ if( len )
+ {
+ j += (len-1);
+ found = true;
+ break;
+ }
+ }
+ }
+
// PCA for term256 support, let's just detect the escape codes directly
if (! found) {
len = is_term256_escape(&prompt[j]);
@@ -246,41 +246,41 @@ static size_t calc_prompt_width_and_lines( const wchar_t *prompt, size_t *out_pr
found = true;
}
}
-
-
- for( p=0; p < (sizeof(esc2)/sizeof(char *)) && !found; p++ )
- {
- if( !esc2[p] )
- continue;
- /*
+
+
+ for( p=0; p < (sizeof(esc2)/sizeof(char *)) && !found; p++ )
+ {
+ if( !esc2[p] )
+ continue;
+ /*
Test both padded and unpadded version, just to
be safe. Most versions of tparm don't actually
seem to do anything these days.
*/
- len = maxi( try_sequence( tparm(esc2[p]), &prompt[j] ),
+ len = maxi( try_sequence( tparm(esc2[p]), &prompt[j] ),
try_sequence( esc2[p], &prompt[j] ));
-
- if( len )
- {
- j += (len-1);
- found = true;
- }
- }
-
- if( !found )
- {
- if( prompt[j+1] == L'k' )
- {
- const env_var_t term_name = env_get_string( L"TERM" );
- if( !term_name.missing() && wcsstr( term_name.c_str(), L"screen" ) == term_name )
- {
- const wchar_t *end;
- j+=2;
- found = true;
- end = wcsstr( &prompt[j], L"\x1b\\" );
- if( end )
- {
- /*
+
+ if( len )
+ {
+ j += (len-1);
+ found = true;
+ }
+ }
+
+ if( !found )
+ {
+ if( prompt[j+1] == L'k' )
+ {
+ const env_var_t term_name = env_get_string( L"TERM" );
+ if( !term_name.missing() && wcsstr( term_name.c_str(), L"screen" ) == term_name )
+ {
+ const wchar_t *end;
+ j+=2;
+ found = true;
+ end = wcsstr( &prompt[j], L"\x1b\\" );
+ if( end )
+ {
+ /*
You'd thing this should be
'(end-prompt)+2', in order to move j
past the end of the string, but there is
@@ -288,35 +288,35 @@ static size_t calc_prompt_width_and_lines( const wchar_t *prompt, size_t *out_pr
should always point to the last menged
character, e.g. +1.
*/
- j = (end-prompt)+1;
- }
- else
- {
- break;
- }
- }
- }
- }
-
- }
- else if( prompt[j] == L'\t' )
- {
- res = next_tab_stop( res );
- }
- else if( prompt[j] == L'\n' )
- {
- res = 0;
+ j = (end-prompt)+1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ }
+ else if( prompt[j] == L'\t' )
+ {
+ res = next_tab_stop( res );
+ }
+ else if( prompt[j] == L'\n' )
+ {
+ res = 0;
*out_prompt_lines += 1;
- }
- else
- {
- /*
+ }
+ else
+ {
+ /*
Ordinary decent character. Just add width.
*/
- res += fish_wcwidth( prompt[j] );
- }
- }
- return res;
+ res += fish_wcwidth( prompt[j] );
+ }
+ }
+ return res;
}
static size_t calc_prompt_width(const wchar_t *prompt)
@@ -345,9 +345,9 @@ static size_t calc_prompt_lines(const wchar_t *prompt)
*/
static int room_for_usec(struct stat *st)
{
- int res = ((&(st->st_atime) + 2) == &(st->st_mtime) &&
- (&(st->st_atime) + 4) == &(st->st_ctime));
- return res;
+ int res = ((&(st->st_atime) + 2) == &(st->st_mtime) &&
+ (&(st->st_atime) + 4) == &(st->st_ctime));
+ return res;
}
/**
@@ -363,37 +363,37 @@ static void s_save_status( screen_t *s)
// tty's ctime as part of its tty_tickets feature
// Disabling this should fix https://github.com/fish-shell/fish-shell/issues/122
#if 0
- /*
- This futimes call tries to trick the system into using st_mtime
- as a tampering flag. This of course only works on systems where
- futimes is defined, but it should make the status saving stuff
- failsafe.
- */
- struct timeval t[]=
- {
- {
- time(0)-1,
- 0
- }
- ,
- {
- time(0)-1,
- 0
- }
- }
- ;
-
- /*
- Don't check return value on these. We don't care if they fail,
- really. This is all just to make the prompt look ok, which is
- impossible to do 100% reliably. We try, at least.
- */
- futimes( 1, t );
- futimes( 2, t );
+ /*
+ This futimes call tries to trick the system into using st_mtime
+ as a tampering flag. This of course only works on systems where
+ futimes is defined, but it should make the status saving stuff
+ failsafe.
+ */
+ struct timeval t[]=
+ {
+ {
+ time(0)-1,
+ 0
+ }
+ ,
+ {
+ time(0)-1,
+ 0
+ }
+ }
+ ;
+
+ /*
+ Don't check return value on these. We don't care if they fail,
+ really. This is all just to make the prompt look ok, which is
+ impossible to do 100% reliably. We try, at least.
+ */
+ futimes( 1, t );
+ futimes( 2, t );
#endif
- fstat( 1, &s->prev_buff_1 );
- fstat( 2, &s->prev_buff_2 );
+ fstat( 1, &s->prev_buff_1 );
+ fstat( 2, &s->prev_buff_2 );
}
/**
@@ -406,43 +406,43 @@ static void s_save_status( screen_t *s)
static void s_check_status( screen_t *s)
{
- fflush( stdout );
- fflush( stderr );
-
- fstat( 1, &s->post_buff_1 );
- fstat( 2, &s->post_buff_2 );
-
- int changed = ( s->prev_buff_1.st_mtime != s->post_buff_1.st_mtime ) ||
- ( s->prev_buff_2.st_mtime != s->post_buff_2.st_mtime );
-
- if (room_for_usec( &s->post_buff_1))
- {
- changed = changed || ( (&s->prev_buff_1.st_mtime)[1] != (&s->post_buff_1.st_mtime)[1] ) ||
- ( (&s->prev_buff_2.st_mtime)[1] != (&s->post_buff_2.st_mtime)[1] );
- }
-
- if( changed )
- {
- /*
- Ok, someone has been messing with our screen. We will want
- to repaint. However, we do not know where the cursor is. It
- is our best bet that we are still on the same line, so we
- move to the beginning of the line, reset the modelled screen
- contents, and then set the modeled cursor y-pos to its
- earlier value.
- */
-
- int prev_line = s->actual.cursor.y;
- write_loop( 1, "\r", 1 );
- s_reset( s, false );
- s->actual.cursor.y = prev_line;
- }
+ fflush( stdout );
+ fflush( stderr );
+
+ fstat( 1, &s->post_buff_1 );
+ fstat( 2, &s->post_buff_2 );
+
+ int changed = ( s->prev_buff_1.st_mtime != s->post_buff_1.st_mtime ) ||
+ ( s->prev_buff_2.st_mtime != s->post_buff_2.st_mtime );
+
+ if (room_for_usec( &s->post_buff_1))
+ {
+ changed = changed || ( (&s->prev_buff_1.st_mtime)[1] != (&s->post_buff_1.st_mtime)[1] ) ||
+ ( (&s->prev_buff_2.st_mtime)[1] != (&s->post_buff_2.st_mtime)[1] );
+ }
+
+ if( changed )
+ {
+ /*
+ Ok, someone has been messing with our screen. We will want
+ to repaint. However, we do not know where the cursor is. It
+ is our best bet that we are still on the same line, so we
+ move to the beginning of the line, reset the modelled screen
+ contents, and then set the modeled cursor y-pos to its
+ earlier value.
+ */
+
+ int prev_line = s->actual.cursor.y;
+ write_loop( 1, "\r", 1 );
+ s_reset( s, false );
+ s->actual.cursor.y = prev_line;
+ }
}
/**
Appends a character to the end of the line that the output cursor is
on. This function automatically handles linebreaks and lines longer
- than the screen width.
+ than the screen width.
*/
static void s_desired_append_char( screen_t *s,
wchar_t b,
@@ -450,63 +450,63 @@ static void s_desired_append_char( screen_t *s,
int indent,
size_t prompt_width )
{
- int line_no = s->desired.cursor.y;
-
- switch( b )
- {
- case L'\n':
- {
- int i;
+ int line_no = s->desired.cursor.y;
+
+ switch( b )
+ {
+ case L'\n':
+ {
+ int i;
/* Current line is definitely hard wrapped */
s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
s->desired.create_line(s->desired.line_count());
- s->desired.cursor.y++;
- s->desired.cursor.x=0;
- for( i=0; i < prompt_width+indent*INDENT_STEP; i++ )
- {
- s_desired_append_char( s, L' ', 0, indent, prompt_width );
- }
- break;
- }
-
- case L'\r':
- {
+ s->desired.cursor.y++;
+ s->desired.cursor.x=0;
+ for( i=0; i < prompt_width+indent*INDENT_STEP; i++ )
+ {
+ s_desired_append_char( s, L' ', 0, indent, prompt_width );
+ }
+ break;
+ }
+
+ case L'\r':
+ {
line_t &current = s->desired.line(line_no);
current.clear();
s->desired.cursor.x = 0;
- break;
- }
-
- default:
- {
- int screen_width = common_get_width();
- int cw = fish_wcwidth(b);
-
+ break;
+ }
+
+ default:
+ {
+ int screen_width = common_get_width();
+ int cw = fish_wcwidth(b);
+
s->desired.create_line(line_no);
-
- /*
+
+ /*
Check if we are at the end of the line. If so, continue on the next line.
*/
- if( (s->desired.cursor.x + cw) > screen_width )
- {
+ if( (s->desired.cursor.x + cw) > screen_width )
+ {
/* Current line is soft wrapped (assuming we support it) */
s->desired.line(s->desired.cursor.y).is_soft_wrapped = true;
//fprintf(stderr, "\n\n1 Soft wrapping %d\n\n", s->desired.cursor.y);
-
+
line_no = (int)s->desired.line_count();
s->desired.add_line();
- s->desired.cursor.y++;
- s->desired.cursor.x=0;
+ s->desired.cursor.y++;
+ s->desired.cursor.x=0;
for( size_t i=0; i < prompt_width; i++ )
{
s_desired_append_char( s, L' ', 0, indent, prompt_width );
}
- }
-
+ }
+
line_t &line = s->desired.line(line_no);
line.append(b, c);
- s->desired.cursor.x+= cw;
-
+ s->desired.cursor.x+= cw;
+
/* Maybe wrap the cursor to the next line, even if the line itself did not wrap. This avoids wonkiness in the last column. */
if (s->desired.cursor.x >= screen_width)
{
@@ -514,10 +514,10 @@ static void s_desired_append_char( screen_t *s,
s->desired.cursor.x = 0;
s->desired.cursor.y++;
}
- break;
- }
- }
-
+ break;
+ }
+ }
+
}
/**
@@ -526,14 +526,14 @@ static void s_desired_append_char( screen_t *s,
static int s_writeb( char c )
{
s_writeb_buffer->push_back(c);
- return 0;
+ return 0;
}
/**
Write the bytes needed to move screen cursor to the specified
position to the specified buffer. The actual_cursor field of the
specified screen_t will be updated.
-
+
\param s the screen to operate on
\param b the buffer to send the output escape codes to
\param new_x the new x position
@@ -543,73 +543,73 @@ static void s_move( screen_t *s, data_buffer_t *b, int new_x, int new_y )
{
if (s->actual.cursor.x == new_x && s->actual.cursor.y == new_y)
return;
-
- int i;
- int x_steps, y_steps;
-
- char *str;
+
+ int i;
+ int x_steps, y_steps;
+
+ char *str;
/*
- debug( 0, L"move from %d %d to %d %d",
- s->screen_cursor[0], s->screen_cursor[1],
+ debug( 0, L"move from %d %d to %d %d",
+ s->screen_cursor[0], s->screen_cursor[1],
new_x, new_y );
*/
scoped_buffer_t scoped_buffer(b);
-
- y_steps = new_y - s->actual.cursor.y;
-
- if( y_steps > 0 && (strcmp( cursor_down, "\n")==0))
- {
- /*
- This is very strange - it seems some (all?) consoles use a
- simple newline as the cursor down escape. This will of
- course move the cursor to the beginning of the line as well
- as moving it down one step. The cursor_up does not have this
- behaviour...
- */
- s->actual.cursor.x=0;
- }
-
- if( y_steps < 0 )
- {
- str = cursor_up;
- }
- else
- {
- str = cursor_down;
-
- }
-
- for( i=0; i<abs(y_steps); i++)
- {
- writembs(str);
- }
-
-
- x_steps = new_x - s->actual.cursor.x;
-
- if( x_steps && new_x == 0 )
- {
+
+ y_steps = new_y - s->actual.cursor.y;
+
+ if( y_steps > 0 && (strcmp( cursor_down, "\n")==0))
+ {
+ /*
+ This is very strange - it seems some (all?) consoles use a
+ simple newline as the cursor down escape. This will of
+ course move the cursor to the beginning of the line as well
+ as moving it down one step. The cursor_up does not have this
+ behaviour...
+ */
+ s->actual.cursor.x=0;
+ }
+
+ if( y_steps < 0 )
+ {
+ str = cursor_up;
+ }
+ else
+ {
+ str = cursor_down;
+
+ }
+
+ for( i=0; i<abs(y_steps); i++)
+ {
+ writembs(str);
+ }
+
+
+ x_steps = new_x - s->actual.cursor.x;
+
+ if( x_steps && new_x == 0 )
+ {
b->push_back('\r');
- x_steps = 0;
- }
-
- if( x_steps < 0 )
+ x_steps = 0;
+ }
+
+ if( x_steps < 0 )
{
- str = cursor_left;
- }
- else
- {
- str = cursor_right;
- }
-
- for( i=0; i<abs(x_steps); i++)
- {
- writembs(str);
- }
-
-
- s->actual.cursor.x = new_x;
- s->actual.cursor.y = new_y;
+ str = cursor_left;
+ }
+ else
+ {
+ str = cursor_right;
+ }
+
+ for( i=0; i<abs(x_steps); i++)
+ {
+ writembs(str);
+ }
+
+
+ s->actual.cursor.x = new_x;
+ s->actual.cursor.y = new_y;
}
/**
@@ -618,10 +618,10 @@ static void s_move( screen_t *s, data_buffer_t *b, int new_x, int new_y )
static void s_set_color( screen_t *s, data_buffer_t *b, int c )
{
scoped_buffer_t scoped_buffer(b);
-
+
unsigned int uc = (unsigned int)c;
- set_color( highlight_get_color( uc & 0xffff, false ),
- highlight_get_color( (uc>>16)&0xffff, true ) );
+ set_color( highlight_get_color( uc & 0xffff, false ),
+ highlight_get_color( (uc>>16)&0xffff, true ) );
}
/**
@@ -630,14 +630,14 @@ static void s_set_color( screen_t *s, data_buffer_t *b, int c )
*/
static void s_write_char( screen_t *s, data_buffer_t *b, wchar_t c )
{
- scoped_buffer_t scoped_buffer(b);
- s->actual.cursor.x+=fish_wcwidth( c );
- writech( c );
+ scoped_buffer_t scoped_buffer(b);
+ s->actual.cursor.x+=fish_wcwidth( c );
+ writech( c );
if (s->actual.cursor.x == s->actual_width && allow_soft_wrap())
{
s->soft_wrap_location.x = 0;
s->soft_wrap_location.y = s->actual.cursor.y + 1;
-
+
/* If auto_right_margin is set, then the cursor sticks to the right edge when it's in the rightmost column, so reflect that fact */
if (auto_right_margin)
s->actual.cursor.x--;
@@ -655,7 +655,7 @@ static void s_write_char( screen_t *s, data_buffer_t *b, wchar_t c )
static void s_write_mbs( data_buffer_t *b, char *s )
{
scoped_buffer_t scoped_buffer(b);
- writembs( s );
+ writembs( s );
}
/**
@@ -665,7 +665,7 @@ static void s_write_mbs( data_buffer_t *b, char *s )
static void s_write_str( data_buffer_t *b, const wchar_t *s )
{
scoped_buffer_t scoped_buffer(b);
- writestr( s );
+ writestr( s );
}
/** Returns the length of the "shared prefix" of the two lines, which is the run of matching text and colors.
@@ -675,7 +675,7 @@ static size_t line_shared_prefix(const line_t &a, const line_t &b)
{
size_t idx, max = std::min(a.size(), b.size());
for (idx=0; idx < max; idx++)
- {
+ {
wchar_t ac = a.char_at(idx), bc = b.char_at(idx);
if (fish_wcwidth(ac) < 1 || fish_wcwidth(bc) < 1)
{
@@ -683,7 +683,7 @@ static size_t line_shared_prefix(const line_t &a, const line_t &b)
if (idx > 0) idx--;
break;
}
-
+
/* We're done if the text or colors are different */
if (ac != bc || a.color_at(idx) != b.color_at(idx))
break;
@@ -717,29 +717,29 @@ static void invalidate_soft_wrap(screen_t *scr)
*/
static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *right_prompt )
{
- const size_t left_prompt_width = calc_prompt_width( left_prompt );
+ const size_t left_prompt_width = calc_prompt_width( left_prompt );
const size_t right_prompt_width = calc_prompt_width( right_prompt );
-
- int screen_width = common_get_width();
- bool need_clear = scr->need_clear;
+
+ int screen_width = common_get_width();
+ bool need_clear = scr->need_clear;
bool has_cleared_screen = false;
-
+
/* Figure out how many following lines we need to clear (probably 0) */
size_t actual_lines_before_reset = scr->actual_lines_before_reset;
scr->actual_lines_before_reset = 0;
-
- data_buffer_t output;
-
- scr->need_clear = false;
-
- if( scr->actual_width != screen_width )
- {
- need_clear = true;
- s_move( scr, &output, 0, 0 );
- scr->actual_width = screen_width;
- s_reset( scr, false, false /* don't clear prompt */);
- }
-
+
+ data_buffer_t output;
+
+ scr->need_clear = false;
+
+ if( scr->actual_width != screen_width )
+ {
+ need_clear = true;
+ s_move( scr, &output, 0, 0 );
+ scr->actual_width = screen_width;
+ s_reset( scr, false, false /* don't clear prompt */);
+ }
+
/* Determine how many lines have stuff on them; we need to clear lines with stuff that we don't want */
const size_t lines_with_stuff = maxi(actual_lines_before_reset, scr->actual.line_count());
if (lines_with_stuff > scr->desired.line_count())
@@ -747,28 +747,28 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
/* There are lines that we output to previously that will need to be cleared */
need_clear = true;
}
-
- if( wcscmp( left_prompt, scr->actual_left_prompt.c_str() ) )
- {
- s_move( scr, &output, 0, 0 );
- s_write_str( &output, left_prompt );
+
+ if( wcscmp( left_prompt, scr->actual_left_prompt.c_str() ) )
+ {
+ s_move( scr, &output, 0, 0 );
+ s_write_str( &output, left_prompt );
scr->actual_left_prompt = left_prompt;
- scr->actual.cursor.x = (int)left_prompt_width;
- }
-
+ scr->actual.cursor.x = (int)left_prompt_width;
+ }
+
for (size_t i=0; i < scr->desired.line_count(); i++)
- {
- const line_t &o_line = scr->desired.line(i);
- line_t &s_line = scr->actual.create_line(i);
- size_t start_pos = (i==0 ? left_prompt_width : 0);
+ {
+ const line_t &o_line = scr->desired.line(i);
+ line_t &s_line = scr->actual.create_line(i);
+ size_t start_pos = (i==0 ? left_prompt_width : 0);
int current_width = 0;
-
+
/* If this is the last line, maybe we should clear the screen */
const bool should_clear_screen_this_line = (need_clear && i + 1 == scr->desired.line_count() && clr_eos != NULL);
-
+
/* Note that skip_remaining is a width, not a character count */
size_t skip_remaining = start_pos;
-
+
if (! should_clear_screen_this_line) {
/* Compute how much we should skip. At a minimum we skip over the prompt. But also skip over the shared prefix of what we want to output now, and what we output before, to avoid repeatedly outputting it. */
const size_t shared_prefix = line_shared_prefix(o_line, s_line);
@@ -778,12 +778,12 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
if (prefix_width > skip_remaining)
skip_remaining = prefix_width;
}
-
+
/* Don't skip over the last two characters in a soft-wrapped line, so that we maintain soft-wrapping */
if (o_line.is_soft_wrapped)
skip_remaining = mini(skip_remaining, (size_t)(scr->actual_width - 2));
}
-
+
/* Skip over skip_remaining width worth of characters */
size_t j = 0;
for ( ; j < o_line.size(); j++)
@@ -794,7 +794,7 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
skip_remaining -= width;
current_width += width;
}
-
+
/* Skip over zero-width characters (e.g. combining marks at the end of the prompt) */
for ( ; j < o_line.size(); j++)
{
@@ -802,14 +802,14 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
if (width > 0)
break;
}
-
+
/* Maybe clear the screen before outputting. If we clear the screen after outputting, then we may erase the last character due to the sticky right margin. */
if (should_clear_screen_this_line) {
s_move( scr, &output, current_width, (int)i );
s_write_mbs(&output, clr_eos);
has_cleared_screen = true;
}
-
+
/* Now actually output stuff */
for ( ; j < o_line.size(); j++)
{
@@ -819,7 +819,7 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
s_write_char( scr, &output, o_line.char_at(j) );
current_width += fish_wcwidth(o_line.char_at(j));
}
-
+
bool clear_remainder = false;
/* Clear the remainder of the line if we need to clear and if we didn't write to the end of the line. If we did write to the end of the line, the "sticky right edge" (as part of auto_right_margin) means that we'll be clearing the last character we wrote! */
if (has_cleared_screen)
@@ -839,14 +839,14 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
{
int prev_width = (s_line.text.empty() ? 0 : fish_wcswidth(&s_line.text.at(0), s_line.text.size()));
clear_remainder = prev_width > current_width;
-
+
}
if (clear_remainder)
- {
- s_move( scr, &output, current_width, (int)i );
- s_write_mbs( &output, clr_eol);
- }
-
+ {
+ s_move( scr, &output, current_width, (int)i );
+ s_write_mbs( &output, clr_eol);
+ }
+
/* Output any rprompt if this is the first line. */
if (i == 0 && right_prompt_width > 0)
{
@@ -857,8 +857,8 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
s_write_str( &output, L"\r");
scr->actual.cursor.x = 0;
}
- }
-
+ }
+
/* Clear remaining lines if we haven't done so already */
if (need_clear && ! has_cleared_screen)
@@ -870,15 +870,15 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
s_write_mbs( &output, clr_eol);
}
}
-
- s_move( scr, &output, scr->desired.cursor.x, scr->desired.cursor.y );
- s_set_color( scr, &output, 0xffffffff);
-
- if( ! output.empty() )
- {
- write_loop( 1, &output.at(0), output.size() );
- }
-
+
+ s_move( scr, &output, scr->desired.cursor.x, scr->desired.cursor.y );
+ s_set_color( scr, &output, 0xffffffff);
+
+ if( ! output.empty() )
+ {
+ write_loop( 1, &output.at(0), output.size() );
+ }
+
/* We have now synced our actual screen against our desired screen. Note that this is a big assignment! */
scr->actual = scr->desired;
scr->last_right_prompt_width = right_prompt_width;
@@ -887,22 +887,22 @@ static void s_update( screen_t *scr, const wchar_t *left_prompt, const wchar_t *
/** Returns true if we are using a dumb terminal. */
static bool is_dumb(void)
{
- return ( !cursor_up || !cursor_down || !cursor_left || !cursor_right );
+ return ( !cursor_up || !cursor_down || !cursor_left || !cursor_right );
}
struct screen_layout_t {
/* The left prompt that we're going to use */
wcstring left_prompt;
-
+
/* How much space to leave for it */
size_t left_prompt_space;
-
+
/* The right prompt */
wcstring right_prompt;
-
+
/* The autosuggestion */
wcstring autosuggestion;
-
+
/* Whether the prompts get their own line or not */
bool prompts_get_own_line;
};
@@ -922,67 +922,67 @@ static size_t truncation_offset_for_width(const std::vector<size_t> &width_by_of
}
static screen_layout_t compute_layout(screen_t *s,
- size_t screen_width,
- const wcstring &left_prompt_str,
+ size_t screen_width,
+ const wcstring &left_prompt_str,
const wcstring &right_prompt_str,
- const wcstring &commandline,
+ const wcstring &commandline,
const wcstring &autosuggestion_str,
- const int *indent)
+ const int *indent)
{
screen_layout_t result = {};
-
+
/* Start by ensuring that the prompts themselves can fit */
const wchar_t *left_prompt = left_prompt_str.c_str();
const wchar_t *right_prompt = right_prompt_str.c_str();
const wchar_t *autosuggestion = autosuggestion_str.c_str();
-
- size_t left_prompt_width = calc_prompt_width( left_prompt );
+
+ size_t left_prompt_width = calc_prompt_width( left_prompt );
size_t right_prompt_width = calc_prompt_width( right_prompt );
-
+
if (left_prompt_width + right_prompt_width >= screen_width)
{
/* Nix right_prompt */
right_prompt = L"";
right_prompt_width = 0;
}
-
+
if (left_prompt_width + right_prompt_width >= screen_width)
{
/* Still doesn't fit, neuter left_prompt */
left_prompt = L"> ";
left_prompt_width = 2;
}
-
+
/* Now we should definitely fit */
assert(left_prompt_width + right_prompt_width < screen_width);
-
+
/* Convert commandline to a list of lines and their widths */
wcstring_list_t command_lines(1);
std::vector<size_t> line_widths(1);
for (size_t i=0; i < commandline.size(); i++)
- {
+ {
wchar_t c = commandline.at(i);
- if (c == L'\n')
- {
+ if (c == L'\n')
+ {
/* Make a new line */
command_lines.push_back(wcstring());
line_widths.push_back(indent[i]*INDENT_STEP);
- }
- else
- {
+ }
+ else
+ {
command_lines.back() += c;
- line_widths.back() += fish_wcwidth(c);
- }
- }
+ line_widths.back() += fish_wcwidth(c);
+ }
+ }
const size_t first_command_line_width = line_widths.at(0);
-
+
/* If we have more than one line, ensure we have no autosuggestion */
if (command_lines.size() > 1)
{
autosuggestion = L"";
}
-
+
/* Compute the width of the autosuggestion at all possible truncation offsets */
std::vector<size_t> autosuggestion_truncated_widths;
autosuggestion_truncated_widths.reserve(1 + wcslen(autosuggestion));
@@ -992,17 +992,17 @@ static screen_layout_t compute_layout(screen_t *s,
autosuggestion_truncated_widths.push_back(autosuggestion_total_width);
autosuggestion_total_width += fish_wcwidth(autosuggestion[i]);
}
-
+
/* Here are the layouts we try in turn:
-
+
1. Left prompt visible, right prompt visible, command line visible, autosuggestion visible
2. Left prompt visible, right prompt visible, command line visible, autosuggestion truncated (possibly to zero)
3. Left prompt visible, right prompt hidden, command line visible, autosuggestion hidden
4. Newline separator (left prompt visible, right prompt visible, command line visible, autosuggestion visible)
*/
-
+
bool done = false;
-
+
/* Case 1 */
if (! done && left_prompt_width + right_prompt_width + first_command_line_width + autosuggestion_total_width + 10 < screen_width)
{
@@ -1012,14 +1012,14 @@ static screen_layout_t compute_layout(screen_t *s,
result.autosuggestion = autosuggestion;
done = true;
}
-
+
/* Case 2. Note that we require strict inequality so that there's always at least one space between the left edge and the rprompt */
if (! done && left_prompt_width + right_prompt_width + first_command_line_width < screen_width)
{
result.left_prompt = left_prompt;
result.left_prompt_space = left_prompt_width;
result.right_prompt = right_prompt;
-
+
/* Need at least two characters to show an autosuggestion */
size_t available_autosuggestion_space = screen_width - (left_prompt_width + right_prompt_width + first_command_line_width);
if (autosuggestion_total_width > 0 && available_autosuggestion_space > 2)
@@ -1030,7 +1030,7 @@ static screen_layout_t compute_layout(screen_t *s,
}
done = true;
}
-
+
/* Case 3 */
if (! done && left_prompt_width + first_command_line_width < screen_width)
{
@@ -1038,7 +1038,7 @@ static screen_layout_t compute_layout(screen_t *s,
result.left_prompt_space = left_prompt_width;
done = true;
}
-
+
/* Case 4 */
if (! done)
{
@@ -1048,7 +1048,7 @@ static screen_layout_t compute_layout(screen_t *s,
result.prompts_get_own_line = true;
done = true;
}
-
+
assert(done);
return result;
}
@@ -1063,193 +1063,193 @@ void s_write( screen_t *s,
const int *indent,
size_t cursor_pos )
{
- screen_data_t::cursor_t cursor_arr;
+ screen_data_t::cursor_t cursor_arr;
+
+ CHECK( s, );
+ CHECK( indent, );
- CHECK( s, );
- CHECK( indent, );
-
/* Turn the command line into the explicit portion and the autosuggestion */
const wcstring explicit_command_line = commandline.substr(0, explicit_len);
const wcstring autosuggestion = commandline.substr(explicit_len);
-
- /*
- If we are using a dumb terminal, don't try any fancy stuff,
- just print out the text. right_prompt not supported.
- */
- if( is_dumb() )
- {
- const std::string prompt_narrow = wcs2string( left_prompt );
- const std::string command_line_narrow = wcs2string( explicit_command_line );
-
- write_loop( 1, "\r", 1 );
- write_loop( 1, prompt_narrow.c_str(), prompt_narrow.size() );
- write_loop( 1, command_line_narrow.c_str(), command_line_narrow.size() );
-
- return;
- }
-
- s_check_status( s );
+
+ /*
+ If we are using a dumb terminal, don't try any fancy stuff,
+ just print out the text. right_prompt not supported.
+ */
+ if( is_dumb() )
+ {
+ const std::string prompt_narrow = wcs2string( left_prompt );
+ const std::string command_line_narrow = wcs2string( explicit_command_line );
+
+ write_loop( 1, "\r", 1 );
+ write_loop( 1, prompt_narrow.c_str(), prompt_narrow.size() );
+ write_loop( 1, command_line_narrow.c_str(), command_line_narrow.size() );
+
+ return;
+ }
+
+ s_check_status( s );
const size_t screen_width = common_get_width();
-
- /* Completely ignore impossibly small screens */
- if( screen_width < 4 )
- {
- return;
- }
-
+
+ /* Completely ignore impossibly small screens */
+ if( screen_width < 4 )
+ {
+ return;
+ }
+
/* Compute a layout */
const screen_layout_t layout = compute_layout(s, screen_width, left_prompt, right_prompt, explicit_command_line, autosuggestion, indent);
/* Clear the desired screen */
s->desired.resize(0);
- s->desired.cursor.x = s->desired.cursor.y = 0;
+ s->desired.cursor.x = s->desired.cursor.y = 0;
/* Append spaces for the left prompt */
- for (size_t i=0; i < layout.left_prompt_space; i++)
- {
- s_desired_append_char( s, L' ', 0, 0, layout.left_prompt_space );
- }
-
- /* If overflowing, give the prompt its own line to improve the situation. */
+ for (size_t i=0; i < layout.left_prompt_space; i++)
+ {
+ s_desired_append_char( s, L' ', 0, 0, layout.left_prompt_space );
+ }
+
+ /* If overflowing, give the prompt its own line to improve the situation. */
size_t first_line_prompt_space = layout.left_prompt_space;
if (layout.prompts_get_own_line)
{
- s_desired_append_char( s, L'\n', 0, 0, 0 );
+ s_desired_append_char( s, L'\n', 0, 0, 0 );
first_line_prompt_space = 0;
}
-
+
/* Reconstruct the command line */
wcstring effective_commandline = explicit_command_line + layout.autosuggestion;
-
+
/* Output the command line */
size_t i;
- for( i=0; i < effective_commandline.size(); i++ )
- {
- int color = colors[i];
-
- if( i == cursor_pos )
- {
- color = 0;
- }
-
- if( i == cursor_pos )
- {
+ for( i=0; i < effective_commandline.size(); i++ )
+ {
+ int color = colors[i];
+
+ if( i == cursor_pos )
+ {
+ color = 0;
+ }
+
+ if( i == cursor_pos )
+ {
cursor_arr = s->desired.cursor;
- }
-
- s_desired_append_char( s, effective_commandline.at(i), color, indent[i], first_line_prompt_space );
- }
- if( i == cursor_pos )
- {
+ }
+
+ s_desired_append_char( s, effective_commandline.at(i), color, indent[i], first_line_prompt_space );
+ }
+ if( i == cursor_pos )
+ {
cursor_arr = s->desired.cursor;
- }
-
+ }
+
s->desired.cursor = cursor_arr;
- s_update( s, layout.left_prompt.c_str(), layout.right_prompt.c_str());
- s_save_status( s );
+ s_update( s, layout.left_prompt.c_str(), layout.right_prompt.c_str());
+ s_save_status( s );
}
void s_write_OLD( screen_t *s,
- const wchar_t *left_prompt,
+ const wchar_t *left_prompt,
const wchar_t *right_prompt,
- const wchar_t *commandline,
- size_t explicit_len,
- const int *c,
- const int *indent,
- size_t cursor_pos )
+ const wchar_t *commandline,
+ size_t explicit_len,
+ const int *c,
+ const int *indent,
+ size_t cursor_pos )
{
- screen_data_t::cursor_t cursor_arr;
+ screen_data_t::cursor_t cursor_arr;
- int current_line_width = 0, newline_count = 0, explicit_portion_width = 0;
+ int current_line_width = 0, newline_count = 0, explicit_portion_width = 0;
size_t max_line_width = 0;
-
- CHECK( s, );
- CHECK( left_prompt, );
- CHECK( right_prompt, );
- CHECK( commandline, );
- CHECK( c, );
- CHECK( indent, );
-
- /*
- If we are using a dumb terminal, don't try any fancy stuff,
- just print out the text. right_prompt not supported.
- */
- if( is_dumb() )
- {
- char *prompt_narrow = wcs2str( left_prompt );
- char *buffer_narrow = wcs2str( commandline );
-
- write_loop( 1, "\r", 1 );
- write_loop( 1, prompt_narrow, strlen( prompt_narrow ) );
- write_loop( 1, buffer_narrow, strlen( buffer_narrow ) );
-
- free( prompt_narrow );
- free( buffer_narrow );
-
- return;
- }
-
- size_t left_prompt_width = calc_prompt_width( left_prompt );
+
+ CHECK( s, );
+ CHECK( left_prompt, );
+ CHECK( right_prompt, );
+ CHECK( commandline, );
+ CHECK( c, );
+ CHECK( indent, );
+
+ /*
+ If we are using a dumb terminal, don't try any fancy stuff,
+ just print out the text. right_prompt not supported.
+ */
+ if( is_dumb() )
+ {
+ char *prompt_narrow = wcs2str( left_prompt );
+ char *buffer_narrow = wcs2str( commandline );
+
+ write_loop( 1, "\r", 1 );
+ write_loop( 1, prompt_narrow, strlen( prompt_narrow ) );
+ write_loop( 1, buffer_narrow, strlen( buffer_narrow ) );
+
+ free( prompt_narrow );
+ free( buffer_narrow );
+
+ return;
+ }
+
+ size_t left_prompt_width = calc_prompt_width( left_prompt );
size_t right_prompt_width = calc_prompt_width( right_prompt );
- const size_t screen_width = common_get_width();
-
- s_check_status( s );
-
- /*
- Ignore prompts wider than the screen - only print a two
- character placeholder...
-
- It would be cool to truncate the prompt, but because it can
- contain escape sequences, this is harder than you'd think.
- */
- if( left_prompt_width >= screen_width )
- {
- left_prompt = L"> ";
- left_prompt_width = 2;
-
+ const size_t screen_width = common_get_width();
+
+ s_check_status( s );
+
+ /*
+ Ignore prompts wider than the screen - only print a two
+ character placeholder...
+
+ It would be cool to truncate the prompt, but because it can
+ contain escape sequences, this is harder than you'd think.
+ */
+ if( left_prompt_width >= screen_width )
+ {
+ left_prompt = L"> ";
+ left_prompt_width = 2;
+
right_prompt = L"";
right_prompt_width = 0;
- }
-
- /*
- Completely ignore impossibly small screens
- */
- if( screen_width < 4 )
- {
- return;
- }
-
- /*
- Check if we are overflowing
- */
+ }
+
+ /*
+ Completely ignore impossibly small screens
+ */
+ if( screen_width < 4 )
+ {
+ return;
+ }
+
+ /*
+ Check if we are overflowing
+ */
size_t last_char_that_fits = 0;
- for( size_t i=0; commandline[i]; i++ )
- {
- if( commandline[i] == L'\n' )
- {
- if( current_line_width > max_line_width )
- max_line_width = current_line_width;
- current_line_width = indent[i]*INDENT_STEP;
+ for( size_t i=0; commandline[i]; i++ )
+ {
+ if( commandline[i] == L'\n' )
+ {
+ if( current_line_width > max_line_width )
+ max_line_width = current_line_width;
+ current_line_width = indent[i]*INDENT_STEP;
newline_count++;
- }
- else
- {
+ }
+ else
+ {
int width = fish_wcwidth(commandline[i]);
- current_line_width += width;
+ current_line_width += width;
if (i < explicit_len)
explicit_portion_width += width;
-
+
if (left_prompt_width + current_line_width < screen_width)
last_char_that_fits = i;
- }
- }
- if( current_line_width > max_line_width )
- max_line_width = current_line_width;
+ }
+ }
+ if( current_line_width > max_line_width )
+ max_line_width = current_line_width;
s->desired.resize(0);
- s->desired.cursor.x = s->desired.cursor.y = 0;
-
+ s->desired.cursor.x = s->desired.cursor.y = 0;
+
/* If we cannot fit with the autosuggestion, but we can fit without it, truncate the autosuggestion. We limit this check to just one line to avoid confusion; not sure how well this would work with multiple lines */
wcstring truncated_autosuggestion_line;
if (newline_count == 0 && left_prompt_width + right_prompt_width + max_line_width >= screen_width && left_prompt_width + explicit_portion_width < screen_width)
@@ -1260,88 +1260,88 @@ void s_write_OLD( screen_t *s,
truncated_autosuggestion_line.push_back(ellipsis_char);
commandline = truncated_autosuggestion_line.c_str();
}
- for( size_t i=0; i<left_prompt_width; i++ )
- {
- s_desired_append_char( s, L' ', 0, 0, left_prompt_width );
- }
-
- /*
- If overflowing, give the prompt its own line to improve the
- situation.
- */
- if( max_line_width + left_prompt_width >= screen_width )
- {
- s_desired_append_char( s, L'\n', 0, 0, 0 );
- left_prompt_width = 0;
- }
-
+ for( size_t i=0; i<left_prompt_width; i++ )
+ {
+ s_desired_append_char( s, L' ', 0, 0, left_prompt_width );
+ }
+
+ /*
+ If overflowing, give the prompt its own line to improve the
+ situation.
+ */
+ if( max_line_width + left_prompt_width >= screen_width )
+ {
+ s_desired_append_char( s, L'\n', 0, 0, 0 );
+ left_prompt_width = 0;
+ }
+
size_t i;
- for( i=0; commandline[i]; i++ )
- {
- int col = c[i];
-
- if( i == cursor_pos )
- {
- col = 0;
- }
-
- if( i == cursor_pos )
- {
+ for( i=0; commandline[i]; i++ )
+ {
+ int col = c[i];
+
+ if( i == cursor_pos )
+ {
+ col = 0;
+ }
+
+ if( i == cursor_pos )
+ {
cursor_arr = s->desired.cursor;
- }
-
- s_desired_append_char( s, commandline[i], col, indent[i], left_prompt_width );
- }
- if( i == cursor_pos )
- {
+ }
+
+ s_desired_append_char( s, commandline[i], col, indent[i], left_prompt_width );
+ }
+ if( i == cursor_pos )
+ {
cursor_arr = s->desired.cursor;
- }
-
+ }
+
s->desired.cursor = cursor_arr;
- s_update( s, left_prompt, right_prompt);
- s_save_status( s );
+ s_update( s, left_prompt, right_prompt);
+ s_save_status( s );
}
void s_reset( screen_t *s, bool reset_cursor, bool reset_prompt )
{
- CHECK( s, );
-
+ CHECK( s, );
+
/* If we're resetting the cursor, we must also be resetting the prompt */
assert(! reset_cursor || reset_prompt);
-
+
/* If we are resetting the cursor, we're going to make a new line and leave junk behind. If we are not resetting the cursor, we need to remember how many lines we had output to, so we can clear the remaining lines in the next call to s_update. This prevents leaving junk underneath the cursor when resizing a window wider such that it reduces our desired line count. */
if (! reset_cursor) {
s->actual_lines_before_reset = s->actual.line_count();
}
-
- int prev_line = s->actual.cursor.y;
-
+
+ int prev_line = s->actual.cursor.y;
+
if (reset_prompt) {
/* If the prompt is multi-line, we need to move up to the prompt's initial line. We do this by lying to ourselves and claiming that we're really below what we consider "line 0" (which is the last line of the prompt). This will cause is to move up to try to get back to line 0, but really we're getting back to the initial line of the prompt. */
const size_t prompt_line_count = calc_prompt_lines(s->actual_left_prompt.c_str());
assert(prompt_line_count >= 1);
prev_line += (prompt_line_count - 1);
-
+
/* Clear the prompt */
s->actual_left_prompt.clear();
}
-
+
s->actual.resize(0);
s->actual.cursor.x = 0;
s->actual.cursor.y = 0;
- s->need_clear=true;
-
- if( !reset_cursor )
- {
- /*
+ s->need_clear=true;
+
+ if( !reset_cursor )
+ {
+ /*
This should prevent reseting the cursor position during the
next repaint.
*/
- write_loop( 1, "\r", 1 );
- s->actual.cursor.y = prev_line;
- }
- fstat( 1, &s->prev_buff_1 );
- fstat( 2, &s->prev_buff_2 );
+ write_loop( 1, "\r", 1 );
+ s->actual.cursor.y = prev_line;
+ }
+ fstat( 1, &s->prev_buff_1 );
+ fstat( 2, &s->prev_buff_2 );
}
screen_t::screen_t() :
diff --git a/screen.h b/screen.h
index 31a5cf70..2c36f11a 100644
--- a/screen.h
+++ b/screen.h
@@ -1,13 +1,13 @@
/** \file screen.h High level library for handling the terminal screen
- The screen library allows the interactive reader to write its
- output to screen efficiently by keeping an inetrnal representation
- of the current screen contents and trying to find a reasonably
- efficient way for transforming that to the desired screen content.
-
- The current implementation is less smart than ncurses allows
- and can not for example move blocks of text around to handle text
- insertion.
+ The screen library allows the interactive reader to write its
+ output to screen efficiently by keeping an inetrnal representation
+ of the current screen contents and trying to find a reasonably
+ efficient way for transforming that to the desired screen content.
+
+ The current implementation is less smart than ncurses allows
+ and can not for example move blocks of text around to handle text
+ insertion.
*/
#ifndef FISH_SCREEN_H
#define FISH_SCREEN_H
@@ -22,38 +22,38 @@ struct line_t
std::vector<wchar_t> text;
std::vector<int> colors;
bool is_soft_wrapped;
-
+
line_t() : text(), colors(), is_soft_wrapped(false)
{
}
-
+
void clear(void)
{
text.clear();
colors.clear();
}
-
+
void append(wchar_t txt, int color)
{
text.push_back(txt);
colors.push_back(color);
}
-
+
size_t size(void) const
{
return text.size();
}
-
+
wchar_t char_at(size_t idx) const
{
return text.at(idx);
}
-
+
int color_at(size_t idx) const
{
return colors.at(idx);
}
-
+
};
/**
@@ -62,36 +62,36 @@ struct line_t
class screen_data_t
{
std::vector<line_t> line_datas;
-
+
public:
-
+
struct cursor_t {
int x;
int y;
cursor_t() : x(0), y(0) { }
cursor_t(int a, int b) : x(a), y(b) { }
} cursor;
-
+
line_t &add_line(void) {
line_datas.resize(line_datas.size() + 1);
return line_datas.back();
}
-
+
void resize(size_t size) {
line_datas.resize(size);
}
-
+
line_t &create_line(size_t idx) {
if (idx >= line_datas.size()) {
line_datas.resize(idx + 1);
}
return line_datas.at(idx);
}
-
+
line_t &line(size_t idx) {
return line_datas.at(idx);
}
-
+
size_t line_count(void) {
return line_datas.size();
}
@@ -121,7 +121,7 @@ class screen_t
the screen.
*/
wcstring actual_left_prompt;
-
+
/** Last right prompt width */
size_t last_right_prompt_width;
@@ -130,26 +130,26 @@ class screen_t
write.
*/
int actual_width;
-
+
/** If we support soft wrapping, we can output to this location without any cursor motion. */
screen_data_t::cursor_t soft_wrap_location;
/**
- This flag is set to true when there is reason to suspect that
- the parts of the screen lines where the actual content is not
- filled in may be non-empty. This means that a clr_eol command
- has to be sent to the terminal at the end of each line.
- */
- bool need_clear;
-
+ This flag is set to true when there is reason to suspect that
+ the parts of the screen lines where the actual content is not
+ filled in may be non-empty. This means that a clr_eol command
+ has to be sent to the terminal at the end of each line.
+ */
+ bool need_clear;
+
/** If we need to clear, this is how many lines the actual screen had, before we reset it. This is used when resizing the window larger: if the cursor jumps to the line above, we need to remember to clear the subsequent lines. */
size_t actual_lines_before_reset;
-
- /**
- These status buffers are used to check if any output has occurred
- other than from fish's main loop, in which case we need to redraw.
- */
- struct stat prev_buff_1, prev_buff_2, post_buff_1, post_buff_2;
+
+ /**
+ These status buffers are used to check if any output has occurred
+ other than from fish's main loop, in which case we need to redraw.
+ */
+ struct stat prev_buff_1, prev_buff_2, post_buff_1, post_buff_2;
};
/**
@@ -158,7 +158,7 @@ class screen_t
will use it's knowlege of the current contents of the screen in
order to render the desired output using as few terminal commands
as possible.
-
+
\param s the screen on which to write
\param left_prompt the prompt to prepend to the command line
\param right_prompt the right prompt, or NULL if none
@@ -168,14 +168,14 @@ class screen_t
\param indent the indent to use for the command line
\param cursor_pos where the cursor is
*/
-void s_write( screen_t *s,
- const wchar_t *left_prompt,
- const wchar_t *right_prompt,
- const wchar_t *commandline,
- size_t explicit_len,
- const int *colors,
- const int *indent,
- size_t cursor_pos );
+void s_write( screen_t *s,
+ const wchar_t *left_prompt,
+ const wchar_t *right_prompt,
+ const wchar_t *commandline,
+ size_t explicit_len,
+ const int *colors,
+ const int *indent,
+ size_t cursor_pos );
void s_write( screen_t *s,
@@ -187,7 +187,7 @@ void s_write( screen_t *s,
const int *indent,
size_t cursor_pos );
-/**
+/**
This function resets the screen buffers internal knowledge about
the contents of the screen. Use this function when some other
function than s_write has written to the screen.
diff --git a/set_color.cpp b/set_color.cpp
index 78799b66..4de3ba60 100644
--- a/set_color.cpp
+++ b/set_color.cpp
@@ -70,53 +70,53 @@
const char *col[]=
{
- "black",
- "red",
- "green",
- "brown",
- "yellow",
- "blue",
- "magenta",
- "purple",
- "cyan",
- "white",
- "normal"
+ "black",
+ "red",
+ "green",
+ "brown",
+ "yellow",
+ "blue",
+ "magenta",
+ "purple",
+ "cyan",
+ "white",
+ "normal"
};
const int col_idx[]=
{
- 0,
- 1,
- 2,
- 3,
- 3,
- 4,
- 5,
- 5,
- 6,
- 7,
- 8
+ 0,
+ 1,
+ 2,
+ 3,
+ 3,
+ 4,
+ 5,
+ 5,
+ 6,
+ 7,
+ 8
};
void print_colors()
{
- size_t i;
- for( i=0; i<COLORS; i++ )
- {
- printf( "%s\n", col[i] );
- }
+ size_t i;
+ for( i=0; i<COLORS; i++ )
+ {
+ printf( "%s\n", col[i] );
+ }
}
static void check_locale_init()
{
- static int is_init = 0;
- if( is_init )
- return;
-
- is_init = 1;
- setlocale( LC_ALL, "" );
- bindtextdomain( PACKAGE_NAME, LOCALEDIR );
- textdomain( PACKAGE_NAME );
+ static int is_init = 0;
+ if( is_init )
+ return;
+
+ is_init = 1;
+ setlocale( LC_ALL, "" );
+ bindtextdomain( PACKAGE_NAME, LOCALEDIR );
+ textdomain( PACKAGE_NAME );
}
/* A lot of this code is taken straight from output.cpp; it sure would be nice to factor these together. */
@@ -185,111 +185,111 @@ int main( int argc, char **argv )
/* Some code passes variables to set_color that don't exist, like $fish_user_whatever. As a hack, quietly return failure. */
if (argc <= 1)
return EXIT_FAILURE;
-
- char *bgcolor=0;
- char *fgcolor=0;
- bool bold=false;
- bool underline=false;
-
- while( 1 )
- {
- static struct option
- long_options[] =
- {
- {
- "background", required_argument, 0, 'b'
- }
- ,
- {
- "help", no_argument, 0, 'h'
- }
- ,
- {
- "bold", no_argument, 0, 'o'
- }
- ,
- {
- "underline", no_argument, 0, 'u'
- }
- ,
- {
- "version", no_argument, 0, 'v'
- }
- ,
- {
- "print-colors", no_argument, 0, 'c'
- }
- ,
- {
- 0, 0, 0, 0
- }
- }
- ;
-
- int opt_index = 0;
-
- int opt = getopt_long( argc,
- argv,
- GETOPT_STRING,
- long_options,
- &opt_index );
-
- if( opt == -1 )
- break;
-
- switch( opt )
- {
- case 0:
- break;
-
- case 'b':
- bgcolor = optarg;
- break;
- case 'h':
- print_help( argv[0], 1 );
- exit(0);
-
- case 'o':
- bold=true;
- break;
-
- case 'u':
- underline=true;
- break;
-
- case 'v':
- check_locale_init();
- fprintf( stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION );
- exit( 0 );
-
- case 'c':
- print_colors();
- exit(0);
-
- case '?':
- return 1;
-
- }
-
- }
-
- switch( argc-optind)
- {
- case 0:
-// printf( "no fg\n" );
- break;
-
- case 1:
- fgcolor=argv[optind];
-// printf( "fg %s\n", fgcolor );
- break;
-
- default:
- check_locale_init();
- printf( _("%s: Too many arguments\n"), SET_COLOR );
- return 1;
- }
-
+
+ char *bgcolor=0;
+ char *fgcolor=0;
+ bool bold=false;
+ bool underline=false;
+
+ while( 1 )
+ {
+ static struct option
+ long_options[] =
+ {
+ {
+ "background", required_argument, 0, 'b'
+ }
+ ,
+ {
+ "help", no_argument, 0, 'h'
+ }
+ ,
+ {
+ "bold", no_argument, 0, 'o'
+ }
+ ,
+ {
+ "underline", no_argument, 0, 'u'
+ }
+ ,
+ {
+ "version", no_argument, 0, 'v'
+ }
+ ,
+ {
+ "print-colors", no_argument, 0, 'c'
+ }
+ ,
+ {
+ 0, 0, 0, 0
+ }
+ }
+ ;
+
+ int opt_index = 0;
+
+ int opt = getopt_long( argc,
+ argv,
+ GETOPT_STRING,
+ long_options,
+ &opt_index );
+
+ if( opt == -1 )
+ break;
+
+ switch( opt )
+ {
+ case 0:
+ break;
+
+ case 'b':
+ bgcolor = optarg;
+ break;
+ case 'h':
+ print_help( argv[0], 1 );
+ exit(0);
+
+ case 'o':
+ bold=true;
+ break;
+
+ case 'u':
+ underline=true;
+ break;
+
+ case 'v':
+ check_locale_init();
+ fprintf( stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION );
+ exit( 0 );
+
+ case 'c':
+ print_colors();
+ exit(0);
+
+ case '?':
+ return 1;
+
+ }
+
+ }
+
+ switch( argc-optind)
+ {
+ case 0:
+// printf( "no fg\n" );
+ break;
+
+ case 1:
+ fgcolor=argv[optind];
+// printf( "fg %s\n", fgcolor );
+ break;
+
+ default:
+ check_locale_init();
+ printf( _("%s: Too many arguments\n"), SET_COLOR );
+ return 1;
+ }
+
/* Infer term256 support */
char *fish_term256 = getenv("fish_term256");
if (fish_term256) {
@@ -299,77 +299,77 @@ int main( int argc, char **argv )
support_term256 = term && strstr(term, "256color");
}
- if( !fgcolor && !bgcolor && !bold && !underline )
- {
- check_locale_init();
- fprintf( stderr, _("%s: Expected an argument\n"), SET_COLOR );
- print_help( argv[0], 2 );
- return 1;
- }
-
+ if( !fgcolor && !bgcolor && !bold && !underline )
+ {
+ check_locale_init();
+ fprintf( stderr, _("%s: Expected an argument\n"), SET_COLOR );
+ print_help( argv[0], 2 );
+ return 1;
+ }
+
rgb_color_t fg = rgb_color_t(fgcolor ? fgcolor : "");
- if( fgcolor && fg.is_none())
- {
- check_locale_init();
- fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, fgcolor );
- return 1;
- }
+ if( fgcolor && fg.is_none())
+ {
+ check_locale_init();
+ fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, fgcolor );
+ return 1;
+ }
rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : "");
- if( bgcolor && bg.is_none())
- {
- check_locale_init();
- fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, bgcolor );
- return 1;
- }
-
- setupterm( 0, STDOUT_FILENO, 0);
-
- if( bold )
- {
- if( enter_bold_mode )
- putp( enter_bold_mode );
- }
-
- if( underline )
- {
- if( enter_underline_mode )
- putp( enter_underline_mode );
- }
-
- if( bgcolor )
- {
- if( bg.is_normal() )
- {
+ if( bgcolor && bg.is_none())
+ {
+ check_locale_init();
+ fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, bgcolor );
+ return 1;
+ }
+
+ setupterm( 0, STDOUT_FILENO, 0);
+
+ if( bold )
+ {
+ if( enter_bold_mode )
+ putp( enter_bold_mode );
+ }
+
+ if( underline )
+ {
+ if( enter_underline_mode )
+ putp( enter_underline_mode );
+ }
+
+ if( bgcolor )
+ {
+ if( bg.is_normal() )
+ {
write_background_color(0);
- putp( tparm(exit_attribute_mode) );
- }
- }
-
- if( fgcolor )
- {
- if( fg.is_normal() )
- {
+ putp( tparm(exit_attribute_mode) );
+ }
+ }
+
+ if( fgcolor )
+ {
+ if( fg.is_normal() )
+ {
write_foreground_color(0);
- putp( tparm(exit_attribute_mode) );
- }
- else
- {
+ putp( tparm(exit_attribute_mode) );
+ }
+ else
+ {
write_foreground_color(index_for_color(fg));
- }
- }
-
- if( bgcolor )
- {
- if( ! bg.is_normal() )
- {
+ }
+ }
+
+ if( bgcolor )
+ {
+ if( ! bg.is_normal() )
+ {
write_background_color(index_for_color(bg));
- }
- }
+ }
+ }
- if( del_curterm( cur_term ) == ERR )
- {
- fprintf( stderr, "%s", _("Error while closing terminfo") );
- }
+ if( del_curterm( cur_term ) == ERR )
+ {
+ fprintf( stderr, "%s", _("Error while closing terminfo") );
+ }
}
diff --git a/share/completions/abook.fish b/share/completions/abook.fish
index 8b983beb..97b144b0 100644
--- a/share/completions/abook.fish
+++ b/share/completions/abook.fish
@@ -3,7 +3,7 @@ complete -c abook -s h -d 'Show usage'
complete -c abook -s C -l config -d 'Use an alternative configuration file' -r
complete -c abook -l datafile -d 'Use an alternative addressbook file' -r
complete -c abook -l mutt-query -d 'Make a query for mutt' -x
-complete -c abook -l add-email -d 'Read email message from stdin and add the sender'
+complete -c abook -l add-email -d 'Read email message from stdin and add the sender'
complete -c abook -l add-email-quiet -d 'Same as --add-email. Without confirmation'
complete -c abook -l convert -d 'Convert address book files'
diff --git a/share/completions/adduser.fish b/share/completions/adduser.fish
index 9704625c..33d28182 100644
--- a/share/completions/adduser.fish
+++ b/share/completions/adduser.fish
@@ -14,7 +14,7 @@ complete -c adduser -l gecos --description 'Set the gecos field for the new entr
complete -c adduser -l gid --description 'When creating a group, this option forces the new groupid to be the given number' -r
complete -c adduser -l group --description 'When combined with --system, a group with the same name and ID as the system user is created'
complete -c adduser -l help --description 'Display brief instructions'
-complete -c adduser -l home --description 'Use specified directory as the user\'s home directory' -x -a '(__fish_complete_directories)'
+complete -c adduser -l home --description 'Use specified directory as the user\'s home directory' -x -a '(__fish_complete_directories)'
complete -c adduser -l shell --description 'Use shell as the user\'s login shell, rather than the default specified by the configuration file' -x -a '(cat /etc/shells)'
complete -c adduser -l ingroup --description 'Add the new user to GROUP instead of a usergroup or the default group defined by USERS_GID in the configuration file' -x -a '(cat /etc/group|cut -d : -f 1)'
complete -c adduser -l no-create-home --description 'Do not create the home directory, even if it doesni\'t exist'
diff --git a/share/completions/dvipdf.fish b/share/completions/dvipdf.fish
index 8c8a8354..300bb811 100644
--- a/share/completions/dvipdf.fish
+++ b/share/completions/dvipdf.fish
@@ -1,3 +1,3 @@
-complete -c dvipdf -x -a "(
- __fish_complete_suffix .dvi
- )"
+complete -c dvipdf -x -a "(
+ __fish_complete_suffix .dvi
+ )"
diff --git a/share/completions/dvipdfm.fish b/share/completions/dvipdfm.fish
index c49b469e..94f6668c 100644
--- a/share/completions/dvipdfm.fish
+++ b/share/completions/dvipdfm.fish
@@ -1,4 +1,4 @@
-complete -c dvipdfm -x -a "
-(
- __fish_complete_suffix .dvi
-)"
+complete -c dvipdfm -x -a "
+(
+ __fish_complete_suffix .dvi
+)"
diff --git a/share/completions/find.fish b/share/completions/find.fish
index 63f9d874..28b5471a 100644
--- a/share/completions/find.fish
+++ b/share/completions/find.fish
@@ -36,9 +36,9 @@ complete -c find -o cmin --description "File status last changed specified numbe
complete -c find -o cnewer --description "File status last changed more recently than file was modified" -r
complete -c find -o ctime --description "File status last changed specified number of days ago" -r
-complete -c find -o empty --description "File is empty and is either a regular file or a directory"
-complete -c find -o executable --description "File is executable"
-complete -c find -o false --description "Always false"
+complete -c find -o empty --description "File is empty and is either a regular file or a directory"
+complete -c find -o executable --description "File is executable"
+complete -c find -o false --description "Always false"
complete -c find -o fstype --description "File is on filesystem of specified type" -a "(__fish_print_filesystems)" -r
complete -c find -o gid --description "Numeric group id of file" -r
complete -c find -o group --description "Group name of file" -a "(__fish_complete_groups)"
diff --git a/share/completions/kill.fish b/share/completions/kill.fish
index cd7d2353..955795fb 100644
--- a/share/completions/kill.fish
+++ b/share/completions/kill.fish
@@ -6,7 +6,7 @@ for i in $__kill_signals
complete -c kill -o $number -d $name
complete -c kill -o $name -d $name
complete -c kill -o s -x -a \"$number\tSend\ $name\ signal\"
- complete -c kill -o s -x -a \"$name\tSend\ $name\ signal\"
+ complete -c kill -o s -x -a \"$name\tSend\ $name\ signal\"
end
complete -c kill -xa '(__fish_complete_pids)'
diff --git a/share/completions/killall.fish b/share/completions/killall.fish
index dc5fec39..ae70c900 100644
--- a/share/completions/killall.fish
+++ b/share/completions/killall.fish
@@ -6,7 +6,7 @@ for i in $__kill_signals
complete -c killall -o $number -d $name
complete -c killall -o $name -d $name
complete -c killall -o s -x -a \"$number\tSend\ $name\ signal\"
- complete -c killall -o s -x -a \"$name\tSend\ $name\ signal\"
+ complete -c killall -o s -x -a \"$name\tSend\ $name\ signal\"
end
complete -c killall -xa '(__fish_complete_proc)'
diff --git a/share/completions/latexmk.fish b/share/completions/latexmk.fish
index 6b2c33e1..07818dfe 100644
--- a/share/completions/latexmk.fish
+++ b/share/completions/latexmk.fish
@@ -48,7 +48,7 @@ complete -c latexmk -o print=ps -d 'when file is to be printed, print the ps
complete -c latexmk -o print=pdf -d 'when file is to be printed, print the pdf file'
complete -c latexmk -o pv -d 'preview document'
complete -c latexmk -o pv- -d 'turn off preview mode'
-complete -c latexmk -o pvc -d 'preview document and continuously update'
+complete -c latexmk -o pvc -d 'preview document and continuously update'
complete -c latexmk -o pvc- -d 'turn off -pvc'
complete -c latexmk -o quiet -d 'silence progress messages from called programs'
complete -c latexmk -o r -r -d 'Read custom RC file'
diff --git a/share/completions/lpadmin.fish b/share/completions/lpadmin.fish
index f542086c..099309b9 100644
--- a/share/completions/lpadmin.fish
+++ b/share/completions/lpadmin.fish
@@ -6,8 +6,8 @@ complete -c lpadmin -s r -d 'Removes the named printer from class. If the result
complete -c lpadmin -s v -d 'Sets the device-uri attribute of the printer queue' -r
complete -c lpadmin -s D -d 'Provides a textual description of the destination' -x
-complete -c lpadmin -s E -d 'Enables the destination and accepts jobs'
-complete -c lpadmin -s L -d 'Provides a textual location of the destination' -x
+complete -c lpadmin -s E -d 'Enables the destination and accepts jobs'
+complete -c lpadmin -s L -d 'Provides a textual location of the destination' -x
complete -c lpadmin -s P -d 'Specifies a PostScript Printer Description file to use with the printer' -xa "(__fish_complete_suffix .ppd; __fish_complete_suffix .ppd.gz)"
complete -c lpadmin -s o -xa cupsIPPSupplies=true -d 'Specifies whether IPP supply level values should be reported'
complete -c lpadmin -s o -xa cupsIPPSupplies=false -d 'Specifies whether IPP supply level values should be reported'
diff --git a/share/completions/mocp.fish b/share/completions/mocp.fish
index 6d44169f..19020abf 100644
--- a/share/completions/mocp.fish
+++ b/share/completions/mocp.fish
@@ -23,7 +23,7 @@ complete -c mocp -s U -l unpause -d "Unpause"
complete -c mocp -s G -l toggle-pause -d "Toggle between play/pause"
complete -c mocp -s v -l volume -d "(+/-)LEVEL Adjust PCM volume" -xa '+ -'
complete -c mocp -s y -l sync -d "Synchronize the playlist with other clients"
-complete -c mocp -s n -l nosync -d "Don't synchronize the playlist with other client's"
+complete -c mocp -s n -l nosync -d "Don't synchronize the playlist with other client's"
complete -c mocp -s A -l ascii -d "Use ASCII characters to draw lines"
complete -c mocp -s i -l info -d "Print the information about the currently played file"
complete -c mocp -s Q -l format -rf -d "Print the formatted information about the currently played file"
diff --git a/share/completions/pactree.fish b/share/completions/pactree.fish
index 43cb881c..81c37d72 100644
--- a/share/completions/pactree.fish
+++ b/share/completions/pactree.fish
@@ -1,4 +1,4 @@
-complete -c pactree -xa "(pacman -Sl | cut --delim ' ' --fields 2- | tr ' ' \t | sort)"
+complete -c pactree -xa "(pacman -Sl | cut --delim ' ' --fields 2- | tr ' ' \t | sort)"
complete -c pactree -s b -l dbpath -d 'Set an alternate database location' -xa '(__fish_complete_directories)'
complete -c pactree -s c -l color -d 'Colorize output'
complete -c pactree -s d -l depth -d 'Limit the depth of recursion' -x
diff --git a/share/completions/pkgfile.fish b/share/completions/pkgfile.fish
index d76a7977..e8af0b0f 100644
--- a/share/completions/pkgfile.fish
+++ b/share/completions/pkgfile.fish
@@ -3,7 +3,7 @@ complete -c pkgfile -s h -l help -d 'show this help message and exit'
complete -c pkgfile -s b -l binaries -d 'only show files in a {s}bin/ directory. Works with -s, -l'
complete -c pkgfile -s c -l case-sensitive -d 'make searches case sensitive'
complete -c pkgfile -s g -l glob -d 'allow the use of * and ? as wildcards'
-complete -c pkgfile -s r -l regex -d 'allow the use of regex in searches'
+complete -c pkgfile -s r -l regex -d 'allow the use of regex in searches'
complete -c pkgfile -s R -l repo -d 'search only in the specified repository' -xa '(cat /etc/pacman.conf|grep "^\[" | sed "s/\[\|]//g")'
complete -c pkgfile -s v -l verbose -d 'enable verbose output'
complete -c pkgfile -s i -l info -d 'provides information about the package owning a file' -r
diff --git a/share/completions/ps2pdf.fish b/share/completions/ps2pdf.fish
index 05975ced..036b0c1d 100644
--- a/share/completions/ps2pdf.fish
+++ b/share/completions/ps2pdf.fish
@@ -1,3 +1,3 @@
-complete -c ps2pdf -x -a "(
- __fish_complete_suffix .ps
- )"
+complete -c ps2pdf -x -a "(
+ __fish_complete_suffix .ps
+ )"
diff --git a/share/completions/rfkill.fish b/share/completions/rfkill.fish
index a8b78661..4ee6cf3c 100644
--- a/share/completions/rfkill.fish
+++ b/share/completions/rfkill.fish
@@ -1,4 +1,4 @@
-complete -c rfkill -xa 'block unblock list event help' -n 'not __fish_seen_subcommand_from block unblock list event help'
+complete -c rfkill -xa 'block unblock list event help' -n 'not __fish_seen_subcommand_from block unblock list event help'
complete -c rfkill -n '__fish_seen_subcommand_from block unblock list' -d 'device group' -xa "all wifi wlan bluetooth uwb ultrawideband wimax wwan gps fm (rfkill list | tr : \t)"
complete -c rfkill -l version -d 'Print version'
diff --git a/share/completions/setxkbmap.fish b/share/completions/setxkbmap.fish
index b3561346..71aab63e 100644
--- a/share/completions/setxkbmap.fish
+++ b/share/completions/setxkbmap.fish
@@ -13,7 +13,7 @@ complete -c setxkbmap -o keymap -d 'Specifies name of keymap to load' -xa "(c
complete -c setxkbmap -o layout -d 'Specifies layout used to choose component names' -xa "(__fish_complete_setxkbmap layout)"
complete -c setxkbmap -o model -d 'Specifies model used to choose component names' -xa "(__fish_complete_setxkbmap model)"
complete -c setxkbmap -o option -d 'Adds an option used to choose component names' -xa "(__fish_complete_list , '__fish_complete_setxkbmap option')"
-complete -c setxkbmap -o print -d 'Print a complete xkb_keymap description and exit'
+complete -c setxkbmap -o print -d 'Print a complete xkb_keymap description and exit'
complete -c setxkbmap -o query -d 'Print the current layout settings and exit'
complete -c setxkbmap -o rules -d 'Name of rules file to use' -x
complete -c setxkbmap -o symbols -d 'Specifies symbols component name' -xa "(cat /usr/share/X11/xkb/symbols.dir | sed -r $filter)"
diff --git a/share/completions/tree.fish b/share/completions/tree.fish
index 919e9938..b32fb3fc 100644
--- a/share/completions/tree.fish
+++ b/share/completions/tree.fish
@@ -1,5 +1,5 @@
-
+
## Listing options
complete -c tree -s a -d 'All files are listed'
complete -c tree -s d -d 'List directories only'
@@ -16,7 +16,7 @@ complete -c tree -l filelimit -r -d 'Do not descend dirs with more than # files
complete -c tree -l timefmt -x -d 'Print and format time according to the format <f>'
complete -c tree -s o -r -d 'Output to file instead of stdout'
-## File options
+## File options
complete -c tree -s q -d 'Print non-printable characters as \'?\''
complete -c tree -s N -d 'Print non-printable characters as is'
complete -c tree -s Q -d 'Quote filenames with double quotes'
@@ -32,27 +32,27 @@ complete -c tree -l inodes -d 'Print inode number of each file'
complete -c tree -l device -d 'Print device ID number to which each file belongs'
-## Sorting options
+## Sorting options
complete -c tree -s v -d 'Sort files alphanumerically by version'
complete -c tree -s r -d 'Sort files in reverse alphanumeric order'
complete -c tree -s t -d 'Sort files by last modification time'
complete -c tree -s c -d 'Sort files by last status change time'
complete -c tree -s U -d 'Leave files unsorted'
complete -c tree -l dirsfirst -d 'List directories before files (-U disables)'
-
-## Graphics options
+
+## Graphics options
complete -c tree -s i -d 'Don\'t print indentation lines'
complete -c tree -s A -d 'Print ANSI lines graphic indentation lines'
complete -c tree -s S -d 'Print with ASCII graphics indentation lines'
complete -c tree -s n -d 'Turn colorization off always (-C overrides)'
complete -c tree -s C -d 'Turn colorization on always'
-## XML/HTML options
+## XML/HTML options
complete -c tree -s X -d 'Prints out an XML representation of the tree'
complete -c tree -s H -r -d 'Prints out HTML format with baseHREF as top directory'
complete -c tree -s T -r -d 'Replace the default HTML title and H1 header with string'
complete -c tree -l nolinks -d 'Turn off hyperlinks in HTML output'
-
+
## Miscellaneous options
complete -c tree -l version -d 'Print version and exit'
complete -c tree -l help -d 'Print usage and this help message and exit'
diff --git a/share/completions/xdg-mime.fish b/share/completions/xdg-mime.fish
index 13ff942c..e2b597dc 100644
--- a/share/completions/xdg-mime.fish
+++ b/share/completions/xdg-mime.fish
@@ -18,7 +18,7 @@ complete -c xdg-mime -d 'Mimetype' -n '__fish_seen_subcommand_from def
# complete xdg-mime install
complete -c xdg-mime -d 'Add filetype description' -n 'contains_seq xdg-mime install -- (commandline -cop)' -r
complete -c xdg-mime -d 'Set mode' -n 'contains_seq xdg-mime install -- (commandline -cop)' -l mode -xa 'user system'
-complete -c xdg-mime -d 'Disable vendor check' -n 'contains_seq xdg-mime install -- (commandline -cop)' -l novendor
+complete -c xdg-mime -d 'Disable vendor check' -n 'contains_seq xdg-mime install -- (commandline -cop)' -l novendor
# complete xdg-mime uninstall
complete -c xdg-mime -d 'Remove filetype description' -n 'contains_seq xdg-mime uninstall -- (commandline -cop)' -r
diff --git a/share/completions/xrandr.fish b/share/completions/xrandr.fish
index a49fd2b4..a05c832f 100644
--- a/share/completions/xrandr.fish
+++ b/share/completions/xrandr.fish
@@ -6,11 +6,11 @@ complete -c xrandr -s v -l version -d 'Print out the RandR version reported by t
complete -c xrandr -s q -l query -d 'Display the current state of the system'
complete -c xrandr -s d -o display -d 'Select X display to use' -x
complete -c xrandr -l screen -d 'Select which screen to manipulate' -x
-complete -c xrandr -l q1 -d 'Use RandR version 1.1 protocol'
-complete -c xrandr -l q12 -d 'Use RandR version 1.2 protocol'
+complete -c xrandr -l q1 -d 'Use RandR version 1.1 protocol'
+complete -c xrandr -l q12 -d 'Use RandR version 1.2 protocol'
set -l ver (xrandr -v | grep RandR | sed 's/^.\+\s\([0-9\.]\+\)$/\1/')
-if not expr match $ver '^[0-9.]*$' >/dev/null
+if not expr match $ver '^[0-9.]*$' >/dev/null
set ver 10
end
@@ -25,7 +25,7 @@ if expr $ver '>' 1.1
complete -c xrandr -l prop -l properties -d 'Display the contents of properties for each output'
complete -c xrandr -l fb -d 'Set screen size' -x
complete -c xrandr -l fbmm -d 'Set reported physical screen size' -x
- complete -c xrandr -l dpi -d 'Set dpi to calculate reported physical screen size'
+ complete -c xrandr -l dpi -d 'Set dpi to calculate reported physical screen size'
complete -c xrandr -l newmode -d 'Add new mode' -r
complete -c xrandr -l rmmode -d 'Removes a mode from the server' -xa '(__fish_print_xrandr_modes)'
complete -c xrandr -l addmode -d 'Add a mode to the set of valid modes for an output' -xa '(__fish_print_xrandr_outputs)'
@@ -53,7 +53,7 @@ end
if expr $ver '>' 1.2
complete -c xrandr -l noprimary -d 'Don\'t define a primary output.'
complete -c xrandr -l current -d 'Print current screen configuration'
- complete -c xrandr -l panning -d 'Set panning: widthxheight[+x+y[/track_widthxtrack_height+track_x+track_y[/border_left/border_top/border_right/border_bottom]]]' -x
+ complete -c xrandr -l panning -d 'Set panning: widthxheight[+x+y[/track_widthxtrack_height+track_x+track_y[/border_left/border_top/border_right/border_bottom]]]' -x
complete -c xrandr -l transform -d 'Set transformation matrix: a,b,c,d,e,f,g,h,i for [ [a,b,c], [d,e,f], [g,h,i] ]' -x
complete -c xrandr -l scale -d 'Set scren scale' -x
complete -c xrandr -l primary -d 'Set the output as primary'
diff --git a/share/completions/xrdb.fish b/share/completions/xrdb.fish
index bddafb5f..edb5b291 100644
--- a/share/completions/xrdb.fish
+++ b/share/completions/xrdb.fish
@@ -16,6 +16,6 @@ complete -c xrdb -o symbols -d 'show preprocessor symbols'
complete -c xrdb -o remove -d 'remove resources'
complete -c xrdb -o retain -d 'avoid server reset (avoid using this)'
complete -c xrdb -o quiet -d 'don\'t warn about duplicates'
-#complete -c xrdb -s Dname[=value],
-#complete -c xrdb -s Uname,
+#complete -c xrdb -s Dname[=value],
+#complete -c xrdb -s Uname,
#complete -c xrdb -s Idirectory -d 'passed to preprocessor'
diff --git a/share/functions/__fish_complete_atool.fish b/share/functions/__fish_complete_atool.fish
index 62f6dd05..896129a6 100644
--- a/share/functions/__fish_complete_atool.fish
+++ b/share/functions/__fish_complete_atool.fish
@@ -27,7 +27,7 @@ function __fish_complete_atool --description 'Complete atool' --argument-names c
complete -c $cmd -s S -l simulate -d 'simulation mode - no filesystem changes are made'
complete -c $cmd -s o -l option -x -d 'override a configuration optioni (KEY=VALUE)'
complete -c $cmd -l config -r -d 'load configuration defaults from file'
-
+
switch $cmd
case als aunpack acat
complete -c $cmd -a '(__fish_complete_atool_archive_contents)' -d 'Achive content'
diff --git a/share/functions/__fish_complete_cd.fish b/share/functions/__fish_complete_cd.fish
index cb10b7cf..9ca3e93b 100644
--- a/share/functions/__fish_complete_cd.fish
+++ b/share/functions/__fish_complete_cd.fish
@@ -18,7 +18,7 @@ function __fish_complete_cd -d "Completions for the cd command"
else
set mycdpath $CDPATH
end
-
+
# Note how this works: we evaluate $ctoken*/
# That trailing slash ensures that we only expand directories
diff --git a/share/functions/__fish_complete_list.fish b/share/functions/__fish_complete_list.fish
index e9a97bb7..c02a561e 100644
--- a/share/functions/__fish_complete_list.fish
+++ b/share/functions/__fish_complete_list.fish
@@ -1,6 +1,6 @@
function __fish_complete_list --argument div cmd prefix iprefix
if not set -q cmd[1]
- echo "Usage:
+ echo "Usage:
__fish_complete_list <separator> <function> <prefix> <itemprefix>
where:
separator - a symbol, separating individual entries
diff --git a/share/functions/__fish_complete_lpr.fish b/share/functions/__fish_complete_lpr.fish
index 930a2139..c6b2cbf4 100644
--- a/share/functions/__fish_complete_lpr.fish
+++ b/share/functions/__fish_complete_lpr.fish
@@ -2,26 +2,26 @@ function __fish_complete_lpr -d 'Complete lpr common options' --argument-names c
complete -c $cmd -s E -d 'Forces encryption when connecting to the server'
complete -c $cmd -s U -d 'Specifies an alternate username' -xa '(__fish_complete_users)'
- switch $cmd
+ switch $cmd
case lpr lpq lprm
complete -c $cmd -s P -d 'Specifies an alternate printer or class name' -xa '(__fish_print_lpr_printers)'
end
- switch $cmd
- case lpq cancel
+ switch $cmd
+ case lpq cancel
complete -c $cmd -s a -d 'Apply command to all printers'
end
- switch $cmd
+ switch $cmd
case lpq cancel lpmove lpstat lprm lpoptions lp reject accept cupsaccept cupsreject cupsenable cupsdisable
complete -c $cmd -s h -d 'Specifies an alternate server' -xa '(__fish_print_hostnames)'
end
-
- switch $cmd
+
+ switch $cmd
case lp lpr
complete -c $cmd -s o -d 'Sets a job option' -xa '(__fish_complete_lpr_option)'
complete -c $cmd -s m -d 'Send an email on job completion'
-
+
complete -c $cmd -s o -xa landscape -d 'Landscape mode'
complete -c $cmd -s o -xa "media=a4 media=letter media=legal" -d 'Media size'
complete -c $cmd -s o -xa page-ranges= -d 'Page ranges'
diff --git a/share/functions/__fish_complete_pacman.fish b/share/functions/__fish_complete_pacman.fish
index 70cd6522..9967df3a 100644
--- a/share/functions/__fish_complete_pacman.fish
+++ b/share/functions/__fish_complete_pacman.fish
@@ -71,7 +71,7 @@ function __fish_complete_pacman -d 'Complete pacman (ARCH package manager)' --ar
# Query and sync options
for condition in query sync
- complete -c $progname -n $$condition -s g -l groups -d 'Display all packages in GROUP' -xa "$listgroups"
+ complete -c $progname -n $$condition -s g -l groups -d 'Display all packages in GROUP' -xa "$listgroups"
complete -c $progname -n $$condition -s i -l info -d 'Display information on PACKAGE'
complete -c $progname -n $$condition -s q -l quiet -d 'Show less information'
complete -c $progname -n $$condition -s s -l search -r -d 'Search packages for regexp'
diff --git a/share/functions/__fish_complete_python.fish b/share/functions/__fish_complete_python.fish
index 33bc2cb6..899add7f 100644
--- a/share/functions/__fish_complete_python.fish
+++ b/share/functions/__fish_complete_python.fish
@@ -17,18 +17,18 @@ function __fish_complete_python -d 'Make completion for python' --argument-names
complete -c $cmd -s x -d 'Skip first line of source, allowing use of non-Unix forms of #!cmd'
complete -c $cmd -a "(__fish_complete_suffix .py)"
complete -c $cmd -a '-' -d 'Read program from stdin'
-
+
switch (eval $cmd -V 2>| sed 's/^.*\s\(.\).*/\1/')
case 2
complete -c $cmd -s 3 -d 'Warn about Python 3.x incompatibilities that 2to3 cannot trivially fix'
complete -c $cmd -s t --description "Warn on mixed tabs and spaces"
complete -c $cmd -s Q -x -a "old new warn warnall" --description "Division control"
-
+
case 3
complete -c $cmd -s q --description 'Don\'t print version and copyright messages on interactive startup'
complete -c $cmd -s X -x -d 'Set implementation-specific option'
complete -c $cmd -s b -d 'Issue warnings about str(bytes_instance), str(bytearray_instance) and comparing bytes/bytearray with str'
complete -c $cmd -o bb -d 'Issue errors'
-
+
end
end
diff --git a/share/functions/__fish_complete_subcommand.fish b/share/functions/__fish_complete_subcommand.fish
index e263684a..ace0db2d 100644
--- a/share/functions/__fish_complete_subcommand.fish
+++ b/share/functions/__fish_complete_subcommand.fish
@@ -32,7 +32,7 @@ function __fish_complete_subcommand -d "Complete subcommand"
case '-*'
case '*=*'
case '*'
-
+
set had_cmd 1
set res $i
end
diff --git a/share/functions/__fish_complete_svn.fish b/share/functions/__fish_complete_svn.fish
index 52b4392e..51030313 100644
--- a/share/functions/__fish_complete_svn.fish
+++ b/share/functions/__fish_complete_svn.fish
@@ -1,5 +1,5 @@
-function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names svn
+function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names svn
function _svn_cmpl_ -d 'Make a completion for a subcommand' --no-scope-shadowing --argument-names subcommand
set -e argv[1]
complete -c $svn -n "__fish_seen_subcommand_from $subcommand" $argv
@@ -16,17 +16,17 @@ function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names
set -l cleanup cleanup
set -l commit 'ci commit'
set -l copy 'cp copy'
- set -l diff 'di diff'
+ set -l diff 'di diff'
set -l export export
- set -l help '\? h help'
+ set -l help '\? h help'
set -l import import
set -l info info
- set -l list 'ls list'
+ set -l list 'ls list'
set -l lock lock
set -l log log
set -l merge merge
set -l mergeinfo mergeinfo
- set -l mkdir mkdir
+ set -l mkdir mkdir
set -l move 'mv move ren rename'
set -l patch patch
set -l propdel 'pd pdel propdel'
@@ -39,8 +39,8 @@ function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names
set -l resolve resolve
set -l resolved resolved
set -l revert revert
- set -l stat 'st stat status'
- set -l switch 'sw switch'
+ set -l stat 'st stat status'
+ set -l switch 'sw switch'
set -l unlock unlock
set -l update 'up update'
set -l upgrade upgrade
@@ -97,7 +97,7 @@ function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names
# local commands
#
for cmd in $commit $copy $import $lock $mkdir $move $propedit $remove
- if not test $cmd = lock
+ if not test $cmd = lock
_svn_cmpl_ $cmd -l editor-cmd -x --description 'Use ARG as external editor'
end
_svn_cmpl_ $cmd -l message -s m --description 'Specify log message'
@@ -142,7 +142,7 @@ function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names
_svn_cmpl_ $cmd -l change -s c -d 'The change made in revision ARG' -xa '(__fish_print_svn_rev)'
end
- for cmd in $blame $cat $checkout $copy $diff $export $info $list $log $merge $mergeinfo $move $propedit $propget $propdel $proplist $propset $switch $update
+ for cmd in $blame $cat $checkout $copy $diff $export $info $list $log $merge $mergeinfo $move $propedit $propget $propdel $proplist $propset $switch $update
_svn_cmpl_ $cmd -l revision -s r -d 'Which revision the target is first looked up' -xa '(__fish_print_svn_rev)'
end
@@ -169,8 +169,8 @@ function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names
_svn_cmpl_ $cmd -l extensions -s x -d 'Ignore eol style' -xa '-w --ignore-eol-style'
_svn_cmpl_ $cmd -l extensions -s x -d 'Show C function name' -xa '-p --shoe-c-function'
- # Next completion doesn't work, since fish doesn't respect -x key
- #_svn_cmpl_ $cmd -l extensions -n '__fish_seen_subcommand_from --diff-cmd' -xa '(__fish_complete_svn_diff)'
+ # Next completion doesn't work, since fish doesn't respect -x key
+ #_svn_cmpl_ $cmd -l extensions -n '__fish_seen_subcommand_from --diff-cmd' -xa '(__fish_complete_svn_diff)'
end
for cmd in $cleanup $merge $switch $update
@@ -185,28 +185,28 @@ function __fish_complete_svn -d 'Complete svn and its wrappers' --argument-names
_svn_cmpl_ $cmd -l no-ignore -d 'Disregard default and svn:ignore property ignores'
end
- for cmd in $merge $patch
+ for cmd in $merge $patch
_svn_cmpl_ $cmd -l dry-run --description 'Try operation but make no changes'
end
- for cmd in $merge $switch
+ for cmd in $merge $switch
_svn_cmpl_ $cmd -l ignore-ancestry --description 'Ignore ancestry when calculating merges'
end
- for cmd in $diff $log
+ for cmd in $diff $log
_svn_cmpl_ $cmd -l internal-diff --description 'Override diff-cmd specified in config file'
_svn_cmpl_ $cmd -l diff-cmd --description 'Use external diff command' -xa "(complete -C(commandline -ct))"
end
- for cmd in $add $import
+ for cmd in $add $import
_svn_cmpl_ $cmd -l no-auto-props --description 'Disable automatic properties'
end
- for cmd in $switch $update
+ for cmd in $switch $update
_svn_cmpl_ $cmd -l set-depth --description 'Set new working copy depth' -xa 'exclude empty files immediates infinity'
end
- for cmd in $blame $log
+ for cmd in $blame $log
_svn_cmpl_ $cmd -l use-merge-history -s g -d 'Use/display additional information from merge history'
end
diff --git a/share/functions/__fish_complete_svn_diff.fish b/share/functions/__fish_complete_svn_diff.fish
index 1969c164..ada2dd0e 100644
--- a/share/functions/__fish_complete_svn_diff.fish
+++ b/share/functions/__fish_complete_svn_diff.fish
@@ -2,7 +2,7 @@ function __fish_complete_svn_diff --description 'Complete "svn diff" arguments'
set -l cmdl (commandline -cop)
#set -l cmdl svn diff --diff-cmd diff --extensions '-a -b'
set -l diff diff
-set -l args
+set -l args
while set -q cmdl[1]
switch $cmdl[1]
case --diff-cmd
diff --git a/share/functions/__fish_complete_tex.fish b/share/functions/__fish_complete_tex.fish
index 1c8876fe..1334ddda 100644
--- a/share/functions/__fish_complete_tex.fish
+++ b/share/functions/__fish_complete_tex.fish
@@ -14,7 +14,7 @@ function __fish_complete_tex -d "Common completions for all tex commands"
complete -c $argv -o interaction=nonstopmode -d "Set interation mode"
complete -c $argv -o interaction=scrollmode -d "Set interation mode"
complete -c $argv -o interaction=errorstopmode -d "Set interation mode"
- complete -c $argv -o output-directory= -x -a "(__fish_complete_directories (commandline -ct))" -d "Output directory"
+ complete -c $argv -o output-directory= -x -a "(__fish_complete_directories (commandline -ct))" -d "Output directory"
complete -c $argv -o shell-escape -d "Enable \write18{SHELL COMMAND}"
complete -c $argv -o no-shell-escape -d "Disable \write18{SHELL COMMAND}"
complete -c $argv -o src-specials -d "Insert source specials into the DVI file"
diff --git a/share/functions/__fish_make_completion_signals.fish b/share/functions/__fish_make_completion_signals.fish
index a8d97819..81347569 100644
--- a/share/functions/__fish_make_completion_signals.fish
+++ b/share/functions/__fish_make_completion_signals.fish
@@ -2,7 +2,7 @@ function __fish_make_completion_signals --description 'Make list of kill signals
set -q __kill_signals; and return 0
if kill -L ^/dev/null >/dev/null
- # Debian and some related systems use 'kill -L' to write out a numbered list
+ # Debian and some related systems use 'kill -L' to write out a numbered list
# of signals. Use this to complete on both number _and_ on signal name.
complete -c kill -s L --description "List codes and names of available signals"
set -g __kill_signals (kill -L | sed -e 's/\([0-9][0-9]*\) *\([A-Z,0-9][A-Z,0-9]*\)/\1 \2\n/g;s/ +/ /g' | sed -e 's/^ \+//' | sgrep -E '^[^ ]+')
diff --git a/share/functions/__fish_print_help.fish b/share/functions/__fish_print_help.fish
index 07df075c..8e4d3000 100644
--- a/share/functions/__fish_print_help.fish
+++ b/share/functions/__fish_print_help.fish
@@ -8,7 +8,7 @@ function __fish_print_help --description "Print help message for the specified f
case '*'
set item $argv[1]
end
-
+
# Do nothing if the file does not exist
if not test -e "$__fish_datadir/man/man1/$item.1"
return
diff --git a/share/functions/dirh.fish b/share/functions/dirh.fish
index 639e920a..44244e8c 100644
--- a/share/functions/dirh.fish
+++ b/share/functions/dirh.fish
@@ -25,7 +25,7 @@ function dirh --description "Print the current directory history (the back- and
set_color $fish_color_history_current
echo -n -e $current$separator
set_color normal
-
+
# BSD seq 0 outputs '1 0' instead of nothing
if count $dirnext > /dev/null
for i in (seq (echo (count $dirnext)) -1 1)
diff --git a/share/functions/funced.fish b/share/functions/funced.fish
index f35a72fa..399439fd 100644
--- a/share/functions/funced.fish
+++ b/share/functions/funced.fish
@@ -11,7 +11,7 @@ function funced --description 'Edit function definition'
case -e --editor
set editor $argv[2]
set -e argv[2]
-
+
case -i --interactive
set interactive 1
@@ -83,7 +83,7 @@ function funced --description 'Edit function definition'
if eval $editor $tmpname
. $tmpname
end
- set -l stat $status
+ set -l stat $status
rm -f $tmpname >/dev/null
return $stat
end
diff --git a/share/functions/history.fish b/share/functions/history.fish
index 73fea995..b943719e 100644
--- a/share/functions/history.fish
+++ b/share/functions/history.fish
@@ -12,7 +12,7 @@ function history --description "Deletes an item from history"
set -l search_mode none
- if test $argc -gt 0
+ if test $argc -gt 0
for i in (seq $argc)
switch $argv[$i]
case --delete
@@ -43,7 +43,7 @@ function history --description "Deletes an item from history"
# Note this may end up passing --search twice to the builtin,
# but that's harmless
builtin history --search $argv
-
+
case delete
# Interactively delete history
set -l found_items ""
@@ -57,43 +57,43 @@ function history --description "Deletes an item from history"
#Save changes after deleting item
builtin history --save
- return 0
+ return 0
end
-
+
set found_items_count (count $found_items)
- if test $found_items_count -gt 0
+ if test $found_items_count -gt 0
echo "[0] cancel"
echo "[1] all"
echo
-
+
for i in (seq $found_items_count)
printf "[%s] %s \n" (math $i + 1) $found_items[$i]
end
-
+
read --local --prompt "echo 'Delete which entries? > '" choice
set choice (echo $choice | tr " " "\n")
-
+
for i in $choice
-
+
# Skip empty input, for example, if the user just hits return
if test -z $i
continue
end
-
- #Following two validations could be embedded with "and" but I find the syntax kind of weird.
+
+ #Following two validations could be embedded with "and" but I find the syntax kind of weird.
if not echo $i | grep -E -q "^[0-9]+\$"
- printf "Invalid input: %s\n" $i
- continue
+ printf "Invalid input: %s\n" $i
+ continue
end
-
+
if test $i -gt (math $found_items_count + 1)
- printf "Invalid input : %s\n" $i
+ printf "Invalid input : %s\n" $i
continue
end
-
+
if test $i = "0"
printf "Cancel\n"
- return
+ return
else
if test $i = "1"
for item in $found_items
diff --git a/share/tools/create_manpage_completions.py b/share/tools/create_manpage_completions.py
index 7b0c6de9..775fa5c3 100755
--- a/share/tools/create_manpage_completions.py
+++ b/share/tools/create_manpage_completions.py
@@ -4,10 +4,10 @@
# Run me like this: ./create_manpage_completions.py /usr/share/man/man1/* > man_completions.fish
"""
-<OWNER> = Siteshwar Vashisht
-<YEAR> = 2012
+<OWNER> = Siteshwar Vashisht
+<YEAR> = 2012
-Copyright (c) 2012, Siteshwar Vashisht
+Copyright (c) 2012, Siteshwar Vashisht
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -47,7 +47,7 @@ def add_diagnostic(dgn, msg_verbosity = VERY_VERBOSE):
# Add a diagnostic message, if msg_verbosity <= VERBOSITY
if msg_verbosity <= VERBOSITY:
diagnostic_output.append(' '*diagnostic_indent + dgn)
-
+
def flush_diagnostics(where):
if diagnostic_output:
output_str = '\n'.join(diagnostic_output) + '\n'
@@ -77,7 +77,7 @@ def unquoteSingleQuotes(data):
if data[0] == '`' and data[len(data)-1] == '\'':
data = data[1:len(data)-1]
return data
-
+
# Make a string of characters that are deemed safe in fish without needing to be escaped
# Note that space is not included
@@ -88,7 +88,7 @@ def fish_escape_single_quote(str):
# If it has no non-safe chars, there's nothing to do
if g_fish_safe_chars.issuperset(str):
return str
-
+
str = str.replace('\\', '\\\\') # Replace one backslash with two
str = str.replace("'", "\\'") # Replace one single quote with a backslash-single-quote
return "'" + str + "'"
@@ -107,10 +107,10 @@ def builtcommand(options, description):
fish_options = []
for option in man_optionlist:
option = option.strip()
-
+
# Skip some problematic cases
if option in ['-', '--']: continue
-
+
if option.startswith('--'):
# New style long option (--recursive)
fish_options.append('-l ' + fish_escape_single_quote(option[2:]))
@@ -120,29 +120,29 @@ def builtcommand(options, description):
elif option.startswith('-') and len(option) > 2:
# Old style long option (-recursive)
fish_options.append('-o ' + fish_escape_single_quote(option[1:]))
-
+
# Determine which options are new (not already in existing_options)
# Then add those to the existing options
existing_options = already_output_completions.setdefault(CMDNAME, set())
fish_options = [opt for opt in fish_options if opt not in existing_options]
existing_options.update(fish_options)
-
+
# Maybe it's all for naught
if not fish_options: return
-
- first_period = description.find(".")
+
+ first_period = description.find(".")
if first_period >= 45 or (first_period == -1 and len(description) > 45):
description = description[:45] + '... [See Man Page]'
elif first_period >= 0:
description = description[:first_period]
-
+
# Escape some more things
description = fish_escape_single_quote(description)
escaped_cmd = fish_escape_single_quote(CMDNAME)
-
+
output_complete_command(escaped_cmd, fish_options, description, built_command_output)
-
+
def removeGroffFormatting(data):
# data = data.replace("\fI","")
@@ -193,7 +193,7 @@ class Type1ManParser(ManParser):
def parseManPage(self, manpage):
options_section_regex = re.compile( "\.SH \"OPTIONS\"(.*?)(\.SH|\Z)", re.DOTALL)
options_section_matched = re.search( options_section_regex, manpage)
-
+
options_section = options_section_matched.group(0)
# print options_section
options_parts_regex = re.compile("\.PP(.*?)\.RE", re.DOTALL)
@@ -208,7 +208,7 @@ class Type1ManParser(ManParser):
elif (self.fallback2(options_section) ):
return True
return False
-
+
while (options_matched != None):
# print len(options_matched.groups())
# print options_matched.group()
@@ -222,7 +222,7 @@ class Type1ManParser(ManParser):
# print data
if (len (data) > 1): #and len(data[1]) <= 300):
optionName = data[0].strip()
-
+
if ( optionName.find("-") == -1):
add_diagnostic(optionName + " doesn't contain - ")
# return False
@@ -232,7 +232,7 @@ class Type1ManParser(ManParser):
optionDescription = data[1].strip().replace("\n"," ")
# print >> sys.stderr, "Option: ", optionName," Description: ", optionDescription , '\n'
builtcommand(optionName, optionDescription)
-
+
else:
add_diagnostic('Unable to split option from description')
return False
@@ -283,7 +283,7 @@ class Type1ManParser(ManParser):
return False
while options_matched != None:
data = options_matched.group(1)
-
+
# print "Data is : ", data
data = removeGroffFormatting(data)
data = data.strip()
@@ -293,7 +293,7 @@ class Type1ManParser(ManParser):
# data = re.sub(trailing_num_regex, "", data)
optionName = re.sub(trailing_num_regex, "", data[0].strip())
-
+
if ('-' not in optionName):
add_diagnostic(optionName + " doesn't contain -")
else:
@@ -311,7 +311,7 @@ class Type1ManParser(ManParser):
options_section = options_section[options_matched.end()-3:]
options_matched = re.search(options_parts_regex, options_section)
return True
-
+
def name(self):
return "Type1"
@@ -328,7 +328,7 @@ class Type2ManParser(ManParser):
def parseManPage(self, manpage):
options_section_regex = re.compile( "\.SH OPTIONS(.*?)(\.SH|\Z)", re.DOTALL)
options_section_matched = re.search( options_section_regex, manpage)
-
+
# if (options_section_matched == None):
# print "Falling Back"
# options_section_regex = re.compile( "\.SH OPTIONS(.*?)$", re.DOTALL)
@@ -372,13 +372,13 @@ class Type2ManParser(ManParser):
else:
# print >> sys.stderr, data
add_diagnostic('Unable to split option from description')
-
+
# return False
options_section = options_section[options_matched.end()-3:]
options_matched = re.search(options_parts_regex, options_section)
-
+
def name(self):
return "Type2"
@@ -396,7 +396,7 @@ class Type3ManParser(ManParser):
def parseManPage(self, manpage):
options_section_regex = re.compile( "\.SH DESCRIPTION(.*?)(\.SH|\Z)", re.DOTALL)
options_section_matched = re.search( options_section_regex, manpage)
-
+
options_section = options_section_matched.group(1)
# print options_section
# sys.exit(1)
@@ -452,7 +452,7 @@ class Type4ManParser(ManParser):
def parseManPage(self, manpage):
options_section_regex = re.compile( "\.SH FUNCTION LETTERS(.*?)(\.SH|\Z)", re.DOTALL)
options_section_matched = re.search( options_section_regex, manpage)
-
+
options_section = options_section_matched.group(1)
# print options_section
# sys.exit(1)
@@ -499,7 +499,7 @@ class TypeDarwinManParser(ManParser):
def isMyType(self, manpage):
options_section_matched = compileAndSearch("\.S[hH] DESCRIPTION", manpage)
return options_section_matched != None
-
+
def trim_groff(self, line):
# Remove initial period
if line.startswith('.'):
@@ -508,49 +508,49 @@ class TypeDarwinManParser(ManParser):
while re.match('[A-Z][a-z]\s', line):
line = line[3:]
return line
-
+
# Replace some groff escapes. There's a lot we don't bother to handle.
def groff_replace_escapes(self, line):
line = line.replace('\\ ', ' ')
line = line.replace('\& ', '')
return line
-
+
def is_option(self, line):
return line.startswith('.It Fl')
-
+
def parseManPage(self, manpage):
got_something = False
lines = manpage.splitlines()
# Discard lines until we get to ".sh Description"
while lines and not (lines[0].startswith('.Sh DESCRIPTION') or lines[0].startswith('.SH DESCRIPTION')):
lines.pop(0)
-
+
while lines:
# Pop until we get to the next option
while lines and not self.is_option(lines[0]):
lines.pop(0)
-
+
if not lines:
continue
-
+
# Get the line and clean it up
line = lines.pop(0)
line = self.groff_replace_escapes(line)
line = self.trim_groff(line)
line = line.strip()
if not line: continue
-
+
# Extract the name
name = line.split(None, 2)[0]
-
+
# Extract the description
desc = ''
while lines and not self.is_option(lines[0]):
# print "*", lines[0]
desc = desc + lines.pop(0)
-
+
# print "name: ", name
-
+
if name == '-':
# Skip double -- arguments
continue
@@ -561,9 +561,9 @@ class TypeDarwinManParser(ManParser):
elif len(name) == 1:
builtcommand('-' + name, desc)
got_something = True
-
+
return got_something
-
+
def name(self):
return "Darwin man parser"
@@ -571,25 +571,25 @@ class TypeDarwinManParser(ManParser):
class TypeDeroffManParser(ManParser):
def isMyType(self, manpage):
return True # We're optimists
-
+
def is_option(self, line):
return line.startswith('-')
-
+
def could_be_description(self, line):
return len(line) > 0 and not line.startswith('-')
-
+
def parseManPage(self, manpage):
d = Deroffer()
d.deroff(manpage)
output = d.get_output()
lines = output.split('\n')
-
+
got_something = False
-
+
# Discard lines until we get to DESCRIPTION or OPTIONS
while lines and not (lines[0].startswith('DESCRIPTION') or lines[0].startswith('OPTIONS') or lines[0].startswith('COMMAND OPTIONS')):
lines.pop(0)
-
+
# Look for BUGS and stop there
for idx in range(len(lines)):
line = lines[idx]
@@ -597,32 +597,32 @@ class TypeDeroffManParser(ManParser):
# Drop remaining elements
lines[idx:] = []
break
-
+
while lines:
# Pop until we get to the next option
while lines and not self.is_option(lines[0]):
line = lines.pop(0)
-
+
if not lines:
continue
-
+
options = lines.pop(0)
-
+
# Pop until we get to either an empty line or a line starting with -
description = ''
while lines and self.could_be_description(lines[0]):
if description: description += ' '
description += lines.pop(0)
-
+
builtcommand(options, description)
got_something = True
-
+
return got_something
-
-
+
+
def name(self):
return "Deroffing man parser"
-
+
# Return whether the file at the given path is overwritable
# Raises IOError if it cannot be opened
def file_is_overwritable(path):
@@ -633,16 +633,16 @@ def file_is_overwritable(path):
line = line.strip()
if not line:
continue
-
+
# We look in the initial run of lines that start with #
if not line.startswith('#'):
break
-
+
# See if this contains the magic word
if 'Autogenerated' in line:
result = True
break
-
+
file.close()
return result
@@ -658,7 +658,7 @@ def file_missing_or_overwritable(path):
else:
# Something else happened
return False
-
+
# Delete the file if it is autogenerated
def cleanup_autogenerated_file(path):
try:
@@ -678,7 +678,7 @@ def parse_manpage_at_path(manpage_path, yield_to_dirs, output_directory):
# Set up some diagnostics
add_diagnostic('Considering ' + manpage_path)
diagnostic_indent += 1
-
+
if manpage_path.endswith('.gz'):
fd = gzip.open(manpage_path, 'r')
manpage = fd.read()
@@ -692,32 +692,32 @@ def parse_manpage_at_path(manpage_path, yield_to_dirs, output_directory):
fd.close()
manpage = str(manpage)
-
+
# Get the "base" command, e.g. gcc.1.gz -> gcc
cmd_base = CMDNAME.split('.', 1)[0]
ignoredcommands = ["cc", "g++", "gcc", "c++", "cpp", "emacs", "gprof", "wget", "ld", "awk"]
if cmd_base in ignoredcommands:
return
-
+
# Ignore perl's gazillion man pages
ignored_prefixes = ['perl', 'zsh']
for prefix in ignored_prefixes:
if cmd_base.startswith(prefix):
return
-
+
# Ignore the millions of links to BUILTIN(1)
if manpage.find('BUILTIN 1') != -1:
return
-
+
# Clear the output list
built_command_output[:] = []
-
+
if DEROFF_ONLY:
parsers = [TypeDeroffManParser()]
else:
parsers = [Type1ManParser(), Type2ManParser(), Type4ManParser(), Type3ManParser(), TypeDarwinManParser(), TypeDeroffManParser()]
parsersToTry = [p for p in parsers if p.isMyType(manpage)]
-
+
success = False
if not parsersToTry:
add_diagnostic(manpage_path + ": Not supported")
@@ -731,7 +731,7 @@ def parse_manpage_at_path(manpage_path, yield_to_dirs, output_directory):
if success:
PARSER_INFO.setdefault(parser_name, []).append(CMDNAME)
break
-
+
if success:
if WRITE_TO_STDOUT:
output_file = sys.stdout
@@ -742,13 +742,13 @@ def parse_manpage_at_path(manpage_path, yield_to_dirs, output_directory):
output_file = open(fullpath, 'w')
else:
add_diagnostic("Not overwriting the file at '%s'" % fullpath)
-
+
except IOError as err:
add_diagnostic("Unable to open file '%s': error(%d): %s" % (fullpath, err.errno, err.strerror))
return False
-
+
built_command_output.insert(0, "# %s: %s" % (CMDNAME, parser.name()))
-
+
# Output the magic word Autogenerated so we can tell if we can overwrite this
built_command_output.insert(1, "# Autogenerated from man pages")
built_command_output.insert(2, "# using " + parser_name)
@@ -780,22 +780,22 @@ def should_skip_man_page(output_path, filename, yield_to_dirs):
# No reason to skip if we're writing to stdout
if WRITE_TO_STDOUT:
return false
-
+
# Check all the yield directories
for yield_dir in yield_to_dirs:
test_path = os.path.join(yield_dir, filename)
if os.path.isfile(test_path):
# Yield to the existing file
return true
-
+
# See if there's a hand-written file already
if not file_missing_or_overwritable(output_path):
return true
-
+
# We made it through, so don't skip
return false
-
-
+
+
def parse_and_output_man_pages(paths, output_directory, yield_to_dirs, show_progress):
global diagnostic_indent, CMDNAME
@@ -808,12 +808,12 @@ def parse_and_output_man_pages(paths, output_directory, yield_to_dirs, show_prog
print("Parsing man pages and writing completions to {0}".format(output_directory))
for manpage_path in paths:
index += 1
-
+
# Get the "base" command, e.g. gcc.1.gz -> gcc
man_file_name = os.path.basename(manpage_path)
CMDNAME = man_file_name.split('.', 1)[0]
output_file_name = CMDNAME + '.fish'
-
+
# Show progress if we're doing that
if show_progress:
progress_str = ' {0} / {1} : {2}'.format((str(index).rjust(padding_len)), total_count, man_file_name)
@@ -822,7 +822,7 @@ def parse_and_output_man_pages(paths, output_directory, yield_to_dirs, show_prog
last_progress_string_length = len(progress_str)
sys.stdout.write("\r{0}\r".format(padded_progress_str))
sys.stdout.flush()
-
+
# Maybe we want to skip this item
skip = False
if not WRITE_TO_STDOUT:
@@ -840,7 +840,7 @@ def parse_and_output_man_pages(paths, output_directory, yield_to_dirs, show_prog
# Now skip if requested
if skip:
continue
-
+
try:
if parse_manpage_at_path(manpage_path, yield_to_dirs, output_directory):
successful_count += 1
@@ -878,8 +878,8 @@ def get_paths_from_manpath():
for name in names:
result.append(os.path.join(directory_path, name))
return result
-
-
+
+
def usage(script_name):
print("Usage: {0} [-v, --verbose] [-s, --stdout] [-d, --directory] [-p, --progress] files...".format(script_name))
@@ -901,11 +901,11 @@ if __name__ == "__main__":
print(err.msg) # will print something like "option -a not recognized"
usage(script_name)
sys.exit(2)
-
+
# If a completion already exists in one of the yield-to directories, then don't overwrite it
# And even delete an existing autogenerated one
yield_to_dirs = []
-
+
use_manpath, show_progress, custom_dir = False, False, False
output_directory = ''
for opt, value in opts:
@@ -930,15 +930,15 @@ if __name__ == "__main__":
DEROFF_ONLY = True
else:
assert False, "unhandled option"
-
+
if use_manpath:
# Fetch all man1 files from the manpath
file_paths.extend(get_paths_from_manpath())
-
+
if not file_paths:
print("No paths specified")
sys.exit(0)
-
+
if not WRITE_TO_STDOUT and not output_directory:
# Default to ~/.config/fish/completions/
# Create it if it doesn't exist
@@ -948,7 +948,7 @@ if __name__ == "__main__":
except OSError as e:
if e.errno != errno.EEXIST:
raise
-
+
if True:
parse_and_output_man_pages(file_paths, output_directory, yield_to_dirs, show_progress)
else:
@@ -957,7 +957,7 @@ if __name__ == "__main__":
cProfile.run('parse_and_output_man_pages(file_paths, output_directory, yield_to_dirs, show_progress)', 'fooprof')
p = pstats.Stats('fooprof')
p.sort_stats('cumulative').print_stats(100)
-
+
# Here we can write out all the parser infos
if False:
for name in PARSER_INFO:
diff --git a/share/tools/deroff.py b/share/tools/deroff.py
index eb8b0d6c..13737aa1 100755
--- a/share/tools/deroff.py
+++ b/share/tools/deroff.py
@@ -78,17 +78,17 @@ class Deroffer:
'/O': '\330',
'oA': '\305',
'oa': '\345',
-
+
# Ligatures
'fi': 'fi',
'ff': 'ff',
'fl': 'fl',
-
+
'Fi': 'ffi',
'Ff': 'fff',
'Fl': 'ffl'
}
-
+
g_specs = {
'mi': '-',
'en': '-',
@@ -212,7 +212,7 @@ class Deroffer:
'/_': "/_",
'lz': "<>",
'an': '-',
-
+
# Output Greek
'*A': "Alpha",
'*B': "Beta",
@@ -267,16 +267,16 @@ class Deroffer:
'*z': "zeta",
'ts': "sigma",
}
-
+
g_re_word = re.compile(r'[a-zA-Z_]+') # equivalent to the word() method
g_re_number = re.compile(r'[+-]?\d+') # equivalent to the number() method
g_re_esc_char = re.compile(r"""([a-zA-Z_]) | # Word
([+-]?\d) | # Number
\\ # Backslash (for escape seq)
""", re.VERBOSE)
-
+
g_re_not_backslash_or_whitespace = re.compile(r'[^ \t\n\r\f\v\\]+') # Match a sequence of not backslash or whitespace
-
+
g_re_newline_collapse = re.compile(r'\n{3,}')
g_re_font = re.compile(r"""\\f( # Starts with backslash f
@@ -284,10 +284,10 @@ class Deroffer:
(\[\S*?\]) | # Open bracket, zero or more printable characters, then close bracket
\S) # Any printable character
""", re.VERBOSE)
-
+
# This gets filled in in __init__ below
g_macro_dict = False
-
+
def __init__(self):
self.reg_table = {}
self.tr_from = ''
@@ -310,13 +310,13 @@ class Deroffer:
self.ignore_sonx = False
self.output = []
self.name = ''
-
+
self.OPTIONS = 0
self.FORMAT = 1
self.DATA = 2
-
+
# words is uninteresting and should be treated as false
-
+
if not Deroffer.g_macro_dict:
Deroffer.g_macro_dict = {
'SH': Deroffer.macro_sh,
@@ -363,41 +363,41 @@ class Deroffer:
'tr': Deroffer.macro_tr,
'sp': Deroffer.macro_sp
}
-
+
def flush_output(self, where):
if where:
where.write(self.get_output())
self.output[:] = []
-
+
def get_output(self):
res = ''.join(self.output)
clean_res = Deroffer.g_re_newline_collapse.sub('\n', res)
return clean_res
-
+
def putchar(self, c):
self.output.append(c)
return c
-
+
# This gets swapped in in place of condputs the first time tr gets modified
def condputs_tr(self, str):
special = self.pic or self.eqn or self.refer or self.macro or (self.skiplists and self.inlist) or (self.skipheaders and self.inheader)
if not special:
self.output.append(str.translate(self.tr))
-
+
def condputs(self, str):
special = self.pic or self.eqn or self.refer or self.macro or (self.skiplists and self.inlist) or (self.skipheaders and self.inheader)
- if not special:
+ if not special:
self.output.append(str)
-
+
def str_at(self, idx):
return self.s[idx:idx+1]
-
+
def skip_char(self, amt=1):
self.s = self.s[amt:]
-
+
def skip_leading_whitespace(self):
self.s = self.s.lstrip()
-
+
def is_white(self, idx):
# Note this returns false for empty strings (idx >= len(self.s))
return self.s[idx:idx+1].isspace()
@@ -415,7 +415,7 @@ class Deroffer:
if not match: return False
self.skip_char(match.end())
return True
-
+
def font2(self):
if self.s[0:2] == '\\f':
c = self.str_at(2)
@@ -430,7 +430,7 @@ class Deroffer:
self.skip_char(3)
return True
return False
-
+
def comment(self):
# Here we require that the string start with \"
while self.str_at(0) and self.str_at(0) != '\n': self.skip_char()
@@ -485,7 +485,7 @@ class Deroffer:
self.skip_char(3)
else:
return False
-
+
if reg in self.reg_table:
old_s = self.s
self.s = self.reg_table[reg]
@@ -518,7 +518,7 @@ class Deroffer:
return True
else:
return False
-
+
def esc(self):
# We require that the string start with backslash
c = self.s[1:2]
@@ -544,11 +544,11 @@ class Deroffer:
got_something = True
self.condputs(match.group(0))
self.skip_char(match.end(0))
-
+
# Consume all specials
while self.spec():
if not self.specletter: break
-
+
return got_something
@@ -571,7 +571,7 @@ class Deroffer:
ch = self.str_at(idx)
return ch.isalpha() or ch == '_' # underscore is used in C identifiers
-
+
def digit(self, idx):
ch = self.str_at(idx)
return ch.isdigit()
@@ -584,7 +584,7 @@ class Deroffer:
self.condputs(match.group(0))
self.skip_char(match.end())
return True
-
+
def esc_char_backslash(self):
# Like esc_char, but we know the string starts with a backslash
c = self.s[1:2]
@@ -620,7 +620,7 @@ class Deroffer:
return True
else:
return False
-
+
def text_arg(self):
# PCA: The deroff.c textArg() disallowed quotes at the start of an argument
# I'm not sure if this was a bug or not
@@ -632,21 +632,21 @@ class Deroffer:
self.condputs(match.group(0))
self.skip_char(match.end(0))
got_something = True
-
+
# Next is either an escape, or whitespace, or the end
# If it's the whitespace or the end, we're done
if not self.s or self.is_white(0):
return got_something
-
+
# Try an escape
if not self.esc_char():
# Some busted escape? Just output it
self.condputs(self.str_at(0))
self.skip_char()
got_something = True
-
-
-
+
+
+
def text_arg2(self):
if not self.esc_char():
if self.s and not self.is_white(0):
@@ -673,95 +673,95 @@ class Deroffer:
# Did not find a header string
self.inheader = False
self.nobody = True
-
+
def macro_ss_ip(self):
self.nobody = True
return False
-
+
def macro_i_ir(self):
pass
return False
-
+
def macro_Nm(self):
if self.s == 'Nm\n':
self.condputs(self.name)
else:
self.name = self.s[3:].strip() + ' '
return True
-
+
def macro_close_bracket(self):
self.refer = False
return False
-
+
def macro_ps(self):
if self.is_white(2): self.pic = True
self.condputs('\n')
return True
-
+
def macro_pe(self):
if self.is_white(2): self.pic = False
self.condputs('\n')
return True
-
+
def macro_ts(self):
if self.is_white(2): self.tbl, self.tblstate = True, self.OPTIONS
self.condputs('\n')
return True
-
+
def macro_t_and(self):
if self.is_white(2): self.tbl, self.tblstate = True, self.FORMAT
self.condputs('\n')
return True
-
+
def macro_te(self):
if self.is_white(2): self.tbl = False
self.condputs('\n')
return True
-
+
def macro_eq(self):
if self.is_white(2): self.eqn = True
self.condputs('\n')
return True
-
+
def macro_en(self):
if self.is_white(2): self.eqn = False
self.condputs('\n')
return True
-
+
def macro_r1(self):
if self.is_white(2): self.refer2 = True
self.condputs('\n')
return True
-
+
def macro_r2(self):
if self.is_white(2): self.refer2 = False
self.condputs('\n')
return True
-
+
def macro_de(self):
macro=True
self.condputs('\n')
return True
-
+
def macro_bl_vl(self):
if self.is_white(2): self.inlist = True
self.condputs('\n')
return True
-
+
def macro_bv(self):
if self.str_at(2) == 'L' and self.white(self.str_at(3)): self.inlist = True
self.condputs('\n')
return True
-
+
def macro_le(self):
if self.is_white(2): self.inlist = False
self.condputs('\n')
return True
-
+
def macro_lp_pp(self):
self.condputs('\n')
return True
-
+
def macro_ds(self):
self.skip_char(2)
self.skip_leading_whitespace()
@@ -774,13 +774,13 @@ class Deroffer:
self.reg_table[name] = value
self.condputs('\n')
return True
-
+
def macro_so_nx(self):
# We always ignore include directives
# deroff.c for some reason allowed this to fall through to the 'tr' case
# I think that was just a bug so I won't replicate it
return True
-
+
def macro_tr(self):
self.skip_char(2)
self.skip_leading_whitespace()
@@ -791,7 +791,7 @@ class Deroffer:
if not ns or ns == '\n': ns = ' '
self.tr_from += c
self.tr_to += ns
-
+
# Update our table, then swap in the slower tr-savvy condputs
try: #Python2
self.tr = string.maketrans(self.tr_from, self.tr_to)
@@ -799,11 +799,11 @@ class Deroffer:
self.tr = "".maketrans(self.tr_from, self.tr_to)
self.condputs = self.condputs_tr
return True
-
+
def macro_sp(self):
self.condputs('\n')
return True
-
+
def macro_other(self):
self.condputs('\n')
return True
@@ -830,16 +830,16 @@ class Deroffer:
self.macro = False
self.condputs('\n')
return True
-
+
self.nobody = False
s0s1 = self.s[0:2]
-
+
macro_func = Deroffer.g_macro_dict.get(s0s1, Deroffer.macro_other)
if macro_func(self):
return True
-
+
if self.skipheaders and self.nobody: return True
-
+
self.skip_leading_whitespace()
while self.s and not self.is_white(0): self.skip_char()
self.skip_leading_whitespace()
@@ -873,7 +873,7 @@ class Deroffer:
self.macro = False
self.condputs('\n')
return True
-
+
self.nobody = False
s0s1 = self.s[0:2]
if s0s1 == 'SH':
@@ -973,14 +973,14 @@ class Deroffer:
if not ns or ns == '\n': ns = ' '
self.tr_from += c
self.tr_to += ns
-
+
# Update our table, then swap in the slower tr-savvy condputs
try: #Python2
self.tr = string.maketrans(self.tr_from, self.tr_to)
except AttributeError: #Python3
self.tr = "".maketrans(self.tr_from, self.tr_to)
self.condputs = self.condputs_tr
-
+
return True
elif s0s1 in ['sp']:
self.condputs('\n')
@@ -988,9 +988,9 @@ class Deroffer:
else:
self.condputs('\n')
return True
-
+
if self.skipheaders and self.nobody: return True
-
+
self.skip_leading_whitespace()
while self.s and not self.is_white(0): self.skip_char()
self.skip_leading_whitespace()
@@ -1011,21 +1011,21 @@ class Deroffer:
# deroff.c has a bug where it can loop forever here...we try to work around it
self.skip_char()
else: # Parse option
-
+
option = self.s
arg = ''
-
+
idx = 0
while option[idx:idx+1].isalpha():
idx += 1
-
+
if option[idx:idx+1] == '(':
option = option[:idx]
self.s = self.s[idx+1:]
arg = self.s
else:
self.s = ''
-
+
if arg:
idx = arg.find(')')
if idx != -1:
@@ -1034,18 +1034,18 @@ class Deroffer:
else:
#self.skip_char()
pass
-
+
if option.lower() == 'tab':
self.tblTab = arg[0:1]
-
+
self.tblstate = self.FORMAT
self.condputs('\n')
-
+
elif self.tblstate == self.FORMAT:
while self.s and self.str_at(0) != '.' and self.str_at(0) != '\n':
self.skip_leading_whitespace()
if self.str_at(0): self.skip_char()
-
+
if self.str_at(0) == '.': self.tblstate = self.DATA
self.condputs('\n')
elif self.tblstate == self.DATA:
@@ -1062,7 +1062,7 @@ class Deroffer:
else:
self.text()
return True
-
+
def deroff(self, str):
lines = str.split('\n')
for line in lines:
@@ -1086,7 +1086,7 @@ def deroff_files(files):
d.flush_output(sys.stdout)
f.close()
-
+
if __name__ == "__main__":
import gzip
diff --git a/signal.cpp b/signal.cpp
index 2c51e9d2..d25f2b06 100644
--- a/signal.cpp
+++ b/signal.cpp
@@ -36,18 +36,18 @@ The library for various signal related issues
*/
struct lookup_entry
{
- /**
- Signal id
- */
- int signal;
- /**
- Signal name
- */
- const wchar_t *name;
- /**
- Signal description
- */
- const wchar_t *desc;
+ /**
+ Signal id
+ */
+ int signal;
+ /**
+ Signal name
+ */
+ const wchar_t *name;
+ /**
+ Signal description
+ */
+ const wchar_t *desc;
};
/**
@@ -63,363 +63,363 @@ static int block_count=0;
static const struct lookup_entry lookup[] =
{
#ifdef SIGHUP
- {
- SIGHUP,
- L"SIGHUP",
- N_( L"Terminal hung up" )
- }
- ,
+ {
+ SIGHUP,
+ L"SIGHUP",
+ N_( L"Terminal hung up" )
+ }
+ ,
#endif
#ifdef SIGINT
- {
- SIGINT,
- L"SIGINT",
- N_( L"Quit request from job control (^C)" )
- }
- ,
+ {
+ SIGINT,
+ L"SIGINT",
+ N_( L"Quit request from job control (^C)" )
+ }
+ ,
#endif
#ifdef SIGQUIT
- {
- SIGQUIT,
- L"SIGQUIT",
- N_( L"Quit request from job control with core dump (^\\)" )
- }
- ,
+ {
+ SIGQUIT,
+ L"SIGQUIT",
+ N_( L"Quit request from job control with core dump (^\\)" )
+ }
+ ,
#endif
#ifdef SIGILL
- {
- SIGILL,
- L"SIGILL",
- N_( L"Illegal instruction" )
- }
- ,
+ {
+ SIGILL,
+ L"SIGILL",
+ N_( L"Illegal instruction" )
+ }
+ ,
#endif
#ifdef SIGTRAP
- {
- SIGTRAP,
- L"SIGTRAP",
- N_( L"Trace or breakpoint trap" )
- }
- ,
+ {
+ SIGTRAP,
+ L"SIGTRAP",
+ N_( L"Trace or breakpoint trap" )
+ }
+ ,
#endif
#ifdef SIGABRT
- {
- SIGABRT,
- L"SIGABRT",
- N_( L"Abort" )
- }
- ,
+ {
+ SIGABRT,
+ L"SIGABRT",
+ N_( L"Abort" )
+ }
+ ,
#endif
#ifdef SIGBUS
- {
- SIGBUS,
- L"SIGBUS",
- N_( L"Misaligned address error" )
- }
- ,
+ {
+ SIGBUS,
+ L"SIGBUS",
+ N_( L"Misaligned address error" )
+ }
+ ,
#endif
#ifdef SIGFPE
- {
- SIGFPE,
- L"SIGFPE",
- N_( L"Floating point exception" )
- }
- ,
+ {
+ SIGFPE,
+ L"SIGFPE",
+ N_( L"Floating point exception" )
+ }
+ ,
#endif
#ifdef SIGKILL
- {
- SIGKILL,
- L"SIGKILL",
- N_( L"Forced quit" )
- }
- ,
+ {
+ SIGKILL,
+ L"SIGKILL",
+ N_( L"Forced quit" )
+ }
+ ,
#endif
#ifdef SIGUSR1
- {
- SIGUSR1,
- L"SIGUSR1",
- N_( L"User defined signal 1" )
- }
- ,
+ {
+ SIGUSR1,
+ L"SIGUSR1",
+ N_( L"User defined signal 1" )
+ }
+ ,
#endif
#ifdef SIGUSR2
- {
- SIGUSR2, L"SIGUSR2",
- N_( L"User defined signal 2" )
- }
- ,
+ {
+ SIGUSR2, L"SIGUSR2",
+ N_( L"User defined signal 2" )
+ }
+ ,
#endif
#ifdef SIGSEGV
- {
- SIGSEGV,
- L"SIGSEGV",
- N_( L"Address boundary error" )
- }
- ,
+ {
+ SIGSEGV,
+ L"SIGSEGV",
+ N_( L"Address boundary error" )
+ }
+ ,
#endif
#ifdef SIGPIPE
- {
- SIGPIPE,
- L"SIGPIPE",
- N_( L"Broken pipe" )
- }
- ,
+ {
+ SIGPIPE,
+ L"SIGPIPE",
+ N_( L"Broken pipe" )
+ }
+ ,
#endif
#ifdef SIGALRM
- {
- SIGALRM,
- L"SIGALRM",
- N_( L"Timer expired" )
- }
- ,
+ {
+ SIGALRM,
+ L"SIGALRM",
+ N_( L"Timer expired" )
+ }
+ ,
#endif
#ifdef SIGTERM
- {
- SIGTERM,
- L"SIGTERM",
- N_( L"Polite quit request" )
- }
- ,
+ {
+ SIGTERM,
+ L"SIGTERM",
+ N_( L"Polite quit request" )
+ }
+ ,
#endif
#ifdef SIGCHLD
- {
- SIGCHLD,
- L"SIGCHLD",
- N_( L"Child process status changed" )
- }
- ,
+ {
+ SIGCHLD,
+ L"SIGCHLD",
+ N_( L"Child process status changed" )
+ }
+ ,
#endif
#ifdef SIGCONT
- {
- SIGCONT,
- L"SIGCONT",
- N_( L"Continue previously stopped process" )
- }
- ,
+ {
+ SIGCONT,
+ L"SIGCONT",
+ N_( L"Continue previously stopped process" )
+ }
+ ,
#endif
#ifdef SIGSTOP
- {
- SIGSTOP,
- L"SIGSTOP",
- N_( L"Forced stop" )
- }
- ,
+ {
+ SIGSTOP,
+ L"SIGSTOP",
+ N_( L"Forced stop" )
+ }
+ ,
#endif
#ifdef SIGTSTP
- {
- SIGTSTP,
- L"SIGTSTP",
- N_( L"Stop request from job control (^Z)" )
- }
- ,
+ {
+ SIGTSTP,
+ L"SIGTSTP",
+ N_( L"Stop request from job control (^Z)" )
+ }
+ ,
#endif
#ifdef SIGTTIN
- {
- SIGTTIN,
- L"SIGTTIN",
- N_( L"Stop from terminal input" )
- }
- ,
+ {
+ SIGTTIN,
+ L"SIGTTIN",
+ N_( L"Stop from terminal input" )
+ }
+ ,
#endif
#ifdef SIGTTOU
- {
- SIGTTOU,
- L"SIGTTOU",
- N_( L"Stop from terminal output" )
- }
- ,
+ {
+ SIGTTOU,
+ L"SIGTTOU",
+ N_( L"Stop from terminal output" )
+ }
+ ,
#endif
#ifdef SIGURG
- {
- SIGURG,
- L"SIGURG",
- N_( L"Urgent socket condition" )
- }
- ,
+ {
+ SIGURG,
+ L"SIGURG",
+ N_( L"Urgent socket condition" )
+ }
+ ,
#endif
#ifdef SIGXCPU
- {
- SIGXCPU,
- L"SIGXCPU",
- N_( L"CPU time limit exceeded" )
- }
- ,
+ {
+ SIGXCPU,
+ L"SIGXCPU",
+ N_( L"CPU time limit exceeded" )
+ }
+ ,
#endif
#ifdef SIGXFSZ
- {
- SIGXFSZ,
- L"SIGXFSZ",
- N_( L"File size limit exceeded" )
- }
- ,
+ {
+ SIGXFSZ,
+ L"SIGXFSZ",
+ N_( L"File size limit exceeded" )
+ }
+ ,
#endif
#ifdef SIGVTALRM
- {
- SIGVTALRM,
- L"SIGVTALRM",
- N_( L"Virtual timer expired" )
- }
- ,
+ {
+ SIGVTALRM,
+ L"SIGVTALRM",
+ N_( L"Virtual timer expired" )
+ }
+ ,
#endif
#ifdef SIGPROF
- {
- SIGPROF,
- L"SIGPROF",
- N_( L"Profiling timer expired" )
- }
- ,
+ {
+ SIGPROF,
+ L"SIGPROF",
+ N_( L"Profiling timer expired" )
+ }
+ ,
#endif
#ifdef SIGWINCH
- {
- SIGWINCH,
- L"SIGWINCH",
- N_( L"Window size change" )
- }
- ,
+ {
+ SIGWINCH,
+ L"SIGWINCH",
+ N_( L"Window size change" )
+ }
+ ,
#endif
#ifdef SIGWIND
- {
- SIGWIND,
- L"SIGWIND",
- N_( L"Window size change" )
- }
- ,
+ {
+ SIGWIND,
+ L"SIGWIND",
+ N_( L"Window size change" )
+ }
+ ,
#endif
#ifdef SIGIO
- {
- SIGIO,
- L"SIGIO",
- N_( L"I/O on asynchronous file descriptor is possible" )
- }
- ,
+ {
+ SIGIO,
+ L"SIGIO",
+ N_( L"I/O on asynchronous file descriptor is possible" )
+ }
+ ,
#endif
#ifdef SIGPWR
- {
- SIGPWR,
- L"SIGPWR",
- N_( L"Power failure" )
- }
- ,
+ {
+ SIGPWR,
+ L"SIGPWR",
+ N_( L"Power failure" )
+ }
+ ,
#endif
#ifdef SIGSYS
- {
- SIGSYS,
- L"SIGSYS",
- N_( L"Bad system call" )
- }
- ,
+ {
+ SIGSYS,
+ L"SIGSYS",
+ N_( L"Bad system call" )
+ }
+ ,
#endif
#ifdef SIGINFO
- {
- SIGINFO,
- L"SIGINFO",
- N_( L"Information request" )
- }
- ,
+ {
+ SIGINFO,
+ L"SIGINFO",
+ N_( L"Information request" )
+ }
+ ,
#endif
#ifdef SIGSTKFLT
- {
- SIGSTKFLT,
- L"SISTKFLT",
- N_( L"Stack fault" )
- }
- ,
+ {
+ SIGSTKFLT,
+ L"SISTKFLT",
+ N_( L"Stack fault" )
+ }
+ ,
#endif
#ifdef SIGEMT
- {
- SIGEMT,
- L"SIGEMT",
- N_( L"Emulator trap" )
- }
- ,
+ {
+ SIGEMT,
+ L"SIGEMT",
+ N_( L"Emulator trap" )
+ }
+ ,
#endif
#ifdef SIGIOT
- {
- SIGIOT,
- L"SIGIOT",
- N_( L"Abort (Alias for SIGABRT)" )
- }
- ,
+ {
+ SIGIOT,
+ L"SIGIOT",
+ N_( L"Abort (Alias for SIGABRT)" )
+ }
+ ,
#endif
#ifdef SIGUNUSED
- {
- SIGUNUSED,
- L"SIGUNUSED",
- N_( L"Unused signal" )
- }
- ,
-#endif
- {
- 0,
- 0,
- 0
- }
+ {
+ SIGUNUSED,
+ L"SIGUNUSED",
+ N_( L"Unused signal" )
+ }
+ ,
+#endif
+ {
+ 0,
+ 0,
+ 0
+ }
}
- ;
+ ;
/**
- Test if \c name is a string describing the signal named \c canonical.
+ Test if \c name is a string describing the signal named \c canonical.
*/
-static int match_signal_name( const wchar_t *canonical,
- const wchar_t *name )
+static int match_signal_name( const wchar_t *canonical,
+ const wchar_t *name )
{
- if( wcsncasecmp( name, L"sig", 3 )==0)
- name +=3;
+ if( wcsncasecmp( name, L"sig", 3 )==0)
+ name +=3;
- return wcscasecmp( canonical+3,name ) == 0;
+ return wcscasecmp( canonical+3,name ) == 0;
}
int wcs2sig( const wchar_t *str )
{
- int i;
- wchar_t *end=0;
-
- for( i=0; lookup[i].desc ; i++ )
- {
- if( match_signal_name( lookup[i].name, str) )
- {
- return lookup[i].signal;
- }
- }
- errno=0;
- int res = fish_wcstoi( str, &end, 10 );
- if( !errno && res>=0 && !*end )
- return res;
-
- return -1;
+ int i;
+ wchar_t *end=0;
+
+ for( i=0; lookup[i].desc ; i++ )
+ {
+ if( match_signal_name( lookup[i].name, str) )
+ {
+ return lookup[i].signal;
+ }
+ }
+ errno=0;
+ int res = fish_wcstoi( str, &end, 10 );
+ if( !errno && res>=0 && !*end )
+ return res;
+
+ return -1;
}
const wchar_t *sig2wcs( int sig )
{
- int i;
+ int i;
- for( i=0; lookup[i].desc ; i++ )
- {
- if( lookup[i].signal == sig )
- {
- return lookup[i].name;
- }
- }
+ for( i=0; lookup[i].desc ; i++ )
+ {
+ if( lookup[i].signal == sig )
+ {
+ return lookup[i].name;
+ }
+ }
- return _(L"Unknown");
+ return _(L"Unknown");
}
const wchar_t *signal_get_desc( int sig )
{
- int i;
+ int i;
- for( i=0; lookup[i].desc ; i++ )
- {
- if( lookup[i].signal == sig )
- {
- return _(lookup[i].desc);
- }
- }
+ for( i=0; lookup[i].desc ; i++ )
+ {
+ if( lookup[i].signal == sig )
+ {
+ return _(lookup[i].desc);
+ }
+ }
- return _(L"Unknown");
+ return _(L"Unknown");
}
/**
@@ -429,8 +429,8 @@ static void default_handler(int signal, siginfo_t *info, void *context)
{
if (event_is_signal_observed(signal))
{
- event_fire_signal(signal);
- }
+ event_fire_signal(signal);
+ }
}
/**
@@ -438,8 +438,8 @@ static void default_handler(int signal, siginfo_t *info, void *context)
*/
static void handle_winch( int sig, siginfo_t *info, void *context )
{
- common_handle_winch( sig );
- default_handler( sig, 0, 0 );
+ common_handle_winch( sig );
+ default_handler( sig, 0, 0 );
}
/**
@@ -448,14 +448,14 @@ static void handle_winch( int sig, siginfo_t *info, void *context )
*/
static void handle_hup( int sig, siginfo_t *info, void *context )
{
- if (event_is_signal_observed(SIGHUP))
- {
- default_handler(sig, 0, 0);
- }
- else
- {
- reader_exit(1, 1);
- }
+ if (event_is_signal_observed(SIGHUP))
+ {
+ default_handler(sig, 0, 0);
+ }
+ else
+ {
+ reader_exit(1, 1);
+ }
}
/**
@@ -464,8 +464,8 @@ static void handle_hup( int sig, siginfo_t *info, void *context )
*/
static void handle_int( int sig, siginfo_t *info, void *context )
{
- reader_handle_int( sig );
- default_handler( sig, info, context);
+ reader_handle_int( sig );
+ default_handler( sig, info, context);
}
/**
@@ -473,23 +473,23 @@ static void handle_int( int sig, siginfo_t *info, void *context )
*/
static void handle_chld( int sig, siginfo_t *info, void *context )
{
- job_handle_signal( sig, info, context );
- default_handler( sig, info, context);
+ job_handle_signal( sig, info, context );
+ default_handler( sig, info, context);
}
void signal_reset_handlers()
{
- int i;
-
- struct sigaction act;
- sigemptyset( & act.sa_mask );
- act.sa_flags=0;
- act.sa_handler=SIG_DFL;
-
- for( i=0; lookup[i].desc ; i++ )
- {
- sigaction( lookup[i].signal, &act, 0);
- }
+ int i;
+
+ struct sigaction act;
+ sigemptyset( & act.sa_mask );
+ act.sa_flags=0;
+ act.sa_handler=SIG_DFL;
+
+ for( i=0; lookup[i].desc ; i++ )
+ {
+ sigaction( lookup[i].signal, &act, 0);
+ }
}
@@ -498,187 +498,187 @@ void signal_reset_handlers()
*/
void signal_set_handlers()
{
- struct sigaction act;
-
- if( get_is_interactive() == -1 )
- return;
-
- sigemptyset( & act.sa_mask );
- act.sa_flags=SA_SIGINFO;
- act.sa_sigaction = &default_handler;
-
- /*
- First reset everything to a use default_handler, a function
- whose sole action is to fire of an event
- */
- sigaction( SIGINT, &act, 0);
- sigaction( SIGQUIT, &act, 0);
- sigaction( SIGTSTP, &act, 0);
- sigaction( SIGTTIN, &act, 0);
- sigaction( SIGTTOU, &act, 0);
- sigaction( SIGCHLD, &act, 0);
-
- /*
- Ignore sigpipe, it is generated if fishd dies, but we can
- recover.
- */
- sigaction( SIGPIPE, &act, 0);
-
- if( get_is_interactive() )
- {
- /*
- Interactive mode. Ignore interactive signals. We are a
- shell, we know whats best for the user. ;-)
- */
-
- act.sa_handler=SIG_IGN;
-
- sigaction( SIGINT, &act, 0);
- sigaction( SIGQUIT, &act, 0);
- sigaction( SIGTSTP, &act, 0);
- sigaction( SIGTTIN, &act, 0);
- sigaction( SIGTTOU, &act, 0);
-
- act.sa_sigaction = &handle_int;
- act.sa_flags = SA_SIGINFO;
- if( sigaction( SIGINT, &act, 0) )
- {
- wperror( L"sigaction" );
- FATAL_EXIT();
- }
-
- act.sa_sigaction = &handle_chld;
- act.sa_flags = SA_SIGINFO;
- if( sigaction( SIGCHLD, &act, 0) )
- {
- wperror( L"sigaction" );
- FATAL_EXIT();
- }
-
+ struct sigaction act;
+
+ if( get_is_interactive() == -1 )
+ return;
+
+ sigemptyset( & act.sa_mask );
+ act.sa_flags=SA_SIGINFO;
+ act.sa_sigaction = &default_handler;
+
+ /*
+ First reset everything to a use default_handler, a function
+ whose sole action is to fire of an event
+ */
+ sigaction( SIGINT, &act, 0);
+ sigaction( SIGQUIT, &act, 0);
+ sigaction( SIGTSTP, &act, 0);
+ sigaction( SIGTTIN, &act, 0);
+ sigaction( SIGTTOU, &act, 0);
+ sigaction( SIGCHLD, &act, 0);
+
+ /*
+ Ignore sigpipe, it is generated if fishd dies, but we can
+ recover.
+ */
+ sigaction( SIGPIPE, &act, 0);
+
+ if( get_is_interactive() )
+ {
+ /*
+ Interactive mode. Ignore interactive signals. We are a
+ shell, we know whats best for the user. ;-)
+ */
+
+ act.sa_handler=SIG_IGN;
+
+ sigaction( SIGINT, &act, 0);
+ sigaction( SIGQUIT, &act, 0);
+ sigaction( SIGTSTP, &act, 0);
+ sigaction( SIGTTIN, &act, 0);
+ sigaction( SIGTTOU, &act, 0);
+
+ act.sa_sigaction = &handle_int;
+ act.sa_flags = SA_SIGINFO;
+ if( sigaction( SIGINT, &act, 0) )
+ {
+ wperror( L"sigaction" );
+ FATAL_EXIT();
+ }
+
+ act.sa_sigaction = &handle_chld;
+ act.sa_flags = SA_SIGINFO;
+ if( sigaction( SIGCHLD, &act, 0) )
+ {
+ wperror( L"sigaction" );
+ FATAL_EXIT();
+ }
+
#ifdef SIGWINCH
- act.sa_flags = SA_SIGINFO;
- act.sa_sigaction= &handle_winch;
- if( sigaction( SIGWINCH, &act, 0 ) )
- {
- wperror( L"sigaction" );
- FATAL_EXIT();
- }
-#endif
-
- act.sa_flags = SA_SIGINFO;
- act.sa_sigaction= &handle_hup;
- if( sigaction( SIGHUP, &act, 0 ) )
- {
- wperror( L"sigaction" );
- FATAL_EXIT();
- }
-
- }
- else
- {
- /*
- Non-interactive. Ignore interrupt, check exit status of
- processes to determine result instead.
- */
- act.sa_handler=SIG_IGN;
-
- sigaction( SIGINT, &act, 0);
- sigaction( SIGQUIT, &act, 0);
-
- act.sa_handler=SIG_DFL;
-
- act.sa_sigaction = &handle_chld;
- act.sa_flags = SA_SIGINFO;
- if( sigaction( SIGCHLD, &act, 0) )
- {
- wperror( L"sigaction" );
- exit_without_destructors(1);
- }
- }
-
+ act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction= &handle_winch;
+ if( sigaction( SIGWINCH, &act, 0 ) )
+ {
+ wperror( L"sigaction" );
+ FATAL_EXIT();
+ }
+#endif
+
+ act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction= &handle_hup;
+ if( sigaction( SIGHUP, &act, 0 ) )
+ {
+ wperror( L"sigaction" );
+ FATAL_EXIT();
+ }
+
+ }
+ else
+ {
+ /*
+ Non-interactive. Ignore interrupt, check exit status of
+ processes to determine result instead.
+ */
+ act.sa_handler=SIG_IGN;
+
+ sigaction( SIGINT, &act, 0);
+ sigaction( SIGQUIT, &act, 0);
+
+ act.sa_handler=SIG_DFL;
+
+ act.sa_sigaction = &handle_chld;
+ act.sa_flags = SA_SIGINFO;
+ if( sigaction( SIGCHLD, &act, 0) )
+ {
+ wperror( L"sigaction" );
+ exit_without_destructors(1);
+ }
+ }
+
}
void signal_handle( int sig, int do_handle )
{
- struct sigaction act;
-
- /*
- These should always be handled
- */
- if( (sig == SIGINT) ||
- (sig == SIGQUIT) ||
- (sig == SIGTSTP) ||
- (sig == SIGTTIN) ||
- (sig == SIGTTOU) ||
- (sig == SIGCHLD) )
- return;
-
- sigemptyset( &act.sa_mask );
- if( do_handle )
- {
- act.sa_flags = SA_SIGINFO;
- act.sa_sigaction = &default_handler;
- }
- else
- {
- act.sa_flags = 0;
- act.sa_handler = SIG_DFL;
- }
-
- sigaction( sig, &act, 0);
+ struct sigaction act;
+
+ /*
+ These should always be handled
+ */
+ if( (sig == SIGINT) ||
+ (sig == SIGQUIT) ||
+ (sig == SIGTSTP) ||
+ (sig == SIGTTIN) ||
+ (sig == SIGTTOU) ||
+ (sig == SIGCHLD) )
+ return;
+
+ sigemptyset( &act.sa_mask );
+ if( do_handle )
+ {
+ act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = &default_handler;
+ }
+ else
+ {
+ act.sa_flags = 0;
+ act.sa_handler = SIG_DFL;
+ }
+
+ sigaction( sig, &act, 0);
}
void get_signals_with_handlers(sigset_t *set)
{
sigemptyset(set);
- for( int i=0; lookup[i].desc ; i++ )
- {
+ for( int i=0; lookup[i].desc ; i++ )
+ {
struct sigaction act = {};
- sigaction(lookup[i].signal, NULL, &act);
+ sigaction(lookup[i].signal, NULL, &act);
if (act.sa_handler != SIG_DFL)
sigaddset(set, lookup[i].signal);
- }
+ }
}
void signal_block()
{
ASSERT_IS_MAIN_THREAD();
- sigset_t chldset;
-
- if( !block_count )
- {
- sigfillset( &chldset );
- VOMIT_ON_FAILURE(pthread_sigmask(SIG_BLOCK, &chldset, NULL));
- }
-
- block_count++;
-// debug( 0, L"signal block level increased to %d", block_count );
+ sigset_t chldset;
+
+ if( !block_count )
+ {
+ sigfillset( &chldset );
+ VOMIT_ON_FAILURE(pthread_sigmask(SIG_BLOCK, &chldset, NULL));
+ }
+
+ block_count++;
+// debug( 0, L"signal block level increased to %d", block_count );
}
void signal_unblock()
{
ASSERT_IS_MAIN_THREAD();
- sigset_t chldset;
-
- block_count--;
-
- if( block_count < 0 )
- {
- debug( 0, _( L"Signal block mismatch" ) );
- bugreport();
- FATAL_EXIT();
- }
-
- if( !block_count )
- {
- sigfillset( &chldset );
- VOMIT_ON_FAILURE(pthread_sigmask(SIG_UNBLOCK, &chldset, 0));
- }
-// debug( 0, L"signal block level decreased to %d", block_count );
+ sigset_t chldset;
+
+ block_count--;
+
+ if( block_count < 0 )
+ {
+ debug( 0, _( L"Signal block mismatch" ) );
+ bugreport();
+ FATAL_EXIT();
+ }
+
+ if( !block_count )
+ {
+ sigfillset( &chldset );
+ VOMIT_ON_FAILURE(pthread_sigmask(SIG_UNBLOCK, &chldset, 0));
+ }
+// debug( 0, L"signal block level decreased to %d", block_count );
}
int signal_is_blocked()
{
- return !!block_count;
+ return !!block_count;
}
diff --git a/tokenizer.cpp b/tokenizer.cpp
index 5af71bf9..537f1332 100644
--- a/tokenizer.cpp
+++ b/tokenizer.cpp
@@ -61,21 +61,21 @@ segments.
*/
static const wchar_t *tok_desc[] =
{
- N_(L"Tokenizer not yet initialized"),
- N_( L"Tokenizer error" ),
- N_( L"Invalid token" ),
- N_( L"String" ),
- N_( L"Pipe" ),
- N_( L"End of command" ),
- N_( L"Redirect output to file" ),
- N_( L"Append output to file" ),
- N_( L"Redirect input to file" ),
- N_( L"Redirect to file descriptor" ),
- N_( L"Redirect output to file if file does not exist" ),
- N_( L"Run job in background" ),
- N_( L"Comment" )
+ N_(L"Tokenizer not yet initialized"),
+ N_( L"Tokenizer error" ),
+ N_( L"Invalid token" ),
+ N_( L"String" ),
+ N_( L"Pipe" ),
+ N_( L"End of command" ),
+ N_( L"Redirect output to file" ),
+ N_( L"Append output to file" ),
+ N_( L"Redirect input to file" ),
+ N_( L"Redirect to file descriptor" ),
+ N_( L"Redirect output to file if file does not exist" ),
+ N_( L"Run job in background" ),
+ N_( L"Comment" )
}
- ;
+ ;
/**
Tests if the tokenizer buffer is large enough to hold contents of
@@ -85,19 +85,19 @@ static const wchar_t *tok_desc[] =
*/
static int check_size( tokenizer *tok, size_t len )
{
- if( tok->last_len <= len )
- {
- wchar_t *tmp;
- tok->last_len = len +1;
- tmp = (wchar_t *)realloc( tok->last, sizeof(wchar_t)*tok->last_len );
- if( tmp == 0 )
- {
- wperror( L"realloc" );
- return 0;
- }
- tok->last = tmp;
- }
- return 1;
+ if( tok->last_len <= len )
+ {
+ wchar_t *tmp;
+ tok->last_len = len +1;
+ tmp = (wchar_t *)realloc( tok->last, sizeof(wchar_t)*tok->last_len );
+ if( tmp == 0 )
+ {
+ wperror( L"realloc" );
+ return 0;
+ }
+ tok->last = tmp;
+ }
+ return 1;
}
/**
@@ -105,21 +105,21 @@ static int check_size( tokenizer *tok, size_t len )
*/
static void tok_call_error( tokenizer *tok, int error_type, const wchar_t *error_message )
{
- tok->last_type = TOK_ERROR;
- tok->error = error_type;
- if( !check_size( tok, wcslen( error_message)+1 ))
- {
- if( tok->last != 0 )
- *tok->last=0;
- return;
- }
-
- wcscpy( tok->last, error_message );
+ tok->last_type = TOK_ERROR;
+ tok->error = error_type;
+ if( !check_size( tok, wcslen( error_message)+1 ))
+ {
+ if( tok->last != 0 )
+ *tok->last=0;
+ return;
+ }
+
+ wcscpy( tok->last, error_message );
}
int tok_get_error( tokenizer *tok )
{
- return tok->error;
+ return tok->error;
}
@@ -130,58 +130,58 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
if (! (flags & TOK_SQUASH_ERRORS)) {
ASSERT_IS_MAIN_THREAD();
}
-
- CHECK( tok, );
- memset( tok, 0, sizeof( tokenizer) );
+ CHECK( tok, );
+
+ memset( tok, 0, sizeof( tokenizer) );
- CHECK( b, );
+ CHECK( b, );
- tok->accept_unfinished = !! (flags & TOK_ACCEPT_UNFINISHED);
- tok->show_comments = !! (flags & TOK_SHOW_COMMENTS);
+ tok->accept_unfinished = !! (flags & TOK_ACCEPT_UNFINISHED);
+ tok->show_comments = !! (flags & TOK_SHOW_COMMENTS);
tok->squash_errors = !! (flags & TOK_SQUASH_ERRORS);
- tok->has_next=true;
+ tok->has_next=true;
- tok->has_next = (*b != L'\0');
- tok->orig_buff = tok->buff = b;
+ tok->has_next = (*b != L'\0');
+ tok->orig_buff = tok->buff = b;
tok->cached_lineno_offset = 0;
tok->cached_lineno_count = 0;
- tok_next( tok );
+ tok_next( tok );
}
void tok_destroy( tokenizer *tok )
{
- CHECK( tok, );
-
- free( tok->last );
+ CHECK( tok, );
+
+ free( tok->last );
}
int tok_last_type( tokenizer *tok )
{
- CHECK( tok, TOK_ERROR );
- CHECK( tok->buff, TOK_ERROR );
-
- return tok->last_type;
+ CHECK( tok, TOK_ERROR );
+ CHECK( tok->buff, TOK_ERROR );
+
+ return tok->last_type;
}
wchar_t *tok_last( tokenizer *tok )
{
- CHECK( tok, 0 );
-
- return tok->last;
+ CHECK( tok, 0 );
+
+ return tok->last;
}
int tok_has_next( tokenizer *tok )
{
- /*
- Return 1 on broken tokenizer
- */
- CHECK( tok, 1 );
- CHECK( tok->buff, 1 );
-
-/* fwprintf( stderr, L"has_next is %ls \n", tok->has_next?L"true":L"false" );*/
- return tok->has_next;
+ /*
+ Return 1 on broken tokenizer
+ */
+ CHECK( tok, 1 );
+ CHECK( tok->buff, 1 );
+
+/* fwprintf( stderr, L"has_next is %ls \n", tok->has_next?L"true":L"false" );*/
+ return tok->has_next;
}
int tokenizer::line_number_of_character_at_offset(size_t offset)
@@ -189,13 +189,13 @@ int tokenizer::line_number_of_character_at_offset(size_t offset)
// we want to return (one plus) the number of newlines at offsets less than the given offset
// cached_lineno_count is the number of newlines at indexes less than cached_lineno_offset
const wchar_t *str = orig_buff;
- if (! str)
- return 0;
-
+ if (! str)
+ return 0;
+
// easy hack to handle 0
if (offset == 0)
return 1;
-
+
size_t i;
if (offset > cached_lineno_offset)
{
@@ -217,7 +217,7 @@ int tokenizer::line_number_of_character_at_offset(size_t offset)
}
cached_lineno_offset = offset;
}
- return cached_lineno_count + 1;
+ return cached_lineno_count + 1;
}
/**
@@ -240,14 +240,14 @@ static bool is_string_char( wchar_t c, bool is_first )
case L'>':
case L'&':
return false;
-
+
/* Conditional separator */
case L'^':
return ! is_first;
-
+
default:
return true;
-
+
}
}
@@ -259,7 +259,7 @@ static bool is_string_char( wchar_t c, bool is_first )
*/
static int myal( wchar_t c )
{
- return (c>=L'a' && c<=L'z') || (c>=L'A'&&c<=L'Z');
+ return (c>=L'a' && c<=L'z') || (c>=L'A'&&c<=L'Z');
}
/**
@@ -267,199 +267,199 @@ static int myal( wchar_t c )
*/
static void read_string( tokenizer *tok )
{
- const wchar_t *start;
- long len;
- int mode=0;
- int do_loop=1;
- int paran_count=0;
+ const wchar_t *start;
+ long len;
+ int mode=0;
+ int do_loop=1;
+ int paran_count=0;
- start = tok->buff;
+ start = tok->buff;
bool is_first = true;
-
- while( 1 )
- {
-
- if( !myal( *tok->buff ) )
- {
-// debug(1, L"%lc", *tok->buff );
-
- if( *tok->buff == L'\\' )
- {
- tok->buff++;
- if( *tok->buff == L'\0' )
- {
- if( (!tok->accept_unfinished) )
- {
- TOK_CALL_ERROR( tok, TOK_UNTERMINATED_ESCAPE, QUOTE_ERROR );
- return;
- }
- else
- {
- do_loop = 0;
- }
-
-
- }
- else if( *tok->buff == L'\n' && mode == 0)
- {
- tok->buff--;
- do_loop = 0;
- break;
- }
-
- tok->buff++;
- continue;
- }
-
-
- /*
- The modes are as follows:
-
- 0: regular text
- 1: inside of subshell
- 2: inside of array brackets
- 3: inside of array brackets and subshell, like in '$foo[(ech'
- */
- switch( mode )
- {
- case 0:
- {
- switch( *tok->buff )
- {
- case L'(':
- {
- paran_count=1;
- mode = 1;
- break;
- }
-
- case L'[':
- {
- if( tok->buff != start )
- mode=2;
- break;
- }
-
- case L'\'':
- case L'"':
- {
-
- const wchar_t *end = quote_end( tok->buff );
- tok->last_quote = *tok->buff;
- if( end )
- {
- tok->buff=(wchar_t *)end;
- }
- else
- {
- tok->buff += wcslen( tok->buff );
-
- if( (!tok->accept_unfinished) )
- {
- TOK_CALL_ERROR( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR );
- return;
- }
- do_loop = 0;
-
- }
- break;
- }
-
- default:
- {
- if( !is_string_char(*(tok->buff), is_first) )
- {
- do_loop=0;
- }
- }
- }
- break;
- }
-
- case 3:
- case 1:
- switch( *tok->buff )
- {
- case L'\'':
- case L'\"':
- {
- const wchar_t *end = quote_end( tok->buff );
- if( end )
- {
- tok->buff=(wchar_t *)end;
- }
- else
- {
- tok->buff += wcslen( tok->buff );
- if( (!tok->accept_unfinished) )
- {
- TOK_CALL_ERROR( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR );
- return;
- }
- do_loop = 0;
- }
-
- break;
- }
-
- case L'(':
- paran_count++;
- break;
- case L')':
- paran_count--;
- if( paran_count == 0 )
- {
- mode--;
- }
- break;
- case L'\0':
- do_loop = 0;
- break;
- }
- break;
- case 2:
- switch( *tok->buff )
- {
- case L'(':
- paran_count=1;
- mode = 3;
- break;
-
- case L']':
- mode=0;
- break;
-
- case L'\0':
- do_loop = 0;
- break;
- }
- break;
- }
- }
-
-
- if( !do_loop )
- break;
-
- tok->buff++;
+
+ while( 1 )
+ {
+
+ if( !myal( *tok->buff ) )
+ {
+// debug(1, L"%lc", *tok->buff );
+
+ if( *tok->buff == L'\\' )
+ {
+ tok->buff++;
+ if( *tok->buff == L'\0' )
+ {
+ if( (!tok->accept_unfinished) )
+ {
+ TOK_CALL_ERROR( tok, TOK_UNTERMINATED_ESCAPE, QUOTE_ERROR );
+ return;
+ }
+ else
+ {
+ do_loop = 0;
+ }
+
+
+ }
+ else if( *tok->buff == L'\n' && mode == 0)
+ {
+ tok->buff--;
+ do_loop = 0;
+ break;
+ }
+
+ tok->buff++;
+ continue;
+ }
+
+
+ /*
+ The modes are as follows:
+
+ 0: regular text
+ 1: inside of subshell
+ 2: inside of array brackets
+ 3: inside of array brackets and subshell, like in '$foo[(ech'
+ */
+ switch( mode )
+ {
+ case 0:
+ {
+ switch( *tok->buff )
+ {
+ case L'(':
+ {
+ paran_count=1;
+ mode = 1;
+ break;
+ }
+
+ case L'[':
+ {
+ if( tok->buff != start )
+ mode=2;
+ break;
+ }
+
+ case L'\'':
+ case L'"':
+ {
+
+ const wchar_t *end = quote_end( tok->buff );
+ tok->last_quote = *tok->buff;
+ if( end )
+ {
+ tok->buff=(wchar_t *)end;
+ }
+ else
+ {
+ tok->buff += wcslen( tok->buff );
+
+ if( (!tok->accept_unfinished) )
+ {
+ TOK_CALL_ERROR( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR );
+ return;
+ }
+ do_loop = 0;
+
+ }
+ break;
+ }
+
+ default:
+ {
+ if( !is_string_char(*(tok->buff), is_first) )
+ {
+ do_loop=0;
+ }
+ }
+ }
+ break;
+ }
+
+ case 3:
+ case 1:
+ switch( *tok->buff )
+ {
+ case L'\'':
+ case L'\"':
+ {
+ const wchar_t *end = quote_end( tok->buff );
+ if( end )
+ {
+ tok->buff=(wchar_t *)end;
+ }
+ else
+ {
+ tok->buff += wcslen( tok->buff );
+ if( (!tok->accept_unfinished) )
+ {
+ TOK_CALL_ERROR( tok, TOK_UNTERMINATED_QUOTE, QUOTE_ERROR );
+ return;
+ }
+ do_loop = 0;
+ }
+
+ break;
+ }
+
+ case L'(':
+ paran_count++;
+ break;
+ case L')':
+ paran_count--;
+ if( paran_count == 0 )
+ {
+ mode--;
+ }
+ break;
+ case L'\0':
+ do_loop = 0;
+ break;
+ }
+ break;
+ case 2:
+ switch( *tok->buff )
+ {
+ case L'(':
+ paran_count=1;
+ mode = 3;
+ break;
+
+ case L']':
+ mode=0;
+ break;
+
+ case L'\0':
+ do_loop = 0;
+ break;
+ }
+ break;
+ }
+ }
+
+
+ if( !do_loop )
+ break;
+
+ tok->buff++;
is_first = false;
- }
+ }
- if( (!tok->accept_unfinished) && (mode!=0) )
- {
- TOK_CALL_ERROR( tok, TOK_UNTERMINATED_SUBSHELL, PARAN_ERROR );
- return;
- }
+ if( (!tok->accept_unfinished) && (mode!=0) )
+ {
+ TOK_CALL_ERROR( tok, TOK_UNTERMINATED_SUBSHELL, PARAN_ERROR );
+ return;
+ }
- len = tok->buff - start;
+ len = tok->buff - start;
- if( !check_size( tok, len ))
- return;
+ if( !check_size( tok, len ))
+ return;
- memcpy( tok->last, start, sizeof(wchar_t)*len );
- tok->last[len] = L'\0';
- tok->last_type = TOK_STRING;
+ memcpy( tok->last, start, sizeof(wchar_t)*len );
+ tok->last[len] = L'\0';
+ tok->last_type = TOK_STRING;
}
/**
@@ -467,19 +467,19 @@ static void read_string( tokenizer *tok )
*/
static void read_comment( tokenizer *tok )
{
- const wchar_t *start;
+ const wchar_t *start;
- start = tok->buff;
- while( *(tok->buff)!= L'\n' && *(tok->buff)!= L'\0' )
- tok->buff++;
+ start = tok->buff;
+ while( *(tok->buff)!= L'\n' && *(tok->buff)!= L'\0' )
+ tok->buff++;
- size_t len = tok->buff - start;
- if( !check_size( tok, len ))
- return;
+ size_t len = tok->buff - start;
+ if( !check_size( tok, len ))
+ return;
- memcpy( tok->last, start, sizeof(wchar_t)*len );
- tok->last[len] = L'\0';
- tok->last_type = TOK_COMMENT;
+ memcpy( tok->last, start, sizeof(wchar_t)*len );
+ tok->last[len] = L'\0';
+ tok->last_type = TOK_COMMENT;
}
/**
@@ -487,74 +487,74 @@ static void read_comment( tokenizer *tok )
*/
static void read_redirect( tokenizer *tok, int fd )
{
- int mode = -1;
-
- if( (*tok->buff == L'>') ||
- (*tok->buff == L'^') )
- {
- tok->buff++;
- if( *tok->buff == *(tok->buff-1) )
- {
- tok->buff++;
- mode = 1;
- }
- else
- {
- mode = 0;
- }
-
- if( *tok->buff == L'|' )
- {
- if( fd == 0 )
- {
- TOK_CALL_ERROR( tok, TOK_OTHER, PIPE_ERROR );
- return;
- }
- check_size( tok, FD_STR_MAX_LEN );
- tok->buff++;
- swprintf( tok->last, FD_STR_MAX_LEN, L"%d", fd );
- tok->last_type = TOK_PIPE;
- return;
- }
- }
- else if( *tok->buff == L'<' )
- {
- tok->buff++;
- mode = 2;
- }
- else
- {
- TOK_CALL_ERROR( tok, TOK_OTHER, REDIRECT_ERROR);
- }
-
- if( !check_size( tok, 2 ))
- {
- return;
- }
-
- swprintf( tok->last, tok->last_len, L"%d", fd );
-
- if( *tok->buff == L'&' )
- {
- tok->buff++;
- tok->last_type = TOK_REDIRECT_FD;
- }
- else if( *tok->buff == L'?' )
- {
- tok->buff++;
- tok->last_type = TOK_REDIRECT_NOCLOB;
- }
- else
- {
- tok->last_type = TOK_REDIRECT_OUT + mode;
- }
+ int mode = -1;
+
+ if( (*tok->buff == L'>') ||
+ (*tok->buff == L'^') )
+ {
+ tok->buff++;
+ if( *tok->buff == *(tok->buff-1) )
+ {
+ tok->buff++;
+ mode = 1;
+ }
+ else
+ {
+ mode = 0;
+ }
+
+ if( *tok->buff == L'|' )
+ {
+ if( fd == 0 )
+ {
+ TOK_CALL_ERROR( tok, TOK_OTHER, PIPE_ERROR );
+ return;
+ }
+ check_size( tok, FD_STR_MAX_LEN );
+ tok->buff++;
+ swprintf( tok->last, FD_STR_MAX_LEN, L"%d", fd );
+ tok->last_type = TOK_PIPE;
+ return;
+ }
+ }
+ else if( *tok->buff == L'<' )
+ {
+ tok->buff++;
+ mode = 2;
+ }
+ else
+ {
+ TOK_CALL_ERROR( tok, TOK_OTHER, REDIRECT_ERROR);
+ }
+
+ if( !check_size( tok, 2 ))
+ {
+ return;
+ }
+
+ swprintf( tok->last, tok->last_len, L"%d", fd );
+
+ if( *tok->buff == L'&' )
+ {
+ tok->buff++;
+ tok->last_type = TOK_REDIRECT_FD;
+ }
+ else if( *tok->buff == L'?' )
+ {
+ tok->buff++;
+ tok->last_type = TOK_REDIRECT_NOCLOB;
+ }
+ else
+ {
+ tok->last_type = TOK_REDIRECT_OUT + mode;
+ }
}
wchar_t tok_last_quote( tokenizer *tok )
{
- CHECK( tok, 0 );
-
- return tok->last_quote;
+ CHECK( tok, 0 );
+
+ return tok->last_quote;
}
/**
@@ -563,189 +563,189 @@ wchar_t tok_last_quote( tokenizer *tok )
*/
static int my_iswspace( wchar_t c )
{
- if( c == L'\n' )
- return 0;
- else
- return iswspace( c );
+ if( c == L'\n' )
+ return 0;
+ else
+ return iswspace( c );
}
const wchar_t *tok_get_desc( int type )
{
- if( type < 0 || (size_t)type >= sizeof( tok_desc ) )
- {
- return _(L"Invalid token type");
- }
- return _(tok_desc[type]);
+ if( type < 0 || (size_t)type >= sizeof( tok_desc ) )
+ {
+ return _(L"Invalid token type");
+ }
+ return _(tok_desc[type]);
}
void tok_next( tokenizer *tok )
{
- CHECK( tok, );
- CHECK( tok->buff, );
-
- if( tok_last_type( tok ) == TOK_ERROR )
- {
- tok->has_next=false;
- return;
- }
-
- if( !tok->has_next )
- {
-/* wprintf( L"EOL\n" );*/
- tok->last_type = TOK_END;
- return;
- }
-
- while( 1 )
- {
- if( my_iswspace(*(tok->buff) ) )
- {
- tok->buff++;
- }
- else
- {
- if(( *(tok->buff) == L'\\') &&( *(tok->buff+1) == L'\n') )
- {
- tok->last_pos = tok->buff - tok->orig_buff;
- tok->buff+=2;
- tok->last_type = TOK_END;
- return;
- }
- break;
- }
- }
-
-
- if( *tok->buff == L'#')
- {
- if( tok->show_comments )
- {
- tok->last_pos = tok->buff - tok->orig_buff;
- read_comment( tok );
- return;
- }
- else
- {
- while( *(tok->buff)!= L'\n' && *(tok->buff)!= L'\0' )
- tok->buff++;
- }
-
- while( my_iswspace(*(tok->buff) ) )
- tok->buff++;
- }
-
- tok->last_pos = tok->buff - tok->orig_buff;
-
- switch( *tok->buff )
- {
-
- case L'\0':
- tok->last_type = TOK_END;
- /*fwprintf( stderr, L"End of string\n" );*/
- tok->has_next = false;
- break;
- case 13:
- case L'\n':
- case L';':
- tok->last_type = TOK_END;
- tok->buff++;
- break;
- case L'&':
- tok->last_type = TOK_BACKGROUND;
- tok->buff++;
- break;
-
- case L'|':
- check_size( tok, 2 );
-
- tok->last[0]=L'1';
- tok->last[1]=L'\0';
- tok->last_type = TOK_PIPE;
- tok->buff++;
- break;
-
- case L'>':
- read_redirect( tok, 1 );
- return;
- case L'<':
- read_redirect( tok, 0 );
- return;
- case L'^':
- read_redirect( tok, 2 );
- return;
-
- default:
- {
- if( iswdigit( *tok->buff ) )
- {
- const wchar_t *orig = tok->buff;
- int fd = 0;
- while( iswdigit( *tok->buff ) )
- fd = (fd*10) + (*(tok->buff++) - L'0');
-
- switch( *(tok->buff))
- {
- case L'^':
- case L'>':
- case L'<':
- read_redirect( tok, fd );
- return;
- }
- tok->buff = orig;
- }
- read_string( tok );
- }
-
- }
+ CHECK( tok, );
+ CHECK( tok->buff, );
+
+ if( tok_last_type( tok ) == TOK_ERROR )
+ {
+ tok->has_next=false;
+ return;
+ }
+
+ if( !tok->has_next )
+ {
+/* wprintf( L"EOL\n" );*/
+ tok->last_type = TOK_END;
+ return;
+ }
+
+ while( 1 )
+ {
+ if( my_iswspace(*(tok->buff) ) )
+ {
+ tok->buff++;
+ }
+ else
+ {
+ if(( *(tok->buff) == L'\\') &&( *(tok->buff+1) == L'\n') )
+ {
+ tok->last_pos = tok->buff - tok->orig_buff;
+ tok->buff+=2;
+ tok->last_type = TOK_END;
+ return;
+ }
+ break;
+ }
+ }
+
+
+ if( *tok->buff == L'#')
+ {
+ if( tok->show_comments )
+ {
+ tok->last_pos = tok->buff - tok->orig_buff;
+ read_comment( tok );
+ return;
+ }
+ else
+ {
+ while( *(tok->buff)!= L'\n' && *(tok->buff)!= L'\0' )
+ tok->buff++;
+ }
+
+ while( my_iswspace(*(tok->buff) ) )
+ tok->buff++;
+ }
+
+ tok->last_pos = tok->buff - tok->orig_buff;
+
+ switch( *tok->buff )
+ {
+
+ case L'\0':
+ tok->last_type = TOK_END;
+ /*fwprintf( stderr, L"End of string\n" );*/
+ tok->has_next = false;
+ break;
+ case 13:
+ case L'\n':
+ case L';':
+ tok->last_type = TOK_END;
+ tok->buff++;
+ break;
+ case L'&':
+ tok->last_type = TOK_BACKGROUND;
+ tok->buff++;
+ break;
+
+ case L'|':
+ check_size( tok, 2 );
+
+ tok->last[0]=L'1';
+ tok->last[1]=L'\0';
+ tok->last_type = TOK_PIPE;
+ tok->buff++;
+ break;
+
+ case L'>':
+ read_redirect( tok, 1 );
+ return;
+ case L'<':
+ read_redirect( tok, 0 );
+ return;
+ case L'^':
+ read_redirect( tok, 2 );
+ return;
+
+ default:
+ {
+ if( iswdigit( *tok->buff ) )
+ {
+ const wchar_t *orig = tok->buff;
+ int fd = 0;
+ while( iswdigit( *tok->buff ) )
+ fd = (fd*10) + (*(tok->buff++) - L'0');
+
+ switch( *(tok->buff))
+ {
+ case L'^':
+ case L'>':
+ case L'<':
+ read_redirect( tok, fd );
+ return;
+ }
+ tok->buff = orig;
+ }
+ read_string( tok );
+ }
+
+ }
}
const wchar_t *tok_string( tokenizer *tok )
{
- return tok?tok->orig_buff:0;
+ return tok?tok->orig_buff:0;
}
wchar_t *tok_first( const wchar_t *str )
{
- tokenizer t;
- wchar_t *res=0;
-
- CHECK( str, 0 );
-
- tok_init( &t, str, TOK_SQUASH_ERRORS);
-
- switch( tok_last_type( &t ) )
- {
- case TOK_STRING:
-// fwprintf( stderr, L"Got token %ls\n", tok_last( &t ));
- res = wcsdup(tok_last( &t ));
- break;
- default:
- break;
- }
-
- tok_destroy( &t );
- return res;
+ tokenizer t;
+ wchar_t *res=0;
+
+ CHECK( str, 0 );
+
+ tok_init( &t, str, TOK_SQUASH_ERRORS);
+
+ switch( tok_last_type( &t ) )
+ {
+ case TOK_STRING:
+// fwprintf( stderr, L"Got token %ls\n", tok_last( &t ));
+ res = wcsdup(tok_last( &t ));
+ break;
+ default:
+ break;
+ }
+
+ tok_destroy( &t );
+ return res;
}
int tok_get_pos( tokenizer *tok )
{
- CHECK( tok, 0 );
-
- return (int)tok->last_pos;
+ CHECK( tok, 0 );
+
+ return (int)tok->last_pos;
}
void tok_set_pos( tokenizer *tok, int pos )
{
- CHECK( tok, );
-
- tok->buff = tok->orig_buff + pos;
- tok->has_next = true;
- tok_next( tok );
+ CHECK( tok, );
+
+ tok->buff = tok->orig_buff + pos;
+ tok->has_next = true;
+ tok_next( tok );
}
@@ -756,38 +756,38 @@ void tok_set_pos( tokenizer *tok, int pos )
*/
int main( int argc, char **argv )
{
- tokenizer tok;
- int i;
- for ( i=1; i<argc; i++ )
- {
- wprintf( L"Tokenizing string %s\n", argv[i] );
- for( tok_init( &tok, str2wcs(argv[i]), 0 ); tok_has_next( &tok ); tok_next( &tok ) )
- {
- switch( tok_last_type( &tok ) )
- {
- case TOK_INVALID:
- wprintf( L"Type: INVALID\n" );
- break;
- case TOK_STRING:
- wprintf( L"Type: STRING\t Value: %ls\n", tok_last( &tok ) );
- break;
- case TOK_PIPE:
- wprintf( L"Type: PIPE\n" );
- break;
- case TOK_END:
- wprintf( L"Type: END\n" );
- break;
- case TOK_ERROR:
- wprintf( L"Type: ERROR\n" );
- break;
- default:
- wprintf( L"Type: Unknown\n" );
- break;
- }
- }
- tok_destroy( &tok );
-
- }
+ tokenizer tok;
+ int i;
+ for ( i=1; i<argc; i++ )
+ {
+ wprintf( L"Tokenizing string %s\n", argv[i] );
+ for( tok_init( &tok, str2wcs(argv[i]), 0 ); tok_has_next( &tok ); tok_next( &tok ) )
+ {
+ switch( tok_last_type( &tok ) )
+ {
+ case TOK_INVALID:
+ wprintf( L"Type: INVALID\n" );
+ break;
+ case TOK_STRING:
+ wprintf( L"Type: STRING\t Value: %ls\n", tok_last( &tok ) );
+ break;
+ case TOK_PIPE:
+ wprintf( L"Type: PIPE\n" );
+ break;
+ case TOK_END:
+ wprintf( L"Type: END\n" );
+ break;
+ case TOK_ERROR:
+ wprintf( L"Type: ERROR\n" );
+ break;
+ default:
+ wprintf( L"Type: Unknown\n" );
+ break;
+ }
+ }
+ tok_destroy( &tok );
+
+ }
}
#endif
diff --git a/tokenizer.h b/tokenizer.h
index 1e30c1ed..e6661d22 100644
--- a/tokenizer.h
+++ b/tokenizer.h
@@ -1,4 +1,4 @@
-/** \file tokenizer.h
+/** \file tokenizer.h
A specialized tokenizer for tokenizing the fish language. In the
future, the tokenizer should be extended to support marks,
@@ -16,19 +16,19 @@
*/
enum token_type
{
- TOK_NONE, /**< Tokenizer not yet constructed */
- TOK_ERROR, /**< Error reading token */
- TOK_INVALID,/**< Invalid token */
- TOK_STRING,/**< String token */
- TOK_PIPE,/**< Pipe token */
- TOK_END,/**< End token */
- TOK_REDIRECT_OUT, /**< redirection token */
- TOK_REDIRECT_APPEND,/**< redirection append token */
- TOK_REDIRECT_IN,/**< input redirection token */
- TOK_REDIRECT_FD,/**< redirection to new fd token */
- TOK_REDIRECT_NOCLOB, /**<? redirection token */
- TOK_BACKGROUND,/**< send job to bg token */
- TOK_COMMENT/**< comment token */
+ TOK_NONE, /**< Tokenizer not yet constructed */
+ TOK_ERROR, /**< Error reading token */
+ TOK_INVALID,/**< Invalid token */
+ TOK_STRING,/**< String token */
+ TOK_PIPE,/**< Pipe token */
+ TOK_END,/**< End token */
+ TOK_REDIRECT_OUT, /**< redirection token */
+ TOK_REDIRECT_APPEND,/**< redirection append token */
+ TOK_REDIRECT_IN,/**< input redirection token */
+ TOK_REDIRECT_FD,/**< redirection to new fd token */
+ TOK_REDIRECT_NOCLOB, /**<? redirection token */
+ TOK_BACKGROUND,/**< send job to bg token */
+ TOK_COMMENT/**< comment token */
};
/**
@@ -36,12 +36,12 @@ enum token_type
*/
enum tokenizer_error
{
- TOK_UNTERMINATED_QUOTE,
- TOK_UNTERMINATED_SUBSHELL,
- TOK_UNTERMINATED_ESCAPE,
- TOK_OTHER
+ TOK_UNTERMINATED_QUOTE,
+ TOK_UNTERMINATED_SUBSHELL,
+ TOK_UNTERMINATED_ESCAPE,
+ TOK_OTHER
}
- ;
+ ;
/**
@@ -63,33 +63,33 @@ enum tokenizer_error
/**
- The tokenizer struct.
+ The tokenizer struct.
*/
struct tokenizer
{
- /** A pointer into the original string, showing where the next token begins */
- const wchar_t *buff;
- /** A copy of the original string */
- const wchar_t *orig_buff;
- /** A pointer to the last token*/
- wchar_t *last;
-
- /** Type of last token*/
- int last_type;
- /** Length of last token*/
- size_t last_len;
- /** Offset of last token*/
- size_t last_pos;
- /** Whether there are more tokens*/
- bool has_next;
- /** Whether incomplete tokens are accepted*/
- bool accept_unfinished;
- /** Whether commants should be returned*/
- bool show_comments;
- /** Type of last quote, can be either ' or ".*/
- wchar_t last_quote;
- /** Last error */
- int error;
+ /** A pointer into the original string, showing where the next token begins */
+ const wchar_t *buff;
+ /** A copy of the original string */
+ const wchar_t *orig_buff;
+ /** A pointer to the last token*/
+ wchar_t *last;
+
+ /** Type of last token*/
+ int last_type;
+ /** Length of last token*/
+ size_t last_len;
+ /** Offset of last token*/
+ size_t last_pos;
+ /** Whether there are more tokens*/
+ bool has_next;
+ /** Whether incomplete tokens are accepted*/
+ bool accept_unfinished;
+ /** Whether commants should be returned*/
+ bool show_comments;
+ /** Type of last quote, can be either ' or ".*/
+ wchar_t last_quote;
+ /** Last error */
+ int error;
/* Whether we are squashing errors */
bool squash_errors;
@@ -112,7 +112,7 @@ struct tokenizer
\param flags Flags to the tokenizer. Setting TOK_ACCEPT_UNFINISHED will cause the tokenizer
to accept incomplete tokens, such as a subshell without a closing
parenthesis, as a valid token. Setting TOK_SHOW_COMMENTS will return comments as tokens
-
+
*/
void tok_init( tokenizer *tok, const wchar_t *b, int flags );
diff --git a/util.cpp b/util.cpp
index 59ed9601..0daabef4 100644
--- a/util.cpp
+++ b/util.cpp
@@ -1,7 +1,7 @@
/** \file util.c
- Generic utilities library.
+ Generic utilities library.
- Contains datastructures such as automatically growing array lists, priority queues, etc.
+ Contains datastructures such as automatically growing array lists, priority queues, etc.
*/
#include "config.h"
@@ -49,79 +49,79 @@
int wcsfilecmp( const wchar_t *a, const wchar_t *b )
{
- CHECK( a, 0 );
- CHECK( b, 0 );
-
- if( *a==0 )
- {
- if( *b==0)
- return 0;
- return -1;
- }
- if( *b==0 )
- {
- return 1;
- }
-
- long secondary_diff=0;
- if( iswdigit( *a ) && iswdigit( *b ) )
- {
- wchar_t *aend, *bend;
- long al;
- long bl;
- long diff;
-
- errno = 0;
- al = wcstol( a, &aend, 10 );
- bl = wcstol( b, &bend, 10 );
-
- if( errno )
- {
- /*
- Huuuuuuuuge numbers - fall back to regular string comparison
- */
- return wcscmp( a, b );
- }
-
- diff = al - bl;
- if( diff )
- return diff > 0 ? 2 : -2;
-
- secondary_diff = (aend-a) - (bend-b);
-
- a=aend-1;
- b=bend-1;
- }
- else
- {
- int diff = towlower(*a) - towlower(*b);
- if( diff != 0 )
- return (diff>0)?2:-2;
-
- secondary_diff = *a-*b;
- }
-
- int res = wcsfilecmp( a+1, b+1 );
-
- if( abs(res) < 2 )
- {
- /*
- No primary difference in rest of string.
- Use secondary difference on this element if found.
- */
- if( secondary_diff )
- {
- return secondary_diff > 0 ? 1 :-1;
- }
- }
-
- return res;
+ CHECK( a, 0 );
+ CHECK( b, 0 );
+
+ if( *a==0 )
+ {
+ if( *b==0)
+ return 0;
+ return -1;
+ }
+ if( *b==0 )
+ {
+ return 1;
+ }
+
+ long secondary_diff=0;
+ if( iswdigit( *a ) && iswdigit( *b ) )
+ {
+ wchar_t *aend, *bend;
+ long al;
+ long bl;
+ long diff;
+
+ errno = 0;
+ al = wcstol( a, &aend, 10 );
+ bl = wcstol( b, &bend, 10 );
+
+ if( errno )
+ {
+ /*
+ Huuuuuuuuge numbers - fall back to regular string comparison
+ */
+ return wcscmp( a, b );
+ }
+
+ diff = al - bl;
+ if( diff )
+ return diff > 0 ? 2 : -2;
+
+ secondary_diff = (aend-a) - (bend-b);
+
+ a=aend-1;
+ b=bend-1;
+ }
+ else
+ {
+ int diff = towlower(*a) - towlower(*b);
+ if( diff != 0 )
+ return (diff>0)?2:-2;
+
+ secondary_diff = *a-*b;
+ }
+
+ int res = wcsfilecmp( a+1, b+1 );
+
+ if( abs(res) < 2 )
+ {
+ /*
+ No primary difference in rest of string.
+ Use secondary difference on this element if found.
+ */
+ if( secondary_diff )
+ {
+ return secondary_diff > 0 ? 1 :-1;
+ }
+ }
+
+ return res;
}
long long get_time()
{
- struct timeval time_struct;
- gettimeofday( &time_struct, 0 );
- return 1000000ll*time_struct.tv_sec+time_struct.tv_usec;
+ struct timeval time_struct;
+ gettimeofday( &time_struct, 0 );
+ return 1000000ll*time_struct.tv_sec+time_struct.tv_usec;
}
diff --git a/util.h b/util.h
index b3893cb1..c16c5912 100644
--- a/util.h
+++ b/util.h
@@ -1,11 +1,11 @@
/** \file util.h
- Generic utilities library.
+ Generic utilities library.
- All containers in this library except strinb_buffer_t are written
- so that they don't allocate any memory until the first element is
- inserted into them. That way it is known to be very cheap to
- initialize various containers at startup, supporting the fish
- notion of doing as much lazy initalization as possible.
+ All containers in this library except strinb_buffer_t are written
+ so that they don't allocate any memory until the first element is
+ inserted into them. That way it is known to be very cheap to
+ initialize various containers at startup, supporting the fish
+ notion of doing as much lazy initalization as possible.
*/
#ifndef FISH_UTIL_H
@@ -20,9 +20,9 @@
*/
typedef struct buffer
{
- char *buff; /**<data buffer*/
- size_t length; /**< Size of buffer */
- size_t used; /**< Size of data in buffer */
+ char *buff; /**<data buffer*/
+ size_t length; /**< Size of buffer */
+ size_t used; /**< Size of data in buffer */
}
buffer_t;
diff --git a/wgetopt.cpp b/wgetopt.cpp
index b956b5a5..3e8f8dea 100644
--- a/wgetopt.cpp
+++ b/wgetopt.cpp
@@ -1,24 +1,24 @@
/** \file wgetopt.c
- A version of the getopt library for use with wide character strings.
-
- This is simply the gnu getopt library, but converted for use with
- wchar_t instead of char. This is not usually useful since the argv
- array is always defined to be of type char**, but in fish, all
- internal commands use wide characters and hence this library is
- useful.
-
- If you want to use this version of getopt in your program,
- download the fish sourcecode, available at <a
- href='http://ridiculousfish.com/shell/'>the fish homepage</a>. Extract
- the sourcode, copy wgetopt.c and wgetopt.h into your program
- directory, include wgetopt.h in your program, and use all the
- regular getopt functions, prefixing every function, global
- variable and structure with a 'w', and use only wide character
- strings. There are no other functional changes in this version of
- getopt besides using wide character strings.
-
- For examples of how to use wgetopt, see the fish builtin
- functions, many of which are defined in builtin.c.
+ A version of the getopt library for use with wide character strings.
+
+ This is simply the gnu getopt library, but converted for use with
+ wchar_t instead of char. This is not usually useful since the argv
+ array is always defined to be of type char**, but in fish, all
+ internal commands use wide characters and hence this library is
+ useful.
+
+ If you want to use this version of getopt in your program,
+ download the fish sourcecode, available at <a
+ href='http://ridiculousfish.com/shell/'>the fish homepage</a>. Extract
+ the sourcode, copy wgetopt.c and wgetopt.h into your program
+ directory, include wgetopt.h in your program, and use all the
+ regular getopt functions, prefixing every function, global
+ variable and structure with a 'w', and use only wide character
+ strings. There are no other functional changes in this version of
+ getopt besides using wide character strings.
+
+ For examples of how to use wgetopt, see the fish builtin
+ functions, many of which are defined in builtin.c.
*/
@@ -70,11 +70,11 @@
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
+#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
-#endif /* GNU C library. */
+#endif /* GNU C library. */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
@@ -170,7 +170,7 @@ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
static enum
{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
@@ -193,13 +193,13 @@ static char *posixly_correct;
#define _(wstr) wstr
#endif
-#ifdef __GNU_LIBRARY__
+#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
-#define my_index wcschr
+#define my_index wcschr
#else
/* Avoid depending on library functions or files
@@ -210,13 +210,13 @@ char *getenv ();
static wchar_t *
my_index (const wchar_t *str, int chr)
{
- while (*str)
+ while (*str)
{
- if (*str == chr)
- return (wchar_t *) str;
- str++;
+ if (*str == chr)
+ return (wchar_t *) str;
+ str++;
}
- return 0;
+ return 0;
}
/* If using GCC, we can safely declare strlen this way.
@@ -254,56 +254,56 @@ static int last_nonopt;
static void
exchange (wchar_t **argv)
{
- int bottom = first_nonopt;
- int middle = last_nonopt;
- int top = woptind;
- wchar_t *tem;
-
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place.
- It leaves the longer segment in the right place overall,
- but it consists of two parts that need to be swapped next. */
-
- while (top > middle && middle > bottom)
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = woptind;
+ wchar_t *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
{
- if (top - middle > middle - bottom)
- {
- /* Bottom segment is the short one. */
- int len = middle - bottom;
- register int i;
-
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[top - (middle - bottom) + i];
- argv[top - (middle - bottom) + i] = tem;
- }
- /* Exclude the moved bottom segment from further swapping. */
- top -= len;
- }
- else
- {
- /* Top segment is the short one. */
- int len = top - middle;
- register int i;
-
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[middle + i];
- argv[middle + i] = tem;
- }
- /* Exclude the moved top segment from further swapping. */
- bottom += len;
- }
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
}
- /* Update records for the slots the non-options now occupy. */
+ /* Update records for the slots the non-options now occupy. */
- first_nonopt += (woptind - last_nonopt);
- last_nonopt = woptind;
+ first_nonopt += (woptind - last_nonopt);
+ last_nonopt = woptind;
}
/* Initialize the internal data when the first call is made. */
@@ -311,34 +311,34 @@ exchange (wchar_t **argv)
static const wchar_t *
_wgetopt_initialize (const wchar_t *optstring)
{
- /* Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
- first_nonopt = last_nonopt = woptind = 1;
+ first_nonopt = last_nonopt = woptind = 1;
- nextchar = NULL;
+ nextchar = NULL;
- posixly_correct = getenv ("POSIXLY_CORRECT");
+ posixly_correct = getenv ("POSIXLY_CORRECT");
- /* Determine how to handle the ordering of options and nonoptions. */
+ /* Determine how to handle the ordering of options and nonoptions. */
- if (optstring[0] == '-')
+ if (optstring[0] == '-')
{
- ordering = RETURN_IN_ORDER;
- ++optstring;
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
}
- else if (optstring[0] == '+')
+ else if (optstring[0] == '+')
{
- ordering = REQUIRE_ORDER;
- ++optstring;
+ ordering = REQUIRE_ORDER;
+ ++optstring;
}
- else if (posixly_correct != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
- return optstring;
+ return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
@@ -400,312 +400,312 @@ _wgetopt_initialize (const wchar_t *optstring)
int
_wgetopt_internal (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct woption *longopts, int *longind, int long_only)
{
- woptarg = NULL;
+ woptarg = NULL;
- if (woptind == 0)
- optstring = _wgetopt_initialize (optstring);
+ if (woptind == 0)
+ optstring = _wgetopt_initialize (optstring);
- if (nextchar == NULL || *nextchar == '\0')
+ if (nextchar == NULL || *nextchar == '\0')
{
- /* Advance to the next ARGV-element. */
-
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != woptind)
- exchange ((wchar_t **) argv);
- else if (last_nonopt != woptind)
- first_nonopt = woptind;
-
- /* Skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (woptind < argc
- && (argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
- woptind++;
- last_nonopt = woptind;
- }
-
- /* The special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (woptind != argc && !wcscmp (argv[woptind], L"--"))
- {
- woptind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != woptind)
- exchange ((wchar_t **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = woptind;
- last_nonopt = argc;
-
- woptind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
-
- if (woptind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- woptind = first_nonopt;
- return EOF;
- }
-
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if ((argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
- {
- if (ordering == REQUIRE_ORDER)
- return EOF;
- woptarg = argv[woptind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element.
- Skip the initial punctuation. */
-
- nextchar = (argv[woptind] + 1
- + (longopts != NULL && argv[woptind][1] == '-'));
+ /* Advance to the next ARGV-element. */
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != woptind)
+ exchange ((wchar_t **) argv);
+ else if (last_nonopt != woptind)
+ first_nonopt = woptind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (woptind < argc
+ && (argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
+ woptind++;
+ last_nonopt = woptind;
}
- /* Decode the current option-ARGV-element. */
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
- /* Check whether the ARGV-element is a long option.
+ if (woptind != argc && !wcscmp (argv[woptind], L"--"))
+ {
+ woptind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != woptind)
+ exchange ((wchar_t **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = woptind;
+ last_nonopt = argc;
+
+ woptind = argc;
+ }
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
+ if (woptind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ woptind = first_nonopt;
+ return EOF;
+ }
- This distinction seems to be the most useful approach. */
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
- if (longopts != NULL
- && (argv[woptind][1] == '-'
- || (long_only && (argv[woptind][2] || !my_index (optstring, argv[woptind][1])))))
+ if ((argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
{
- wchar_t *nameend;
- const struct woption *p;
- const struct woption *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0; /* set to zero by Anton */
- int option_index;
-
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!wcsncmp(p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int)(nameend - nextchar) == (unsigned int)wcslen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- if (wopterr)
- fwprintf (stderr, _(L"%ls: Option '%ls' is ambiguous\n"),
- argv[0], argv[woptind]);
- nextchar += wcslen (nextchar);
- woptind++;
- return '?';
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- woptind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- woptarg = nameend + 1;
- else
- {
- if (wopterr)
- {
- if (argv[woptind - 1][1] == '-')
- /* --option */
- fwprintf (stderr,
- _(L"%ls: Option '--%ls' doesn't allow an argument\n"),
- argv[0], pfound->name);
- else
- /* +option or -option */
- fwprintf (stderr,
- _(L"%ls: Option '%lc%ls' doesn't allow an argument\n"),
- argv[0], argv[woptind - 1][0], pfound->name);
- }
- nextchar += wcslen (nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (woptind < argc)
- woptarg = argv[woptind++];
- else
- {
- if (wopterr)
- fwprintf (stderr, _(L"%ls: Option '%ls' requires an argument\n"),
- argv[0], argv[woptind - 1]);
- nextchar += wcslen (nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += wcslen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
-
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[woptind][1] == '-'
- || my_index (optstring, *nextchar) == NULL)
- {
- if (wopterr)
- {
- if (argv[woptind][1] == '-')
- /* --option */
- fwprintf (stderr, _(L"%ls: Unrecognized option '--%ls'\n"),
- argv[0], nextchar);
- else
- /* +option or -option */
- fwprintf (stderr, _(L"%ls: Unrecognized option '%lc%ls'\n"),
- argv[0], argv[woptind][0], nextchar);
- }
- nextchar = (wchar_t *) L"";
- woptind++;
- return '?';
- }
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ woptarg = argv[woptind++];
+ return 1;
}
- /* Look at and handle the next short option-character. */
-
- {
- wchar_t c = *nextchar++;
- wchar_t *temp = const_cast<wchar_t*>(my_index (optstring, c));
-
- /* Increment `woptind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++woptind;
-
- if (temp == NULL || c == ':')
- {
- if (wopterr)
- {
- if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fwprintf (stderr, _(L"%ls: Illegal option -- %lc\n"), argv[0], c);
- else
- fwprintf (stderr, _(L"%ls: Invalid option -- %lc\n"), argv[0], c);
- }
- woptopt = c;
- return '?';
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- woptarg = nextchar;
- woptind++;
- }
- else
- woptarg = NULL;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- woptarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- woptind++;
- }
- else if (woptind == argc)
- {
- if (wopterr)
- {
- /* 1003.2 specifies the format of this message. */
- fwprintf (stderr, _(L"%ls: Option requires an argument -- %lc\n"),
- argv[0], c);
- }
- woptopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- }
- else
- /* We already incremented `woptind' once;
- increment it again when taking next ARGV-elt as argument. */
- woptarg = argv[woptind++];
- nextchar = NULL;
- }
- }
- return c;
- }
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[woptind] + 1
+ + (longopts != NULL && argv[woptind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[woptind][1] == '-'
+ || (long_only && (argv[woptind][2] || !my_index (optstring, argv[woptind][1])))))
+ {
+ wchar_t *nameend;
+ const struct woption *p;
+ const struct woption *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0; /* set to zero by Anton */
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!wcsncmp(p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int)(nameend - nextchar) == (unsigned int)wcslen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (wopterr)
+ fwprintf (stderr, _(L"%ls: Option '%ls' is ambiguous\n"),
+ argv[0], argv[woptind]);
+ nextchar += wcslen (nextchar);
+ woptind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ woptind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ woptarg = nameend + 1;
+ else
+ {
+ if (wopterr)
+ {
+ if (argv[woptind - 1][1] == '-')
+ /* --option */
+ fwprintf (stderr,
+ _(L"%ls: Option '--%ls' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fwprintf (stderr,
+ _(L"%ls: Option '%lc%ls' doesn't allow an argument\n"),
+ argv[0], argv[woptind - 1][0], pfound->name);
+ }
+ nextchar += wcslen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (woptind < argc)
+ woptarg = argv[woptind++];
+ else
+ {
+ if (wopterr)
+ fwprintf (stderr, _(L"%ls: Option '%ls' requires an argument\n"),
+ argv[0], argv[woptind - 1]);
+ nextchar += wcslen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += wcslen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[woptind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (wopterr)
+ {
+ if (argv[woptind][1] == '-')
+ /* --option */
+ fwprintf (stderr, _(L"%ls: Unrecognized option '--%ls'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fwprintf (stderr, _(L"%ls: Unrecognized option '%lc%ls'\n"),
+ argv[0], argv[woptind][0], nextchar);
+ }
+ nextchar = (wchar_t *) L"";
+ woptind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ wchar_t c = *nextchar++;
+ wchar_t *temp = const_cast<wchar_t*>(my_index (optstring, c));
+
+ /* Increment `woptind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++woptind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (wopterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fwprintf (stderr, _(L"%ls: Illegal option -- %lc\n"), argv[0], c);
+ else
+ fwprintf (stderr, _(L"%ls: Invalid option -- %lc\n"), argv[0], c);
+ }
+ woptopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ woptarg = nextchar;
+ woptind++;
+ }
+ else
+ woptarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ woptarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ woptind++;
+ }
+ else if (woptind == argc)
+ {
+ if (wopterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fwprintf (stderr, _(L"%ls: Option requires an argument -- %lc\n"),
+ argv[0], c);
+ }
+ woptopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `woptind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ woptarg = argv[woptind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
}
int
wgetopt (int argc, wchar_t *const *argv, const wchar_t *optstring)
{
- return _wgetopt_internal (argc, argv, optstring,
- (const struct woption *) 0,
- (int *) 0,
- 0);
+ return _wgetopt_internal (argc, argv, optstring,
+ (const struct woption *) 0,
+ (int *) 0,
+ 0);
}
int
wgetopt_long (int argc, wchar_t *const *argv, const wchar_t *options, const struct woption *long_options, int *opt_index)
{
- return _wgetopt_internal (argc, argv, options, long_options, opt_index, 0);
+ return _wgetopt_internal (argc, argv, options, long_options, opt_index, 0);
}
int
wgetopt_long_only (int argc, wchar_t *const *argv, const wchar_t *options, const struct woption *long_options, int *opt_index)
{
- return _wgetopt_internal (argc, argv, options, long_options, opt_index, 1);
+ return _wgetopt_internal (argc, argv, options, long_options, opt_index, 1);
}
diff --git a/wgetopt.h b/wgetopt.h
index b27f2de1..a2e90bbe 100644
--- a/wgetopt.h
+++ b/wgetopt.h
@@ -1,24 +1,24 @@
/** \file wgetopt.h
- A version of the getopt library for use with wide character strings.
-
- This is simply the gnu getopt library, but converted for use with
- wchar_t instead of char. This is not usually useful since the argv
- array is always defined to be of type char**, but in fish, all
- internal commands use wide characters and hence this library is
- useful.
-
- If you want to use this version of getopt in your program,
- download the fish sourcecode, available at <a
- href='http://ridiculousfish.com/shell/'>the fish homepage</a>. Extract
- the sourcode, copy wgetopt.c and wgetopt.h into your program
- directory, include wgetopt.h in your program, and use all the
- regular getopt functions, prefixing every function, global
- variable and structure with a 'w', and use only wide character
- strings. There are no other functional changes in this version of
- getopt besides using wide character strings.
-
- For examples of how to use wgetopt, see the fish builtin
- functions, many of which are defined in builtin.c.
+ A version of the getopt library for use with wide character strings.
+
+ This is simply the gnu getopt library, but converted for use with
+ wchar_t instead of char. This is not usually useful since the argv
+ array is always defined to be of type char**, but in fish, all
+ internal commands use wide characters and hence this library is
+ useful.
+
+ If you want to use this version of getopt in your program,
+ download the fish sourcecode, available at <a
+ href='http://ridiculousfish.com/shell/'>the fish homepage</a>. Extract
+ the sourcode, copy wgetopt.c and wgetopt.h into your program
+ directory, include wgetopt.h in your program, and use all the
+ regular getopt functions, prefixing every function, global
+ variable and structure with a 'w', and use only wide character
+ strings. There are no other functional changes in this version of
+ getopt besides using wide character strings.
+
+ For examples of how to use wgetopt, see the fish builtin
+ functions, many of which are defined in builtin.c.
*/
@@ -49,7 +49,7 @@ Cambridge, MA 02139, USA. */
#include <wchar.h>
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
@@ -90,9 +90,9 @@ extern int woptopt;
zero.
The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
@@ -107,32 +107,32 @@ extern int woptopt;
struct woption
{
- /**
- long name for switch
- */
+ /**
+ long name for switch
+ */
#if defined (__STDC__) && __STDC__
const wchar_t *name;
#else
wchar_t *name;
#endif
- /**
- Must be one of no_argument, required_argument and
- optional_argument.
+ /**
+ Must be one of no_argument, required_argument and
+ optional_argument.
- has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int.
- */
+ has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int.
+ */
int has_arg;
- /**
- If non-null, the flag whose value should be set if this switch is encountered
- */
+ /**
+ If non-null, the flag whose value should be set if this switch is encountered
+ */
int *flag;
- /**
- If \c flag is non-null, this is the value that flag will be set
- to. Otherwise, this is the return-value of the function call.
- */
+ /**
+ If \c flag is non-null, this is the value that flag will be set
+ to. Otherwise, this is the return-value of the function call.
+ */
int val;
};
@@ -141,69 +141,69 @@ struct woption
/**
Specifies that a switch does not accept an argument
*/
-#define no_argument 0
+#define no_argument 0
/**
Specifies that a switch requires an argument
*/
-#define required_argument 1
+#define required_argument 1
/**
Specifies that a switch accepts an optional argument
*/
-#define optional_argument 2
+#define optional_argument 2
#if defined (__STDC__) && __STDC__
#ifdef __GNU_LIBRARY__
-/**
- Get options from argument list. See the glibc manual for information on how to use this function.
+/**
+ Get options from argument list. See the glibc manual for information on how to use this function.
*/
extern int wgetopt (int argc, wchar_t *const *argv, const wchar_t *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int wgetopt ();
#endif /* __GNU_LIBRARY__ */
-/**
- Get options from argument list. See the glibc manual for information on how to use this function.
+/**
+ Get options from argument list. See the glibc manual for information on how to use this function.
*/
extern int wgetopt_long (int argc, wchar_t *const *argv, const wchar_t *shortopts,
- const struct woption *longopts, int *longind);
-/**
- Get options from argument list. See the glibc manual for information on how to use this function.
+ const struct woption *longopts, int *longind);
+/**
+ Get options from argument list. See the glibc manual for information on how to use this function.
*/
extern int wgetopt_long_only (int argc, wchar_t *const *argv,
- const wchar_t *shortopts,
- const struct woption *longopts, int *longind);
+ const wchar_t *shortopts,
+ const struct woption *longopts, int *longind);
-/**
- Internal only. Users should not call this directly.
+/**
+ Internal only. Users should not call this directly.
*/
extern int _wgetopt_internal (int argc, wchar_t *const *argv,
- const wchar_t *shortopts,
- const struct woption *longopts, int *longind,
- int long_only);
+ const wchar_t *shortopts,
+ const struct woption *longopts, int *longind,
+ int long_only);
#else /* not __STDC__ */
-/**
- Get options from argument list. See the glibc manual for information on how to use this function.
+/**
+ Get options from argument list. See the glibc manual for information on how to use this function.
*/
extern int wgetopt ();
-/**
- Get options from argument list. See the glibc manual for information on how to use this function.
+/**
+ Get options from argument list. See the glibc manual for information on how to use this function.
*/
extern int wgetopt_long ();
-/**
- Get options from argument list. See the glibc manual for information on how to use this function.
+/**
+ Get options from argument list. See the glibc manual for information on how to use this function.
*/
extern int wgetopt_long_only ();
-/**
- Internal only. Users should not call this directly.
+/**
+ Internal only. Users should not call this directly.
*/
extern int _wgetopt_internal ();
#endif /* __STDC__ */
-#ifdef __cplusplus
+#ifdef __cplusplus
}
#endif
diff --git a/wildcard.cpp b/wildcard.cpp
index d32c8e01..07cfcb7c 100644
--- a/wildcard.cpp
+++ b/wildcard.cpp
@@ -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
@@ -108,95 +108,95 @@ static std::map<wcstring, wcstring> suffix_map;
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;
- }
-
- if( internal )
- {
- for( ; *str; str++ )
- {
- if( ( *str == ANY_CHAR ) || (*str == ANY_STRING) || (*str == ANY_STRING_RECURSIVE) )
- return 1;
- }
- }
- else
- {
+ if( !str )
+ {
+ debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
+ return 0;
+ }
+
+ if( internal )
+ {
+ for( ; *str; str++ )
+ {
+ if( ( *str == ANY_CHAR ) || (*str == ANY_STRING) || (*str == ANY_STRING_RECURSIVE) )
+ return 1;
+ }
+ }
+ else
+ {
wchar_t prev=0;
- for( ; *str; str++ )
- {
- if( ( (*str == L'*' ) || (*str == L'?' ) ) && (prev != L'\\') )
- return 1;
- prev = *str;
- }
- }
-
- return 0;
+ for( ; *str; str++ )
+ {
+ if( ( (*str == L'*' ) || (*str == L'?' ) ) && (prev != L'\\') )
+ return 1;
+ 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 bool wildcard_match2(const wchar_t *str,
- const wchar_t *wc,
- bool is_first )
+ const wchar_t *wc,
+ bool is_first )
{
- if( *str == 0 && *wc==0 )
- return true;
-
+ if( *str == 0 && *wc==0 )
+ return true;
+
/* Hackish fix for https://github.com/fish-shell/fish-shell/issues/270. Prevent wildcards from matching . or .., but we must still allow literal matches. */
if (is_first && contains(str, L".", L".."))
{
/* The string is '.' or '..'. Return true if the wildcard exactly matches. */
return ! wcscmp(str, wc);
}
-
- if( *wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE)
- {
- /* Ignore hidden file */
- if( is_first && *str == L'.' )
- {
- return false;
- }
-
- /* Try all submatches */
- do
- {
- if( wildcard_match2( str, wc+1, false ) )
- return true;
- }
- while( *(str++) != 0 );
- return false;
- }
- else if( *str == 0 )
- {
- /*
- End of string, but not end of wildcard, and the next wildcard
- element is not a '*', so this is not a match.
- */
- return false;
- }
-
- if( *wc == ANY_CHAR )
- {
- if( is_first && *str == L'.' )
- {
- return false;
- }
-
- return wildcard_match2( str+1, wc+1, false );
- }
-
- if( *wc == *str )
- return wildcard_match2( str+1, wc+1, false );
-
- return false;
+
+ if( *wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE)
+ {
+ /* Ignore hidden file */
+ if( is_first && *str == L'.' )
+ {
+ return false;
+ }
+
+ /* Try all submatches */
+ do
+ {
+ if( wildcard_match2( str, wc+1, false ) )
+ return true;
+ }
+ while( *(str++) != 0 );
+ return false;
+ }
+ else if( *str == 0 )
+ {
+ /*
+ End of string, but not end of wildcard, and the next wildcard
+ element is not a '*', so this is not a match.
+ */
+ return false;
+ }
+
+ if( *wc == ANY_CHAR )
+ {
+ if( is_first && *str == L'.' )
+ {
+ return false;
+ }
+
+ return wildcard_match2( str+1, wc+1, false );
+ }
+
+ if( *wc == *str )
+ return wildcard_match2( str+1, wc+1, false );
+
+ return false;
}
/**
@@ -204,119 +204,119 @@ static bool wildcard_match2(const wchar_t *str,
possible completion of the string, the remainder of the string is
inserted into the out vector.
*/
-static bool wildcard_complete_internal(const wcstring &orig,
- const wchar_t *str,
- const wchar_t *wc,
- bool is_first,
- const wchar_t *desc,
- wcstring (*desc_func)(const wcstring &),
- std::vector<completion_t> &out,
- int flags )
+static bool wildcard_complete_internal(const wcstring &orig,
+ const wchar_t *str,
+ const wchar_t *wc,
+ bool is_first,
+ const wchar_t *desc,
+ wcstring (*desc_func)(const wcstring &),
+ std::vector<completion_t> &out,
+ int flags )
{
- if( !wc || ! str || orig.empty())
- {
- debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
- return 0;
- }
-
- if( *wc == 0 &&
- ( (str[0] != L'.') || (!is_first)) )
- {
- wcstring out_completion;
+ if( !wc || ! str || orig.empty())
+ {
+ debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
+ return 0;
+ }
+
+ if( *wc == 0 &&
+ ( (str[0] != L'.') || (!is_first)) )
+ {
+ wcstring out_completion;
wcstring out_desc = (desc ? desc : L"");
- if( flags & COMPLETE_NO_CASE )
- {
- out_completion = orig;
- }
- else
- {
- out_completion = str;
- }
+ if( flags & COMPLETE_NO_CASE )
+ {
+ out_completion = orig;
+ }
+ else
+ {
+ out_completion = str;
+ }
size_t complete_sep_loc = out_completion.find(PROG_COMPLETE_SEP);
if (complete_sep_loc != wcstring::npos)
- {
- /* This completion has an embedded description, do not use the generic description */
+ {
+ /* This completion has an embedded description, do not use the generic description */
out_desc.assign(out_completion, complete_sep_loc + 1, out_completion.size() - complete_sep_loc - 1);
- out_completion.resize(complete_sep_loc);
- }
- else
- {
- if( desc_func )
- {
- /*
- A description generating function is specified, call
- it. If it returns something, use that as the
- description.
- */
- wcstring func_desc = desc_func( orig );
- if (! func_desc.empty())
- out_desc = func_desc;
- }
-
- }
-
+ out_completion.resize(complete_sep_loc);
+ }
+ else
+ {
+ if( desc_func )
+ {
+ /*
+ A description generating function is specified, call
+ it. If it returns something, use that as the
+ description.
+ */
+ wcstring func_desc = desc_func( orig );
+ if (! func_desc.empty())
+ out_desc = func_desc;
+ }
+
+ }
+
/* Note: out_completion may be empty if the completion really is empty, e.g. tab-completing 'foo' when a file 'foo' exists. */
append_completion(out, out_completion, out_desc, flags);
- return true;
- }
-
-
- if( *wc == ANY_STRING )
- {
- bool res=false;
-
- /* Ignore hidden file */
- if( is_first && str[0] == L'.' )
- return false;
-
- /* Try all submatches */
- do
- {
- res = wildcard_complete_internal( orig, str, wc+1, 0, desc, desc_func, out, flags );
- if (res)
- break;
- }
- 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 );
- }
- else if( towlower(*wc) == towlower(*str) )
- {
- return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags | COMPLETE_NO_CASE );
- }
- return false;
+ return true;
+ }
+
+
+ if( *wc == ANY_STRING )
+ {
+ bool res=false;
+
+ /* Ignore hidden file */
+ if( is_first && str[0] == L'.' )
+ return false;
+
+ /* Try all submatches */
+ do
+ {
+ res = wildcard_complete_internal( orig, str, wc+1, 0, desc, desc_func, out, flags );
+ if (res)
+ break;
+ }
+ 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 );
+ }
+ else if( towlower(*wc) == towlower(*str) )
+ {
+ return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags | COMPLETE_NO_CASE );
+ }
+ return false;
}
bool wildcard_complete(const wcstring &str,
- const wchar_t *wc,
- const wchar_t *desc,
- wcstring (*desc_func)(const wcstring &),
- std::vector<completion_t> &out,
- int flags )
+ const wchar_t *wc,
+ const wchar_t *desc,
+ wcstring (*desc_func)(const wcstring &),
+ std::vector<completion_t> &out,
+ int flags )
{
- bool res;
- res = wildcard_complete_internal( str, str.c_str(), wc, true, desc, desc_func, out, flags );
- return res;
+ bool res;
+ res = wildcard_complete_internal( str, str.c_str(), wc, true, desc, desc_func, out, flags );
+ return res;
}
bool wildcard_match( const wcstring &str, const wcstring &wc )
{
- return wildcard_match2( str.c_str(), wc.c_str(), true );
+ return wildcard_match2( str.c_str(), wc.c_str(), true );
}
/**
- Creates a path from the specified directory and filename.
+ Creates a path from the specified directory and filename.
*/
static wcstring make_path(const wcstring &base_dir, const wcstring &name) {
return base_dir + name;
@@ -331,35 +331,35 @@ static wcstring complete_get_desc_suffix_internal( const wcstring &suff )
{
wcstring cmd = wcstring(SUFFIX_CMD_STR) + suff;
-
+
wcstring_list_t lst;
wcstring desc;
-
- if( exec_subshell( cmd, lst ) != -1 )
- {
- if( lst.size()>0 )
- {
+
+ if( exec_subshell( cmd, lst ) != -1 )
+ {
+ if( lst.size()>0 )
+ {
const wcstring & ln = lst.at(0);
- if( ln.size() > 0 && ln != L"unknown" )
- {
- desc = ln;
- /*
- I have decided I prefer to have the description
- begin in uppercase and the whole universe will just
- have to accept it. Hah!
- */
- desc[0]=towupper(desc[0]);
- }
- }
- }
-
- if( desc.empty() )
- {
- desc = COMPLETE_FILE_DESC;
- }
-
+ if( ln.size() > 0 && ln != L"unknown" )
+ {
+ desc = ln;
+ /*
+ I have decided I prefer to have the description
+ begin in uppercase and the whole universe will just
+ have to accept it. Hah!
+ */
+ desc[0]=towupper(desc[0]);
+ }
+ }
+ }
+
+ if( desc.empty() )
+ {
+ desc = COMPLETE_FILE_DESC;
+ }
+
suffix_map[suff] = desc.c_str();
- return desc;
+ return desc;
}
@@ -369,34 +369,34 @@ static wcstring complete_get_desc_suffix_internal( const wcstring &suff )
static wcstring complete_get_desc_suffix( const wchar_t *suff_orig )
{
- size_t len;
- wchar_t *suff;
- wchar_t *pos;
- wchar_t *tmp;
-
- len = wcslen(suff_orig );
-
- if( len == 0 )
- return COMPLETE_FILE_DESC;
-
- suff = wcsdup(suff_orig);
-
- /*
- Drop characters that are commonly used as backup suffixes from the suffix
- */
- for( pos=suff; *pos; pos++ )
- {
- if( wcschr( L"?;#~@&", *pos ) )
- {
- *pos=0;
- break;
- }
- }
-
- tmp = escape( suff, 1 );
- free(suff);
- suff = tmp;
-
+ size_t len;
+ wchar_t *suff;
+ wchar_t *pos;
+ wchar_t *tmp;
+
+ len = wcslen(suff_orig );
+
+ if( len == 0 )
+ return COMPLETE_FILE_DESC;
+
+ suff = wcsdup(suff_orig);
+
+ /*
+ Drop characters that are commonly used as backup suffixes from the suffix
+ */
+ for( pos=suff; *pos; pos++ )
+ {
+ if( wcschr( L"?;#~@&", *pos ) )
+ {
+ *pos=0;
+ break;
+ }
+ }
+
+ tmp = escape( suff, 1 );
+ free(suff);
+ suff = tmp;
+
std::map<wcstring, wcstring>::iterator iter = suffix_map.find(suff);
wcstring desc;
if (iter != suffix_map.end()) {
@@ -405,9 +405,9 @@ static wcstring complete_get_desc_suffix( const wchar_t *suff_orig )
desc = complete_get_desc_suffix_internal( suff );
}
- free( suff );
+ free( suff );
- return desc;
+ return desc;
}
@@ -421,130 +421,130 @@ static wcstring 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 wcstring file_get_desc( const wcstring &filename,
- int lstat_res,
- struct stat lbuf,
- int stat_res,
- struct stat buf,
- int err )
+static wcstring file_get_desc( const wcstring &filename,
+ int lstat_res,
+ struct stat lbuf,
+ int stat_res,
+ struct stat buf,
+ int err )
{
- const wchar_t *suffix;
-
- if( !lstat_res )
- {
- if( S_ISLNK(lbuf.st_mode))
- {
- if( !stat_res )
- {
- if( S_ISDIR(buf.st_mode) )
- {
- return COMPLETE_DIRECTORY_SYMLINK_DESC;
- }
- else
- {
-
- if( ( buf.st_mode & S_IXUSR ) ||
- ( buf.st_mode & S_IXGRP ) ||
- ( buf.st_mode & S_IXOTH ) )
- {
-
- if( waccess( filename, X_OK ) == 0 )
- {
- /*
- Weird group permissions and other such
- issues make it non-trivial to find out
- if we can actually execute a file using
- the result from stat. It is much safer
- to use the access function, since it
- tells us exactly what we want to know.
- */
- return COMPLETE_EXEC_LINK_DESC;
- }
- }
- }
-
- return COMPLETE_SYMLINK_DESC;
-
- }
- else
- {
- switch( err )
- {
- case ENOENT:
- {
- return COMPLETE_ROTTEN_SYMLINK_DESC;
- }
-
- case ELOOP:
- {
- return COMPLETE_LOOP_SYMLINK_DESC;
- }
- }
- /*
- On unknown errors we do nothing. The file will be
- given the default 'File' description or one based on the suffix.
- */
- }
-
- }
- else if( S_ISCHR(buf.st_mode) )
- {
- return COMPLETE_CHAR_DESC;
- }
- else if( S_ISBLK(buf.st_mode) )
- {
- return COMPLETE_BLOCK_DESC;
- }
- else if( S_ISFIFO(buf.st_mode) )
- {
- return COMPLETE_FIFO_DESC;
- }
- else if( S_ISSOCK(buf.st_mode))
- {
- return COMPLETE_SOCKET_DESC;
- }
- else if( S_ISDIR(buf.st_mode) )
- {
- return COMPLETE_DIRECTORY_DESC;
- }
- else
- {
- if( ( buf.st_mode & S_IXUSR ) ||
- ( buf.st_mode & S_IXGRP ) ||
- ( buf.st_mode & S_IXOTH ) )
- {
-
- if( waccess( filename, X_OK ) == 0 )
- {
- /*
- Weird group permissions and other such issues
- make it non-trivial to find out if we can
- actually execute a file using the result from
- stat. It is much safer to use the access
- function, since it tells us exactly what we want
- to know.
- */
- return COMPLETE_EXEC_DESC;
- }
- }
- }
- }
-
- suffix = wcsrchr( filename.c_str(), L'.' );
- if( suffix != 0 && !wcsrchr( suffix, L'/' ) )
- {
- return complete_get_desc_suffix( suffix );
- }
-
- return COMPLETE_FILE_DESC ;
+ const wchar_t *suffix;
+
+ if( !lstat_res )
+ {
+ if( S_ISLNK(lbuf.st_mode))
+ {
+ if( !stat_res )
+ {
+ if( S_ISDIR(buf.st_mode) )
+ {
+ return COMPLETE_DIRECTORY_SYMLINK_DESC;
+ }
+ else
+ {
+
+ if( ( buf.st_mode & S_IXUSR ) ||
+ ( buf.st_mode & S_IXGRP ) ||
+ ( buf.st_mode & S_IXOTH ) )
+ {
+
+ if( waccess( filename, X_OK ) == 0 )
+ {
+ /*
+ Weird group permissions and other such
+ issues make it non-trivial to find out
+ if we can actually execute a file using
+ the result from stat. It is much safer
+ to use the access function, since it
+ tells us exactly what we want to know.
+ */
+ return COMPLETE_EXEC_LINK_DESC;
+ }
+ }
+ }
+
+ return COMPLETE_SYMLINK_DESC;
+
+ }
+ else
+ {
+ switch( err )
+ {
+ case ENOENT:
+ {
+ return COMPLETE_ROTTEN_SYMLINK_DESC;
+ }
+
+ case ELOOP:
+ {
+ return COMPLETE_LOOP_SYMLINK_DESC;
+ }
+ }
+ /*
+ On unknown errors we do nothing. The file will be
+ given the default 'File' description or one based on the suffix.
+ */
+ }
+
+ }
+ else if( S_ISCHR(buf.st_mode) )
+ {
+ return COMPLETE_CHAR_DESC;
+ }
+ else if( S_ISBLK(buf.st_mode) )
+ {
+ return COMPLETE_BLOCK_DESC;
+ }
+ else if( S_ISFIFO(buf.st_mode) )
+ {
+ return COMPLETE_FIFO_DESC;
+ }
+ else if( S_ISSOCK(buf.st_mode))
+ {
+ return COMPLETE_SOCKET_DESC;
+ }
+ else if( S_ISDIR(buf.st_mode) )
+ {
+ return COMPLETE_DIRECTORY_DESC;
+ }
+ else
+ {
+ if( ( buf.st_mode & S_IXUSR ) ||
+ ( buf.st_mode & S_IXGRP ) ||
+ ( buf.st_mode & S_IXOTH ) )
+ {
+
+ if( waccess( filename, X_OK ) == 0 )
+ {
+ /*
+ Weird group permissions and other such issues
+ make it non-trivial to find out if we can
+ actually execute a file using the result from
+ stat. It is much safer to use the access
+ function, since it tells us exactly what we want
+ to know.
+ */
+ return COMPLETE_EXEC_DESC;
+ }
+ }
+ }
+ }
+
+ suffix = wcsrchr( filename.c_str(), 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
@@ -556,78 +556,78 @@ static wcstring file_get_desc( const wcstring &filename,
\param wc the wildcard to match against
\param is_cmd whether we are performing command completion
*/
-static void wildcard_completion_allocate( std::vector<completion_t> &list,
- const wcstring &fullname,
- const wcstring &completion,
- const wchar_t *wc,
+static void wildcard_completion_allocate( std::vector<completion_t> &list,
+ const wcstring &fullname,
+ const wcstring &completion,
+ const wchar_t *wc,
expand_flags_t expand_flags)
{
- struct stat buf, lbuf;
+ struct stat buf, lbuf;
wcstring sb;
- wcstring munged_completion;
-
- int flags = 0;
- int stat_res, lstat_res;
- int stat_errno=0;
-
- long long sz;
-
- /*
- If the file is a symlink, we need to stat both the file itself
- _and_ the destination file. But we try to avoid this with
- non-symlinks by first doing an lstat, and if the file is not a
- link we copy the results over to the regular stat buffer.
- */
- if( ( lstat_res = lwstat( fullname, &lbuf ) ) )
- {
+ wcstring munged_completion;
+
+ int flags = 0;
+ int stat_res, lstat_res;
+ int stat_errno=0;
+
+ long long sz;
+
+ /*
+ If the file is a symlink, we need to stat both the file itself
+ _and_ the destination file. But we try to avoid this with
+ non-symlinks by first doing an lstat, and if the file is not a
+ link we copy the results over to the regular stat buffer.
+ */
+ if( ( lstat_res = lwstat( fullname, &lbuf ) ) )
+ {
/* lstat failed! */
- sz=-1;
- stat_res = lstat_res;
- }
- else
- {
- if (S_ISLNK(lbuf.st_mode))
- {
-
- if( ( stat_res = wstat( fullname, &buf ) ) )
- {
- sz=-1;
- }
- else
- {
- 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.
- */
- stat_errno = errno;
- }
- else
- {
- stat_res = lstat_res;
- memcpy( &buf, &lbuf, sizeof( struct stat ) );
- sz = (long long)buf.st_size;
- }
- }
-
-
+ sz=-1;
+ stat_res = lstat_res;
+ }
+ else
+ {
+ if (S_ISLNK(lbuf.st_mode))
+ {
+
+ if( ( stat_res = wstat( fullname, &buf ) ) )
+ {
+ sz=-1;
+ }
+ else
+ {
+ 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.
+ */
+ stat_errno = errno;
+ }
+ else
+ {
+ stat_res = lstat_res;
+ memcpy( &buf, &lbuf, sizeof( struct stat ) );
+ sz = (long long)buf.st_size;
+ }
+ }
+
+
bool wants_desc = ! (expand_flags & EXPAND_NO_DESCRIPTIONS);
- wcstring desc;
+ wcstring desc;
if (wants_desc)
desc = file_get_desc( fullname.c_str(), lstat_res, lbuf, stat_res, buf, stat_errno );
-
- if( sz >= 0 && S_ISDIR(buf.st_mode) )
- {
- flags = flags | COMPLETE_NO_SPACE;
+
+ if( sz >= 0 && S_ISDIR(buf.st_mode) )
+ {
+ flags = flags | COMPLETE_NO_SPACE;
munged_completion = completion;
munged_completion.push_back(L'/');
if (wants_desc)
sb.append(desc);
- }
- else
- {
+ }
+ else
+ {
if (wants_desc)
{
if (! desc.empty())
@@ -637,10 +637,10 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
}
sb.append(format_size(sz));
}
- }
-
+ }
+
const wcstring &completion_to_use = munged_completion.empty() ? completion : munged_completion;
- wildcard_complete(completion_to_use, wc, sb.c_str(), NULL, list, flags);
+ wildcard_complete(completion_to_use, wc, sb.c_str(), NULL, list, flags);
}
/**
@@ -649,30 +649,30 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
EXECUTABLES_ONLY and DIRECTORIES_ONLY.
*/
static int test_flags( const wchar_t *filename,
- int flags )
+ int flags )
{
- if( flags & DIRECTORIES_ONLY )
- {
- struct stat buf;
- if( wstat( filename, &buf ) == -1 )
- {
- return 0;
- }
-
- if( !S_ISDIR( buf.st_mode ) )
- {
- return 0;
- }
- }
-
-
- if( flags & EXECUTABLES_ONLY )
- {
- if ( waccess( filename, X_OK ) != 0)
- return 0;
- }
-
- return 1;
+ if( flags & DIRECTORIES_ONLY )
+ {
+ struct stat buf;
+ if( wstat( filename, &buf ) == -1 )
+ {
+ return 0;
+ }
+
+ if( !S_ISDIR( buf.st_mode ) )
+ {
+ return 0;
+ }
+ }
+
+
+ if( flags & EXECUTABLES_ONLY )
+ {
+ if ( waccess( filename, X_OK ) != 0)
+ return 0;
+ }
+
+ return 1;
}
/** Appends a completion to the completion list, if the string is missing from the set. */
@@ -692,415 +692,415 @@ typedef std::pair<dev_t, ino_t> file_id_t;
This function traverses the relevant directory tree looking for
matches, and recurses when needed to handle wildcrards spanning
multiple components and recursive wildcards.
-
+
Because this function calls itself recursively with substrings,
it's important that the parameters be raw pointers instead of wcstring,
which would be too expensive to construct for all substrings.
*/
static int wildcard_expand_internal( const wchar_t *wc,
- const wchar_t *base_dir,
- expand_flags_t flags,
- std::vector<completion_t> &out,
+ const wchar_t *base_dir,
+ expand_flags_t flags,
+ std::vector<completion_t> &out,
std::set<wcstring> &completion_set,
std::set<file_id_t> &visited_files
)
{
- /* Points to the end of the current wildcard segment */
- const wchar_t *wc_end;
-
- /* Variables for traversing a directory */
- DIR *dir;
-
- /* The result returned */
- int res = 0;
-
- /* Length of the directory to search in */
- size_t base_len;
-
- /* Variables for testing for presense of recursive wildcards */
- const wchar_t *wc_recursive;
- bool is_recursive;
-
- /* Slightly mangled version of base_dir */
- const wchar_t *dir_string;
-
- // debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
-
- if( reader_interrupted() )
- {
- return -1;
- }
-
- if( !wc || !base_dir )
- {
- debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
- return 0;
- }
-
- if( flags & ACCEPT_INCOMPLETE )
- {
- /*
- Avoid excessive number of returned matches for wc ending with a *
- */
- size_t len = wcslen(wc);
- if( len && (wc[len-1]==ANY_STRING) )
- {
- wchar_t * foo = wcsdup( wc );
- foo[len-1]=0;
- int res = wildcard_expand_internal( foo, base_dir, flags, out, completion_set, visited_files );
- free( foo );
- return res;
- }
- }
-
- /*
- Initialize various variables
- */
-
- dir_string = base_dir[0]==L'\0'?L".":base_dir;
-
- if( !(dir = wopendir( dir_string )))
- {
- return 0;
- }
-
- wc_end = wcschr(wc,L'/');
- base_len = wcslen( base_dir );
-
- /*
- 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));
-
- /*
- Is this segment of the wildcard the last?
- */
- if( !wc_end )
- {
- /*
- Wildcard segment is the last segment,
-
- Insert all matching files/directories
- */
- if( wc[0]=='\0' )
- {
- /*
- The last wildcard segment is empty. Insert everything if
- completing, the directory itself otherwise.
- */
- if( flags & ACCEPT_INCOMPLETE )
- {
+ /* Points to the end of the current wildcard segment */
+ const wchar_t *wc_end;
+
+ /* Variables for traversing a directory */
+ DIR *dir;
+
+ /* The result returned */
+ int res = 0;
+
+ /* Length of the directory to search in */
+ size_t base_len;
+
+ /* Variables for testing for presense of recursive wildcards */
+ const wchar_t *wc_recursive;
+ bool is_recursive;
+
+ /* Slightly mangled version of base_dir */
+ const wchar_t *dir_string;
+
+ // debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
+
+ if( reader_interrupted() )
+ {
+ return -1;
+ }
+
+ if( !wc || !base_dir )
+ {
+ debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
+ return 0;
+ }
+
+ if( flags & ACCEPT_INCOMPLETE )
+ {
+ /*
+ Avoid excessive number of returned matches for wc ending with a *
+ */
+ size_t len = wcslen(wc);
+ if( len && (wc[len-1]==ANY_STRING) )
+ {
+ wchar_t * foo = wcsdup( wc );
+ foo[len-1]=0;
+ int res = wildcard_expand_internal( foo, base_dir, flags, out, completion_set, visited_files );
+ free( foo );
+ return res;
+ }
+ }
+
+ /*
+ Initialize various variables
+ */
+
+ dir_string = base_dir[0]==L'\0'?L".":base_dir;
+
+ if( !(dir = wopendir( dir_string )))
+ {
+ return 0;
+ }
+
+ wc_end = wcschr(wc,L'/');
+ base_len = wcslen( base_dir );
+
+ /*
+ 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));
+
+ /*
+ Is this segment of the wildcard the last?
+ */
+ if( !wc_end )
+ {
+ /*
+ Wildcard segment is the last segment,
+
+ Insert all matching files/directories
+ */
+ if( wc[0]=='\0' )
+ {
+ /*
+ The last wildcard segment is empty. Insert everything if
+ completing, the directory itself otherwise.
+ */
+ if( flags & ACCEPT_INCOMPLETE )
+ {
wcstring next;
- while(wreaddir(dir, next))
- {
- if( next[0] != L'.' )
- {
- wcstring long_name = make_path( base_dir, next );
-
- if( test_flags( long_name.c_str(), flags ) )
- {
- wildcard_completion_allocate( out,
- long_name,
- next,
- L"",
+ while(wreaddir(dir, next))
+ {
+ if( next[0] != L'.' )
+ {
+ wcstring long_name = make_path( base_dir, next );
+
+ if( test_flags( long_name.c_str(), flags ) )
+ {
+ wildcard_completion_allocate( out,
+ long_name,
+ next,
+ L"",
flags);
- }
- }
- }
- }
- else
- {
- res = 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ res = 1;
insert_completion_if_missing(base_dir, out, completion_set);
- }
- }
- else
- {
- /*
- This is the last wildcard segment, and it is not empty. Match files/directories.
- */
+ }
+ }
+ else
+ {
+ /*
+ This is the last wildcard segment, and it is not empty. Match files/directories.
+ */
wcstring next;
- while (wreaddir(dir, next))
- {
+ while (wreaddir(dir, next))
+ {
const wchar_t * const name = next.c_str();
- if( flags & ACCEPT_INCOMPLETE )
- {
-
- const wcstring long_name = make_path( base_dir, next );
-
- /*
- Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
- */
- std::vector<completion_t> test;
- if( wildcard_complete( name,
- wc,
- L"",
- 0,
- test,
- 0 ) )
- {
- if( test_flags( long_name.c_str(), flags ) )
- {
- wildcard_completion_allocate( out,
- long_name,
+ if( flags & ACCEPT_INCOMPLETE )
+ {
+
+ const wcstring long_name = make_path( base_dir, next );
+
+ /*
+ Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
+ */
+ std::vector<completion_t> test;
+ if( wildcard_complete( name,
+ wc,
+ L"",
+ 0,
+ test,
+ 0 ) )
+ {
+ if( test_flags( long_name.c_str(), flags ) )
+ {
+ wildcard_completion_allocate( out,
+ long_name,
name,
- wc,
+ wc,
flags);
-
- }
- }
- }
- else
- {
- if( wildcard_match2( name, wc, true ) )
- {
+
+ }
+ }
+ }
+ else
+ {
+ if( wildcard_match2( name, wc, true ) )
+ {
const wcstring long_name = make_path(base_dir, next);
- int skip = 0;
-
- if( is_recursive )
- {
- /*
- In recursive mode, we are only
- interested in adding files -directories
- will be added in the next pass.
- */
- struct stat buf;
- if( !wstat( long_name, &buf ) )
- {
- skip = S_ISDIR(buf.st_mode);
- }
- }
- if (! skip)
- {
+ int skip = 0;
+
+ if( is_recursive )
+ {
+ /*
+ In recursive mode, we are only
+ interested in adding files -directories
+ will be added in the next pass.
+ */
+ struct stat buf;
+ if( !wstat( long_name, &buf ) )
+ {
+ skip = S_ISDIR(buf.st_mode);
+ }
+ }
+ if (! skip)
+ {
insert_completion_if_missing(long_name, out, completion_set);
- }
- res = 1;
- }
- }
- }
- }
- }
-
- if( wc_end || is_recursive )
- {
- /*
- 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
- */
- wchar_t *wc_str;
-
- /*
- new_dir is a scratch area containing the full path to a
- file/directory we are iterating over
- */
- wchar_t *new_dir;
-
- /*
- The maximum length of a file element
- */
- long ln=MAX_FILE_LENGTH;
- char * narrow_dir_string = wcs2str( dir_string );
-
- /*
- In recursive mode, we look through the directory twice. If
- so, this rewind is needed.
- */
- rewinddir( dir );
-
- 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 );
-
- /*
- If not specified, use som large number as fallback
- */
- if( ln < 0 )
- ln = MAX_FILE_LENGTH;
- free( narrow_dir_string );
- }
- new_dir= (wchar_t *)malloc( sizeof(wchar_t)*(base_len+ln+2) );
-
- wc_str = wc_end?wcsndup(wc, wc_end-wc):wcsdup(wc);
-
- if( (!new_dir) || (!wc_str) )
- {
- DIE_MEM();
- }
-
- wcscpy( new_dir, base_dir );
-
+ }
+ res = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if( wc_end || is_recursive )
+ {
+ /*
+ 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
+ */
+ wchar_t *wc_str;
+
+ /*
+ new_dir is a scratch area containing the full path to a
+ file/directory we are iterating over
+ */
+ wchar_t *new_dir;
+
+ /*
+ The maximum length of a file element
+ */
+ long ln=MAX_FILE_LENGTH;
+ char * narrow_dir_string = wcs2str( dir_string );
+
+ /*
+ In recursive mode, we look through the directory twice. If
+ so, this rewind is needed.
+ */
+ rewinddir( dir );
+
+ 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 );
+
+ /*
+ If not specified, use som large number as fallback
+ */
+ if( ln < 0 )
+ ln = MAX_FILE_LENGTH;
+ free( narrow_dir_string );
+ }
+ new_dir= (wchar_t *)malloc( sizeof(wchar_t)*(base_len+ln+2) );
+
+ wc_str = wc_end?wcsndup(wc, wc_end-wc):wcsdup(wc);
+
+ if( (!new_dir) || (!wc_str) )
+ {
+ DIE_MEM();
+ }
+
+ wcscpy( new_dir, base_dir );
+
wcstring next;
- while (wreaddir(dir, next))
- {
- 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, true );
- 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
- for matches.
- */
- if( is_recursive )
- {
- const wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE );
- wchar_t *wc_sub = wcsndup( wc, end-wc+1);
- partial_match = wildcard_match2( name, wc_sub, true );
- free( wc_sub );
- }
-
- if( whole_match || partial_match )
- {
- 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 )
- {
+ while (wreaddir(dir, next))
+ {
+ 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, true );
+ 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
+ for matches.
+ */
+ if( is_recursive )
+ {
+ const wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE );
+ wchar_t *wc_sub = wcsndup( wc, end-wc+1);
+ partial_match = wildcard_match2( name, wc_sub, true );
+ free( wc_sub );
+ }
+
+ if( whole_match || partial_match )
+ {
+ 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 )
+ {
// Insert a "file ID" into visited_files
// If the insertion fails, we've already visited this file (i.e. a symlink loop)
// If we're not recursive, insert anyways (in case we loop back around in a future recursive segment), but continue on; the idea being that literal path components should still work
const file_id_t file_id(buf.st_dev, buf.st_ino);
- if( S_ISDIR(buf.st_mode) && (visited_files.insert(file_id).second || ! is_recursive))
- {
- size_t new_len = wcslen( new_dir );
- new_dir[new_len] = L'/';
- new_dir[new_len+1] = L'\0';
-
- /*
- Regular matching
- */
- if( whole_match )
- {
- const wchar_t *new_wc = L"";
- if( wc_end )
- {
- new_wc=wc_end+1;
- /*
- Accept multiple '/' as a single direcotry separator
- */
- while(*new_wc==L'/')
- {
- new_wc++;
- }
- }
-
- new_res = wildcard_expand_internal( new_wc,
- new_dir,
- flags,
- out,
+ if( S_ISDIR(buf.st_mode) && (visited_files.insert(file_id).second || ! is_recursive))
+ {
+ size_t new_len = wcslen( new_dir );
+ new_dir[new_len] = L'/';
+ new_dir[new_len+1] = L'\0';
+
+ /*
+ Regular matching
+ */
+ if( whole_match )
+ {
+ const wchar_t *new_wc = L"";
+ if( wc_end )
+ {
+ new_wc=wc_end+1;
+ /*
+ Accept multiple '/' as a single direcotry separator
+ */
+ while(*new_wc==L'/')
+ {
+ new_wc++;
+ }
+ }
+
+ new_res = wildcard_expand_internal( new_wc,
+ new_dir,
+ flags,
+ out,
completion_set,
visited_files );
- 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_dir,
- flags | WILDCARD_RECURSIVE,
- 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_dir,
+ flags | WILDCARD_RECURSIVE,
+ out,
completion_set,
visited_files);
- if( new_res == -1 )
- {
- res = -1;
- break;
- }
- res |= new_res;
-
- }
- }
- }
- }
- }
- }
-
- free( wc_str );
- free( new_dir );
- }
- closedir( dir );
-
- return res;
+ if( new_res == -1 )
+ {
+ res = -1;
+ break;
+ }
+ res |= new_res;
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+ free( wc_str );
+ free( new_dir );
+ }
+ closedir( dir );
+
+ return res;
}
int wildcard_expand( const wchar_t *wc,
- const wchar_t *base_dir,
- expand_flags_t flags,
- std::vector<completion_t> &out )
+ const wchar_t *base_dir,
+ expand_flags_t flags,
+ std::vector<completion_t> &out )
{
- size_t c = out.size();
-
+ size_t c = out.size();
+
/* Make a set of used completion strings so we can do fast membership tests inside wildcard_expand_internal. Otherwise wildcards like '**' are very slow, because we end up with an N^2 membership test.
*/
- std::set<wcstring> completion_set;
- for (std::vector<completion_t>::const_iterator iter = out.begin(); iter != out.end(); ++iter)
- {
+ std::set<wcstring> completion_set;
+ for (std::vector<completion_t>::const_iterator iter = out.begin(); iter != out.end(); ++iter)
+ {
completion_set.insert(iter->completion);
- }
-
- std::set<file_id_t> visited_files;
- int res = wildcard_expand_internal( wc, base_dir, flags, out, completion_set, visited_files );
-
- if( flags & ACCEPT_INCOMPLETE )
- {
+ }
+
+ std::set<file_id_t> visited_files;
+ int res = wildcard_expand_internal( wc, base_dir, flags, out, completion_set, visited_files );
+
+ if( flags & ACCEPT_INCOMPLETE )
+ {
wcstring wc_base;
- const wchar_t *wc_base_ptr = wcsrchr( wc, L'/' );
- if( wc_base_ptr )
- {
+ const wchar_t *wc_base_ptr = wcsrchr( wc, L'/' );
+ if( wc_base_ptr )
+ {
wc_base = wcstring(wc, (wc_base_ptr-wc)+1);
- }
-
- for( size_t i=c; i<out.size(); i++ )
- {
- completion_t &c = out.at( i );
-
- if( c.flags & COMPLETE_NO_CASE )
- {
- c.completion = format_string(L"%ls%ls%ls", base_dir, wc_base.c_str(), c.completion.c_str());
- }
- }
- }
- return res;
+ }
+
+ for( size_t i=c; i<out.size(); i++ )
+ {
+ completion_t &c = out.at( i );
+
+ if( c.flags & COMPLETE_NO_CASE )
+ {
+ c.completion = format_string(L"%ls%ls%ls", base_dir, wc_base.c_str(), c.completion.c_str());
+ }
+ }
+ }
+ return res;
}
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> &outputs )
diff --git a/wildcard.h b/wildcard.h
index 9380375c..f2bc5457 100644
--- a/wildcard.h
+++ b/wildcard.h
@@ -1,4 +1,4 @@
-/** \file wildcard.h
+/** \file wildcard.h
My own globbing implementation. Needed to implement this instead
of using libs globbing to support tab-expansion of globbed
@@ -31,41 +31,41 @@ class completion_t;
*/
enum
{
- /** Character representing any character except '/' */
- ANY_CHAR = WILDCARD_RESERVED,
+ /** Character representing any character except '/' */
+ ANY_CHAR = WILDCARD_RESERVED,
- /** Character representing any character string not containing '/' (A slash) */
- ANY_STRING,
+ /** Character representing any character string not containing '/' (A slash) */
+ ANY_STRING,
- /** Character representing any character string */
- ANY_STRING_RECURSIVE,
+ /** Character representing any character string */
+ ANY_STRING_RECURSIVE,
}
- ;
+ ;
/**
- Expand the wildcard by matching against the filesystem.
+ Expand the wildcard by matching against the filesystem.
- New strings are allocated using malloc and should be freed by the caller.
+ New strings are allocated using malloc and should be freed by the caller.
- wildcard_expand works by dividing the wildcard into segments at
- each directory boundary. Each segment is processed separatly. All
- except the last segment are handled by matching the wildcard
- segment against all subdirectories of matching directories, and
- recursively calling wildcard_expand for matches. On the last
- segment, matching is made to any file, and all matches are
- inserted to the list.
+ wildcard_expand works by dividing the wildcard into segments at
+ each directory boundary. Each segment is processed separatly. All
+ except the last segment are handled by matching the wildcard
+ segment against all subdirectories of matching directories, and
+ recursively calling wildcard_expand for matches. On the last
+ segment, matching is made to any file, and all matches are
+ inserted to the list.
- If wildcard_expand encounters any errors (such as insufficient
- priviliges) during matching, no error messages will be printed and
- wildcard_expand will continue the matching process.
+ If wildcard_expand encounters any errors (such as insufficient
+ priviliges) during matching, no error messages will be printed and
+ wildcard_expand will continue the matching process.
- \param wc The wildcard string
- \param base_dir The base directory of the filesystem to perform the match against
- \param flags flags for the search. Can be any combination of ACCEPT_INCOMPLETE and EXECUTABLES_ONLY
- \param out The list in which to put the output
+ \param wc The wildcard string
+ \param base_dir The base directory of the filesystem to perform the match against
+ \param flags flags for the search. Can be any combination of ACCEPT_INCOMPLETE and EXECUTABLES_ONLY
+ \param out The list in which to put the output
+
+ \return 1 if matches where found, 0 otherwise. Return -1 on abort (I.e. ^C was pressed).
- \return 1 if matches where found, 0 otherwise. Return -1 on abort (I.e. ^C was pressed).
-
*/
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> &out );
/**
@@ -87,10 +87,10 @@ int wildcard_has( const wchar_t *str, int internal );
Test wildcard completion
*/
bool wildcard_complete(const wcstring &str,
- const wchar_t *wc,
- const wchar_t *desc,
- wcstring (*desc_func)(const wcstring &),
- std::vector<completion_t> &out,
- expand_flags_t flags );
+ const wchar_t *wc,
+ const wchar_t *desc,
+ wcstring (*desc_func)(const wcstring &),
+ std::vector<completion_t> &out,
+ expand_flags_t flags );
#endif
diff --git a/wutil.cpp b/wutil.cpp
index 661c4e93..fdd6680b 100644
--- a/wutil.cpp
+++ b/wutil.cpp
@@ -1,6 +1,6 @@
/** \file wutil.c
- Wide character equivalents of various standard unix
- functions.
+ Wide character equivalents of various standard unix
+ functions.
*/
#include "config.h"
@@ -70,7 +70,7 @@ bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &ou
{
struct dirent *d = readdir( dir );
if ( !d ) return false;
-
+
out_name = str2wcstring(d->d_name);
if (out_is_dir) {
/* The caller cares if this is a directory, so check */
@@ -100,7 +100,7 @@ bool wreaddir(DIR *dir, std::wstring &out_name)
{
struct dirent *d = readdir( dir );
if ( !d ) return false;
-
+
out_name = str2wcstring(d->d_name);
return true;
}
@@ -108,34 +108,34 @@ bool wreaddir(DIR *dir, std::wstring &out_name)
wchar_t *wgetcwd( wchar_t *buff, size_t sz )
{
- char *buffc = (char *)malloc( sz*MAX_UTF8_BYTES);
- char *res;
- wchar_t *ret = 0;
-
- if( !buffc )
- {
- errno = ENOMEM;
- return 0;
- }
-
- res = getcwd( buffc, sz*MAX_UTF8_BYTES );
- if( res )
- {
- if( (size_t)-1 != mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
- {
- ret = buff;
- }
- }
-
- free( buffc );
-
- return ret;
+ char *buffc = (char *)malloc( sz*MAX_UTF8_BYTES);
+ char *res;
+ wchar_t *ret = 0;
+
+ if( !buffc )
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ res = getcwd( buffc, sz*MAX_UTF8_BYTES );
+ if( res )
+ {
+ if( (size_t)-1 != mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
+ {
+ ret = buff;
+ }
+ }
+
+ free( buffc );
+
+ return ret;
}
int wchdir( const wcstring &dir )
{
cstring tmp = wcs2string(dir);
- return chdir( tmp.c_str() );
+ return chdir( tmp.c_str() );
}
FILE *wfopen(const wcstring &path, const char *mode)
@@ -162,11 +162,11 @@ FILE *wfopen(const wcstring &path, const char *mode)
/* Skip binary */
if (mode[idx] == 'b')
idx++;
-
+
/* Consider append option */
if (mode[idx] == '+')
permissions = O_RDWR;
-
+
int fd = wopen_cloexec(path, permissions | options, 0666);
if (fd < 0)
return NULL;
@@ -210,7 +210,7 @@ static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool
fd = -1;
}
return fd;
-
+
}
int wopen(const wcstring &pathname, int flags, mode_t mode)
{
@@ -266,40 +266,40 @@ int wunlink(const wcstring &file_name)
void wperror(const wcstring &s)
{
- int e = errno;
- if( !s.empty() )
- {
- fwprintf( stderr, L"%ls: ", s.c_str() );
- }
- fwprintf( stderr, L"%s\n", strerror( e ) );
+ int e = errno;
+ if( !s.empty() )
+ {
+ fwprintf( stderr, L"%ls: ", s.c_str() );
+ }
+ fwprintf( stderr, L"%s\n", strerror( e ) );
}
#ifdef HAVE_REALPATH_NULL
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
{
- cstring tmp = wcs2string(pathname);
- char *narrow_res = realpath( tmp.c_str(), 0 );
- wchar_t *res;
-
- if( !narrow_res )
- return 0;
-
- if( resolved_path )
- {
- wchar_t *tmp2 = str2wcs( narrow_res );
- wcslcpy( resolved_path, tmp2, PATH_MAX );
- free( tmp2 );
- res = resolved_path;
- }
- else
- {
- res = str2wcs( narrow_res );
- }
+ cstring tmp = wcs2string(pathname);
+ char *narrow_res = realpath( tmp.c_str(), 0 );
+ wchar_t *res;
+
+ if( !narrow_res )
+ return 0;
+
+ if( resolved_path )
+ {
+ wchar_t *tmp2 = str2wcs( narrow_res );
+ wcslcpy( resolved_path, tmp2, PATH_MAX );
+ free( tmp2 );
+ res = resolved_path;
+ }
+ else
+ {
+ res = str2wcs( narrow_res );
+ }
free( narrow_res );
- return res;
+ return res;
}
#else
@@ -307,25 +307,25 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
{
cstring tmp = wcs2string(pathname);
- char narrow_buff[PATH_MAX];
- char *narrow_res = realpath( tmp.c_str(), narrow_buff );
- wchar_t *res;
-
- if( !narrow_res )
- return 0;
-
- if( resolved_path )
- {
- wchar_t *tmp2 = str2wcs( narrow_res );
- wcslcpy( resolved_path, tmp2, PATH_MAX );
- free( tmp2 );
- res = resolved_path;
- }
- else
- {
- res = str2wcs( narrow_res );
- }
- return res;
+ char narrow_buff[PATH_MAX];
+ char *narrow_res = realpath( tmp.c_str(), narrow_buff );
+ wchar_t *res;
+
+ if( !narrow_res )
+ return 0;
+
+ if( resolved_path )
+ {
+ wchar_t *tmp2 = str2wcs( narrow_res );
+ wcslcpy( resolved_path, tmp2, PATH_MAX );
+ free( tmp2 );
+ res = resolved_path;
+ }
+ else
+ {
+ res = str2wcs( narrow_res );
+ }
+ return res;
}
#endif
@@ -352,8 +352,8 @@ wcstring wbasename( const wcstring &path )
/* Really init wgettext */
static void wgettext_really_init() {
pthread_mutex_init(&wgettext_lock, NULL);
- bindtextdomain( PACKAGE_NAME, LOCALEDIR );
- textdomain( PACKAGE_NAME );
+ bindtextdomain( PACKAGE_NAME, LOCALEDIR );
+ textdomain( PACKAGE_NAME );
}
/**
@@ -367,31 +367,31 @@ static void wgettext_init_if_necessary()
const wchar_t *wgettext( const wchar_t *in )
{
- if( !in )
- return in;
-
- // preserve errno across this since this is often used in printing error messages
- int err = errno;
-
+ if( !in )
+ return in;
+
+ // preserve errno across this since this is often used in printing error messages
+ int err = errno;
+
wgettext_init_if_necessary();
-
- wcstring key = in;
+
+ wcstring key = in;
scoped_lock lock(wgettext_lock);
-
+
wcstring *& val = wgettext_map[key];
if (val == NULL) {
cstring mbs_in = wcs2string(key);
char *out = gettext(mbs_in.c_str());
val = new wcstring(format_string(L"%s", out));
}
- errno = err;
- return val->c_str();
+ errno = err;
+ return val->c_str();
}
wcstring wgettext2(const wcstring &in) {
wgettext_init_if_necessary();
- std::string mbs_in = wcs2string(in);
- char *out = gettext( mbs_in.c_str() );
+ std::string mbs_in = wcs2string(in);
+ char *out = gettext( mbs_in.c_str() );
wcstring result = format_string(L"%s", out);
return result;
}
@@ -400,28 +400,28 @@ const wchar_t *wgetenv( const wcstring &name )
{
ASSERT_IS_MAIN_THREAD();
cstring name_narrow = wcs2string(name);
- char *res_narrow = getenv( name_narrow.c_str() );
- static wcstring out;
+ char *res_narrow = getenv( name_narrow.c_str() );
+ static wcstring out;
+
+ if( !res_narrow )
+ return 0;
- if( !res_narrow )
- return 0;
-
out = format_string(L"%s", res_narrow);
- return out.c_str();
-
+ return out.c_str();
+
}
int wmkdir( const wcstring &name, int mode )
{
- cstring name_narrow = wcs2string(name);
- return mkdir( name_narrow.c_str(), mode );
+ cstring name_narrow = wcs2string(name);
+ return mkdir( name_narrow.c_str(), mode );
}
int wrename( const wcstring &old, const wcstring &newv )
{
cstring old_narrow = wcs2string(old);
- cstring new_narrow =wcs2string(newv);
- return rename( old_narrow.c_str(), new_narrow.c_str() );
+ cstring new_narrow =wcs2string(newv);
+ return rename( old_narrow.c_str(), new_narrow.c_str() );
}
int fish_wcstoi(const wchar_t *str, wchar_t ** endptr, int base)
diff --git a/wutil.h b/wutil.h
index 1b7cb308..d1bf770b 100644
--- a/wutil.h
+++ b/wutil.h
@@ -1,7 +1,7 @@
/** \file wutil.h
Prototypes for wide character equivalents of various standard unix
- functions.
+ functions.
*/
#ifndef FISH_WUTIL_H
#define FISH_WUTIL_H
@@ -91,11 +91,11 @@ wchar_t *wgetcwd( wchar_t *buff, size_t sz );
*/
int wchdir( const wcstring &dir );
-/**
- Wide character version of realpath function. Just like the GNU
- version of realpath, wrealpath will accept 0 as the value for the
- second argument, in which case the result will be allocated using
- malloc, and must be free'd by the user.
+/**
+ Wide character version of realpath function. Just like the GNU
+ version of realpath, wrealpath will accept 0 as the value for the
+ second argument, in which case the result will be allocated using
+ malloc, and must be free'd by the user.
*/
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path);
diff --git a/xdgmime.cpp b/xdgmime.cpp
index 571c77c6..5db32268 100644
--- a/xdgmime.cpp
+++ b/xdgmime.cpp
@@ -2,13 +2,13 @@
/* xdgmime.c: XDG Mime Spec mime resolver. Based on version 0.11 of the spec.
*
* More info can be found at http://www.freedesktop.org/standards/
- *
+ *
* Copyright (C) 2003,2004 Red Hat, Inc.
* Copyright (C) 2003,2004 Jonathan Blandford <jrb@alum.mit.edu>
*
* Licensed under the Academic Free License version 2.0
* Or under the following terms:
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -60,9 +60,9 @@ const char *xdg_mime_type_unknown = "application/octet-stream";
enum
{
- XDG_CHECKED_UNCHECKED,
- XDG_CHECKED_VALID,
- XDG_CHECKED_INVALID
+ XDG_CHECKED_UNCHECKED,
+ XDG_CHECKED_VALID,
+ XDG_CHECKED_INVALID
};
struct XdgDirTimeList
@@ -86,7 +86,7 @@ struct XdgCallbackList
/* Function called by xdg_run_command_on_dirs. If it returns TRUE, further
* directories aren't looked at */
typedef int (*XdgDirectoryFunc) (const char *directory,
- void *user_data);
+ void *user_data);
static XdgDirTimeList *
xdg_dir_time_list_new (void)
@@ -172,7 +172,7 @@ xdg_mime_init_from_directory (const char *directory)
/* Runs a command on all the directories in the search path */
static void
xdg_run_command_on_dirs (XdgDirectoryFunc func,
- void *user_data)
+ void *user_data)
{
const char *xdg_data_home;
const char *xdg_data_dirs;
@@ -182,7 +182,7 @@ xdg_run_command_on_dirs (XdgDirectoryFunc func,
if (xdg_data_home)
{
if ((func) (xdg_data_home, user_data))
- return;
+ return;
}
else
{
@@ -190,19 +190,19 @@ xdg_run_command_on_dirs (XdgDirectoryFunc func,
home = getenv ("HOME");
if (home != NULL)
- {
- char *guessed_xdg_home;
- int stop_processing;
-
- guessed_xdg_home = (char *)malloc (strlen (home) + strlen ("/.local/share/") + 1);
- strcpy (guessed_xdg_home, home);
- strcat (guessed_xdg_home, "/.local/share/");
- stop_processing = (func) (guessed_xdg_home, user_data);
- free (guessed_xdg_home);
-
- if (stop_processing)
- return;
- }
+ {
+ char *guessed_xdg_home;
+ int stop_processing;
+
+ guessed_xdg_home = (char *)malloc (strlen (home) + strlen ("/.local/share/") + 1);
+ strcpy (guessed_xdg_home, home);
+ strcat (guessed_xdg_home, "/.local/share/");
+ stop_processing = (func) (guessed_xdg_home, user_data);
+ free (guessed_xdg_home);
+
+ if (stop_processing)
+ return;
+ }
}
xdg_data_dirs = getenv ("XDG_DATA_DIRS");
@@ -220,18 +220,18 @@ xdg_run_command_on_dirs (XdgDirectoryFunc func,
end_ptr = ptr;
while (*end_ptr != ':' && *end_ptr != '\000')
- end_ptr ++;
+ end_ptr ++;
if (end_ptr == ptr)
- {
- ptr++;
- continue;
- }
+ {
+ ptr++;
+ continue;
+ }
if (*end_ptr == ':')
- len = end_ptr - ptr;
+ len = end_ptr - ptr;
else
- len = end_ptr - ptr + 1;
+ len = end_ptr - ptr + 1;
dir = (char *)malloc (len + 1);
strncpy (dir, ptr, len);
dir[len] = '\0';
@@ -239,7 +239,7 @@ xdg_run_command_on_dirs (XdgDirectoryFunc func,
free (dir);
if (stop_processing)
- return;
+ return;
ptr = end_ptr;
}
@@ -262,18 +262,18 @@ xdg_check_file (const char *file_path)
XdgDirTimeList *list;
for (list = dir_time_list; list; list = list->next)
- {
- if (! strcmp (list->directory_name, file_path) &&
- st.st_mtime == list->mtime)
- {
- if (list->checked == XDG_CHECKED_UNCHECKED)
- list->checked = XDG_CHECKED_VALID;
- else if (list->checked == XDG_CHECKED_VALID)
- list->checked = XDG_CHECKED_INVALID;
-
- return (list->checked != XDG_CHECKED_VALID);
- }
- }
+ {
+ if (! strcmp (list->directory_name, file_path) &&
+ st.st_mtime == list->mtime)
+ {
+ if (list->checked == XDG_CHECKED_UNCHECKED)
+ list->checked = XDG_CHECKED_VALID;
+ else if (list->checked == XDG_CHECKED_VALID)
+ list->checked = XDG_CHECKED_INVALID;
+
+ return (list->checked != XDG_CHECKED_VALID);
+ }
+ }
return TRUE;
}
@@ -282,7 +282,7 @@ xdg_check_file (const char *file_path)
static int
xdg_check_dir (const char *directory,
- int *invalid_dir_list)
+ int *invalid_dir_list)
{
int invalid;
char *file_name;
@@ -326,7 +326,7 @@ xdg_check_dirs (void)
list->checked = XDG_CHECKED_UNCHECKED;
xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_check_dir,
- &invalid_dir_list);
+ &invalid_dir_list);
if (invalid_dir_list)
return TRUE;
@@ -334,7 +334,7 @@ xdg_check_dirs (void)
for (list = dir_time_list; list; list = list->next)
{
if (list->checked != XDG_CHECKED_VALID)
- return TRUE;
+ return TRUE;
}
return FALSE;
@@ -381,7 +381,7 @@ xdg_mime_init (void)
parent_list = _xdg_mime_parent_list_new ();
xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_mime_init_from_directory,
- NULL);
+ NULL);
need_reread = FALSE;
}
@@ -389,7 +389,7 @@ xdg_mime_init (void)
const char *
xdg_mime_get_mime_type_for_data (const void *data,
- size_t len)
+ size_t len)
{
const char *mime_type;
@@ -501,7 +501,7 @@ xdg_mime_shutdown (void)
xdg_dir_time_list_free (dir_time_list);
dir_time_list = NULL;
}
-
+
if (global_hash)
{
_xdg_glob_hash_free (global_hash);
@@ -520,11 +520,11 @@ xdg_mime_shutdown (void)
}
if( parent_list )
- {
- _xdg_mime_parent_list_free ( parent_list);
- }
-
-
+ {
+ _xdg_mime_parent_list_free ( parent_list);
+ }
+
+
for (list = callback_list; list; list = list->next)
(list->callback) (list->data);
@@ -535,7 +535,7 @@ int
xdg_mime_get_max_buffer_extents (void)
{
xdg_mime_init ();
-
+
return _xdg_mime_magic_get_buffer_extents (global_magic);
}
@@ -554,7 +554,7 @@ xdg_mime_unalias_mime_type (const char *mime_type)
int
xdg_mime_mime_type_equal (const char *mime_a,
- const char *mime_b)
+ const char *mime_b)
{
const char *unalias_a, *unalias_b;
@@ -571,14 +571,14 @@ xdg_mime_mime_type_equal (const char *mime_a,
int
xdg_mime_media_type_equal (const char *mime_a,
- const char *mime_b)
+ const char *mime_b)
{
char *sep;
xdg_mime_init ();
sep = const_cast<char*>(strchr (mime_a, '/'));
-
+
if (sep && strncmp (mime_a, mime_b, sep - mime_a + 1) == 0)
return 1;
@@ -604,7 +604,7 @@ xdg_mime_is_super_type (const char *mime)
int
xdg_mime_mime_type_subclass (const char *mime,
- const char *base)
+ const char *base)
{
const char *umime, *ubase;
const char **parents;
@@ -617,7 +617,7 @@ xdg_mime_mime_type_subclass (const char *mime,
if (strcmp (umime, ubase) == 0)
return 1;
-#if 0
+#if 0
/* Handle supertypes */
if (xdg_mime_is_super_type (ubase) &&
xdg_mime_media_type_equal (umime, ubase))
@@ -625,18 +625,18 @@ xdg_mime_mime_type_subclass (const char *mime,
#endif
/* Handle special cases text/plain and application/octet-stream */
- if (strcmp (ubase, "text/plain") == 0 &&
+ if (strcmp (ubase, "text/plain") == 0 &&
strncmp (umime, "text/", 5) == 0)
return 1;
if (strcmp (ubase, "application/octet-stream") == 0)
return 1;
-
+
parents = _xdg_mime_parent_list_lookup (parent_list, umime);
for (; parents && *parents; parents++)
{
if (xdg_mime_mime_type_subclass (*parents, ubase))
- return 1;
+ return 1;
}
return 0;
@@ -654,7 +654,7 @@ xdg_mime_get_mime_parents (const char *mime)
return _xdg_mime_parent_list_lookup (parent_list, umime);
}
-void
+void
xdg_mime_dump (void)
{
printf ("*** ALIASES ***\n\n");
@@ -668,8 +668,8 @@ xdg_mime_dump (void)
*/
int
xdg_mime_register_reload_callback (XdgMimeCallback callback,
- void *data,
- XdgMimeDestroy destroy)
+ void *data,
+ XdgMimeDestroy destroy)
{
XdgCallbackList *list_el;
static int callback_id = 1;
@@ -698,19 +698,19 @@ xdg_mime_remove_callback (int callback_id)
for (list = callback_list; list; list = list->next)
{
if (list->callback_id == callback_id)
- {
- if (list->next)
- list->next = list->prev;
-
- if (list->prev)
- list->prev->next = list->next;
- else
- callback_list = list->next;
-
- /* invoke the destroy handler */
- (list->destroy) (list->data);
- free (list);
- return;
- }
+ {
+ if (list->next)
+ list->next = list->prev;
+
+ if (list->prev)
+ list->prev->next = list->next;
+ else
+ callback_list = list->next;
+
+ /* invoke the destroy handler */
+ (list->destroy) (list->data);
+ free (list);
+ return;
+ }
}
}
diff --git a/xdgmime.h b/xdgmime.h
index fd3647b5..36c61338 100644
--- a/xdgmime.h
+++ b/xdgmime.h
@@ -2,13 +2,13 @@
/* xdgmime.h: XDG Mime Spec mime resolver. Based on version 0.11 of the spec.
*
* More info can be found at http://www.freedesktop.org/standards/
- *
+ *
* Copyright (C) 2003 Red Hat, Inc.
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
*
* Licensed under the Academic Free License version 2.0
* Or under the following terms:
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -44,7 +44,7 @@ extern "C" {
typedef void (*XdgMimeCallback) (void *user_data);
typedef void (*XdgMimeDestroy) (void *user_data);
-
+
#ifdef XDG_PREFIX
#define xdg_mime_get_mime_type_for_data XDG_ENTRY(get_mime_type_for_data)
#define xdg_mime_get_mime_type_for_file XDG_ENTRY(get_mime_type_for_file)
@@ -66,24 +66,24 @@ extern const char *xdg_mime_type_unknown;
#define XDG_MIME_TYPE_UNKNOWN xdg_mime_type_unknown
const char *xdg_mime_get_mime_type_for_data (const void *data,
- size_t len);
+ size_t len);
const char *xdg_mime_get_mime_type_for_file (const char *file_name);
const char *xdg_mime_get_mime_type_from_file_name (const char *file_name);
int xdg_mime_is_valid_mime_type (const char *mime_type);
int xdg_mime_mime_type_equal (const char *mime_a,
- const char *mime_b);
+ const char *mime_b);
int xdg_mime_media_type_equal (const char *mime_a,
- const char *mime_b);
+ const char *mime_b);
int xdg_mime_mime_type_subclass (const char *mime_a,
- const char *mime_b);
-const char **xdg_mime_get_mime_parents (const char *mime);
-const char *xdg_mime_unalias_mime_type (const char *mime);
+ const char *mime_b);
+const char **xdg_mime_get_mime_parents (const char *mime);
+const char *xdg_mime_unalias_mime_type (const char *mime);
int xdg_mime_get_max_buffer_extents (void);
void xdg_mime_shutdown (void);
void xdg_mime_dump (void);
int xdg_mime_register_reload_callback (XdgMimeCallback callback,
- void *data,
- XdgMimeDestroy destroy);
+ void *data,
+ XdgMimeDestroy destroy);
void xdg_mime_remove_callback (int callback_id);
#ifdef __cplusplus
diff --git a/xdgmimealias.cpp b/xdgmimealias.cpp
index e1701dbc..4bb411ef 100644
--- a/xdgmimealias.cpp
+++ b/xdgmimealias.cpp
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -37,17 +37,17 @@
#include <string.h>
#include <fnmatch.h>
-#ifndef FALSE
-#define FALSE (0)
+#ifndef FALSE
+#define FALSE (0)
#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
+#ifndef TRUE
+#define TRUE (!FALSE)
#endif
typedef struct XdgAlias XdgAlias;
-struct XdgAlias
+struct XdgAlias
{
char *alias;
char *mime_type;
@@ -72,7 +72,7 @@ _xdg_mime_alias_list_new (void)
return list;
}
-void
+void
_xdg_mime_alias_list_free (XdgAliasList *list)
{
int i;
@@ -80,10 +80,10 @@ _xdg_mime_alias_list_free (XdgAliasList *list)
if (list->aliases)
{
for (i = 0; i < list->n_aliases; i++)
- {
- free (list->aliases[i].alias);
- free (list->aliases[i].mime_type);
- }
+ {
+ free (list->aliases[i].alias);
+ free (list->aliases[i].mime_type);
+ }
free (list->aliases);
}
free (list);
@@ -97,7 +97,7 @@ alias_entry_cmp (const void *v1, const void *v2)
const char *
_xdg_mime_alias_list_lookup (XdgAliasList *list,
- const char *alias)
+ const char *alias)
{
XdgAlias *entry;
XdgAlias key;
@@ -108,7 +108,7 @@ _xdg_mime_alias_list_lookup (XdgAliasList *list,
key.mime_type = 0;
entry = (XdgAlias *)bsearch (&key, list->aliases, list->n_aliases,
- sizeof (XdgAlias), alias_entry_cmp);
+ sizeof (XdgAlias), alias_entry_cmp);
if (entry)
return entry->mime_type;
}
@@ -118,7 +118,7 @@ _xdg_mime_alias_list_lookup (XdgAliasList *list,
void
_xdg_mime_alias_read_from_file (XdgAliasList *list,
- const char *file_name)
+ const char *file_name)
{
FILE *file;
char line[255];
@@ -138,30 +138,30 @@ _xdg_mime_alias_read_from_file (XdgAliasList *list,
{
char *sep;
if (line[0] == '#')
- continue;
+ continue;
sep = strchr (line, ' ');
if (sep == NULL)
- continue;
+ continue;
*(sep++) = '\000';
sep[strlen (sep) -1] = '\000';
if (list->n_aliases == alloc)
- {
- alloc <<= 1;
- list->aliases = (XdgAlias *)realloc (list->aliases,
- alloc * sizeof (XdgAlias));
- }
+ {
+ alloc <<= 1;
+ list->aliases = (XdgAlias *)realloc (list->aliases,
+ alloc * sizeof (XdgAlias));
+ }
list->aliases[list->n_aliases].alias = strdup (line);
list->aliases[list->n_aliases].mime_type = strdup (sep);
list->n_aliases++;
}
- list->aliases = (XdgAlias *)realloc (list->aliases,
- list->n_aliases * sizeof (XdgAlias));
+ list->aliases = (XdgAlias *)realloc (list->aliases,
+ list->n_aliases * sizeof (XdgAlias));
+
+ fclose (file);
- fclose (file);
-
if (list->n_aliases > 1)
- qsort (list->aliases, list->n_aliases,
+ qsort (list->aliases, list->n_aliases,
sizeof (XdgAlias), alias_entry_cmp);
}
@@ -174,11 +174,11 @@ _xdg_mime_alias_list_dump (XdgAliasList *list)
if (list->aliases)
{
for (i = 0; i < list->n_aliases; i++)
- {
- printf ("%s %s\n",
- list->aliases[i].alias,
- list->aliases[i].mime_type);
- }
+ {
+ printf ("%s %s\n",
+ list->aliases[i].alias,
+ list->aliases[i].mime_type);
+ }
}
}
diff --git a/xdgmimealias.h b/xdgmimealias.h
index 3df18d66..d69593f0 100644
--- a/xdgmimealias.h
+++ b/xdgmimealias.h
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -40,11 +40,11 @@ typedef struct XdgAliasList XdgAliasList;
#endif
void _xdg_mime_alias_read_from_file (XdgAliasList *list,
- const char *file_name);
+ const char *file_name);
XdgAliasList *_xdg_mime_alias_list_new (void);
void _xdg_mime_alias_list_free (XdgAliasList *list);
const char *_xdg_mime_alias_list_lookup (XdgAliasList *list,
- const char *alias);
+ const char *alias);
void _xdg_mime_alias_list_dump (XdgAliasList *list);
#endif /* __XDG_MIME_ALIAS_H__ */
diff --git a/xdgmimeglob.cpp b/xdgmimeglob.cpp
index a485765b..6b6c410e 100644
--- a/xdgmimeglob.cpp
+++ b/xdgmimeglob.cpp
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -37,12 +37,12 @@
#include <string.h>
#include <fnmatch.h>
-#ifndef FALSE
-#define FALSE (0)
+#ifndef FALSE
+#define FALSE (0)
#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
+#ifndef TRUE
+#define TRUE (!FALSE)
#endif
typedef struct XdgGlobHashNode XdgGlobHashNode;
@@ -95,9 +95,9 @@ _xdg_glob_list_free (XdgGlobList *glob_list)
next = ptr->next;
if (ptr->data)
- free ((void *) ptr->data);
+ free ((void *) ptr->data);
if (ptr->mime_type)
- free ((void *) ptr->mime_type);
+ free ((void *) ptr->mime_type);
free (ptr);
ptr = next;
@@ -106,8 +106,8 @@ _xdg_glob_list_free (XdgGlobList *glob_list)
static XdgGlobList *
_xdg_glob_list_append (XdgGlobList *glob_list,
- void *data,
- const char *mime_type)
+ void *data,
+ const char *mime_type)
{
XdgGlobList *new_element;
XdgGlobList *tmp_element;
@@ -130,8 +130,8 @@ _xdg_glob_list_append (XdgGlobList *glob_list,
#if 0
static XdgGlobList *
_xdg_glob_list_prepend (XdgGlobList *glob_list,
- void *data,
- const char *mime_type)
+ void *data,
+ const char *mime_type)
{
XdgGlobList *new_element;
@@ -159,7 +159,7 @@ _xdg_glob_hash_node_new (void)
static void
_xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node,
- int depth)
+ int depth)
{
int i;
for (i = 0; i < depth; i++)
@@ -178,8 +178,8 @@ _xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node,
static XdgGlobHashNode *
_xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
- const char *text,
- const char *mime_type)
+ const char *text,
+ const char *mime_type)
{
XdgGlobHashNode *node;
xdg_unichar_t character;
@@ -209,33 +209,33 @@ _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
node = prev_node->next;
while (node != NULL)
- {
- if (character < node->character)
- {
- node = _xdg_glob_hash_node_new ();
- node->character = character;
- node->next = prev_node->next;
- prev_node->next = node;
-
- found_node = TRUE;
- break;
- }
- else if (character == node->character)
- {
- found_node = TRUE;
- break;
- }
- prev_node = node;
- node = node->next;
- }
+ {
+ if (character < node->character)
+ {
+ node = _xdg_glob_hash_node_new ();
+ node->character = character;
+ node->next = prev_node->next;
+ prev_node->next = node;
+
+ found_node = TRUE;
+ break;
+ }
+ else if (character == node->character)
+ {
+ found_node = TRUE;
+ break;
+ }
+ prev_node = node;
+ node = node->next;
+ }
if (! found_node)
- {
- node = _xdg_glob_hash_node_new ();
- node->character = character;
- node->next = prev_node->next;
- prev_node->next = node;
- }
+ {
+ node = _xdg_glob_hash_node_new ();
+ node->character = character;
+ node->next = prev_node->next;
+ prev_node->next = node;
+ }
}
text = _xdg_utf8_next_char (text);
@@ -252,8 +252,8 @@ _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
static const char *
_xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
- const char *file_name,
- int ignore_case)
+ const char *file_name,
+ int ignore_case)
{
XdgGlobHashNode *node;
xdg_unichar_t character;
@@ -268,22 +268,22 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
for (node = glob_hash_node; node && character >= node->character; node = node->next)
{
if (character == node->character)
- {
- file_name = _xdg_utf8_next_char (file_name);
- if (*file_name == '\000')
- return node->mime_type;
- else
- return _xdg_glob_hash_node_lookup_file_name (node->child,
- file_name,
- ignore_case);
- }
+ {
+ file_name = _xdg_utf8_next_char (file_name);
+ if (*file_name == '\000')
+ return node->mime_type;
+ else
+ return _xdg_glob_hash_node_lookup_file_name (node->child,
+ file_name,
+ ignore_case);
+ }
}
return NULL;
}
const char *
_xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
- const char *file_name)
+ const char *file_name)
{
XdgGlobList *list;
const char *mime_type;
@@ -302,11 +302,11 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
mime_type = (_xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, FALSE));
if (mime_type != NULL)
return mime_type;
-
+
mime_type = (_xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, TRUE));
if (mime_type != NULL)
return mime_type;
-
+
ptr = strchr (ptr+1, '.');
}
@@ -344,7 +344,7 @@ _xdg_glob_hash_free_nodes (XdgGlobHashNode *node)
if (node->next)
_xdg_glob_hash_free_nodes (node->next);
if (node->mime_type)
- free ((void *) node->mime_type);
+ free ((void *) node->mime_type);
free (node);
}
}
@@ -370,9 +370,9 @@ _xdg_glob_determine_type (const char *glob)
while (*ptr != '\000')
{
if (*ptr == '*' && first_char)
- maybe_in_simple_glob = TRUE;
+ maybe_in_simple_glob = TRUE;
else if (*ptr == '\\' || *ptr == '[' || *ptr == '?' || *ptr == '*')
- return XDG_GLOB_FULL;
+ return XDG_GLOB_FULL;
first_char = FALSE;
ptr = _xdg_utf8_next_char (ptr);
@@ -386,8 +386,8 @@ _xdg_glob_determine_type (const char *glob)
/* glob must be valid UTF-8 */
void
_xdg_glob_hash_append_glob (XdgGlobHash *glob_hash,
- const char *glob,
- const char *mime_type)
+ const char *glob,
+ const char *mime_type)
{
XdgGlobType type;
@@ -422,7 +422,7 @@ _xdg_glob_hash_dump (XdgGlobHash *glob_hash)
else
{
for (list = glob_hash->literal_list; list; list = list->next)
- printf (" %s - %s\n", (char *)list->data, list->mime_type);
+ printf (" %s - %s\n", (char *)list->data, list->mime_type);
}
printf ("\nSIMPLE GLOBS\n");
_xdg_glob_hash_node_dump (glob_hash->simple_node, 4);
@@ -435,14 +435,14 @@ _xdg_glob_hash_dump (XdgGlobHash *glob_hash)
else
{
for (list = glob_hash->full_list; list; list = list->next)
- printf (" %s - %s\n", (char *)list->data, list->mime_type);
+ printf (" %s - %s\n", (char *)list->data, list->mime_type);
}
}
void
_xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,
- const char *file_name)
+ const char *file_name)
{
FILE *glob_file;
char line[255];
@@ -459,11 +459,11 @@ _xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,
{
char *colon;
if (line[0] == '#')
- continue;
+ continue;
colon = strchr (line, ':');
if (colon == NULL)
- continue;
+ continue;
*(colon++) = '\000';
colon[strlen (colon) -1] = '\000';
_xdg_glob_hash_append_glob (glob_hash, colon, line);
diff --git a/xdgmimeglob.h b/xdgmimeglob.h
index 771c4527..2e6a577d 100644
--- a/xdgmimeglob.h
+++ b/xdgmimeglob.h
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -39,7 +39,7 @@ typedef enum
XDG_GLOB_FULL /* x*.[ch] */
} XdgGlobType;
-
+
#ifdef XDG_PREFIX
#define _xdg_mime_glob_read_from_file XDG_ENTRY(glob_read_from_file)
#define _xdg_glob_hash_new XDG_ENTRY(hash_new)
@@ -51,14 +51,14 @@ typedef enum
#endif
void _xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,
- const char *file_name);
+ const char *file_name);
XdgGlobHash *_xdg_glob_hash_new (void);
void _xdg_glob_hash_free (XdgGlobHash *glob_hash);
const char *_xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
- const char *text);
+ const char *text);
void _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash,
- const char *glob,
- const char *mime_type);
+ const char *glob,
+ const char *mime_type);
XdgGlobType _xdg_glob_determine_type (const char *glob);
void _xdg_glob_hash_dump (XdgGlobHash *glob_hash);
diff --git a/xdgmimeint.cpp b/xdgmimeint.cpp
index 4a0ac4cc..72e1d78f 100644
--- a/xdgmimeint.cpp
+++ b/xdgmimeint.cpp
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -33,12 +33,12 @@
#include <ctype.h>
#include <string.h>
-#ifndef FALSE
-#define FALSE (0)
+#ifndef FALSE
+#define FALSE (0)
#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
+#ifndef TRUE
+#define TRUE (!FALSE)
#endif
static const char _xdg_utf8_skip_data[256] = {
@@ -70,49 +70,49 @@ _xdg_utf8_to_ucs4(const char *source)
int bytelength = 0;
xdg_unichar_t result;
if ( ! (*source & 0x40) )
- {
- ucs32 = *source;
- }
+ {
+ ucs32 = *source;
+ }
else
- {
- if ( ! (*source & 0x20) )
- {
- result = *source++ & 0x1F;
- bytelength = 2;
- }
- else if ( ! (*source & 0x10) )
- {
- result = *source++ & 0x0F;
- bytelength = 3;
- }
- else if ( ! (*source & 0x08) )
- {
- result = *source++ & 0x07;
- bytelength = 4;
- }
- else if ( ! (*source & 0x04) )
- {
- result = *source++ & 0x03;
- bytelength = 5;
- }
- else if ( ! (*source & 0x02) )
- {
- result = *source++ & 0x01;
- bytelength = 6;
- }
- else
- {
- result = *source++;
- bytelength = 1;
- }
-
- for ( bytelength --; bytelength > 0; bytelength -- )
- {
- result <<= 6;
- result |= *source++ & 0x3F;
- }
- ucs32 = result;
- }
+ {
+ if ( ! (*source & 0x20) )
+ {
+ result = *source++ & 0x1F;
+ bytelength = 2;
+ }
+ else if ( ! (*source & 0x10) )
+ {
+ result = *source++ & 0x0F;
+ bytelength = 3;
+ }
+ else if ( ! (*source & 0x08) )
+ {
+ result = *source++ & 0x07;
+ bytelength = 4;
+ }
+ else if ( ! (*source & 0x04) )
+ {
+ result = *source++ & 0x03;
+ bytelength = 5;
+ }
+ else if ( ! (*source & 0x02) )
+ {
+ result = *source++ & 0x01;
+ bytelength = 6;
+ }
+ else
+ {
+ result = *source++;
+ bytelength = 1;
+ }
+
+ for ( bytelength --; bytelength > 0; bytelength -- )
+ {
+ result <<= 6;
+ result |= *source++ & 0x3F;
+ }
+ ucs32 = result;
+ }
}
return ucs32;
}
diff --git a/xdgmimeint.h b/xdgmimeint.h
index 28814871..4aa9d1a2 100644
--- a/xdgmimeint.h
+++ b/xdgmimeint.h
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -31,12 +31,12 @@
#include "xdgmime.h"
-#ifndef FALSE
-#define FALSE (0)
+#ifndef FALSE
+#define FALSE (0)
#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
+#ifndef TRUE
+#define TRUE (!FALSE)
#endif
/* FIXME: Needs to be configure check */
@@ -55,10 +55,10 @@ typedef unsigned int xdg_uint32_t;
#define SWAP_BE16_TO_LE16(val) (xdg_uint16_t)(((xdg_uint16_t)(val) << 8)|((xdg_uint16_t)(val) >> 8))
-#define SWAP_BE32_TO_LE32(val) (xdg_uint32_t)((((xdg_uint32_t)(val) & 0xFF000000U) >> 24) | \
- (((xdg_uint32_t)(val) & 0x00FF0000U) >> 8) | \
- (((xdg_uint32_t)(val) & 0x0000FF00U) << 8) | \
- (((xdg_uint32_t)(val) & 0x000000FFU) << 24))
+#define SWAP_BE32_TO_LE32(val) (xdg_uint32_t)((((xdg_uint32_t)(val) & 0xFF000000U) >> 24) | \
+ (((xdg_uint32_t)(val) & 0x00FF0000U) >> 8) | \
+ (((xdg_uint32_t)(val) & 0x0000FF00U) << 8) | \
+ (((xdg_uint32_t)(val) & 0x000000FFU) << 24))
/* UTF-8 utils
*/
extern const char *const _xdg_utf8_skip;
diff --git a/xdgmimemagic.cpp b/xdgmimemagic.cpp
index 5b624fe2..5caf1043 100644
--- a/xdgmimemagic.cpp
+++ b/xdgmimemagic.cpp
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -39,12 +39,12 @@
#include <errno.h>
#include <limits.h>
-#ifndef FALSE
-#define FALSE (0)
+#ifndef FALSE
+#define FALSE (0)
#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
+#ifndef TRUE
+#define TRUE (!FALSE)
#endif
extern int errno;
@@ -121,11 +121,11 @@ _xdg_mime_magic_matchlet_free (XdgMimeMagicMatchlet *mime_magic_matchlet)
if (mime_magic_matchlet)
{
if (mime_magic_matchlet->next)
- _xdg_mime_magic_matchlet_free (mime_magic_matchlet->next);
+ _xdg_mime_magic_matchlet_free (mime_magic_matchlet->next);
if (mime_magic_matchlet->value)
- free (mime_magic_matchlet->value);
+ free (mime_magic_matchlet->value);
if (mime_magic_matchlet->mask)
- free (mime_magic_matchlet->mask);
+ free (mime_magic_matchlet->mask);
free (mime_magic_matchlet);
}
}
@@ -144,9 +144,9 @@ _xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match)
next = ptr->next;
if (ptr->mime_type)
- free ((void *) ptr->mime_type);
+ free ((void *) ptr->mime_type);
if (ptr->matchlet)
- _xdg_mime_magic_matchlet_free (ptr->matchlet);
+ _xdg_mime_magic_matchlet_free (ptr->matchlet);
free (ptr);
ptr = next;
@@ -158,7 +158,7 @@ _xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match)
*/
static char *
_xdg_mime_magic_read_to_newline (FILE *magic_file,
- int *end_of_file)
+ int *end_of_file)
{
char *retval;
int c;
@@ -173,18 +173,18 @@ _xdg_mime_magic_read_to_newline (FILE *magic_file,
{
c = getc_unlocked (magic_file);
if (c == EOF)
- {
- *end_of_file = TRUE;
- break;
- }
+ {
+ *end_of_file = TRUE;
+ break;
+ }
if (c == '\n' || c == '\000')
- break;
+ break;
retval[pos++] = (char) c;
if (pos % 128 == 127)
- {
- len = len + 128;
- retval = (char *)realloc (retval, len);
- }
+ {
+ len = len + 128;
+ retval = (char *)realloc (retval, len);
+ }
}
retval[pos] = '\000';
@@ -195,7 +195,7 @@ _xdg_mime_magic_read_to_newline (FILE *magic_file,
*/
static int
_xdg_mime_magic_read_a_number (FILE *magic_file,
- int *end_of_file)
+ int *end_of_file)
{
/* LONG_MAX is about 20 characters on my system */
#define MAX_NUMBER_SIZE 30
@@ -209,19 +209,19 @@ _xdg_mime_magic_read_a_number (FILE *magic_file,
c = getc_unlocked (magic_file);
if (c == EOF)
- {
- *end_of_file = TRUE;
- break;
- }
+ {
+ *end_of_file = TRUE;
+ break;
+ }
if (! isdigit (c))
- {
- ungetc (c, magic_file);
- break;
- }
+ {
+ ungetc (c, magic_file);
+ break;
+ }
number_string[pos] = (char) c;
pos++;
if (pos == MAX_NUMBER_SIZE)
- break;
+ break;
}
if (pos > 0)
{
@@ -230,7 +230,7 @@ _xdg_mime_magic_read_a_number (FILE *magic_file,
retval = strtol (number_string, NULL, 10);
if ((retval < INT_MIN) || (retval > INT_MAX) || (errno != 0))
- return -1;
+ return -1;
}
return retval;
@@ -297,9 +297,9 @@ _xdg_mime_magic_parse_error (FILE *magic_file)
{
c = getc_unlocked (magic_file);
if (c == EOF)
- return XDG_MIME_MAGIC_EOF;
+ return XDG_MIME_MAGIC_EOF;
if (c == '\n')
- return XDG_MIME_MAGIC_SECTION;
+ return XDG_MIME_MAGIC_SECTION;
}
}
@@ -309,7 +309,7 @@ _xdg_mime_magic_parse_error (FILE *magic_file)
*/
static XdgMimeMagicState
_xdg_mime_magic_parse_magic_line (FILE *magic_file,
- XdgMimeMagicMatch *match)
+ XdgMimeMagicMatch *match)
{
XdgMimeMagicMatchlet *matchlet;
int c;
@@ -338,12 +338,12 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
ungetc (c, magic_file);
indent = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
if (end_of_file)
- return XDG_MIME_MAGIC_EOF;
+ return XDG_MIME_MAGIC_EOF;
if (indent == -1)
- return XDG_MIME_MAGIC_ERROR;
+ return XDG_MIME_MAGIC_ERROR;
c = getc_unlocked (magic_file);
if (c == EOF)
- return XDG_MIME_MAGIC_EOF;
+ return XDG_MIME_MAGIC_EOF;
}
if (c != '>')
@@ -406,9 +406,9 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
{
_xdg_mime_magic_matchlet_free (matchlet);
if (feof (magic_file))
- return XDG_MIME_MAGIC_EOF;
+ return XDG_MIME_MAGIC_EOF;
else
- return XDG_MIME_MAGIC_ERROR;
+ return XDG_MIME_MAGIC_ERROR;
}
c = getc_unlocked (magic_file);
@@ -417,19 +417,19 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
matchlet->mask = (unsigned char *)malloc (matchlet->value_length);
/* OOM */
if (matchlet->mask == NULL)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- return XDG_MIME_MAGIC_ERROR;
- }
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ return XDG_MIME_MAGIC_ERROR;
+ }
bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file);
if (bytes_read != matchlet->value_length)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- if (feof (magic_file))
- return XDG_MIME_MAGIC_EOF;
- else
- return XDG_MIME_MAGIC_ERROR;
- }
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ if (feof (magic_file))
+ return XDG_MIME_MAGIC_EOF;
+ else
+ return XDG_MIME_MAGIC_ERROR;
+ }
c = getc_unlocked (magic_file);
}
@@ -437,18 +437,18 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
{
matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
if (end_of_file)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- return XDG_MIME_MAGIC_EOF;
- }
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ return XDG_MIME_MAGIC_EOF;
+ }
if (matchlet->word_size != 0 &&
- matchlet->word_size != 1 &&
- matchlet->word_size != 2 &&
- matchlet->word_size != 4)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- return XDG_MIME_MAGIC_ERROR;
- }
+ matchlet->word_size != 1 &&
+ matchlet->word_size != 2 &&
+ matchlet->word_size != 4)
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ return XDG_MIME_MAGIC_ERROR;
+ }
c = getc_unlocked (magic_file);
}
@@ -456,15 +456,15 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
{
matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
if (end_of_file)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- return XDG_MIME_MAGIC_EOF;
- }
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ return XDG_MIME_MAGIC_EOF;
+ }
if (matchlet->range_length == (unsigned int)-1)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- return XDG_MIME_MAGIC_ERROR;
- }
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ return XDG_MIME_MAGIC_ERROR;
+ }
c = getc_unlocked (magic_file);
}
@@ -473,32 +473,32 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
{
/* We clean up the matchlet, byte swapping if needed */
if (matchlet->word_size > 1)
- {
- size_t i;
- if (matchlet->value_length % matchlet->word_size != 0)
- {
- _xdg_mime_magic_matchlet_free (matchlet);
- return XDG_MIME_MAGIC_ERROR;
- }
- /* FIXME: need to get this defined in a <config.h> style file */
+ {
+ size_t i;
+ if (matchlet->value_length % matchlet->word_size != 0)
+ {
+ _xdg_mime_magic_matchlet_free (matchlet);
+ return XDG_MIME_MAGIC_ERROR;
+ }
+ /* FIXME: need to get this defined in a <config.h> style file */
#if LITTLE_ENDIAN
- for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size)
- {
- if (matchlet->word_size == 2)
- *((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i)));
- else if (matchlet->word_size == 4)
- *((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i)));
- if (matchlet->mask)
- {
- if (matchlet->word_size == 2)
- *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i)));
- else if (matchlet->word_size == 4)
- *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i)));
-
- }
- }
+ for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size)
+ {
+ if (matchlet->word_size == 2)
+ *((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i)));
+ else if (matchlet->word_size == 4)
+ *((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i)));
+ if (matchlet->mask)
+ {
+ if (matchlet->word_size == 2)
+ *((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i)));
+ else if (matchlet->word_size == 4)
+ *((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i)));
+
+ }
+ }
#endif
- }
+ }
matchlet->next = match->matchlet;
match->matchlet = matchlet;
@@ -516,8 +516,8 @@ _xdg_mime_magic_parse_magic_line (FILE *magic_file,
static int
_xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet,
- const void *data,
- size_t len)
+ const void *data,
+ size_t len)
{
size_t i, j;
@@ -526,62 +526,62 @@ _xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet,
int valid_matchlet = TRUE;
if (i + matchlet->value_length > len)
- return FALSE;
+ return FALSE;
if (matchlet->mask)
- {
- for (j = 0; j < matchlet->value_length; j++)
- {
- if ((matchlet->value[j] & matchlet->mask[j]) !=
- ((((unsigned char *) data)[j + i]) & matchlet->mask[j]))
- {
- valid_matchlet = FALSE;
- break;
- }
- }
- }
+ {
+ for (j = 0; j < matchlet->value_length; j++)
+ {
+ if ((matchlet->value[j] & matchlet->mask[j]) !=
+ ((((unsigned char *) data)[j + i]) & matchlet->mask[j]))
+ {
+ valid_matchlet = FALSE;
+ break;
+ }
+ }
+ }
else
- {
- for (j = 0; j < matchlet->value_length; j++)
- {
- if (matchlet->value[j] != ((unsigned char *) data)[j + i])
- {
- valid_matchlet = FALSE;
- break;
- }
- }
- }
+ {
+ for (j = 0; j < matchlet->value_length; j++)
+ {
+ if (matchlet->value[j] != ((unsigned char *) data)[j + i])
+ {
+ valid_matchlet = FALSE;
+ break;
+ }
+ }
+ }
if (valid_matchlet)
- return TRUE;
+ return TRUE;
}
return FALSE;
}
static int
_xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet,
- const void *data,
- size_t len,
- int indent)
+ const void *data,
+ size_t len,
+ int indent)
{
while ((matchlet != NULL) && (matchlet->indent == indent))
{
if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len))
- {
- if ((matchlet->next == NULL) ||
- (matchlet->next->indent <= indent))
- return TRUE;
-
- if (_xdg_mime_magic_matchlet_compare_level (matchlet->next,
- data,
- len,
- indent + 1))
- return TRUE;
- }
+ {
+ if ((matchlet->next == NULL) ||
+ (matchlet->next->indent <= indent))
+ return TRUE;
+
+ if (_xdg_mime_magic_matchlet_compare_level (matchlet->next,
+ data,
+ len,
+ indent + 1))
+ return TRUE;
+ }
do
- {
- matchlet = matchlet->next;
- }
+ {
+ matchlet = matchlet->next;
+ }
while (matchlet && matchlet->indent > indent);
}
@@ -590,15 +590,15 @@ _xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet,
static int
_xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match,
- const void *data,
- size_t len)
+ const void *data,
+ size_t len)
{
return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0);
}
static void
_xdg_mime_magic_insert_match (XdgMimeMagic *mime_magic,
- XdgMimeMagicMatch *match)
+ XdgMimeMagicMatch *match)
{
XdgMimeMagicMatch *list;
@@ -619,11 +619,11 @@ _xdg_mime_magic_insert_match (XdgMimeMagic *mime_magic,
while (list->next != NULL)
{
if (list->next->priority < match->priority)
- {
- match->next = list->next;
- list->next = match;
- return;
- }
+ {
+ match->next = list->next;
+ list->next = match;
+ return;
+ }
list = list->next;
}
list->next = match;
@@ -653,17 +653,17 @@ _xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic)
const char *
_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic,
- const void *data,
- size_t len)
+ const void *data,
+ size_t len)
{
XdgMimeMagicMatch *match;
for (match = mime_magic->match_list; match; match = match->next)
{
if (_xdg_mime_magic_match_compare_to_data (match, data, len))
- {
- return match->mime_type;
- }
+ {
+ return match->mime_type;
+ }
}
return NULL;
@@ -680,13 +680,13 @@ _xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic)
XdgMimeMagicMatchlet *matchlet;
for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next)
- {
- int extent;
+ {
+ int extent;
- extent = matchlet->value_length + matchlet->offset + matchlet->range_length;
- if (max_extent < extent)
- max_extent = extent;
- }
+ extent = matchlet->value_length + matchlet->offset + matchlet->range_length;
+ if (max_extent < extent)
+ max_extent = extent;
+ }
}
mime_magic->max_extent = max_extent;
@@ -719,7 +719,7 @@ _xdg_mime_magic_matchlet_mirror (XdgMimeMagicMatchlet *matchlets)
static void
_xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic,
- FILE *magic_file)
+ FILE *magic_file)
{
XdgMimeMagicState state;
XdgMimeMagicMatch *match = NULL; /* Quiet compiler */
@@ -729,39 +729,39 @@ _xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic,
while (state != XDG_MIME_MAGIC_EOF)
{
switch (state)
- {
- case XDG_MIME_MAGIC_SECTION:
- match = _xdg_mime_magic_match_new ();
- state = _xdg_mime_magic_parse_header (magic_file, match);
- if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
- _xdg_mime_magic_match_free (match);
- break;
- case XDG_MIME_MAGIC_MAGIC:
- state = _xdg_mime_magic_parse_magic_line (magic_file, match);
- if (state == XDG_MIME_MAGIC_SECTION ||
- (state == XDG_MIME_MAGIC_EOF && match->mime_type))
- {
- match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet);
- _xdg_mime_magic_insert_match (mime_magic, match);
- }
- else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
- _xdg_mime_magic_match_free (match);
- break;
- case XDG_MIME_MAGIC_ERROR:
- state = _xdg_mime_magic_parse_error (magic_file);
- break;
- case XDG_MIME_MAGIC_EOF:
- default:
- /* Make the compiler happy */
- assert (0);
- }
+ {
+ case XDG_MIME_MAGIC_SECTION:
+ match = _xdg_mime_magic_match_new ();
+ state = _xdg_mime_magic_parse_header (magic_file, match);
+ if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
+ _xdg_mime_magic_match_free (match);
+ break;
+ case XDG_MIME_MAGIC_MAGIC:
+ state = _xdg_mime_magic_parse_magic_line (magic_file, match);
+ if (state == XDG_MIME_MAGIC_SECTION ||
+ (state == XDG_MIME_MAGIC_EOF && match->mime_type))
+ {
+ match->matchlet = _xdg_mime_magic_matchlet_mirror (match->matchlet);
+ _xdg_mime_magic_insert_match (mime_magic, match);
+ }
+ else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
+ _xdg_mime_magic_match_free (match);
+ break;
+ case XDG_MIME_MAGIC_ERROR:
+ state = _xdg_mime_magic_parse_error (magic_file);
+ break;
+ case XDG_MIME_MAGIC_EOF:
+ default:
+ /* Make the compiler happy */
+ assert (0);
+ }
}
_xdg_mime_update_mime_magic_extents (mime_magic);
}
void
_xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic,
- const char *file_name)
+ const char *file_name)
{
FILE *magic_file;
char header[12];
diff --git a/xdgmimemagic.h b/xdgmimemagic.h
index dea0a3c0..55803268 100644
--- a/xdgmimemagic.h
+++ b/xdgmimemagic.h
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -44,11 +44,11 @@ typedef struct XdgMimeMagic XdgMimeMagic;
XdgMimeMagic *_xdg_mime_magic_new (void);
void _xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic,
- const char *file_name);
+ const char *file_name);
void _xdg_mime_magic_free (XdgMimeMagic *mime_magic);
int _xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic);
const char *_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic,
- const void *data,
- size_t len);
+ const void *data,
+ size_t len);
#endif /* __XDG_MIME_MAGIC_H__ */
diff --git a/xdgmimeparent.cpp b/xdgmimeparent.cpp
index 1585628a..3024d9f9 100644
--- a/xdgmimeparent.cpp
+++ b/xdgmimeparent.cpp
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -37,12 +37,12 @@
#include <string.h>
#include <fnmatch.h>
-#ifndef FALSE
-#define FALSE (0)
+#ifndef FALSE
+#define FALSE (0)
#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
+#ifndef TRUE
+#define TRUE (!FALSE)
#endif
typedef struct XdgMimeParents XdgMimeParents;
@@ -73,7 +73,7 @@ _xdg_mime_parent_list_new (void)
return list;
}
-void
+void
_xdg_mime_parent_list_free (XdgParentList *list)
{
int i;
@@ -82,13 +82,13 @@ _xdg_mime_parent_list_free (XdgParentList *list)
if (list->parents)
{
for (i = 0; i < list->n_mimes; i++)
- {
- for (p = list->parents[i].parents; *p; p++)
- free (*p);
+ {
+ for (p = list->parents[i].parents; *p; p++)
+ free (*p);
- free (list->parents[i].parents);
- free (list->parents[i].mime);
- }
+ free (list->parents[i].parents);
+ free (list->parents[i].mime);
+ }
free (list->parents);
}
free (list);
@@ -102,7 +102,7 @@ parent_entry_cmp (const void *v1, const void *v2)
const char **
_xdg_mime_parent_list_lookup (XdgParentList *list,
- const char *mime)
+ const char *mime)
{
XdgMimeParents *entry;
XdgMimeParents key;
@@ -113,7 +113,7 @@ _xdg_mime_parent_list_lookup (XdgParentList *list,
key.parents = NULL;
entry = (XdgMimeParents *)bsearch (&key, list->parents, list->n_mimes,
- sizeof (XdgMimeParents), &parent_entry_cmp);
+ sizeof (XdgMimeParents), &parent_entry_cmp);
if (entry)
return (const char **)entry->parents;
}
@@ -123,7 +123,7 @@ _xdg_mime_parent_list_lookup (XdgParentList *list,
void
_xdg_mime_parent_read_from_file (XdgParentList *list,
- const char *file_name)
+ const char *file_name)
{
FILE *file;
char line[255];
@@ -144,64 +144,64 @@ _xdg_mime_parent_read_from_file (XdgParentList *list,
{
char *sep;
if (line[0] == '#')
- continue;
+ continue;
sep = strchr (line, ' ');
if (sep == NULL)
- continue;
+ continue;
*(sep++) = '\000';
sep[strlen (sep) -1] = '\000';
entry = NULL;
for (i = 0; i < list->n_mimes; i++)
- {
- if (strcmp (list->parents[i].mime, line) == 0)
- {
- entry = &(list->parents[i]);
- break;
- }
- }
-
+ {
+ if (strcmp (list->parents[i].mime, line) == 0)
+ {
+ entry = &(list->parents[i]);
+ break;
+ }
+ }
+
if (!entry)
- {
- if (list->n_mimes == alloc)
- {
- alloc <<= 1;
- list->parents = (XdgMimeParents *)realloc (list->parents,
- alloc * sizeof (XdgMimeParents));
- }
- list->parents[list->n_mimes].mime = strdup (line);
- list->parents[list->n_mimes].parents = NULL;
- entry = &(list->parents[list->n_mimes]);
- list->n_mimes++;
- }
+ {
+ if (list->n_mimes == alloc)
+ {
+ alloc <<= 1;
+ list->parents = (XdgMimeParents *)realloc (list->parents,
+ alloc * sizeof (XdgMimeParents));
+ }
+ list->parents[list->n_mimes].mime = strdup (line);
+ list->parents[list->n_mimes].parents = NULL;
+ entry = &(list->parents[list->n_mimes]);
+ list->n_mimes++;
+ }
if (!entry->parents)
- {
- entry->n_parents = 1;
- entry->parents = (char **)malloc ((entry->n_parents + 1) * sizeof (char *));
- }
+ {
+ entry->n_parents = 1;
+ entry->parents = (char **)malloc ((entry->n_parents + 1) * sizeof (char *));
+ }
else
- {
- entry->n_parents += 1;
- entry->parents = (char **)realloc (entry->parents,
- (entry->n_parents + 2) * sizeof (char *));
- }
+ {
+ entry->n_parents += 1;
+ entry->parents = (char **)realloc (entry->parents,
+ (entry->n_parents + 2) * sizeof (char *));
+ }
entry->parents[entry->n_parents - 1] = strdup (sep);
entry->parents[entry->n_parents] = NULL;
}
- list->parents = (XdgMimeParents *)realloc (list->parents,
- list->n_mimes * sizeof (XdgMimeParents));
+ list->parents = (XdgMimeParents *)realloc (list->parents,
+ list->n_mimes * sizeof (XdgMimeParents));
+
+ fclose (file);
- fclose (file);
-
if (list->n_mimes > 1)
- qsort (list->parents, list->n_mimes,
+ qsort (list->parents, list->n_mimes,
sizeof (XdgMimeParents), &parent_entry_cmp);
}
-void
+void
_xdg_mime_parent_list_dump (XdgParentList *list)
{
int i;
@@ -210,10 +210,10 @@ _xdg_mime_parent_list_dump (XdgParentList *list)
if (list->parents)
{
for (i = 0; i < list->n_mimes; i++)
- {
- for (p = list->parents[i].parents; *p; p++)
- printf ("%s %s\n", list->parents[i].mime, *p);
- }
+ {
+ for (p = list->parents[i].parents; *p; p++)
+ printf ("%s %s\n", list->parents[i].mime, *p);
+ }
}
}
diff --git a/xdgmimeparent.h b/xdgmimeparent.h
index da29452c..a10846b3 100644
--- a/xdgmimeparent.h
+++ b/xdgmimeparent.h
@@ -16,7 +16,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -40,11 +40,11 @@ typedef struct XdgParentList XdgParentList;
#endif
void _xdg_mime_parent_read_from_file (XdgParentList *list,
- const char *file_name);
+ const char *file_name);
XdgParentList *_xdg_mime_parent_list_new (void);
void _xdg_mime_parent_list_free (XdgParentList *list);
const char **_xdg_mime_parent_list_lookup (XdgParentList *list,
- const char *mime);
+ const char *mime);
void _xdg_mime_parent_list_dump (XdgParentList *list);
#endif /* __XDG_MIME_PARENT_H__ */