Merge branch 'master' into fix-indentation-merge

This commit is contained in:
ridiculousfish 2012-11-18 15:12:22 -08:00
commit bab69f2672
9 changed files with 7379 additions and 7324 deletions

File diff suppressed because it is too large Load Diff

2165
common.cpp

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/** \file common.h /** \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 #ifndef FISH_COMMON_H
@ -85,7 +85,7 @@ typedef unsigned int escape_flags_t;
void exit_without_destructors(int code) __attribute__ ((noreturn)); 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;
@ -118,56 +118,56 @@ extern const wchar_t *program_name;
failiure, the current function is ended at once. The second failiure, the current function is ended at once. The second
parameter is the return value of the current function on failiure. parameter is the return value of the current function on failiure.
*/ */
#define CHECK( arg, retval ) \ #define CHECK( arg, retval ) \
if( !(arg) ) \ if( !(arg) ) \
{ \ { \
debug( 0, \ debug( 0, \
"function %s called with null value for argument %s. ", \ "function %s called with null value for argument %s. ", \
__func__, \ __func__, \
#arg ); \ #arg ); \
bugreport(); \ bugreport(); \
show_stackframe(); \ show_stackframe(); \
return retval; \ return retval; \
} }
/** /**
Pause for input, then exit the program. If supported, print a backtrace first. Pause for input, then exit the program. If supported, print a backtrace first.
*/ */
#define FATAL_EXIT() \ #define FATAL_EXIT() \
{ \ { \
char exit_read_buff; \ char exit_read_buff; \
show_stackframe(); \ show_stackframe(); \
read( 0, &exit_read_buff, 1 ); \ read( 0, &exit_read_buff, 1 ); \
exit_without_destructors( 1 ); \ exit_without_destructors( 1 ); \
} \ } \
/** /**
Exit program at once, leaving an error message about running out of memory. Exit program at once, leaving an error message about running out of memory.
*/ */
#define DIE_MEM() \ #define DIE_MEM() \
{ \ { \
fwprintf( stderr, \ fwprintf( stderr, \
L"fish: Out of memory on line %ld of file %s, shutting down fish\n", \ L"fish: Out of memory on line %ld of file %s, shutting down fish\n", \
(long)__LINE__, \ (long)__LINE__, \
__FILE__ ); \ __FILE__ ); \
FATAL_EXIT(); \ FATAL_EXIT(); \
} }
/** /**
Check if signals are blocked. If so, print an error message and Check if signals are blocked. If so, print an error message and
return from the function performing this check. return from the function performing this check.
*/ */
#define CHECK_BLOCK( retval ) \ #define CHECK_BLOCK( retval ) \
if( signal_is_blocked() ) \ if( signal_is_blocked() ) \
{ \ { \
debug( 0, \ debug( 0, \
"function %s called while blocking signals. ", \ "function %s called while blocking signals. ", \
__func__); \ __func__); \
bugreport(); \ bugreport(); \
show_stackframe(); \ show_stackframe(); \
return retval; \ return retval; \
} }
/** /**
Shorthand for wgettext call Shorthand for wgettext call
@ -651,7 +651,7 @@ wcstring escape_string( const wcstring &in, escape_flags_t flags );
*/ */
wchar_t *unescape( const wchar_t * in, wchar_t *unescape( const wchar_t * in,
int escape_special ); int escape_special );
bool unescape_string( wcstring &str, bool unescape_string( wcstring &str,
int escape_special ); int escape_special );
@ -717,7 +717,7 @@ void bugreport();
double timef(); 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(). This is our replacement for pthread_main_np().
*/ */
void set_main_thread(); void set_main_thread();
@ -729,6 +729,10 @@ void configure_thread_assertions_for_testing();
/** Set up a guard to complain if we try to do certain things (like take a lock) after calling fork */ /** Set up a guard to complain if we try to do certain things (like take a lock) after calling fork */
void setup_fork_guards(void); void setup_fork_guards(void);
/** Save the value of tcgetpgrp so we can restore it on exit */
void save_term_foreground_process_group(void);
void restore_term_foreground_process_group(void);
/** Return whether we are the child of a fork */ /** Return whether we are the child of a fork */
bool is_forked_child(void); bool is_forked_child(void);
void assert_is_not_forked_child(const char *who); void assert_is_not_forked_child(const char *who);

525
fish.cpp
View File

@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file fish.c /** \file fish.c
The main loop of <tt>fish</tt>. The main loop of <tt>fish</tt>.
*/ */
#include "config.h" #include "config.h"
@ -217,27 +217,27 @@ static int read_init(const struct config_paths_t &paths)
{ {
parser_t &parser = parser_t::principal_parser(); parser_t &parser = parser_t::principal_parser();
const io_chain_t empty_ios; 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.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 ); 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 We need to get the configuration directory before we can source the user configuration file
*/ */
wcstring config_dir; wcstring config_dir;
/* /*
If path_get_config returns false then we have no configuration directory If path_get_config returns false then we have no configuration directory
and no custom config to load. and no custom config to load.
*/ */
if (path_get_config(config_dir)) 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()); 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 ); parser.eval( eval_buff, empty_ios, TOP );
} }
return 1; 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 ) static int fish_parse_opt( int argc, char **argv, const char **cmd_ptr )
{ {
int my_optind; int my_optind;
int force_interactive=0; int force_interactive=0;
while( 1 ) while( 1 )
{ {
static struct option static struct option
long_options[] = long_options[] =
{ {
{ {
"command", required_argument, 0, 'c' "command", required_argument, 0, 'c'
} }
, ,
{ {
"debug-level", required_argument, 0, 'd' "debug-level", required_argument, 0, 'd'
} }
, ,
{ {
"interactive", no_argument, 0, 'i' "interactive", no_argument, 0, 'i'
} }
, ,
{ {
"login", no_argument, 0, 'l' "login", no_argument, 0, 'l'
} }
, ,
{ {
"no-execute", no_argument, 0, 'n' "no-execute", no_argument, 0, 'n'
} }
, ,
{ {
"profile", required_argument, 0, 'p' "profile", required_argument, 0, 'p'
} }
, ,
{ {
"help", no_argument, 0, 'h' "help", no_argument, 0, 'h'
} }
, ,
{ {
"version", no_argument, 0, 'v' "version", no_argument, 0, 'v'
} }
, ,
{ {
0, 0, 0, 0 0, 0, 0, 0
} }
} }
; ;
int opt_index = 0; int opt_index = 0;
int opt = getopt_long( argc, int opt = getopt_long( argc,
argv, argv,
GETOPT_STRING, GETOPT_STRING,
long_options, long_options,
&opt_index ); &opt_index );
if( opt == -1 ) if( opt == -1 )
break; break;
switch( opt ) switch( opt )
{ {
case 0: case 0:
{ {
break; break;
} }
case 'c': case 'c':
{ {
*cmd_ptr = optarg; *cmd_ptr = optarg;
is_interactive_session = 0; is_interactive_session = 0;
break; break;
} }
case 'd': case 'd':
{ {
char *end; char *end;
long tmp; long tmp;
errno = 0; errno = 0;
tmp = strtol(optarg, &end, 10); tmp = strtol(optarg, &end, 10);
if( tmp >= 0 && tmp <=10 && !*end && !errno ) if( tmp >= 0 && tmp <=10 && !*end && !errno )
{ {
debug_level = (int)tmp; debug_level = (int)tmp;
} }
else else
{ {
debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg ); debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
exit_without_destructors(1); exit_without_destructors(1);
} }
break; break;
} }
case 'h': case 'h':
{ {
*cmd_ptr = "__fish_print_help fish"; *cmd_ptr = "__fish_print_help fish";
break; break;
} }
case 'i': case 'i':
{ {
force_interactive = 1; force_interactive = 1;
break; break;
} }
case 'l': case 'l':
{ {
is_login=1; is_login=1;
break; break;
} }
case 'n': case 'n':
{ {
no_exec=1; no_exec=1;
break; break;
} }
case 'p': case 'p':
{ {
profile = optarg; profile = optarg;
break; break;
} }
case 'v': case 'v':
{ {
fwprintf( stderr, fwprintf( stderr,
_(L"%s, version %s\n"), _(L"%s, version %s\n"),
PACKAGE_NAME, PACKAGE_NAME,
PACKAGE_VERSION ); PACKAGE_VERSION );
exit_without_destructors( 0 ); exit_without_destructors( 0 );
} }
case '?': case '?':
{ {
exit_without_destructors( 1 ); exit_without_destructors( 1 );
} }
} }
} }
my_optind = optind; my_optind = optind;
is_login |= (strcmp( argv[0], "-fish") == 0); is_login |= (strcmp( argv[0], "-fish") == 0);
/* /*
We are an interactive session if we have not been given an We are an interactive session if we have not been given an
explicit command to execute, _and_ stdin is a tty. explicit command to execute, _and_ stdin is a tty.
*/ */
is_interactive_session &= (*cmd_ptr == 0); is_interactive_session &= (*cmd_ptr == 0);
is_interactive_session &= (my_optind == argc); is_interactive_session &= (my_optind == argc);
is_interactive_session &= isatty(STDIN_FILENO); is_interactive_session &= isatty(STDIN_FILENO);
/* /*
We are also an interactive session if we have are forced- We are also an interactive session if we have are forced-
*/ */
is_interactive_session |= force_interactive; is_interactive_session |= force_interactive;
return my_optind; 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 ) static wcstring full_escape( const wchar_t *in )
{ {
wcstring out; wcstring out;
for( ; *in; in++ ) for( ; *in; in++ )
{ {
if( *in < 32 ) if( *in < 32 )
{ {
append_format( out, L"\\x%.2x", *in ); append_format( out, L"\\x%.2x", *in );
} }
else if( *in < 128 ) else if( *in < 128 )
{ {
out.push_back(*in); out.push_back(*in);
} }
else if( *in < 65536 ) else if( *in < 65536 )
{ {
append_format( out, L"\\u%.4x", *in ); append_format( out, L"\\u%.4x", *in );
} }
else else
{ {
append_format( out, L"\\U%.8x", *in ); append_format( out, L"\\U%.8x", *in );
} }
} }
return out; return out;
} }
extern int g_fork_count; extern int g_fork_count;
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
int res=1; int res=1;
const char *cmd=0; const char *cmd=0;
int my_optind=0; int my_optind=0;
set_main_thread(); set_main_thread();
setup_fork_guards(); setup_fork_guards();
save_term_foreground_process_group();
wsetlocale( LC_ALL, L"" ); wsetlocale( LC_ALL, L"" );
is_interactive_session=1; is_interactive_session=1;
program_name=L"fish"; program_name=L"fish";
//struct stat tmp; //struct stat tmp;
//stat("----------FISH_HIT_MAIN----------", &tmp); //stat("----------FISH_HIT_MAIN----------", &tmp);
my_optind = fish_parse_opt( argc, argv, &cmd ); my_optind = fish_parse_opt( argc, argv, &cmd );
/* /*
No-exec is prohibited when in interactive mode No-exec is prohibited when in interactive mode
*/ */
if( is_interactive_session && no_exec) if( is_interactive_session && no_exec)
{ {
debug( 1, _(L"Can not use the no-execute mode when running an interactive session") ); debug( 1, _(L"Can not use the no-execute mode when running an interactive session") );
no_exec = 0; no_exec = 0;
} }
const struct config_paths_t paths = determine_config_directory_paths(argv[0]); const struct config_paths_t paths = determine_config_directory_paths(argv[0]);
proc_init(); proc_init();
event_init(); event_init();
wutil_init(); wutil_init();
//parser_init(); builtin_init();
builtin_init(); function_init();
function_init(); env_init(&paths);
env_init(&paths); reader_init();
reader_init(); history_init();
history_init();
parser_t &parser = parser_t::principal_parser(); parser_t &parser = parser_t::principal_parser();
@ -481,91 +481,92 @@ int main( int argc, char **argv )
printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count);
const io_chain_t empty_ios; const io_chain_t empty_ios;
if( read_init(paths) ) if( read_init(paths) )
{ {
if( cmd != 0 ) if( cmd != 0 )
{ {
wchar_t *cmd_wcs = str2wcs( cmd ); wchar_t *cmd_wcs = str2wcs( cmd );
res = parser.eval( cmd_wcs, empty_ios, TOP ); res = parser.eval( cmd_wcs, empty_ios, TOP );
free(cmd_wcs); free(cmd_wcs);
reader_exit(0, 0); reader_exit(0, 0);
} }
else else
{ {
if( my_optind == argc ) if( my_optind == argc )
{ {
res = reader_read( STDIN_FILENO, empty_ios ); res = reader_read( STDIN_FILENO, empty_ios );
} }
else else
{ {
char **ptr; char **ptr;
char *file = *(argv+(my_optind++)); char *file = *(argv+(my_optind++));
int i; int i;
int fd; int fd;
wchar_t *rel_filename, *abs_filename; wchar_t *rel_filename, *abs_filename;
if( ( fd = open(file, O_RDONLY) ) == -1 ) if( ( fd = open(file, O_RDONLY) ) == -1 )
{ {
wperror( L"open" ); wperror( L"open" );
return 1; return 1;
} }
// OK to not do this atomically since we cannot have gone multithreaded yet // OK to not do this atomically since we cannot have gone multithreaded yet
set_cloexec(fd); set_cloexec(fd);
if( *(argv+my_optind)) if( *(argv+my_optind))
{ {
wcstring sb; wcstring sb;
for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ ) for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ )
{ {
if( i != 1 ) if( i != 1 )
sb.append( ARRAY_SEP_STR ); sb.append( ARRAY_SEP_STR );
sb.append( str2wcstring( *ptr )); sb.append( str2wcstring( *ptr ));
} }
env_set( L"argv", sb.c_str(), 0 ); env_set( L"argv", sb.c_str(), 0 );
} }
rel_filename = str2wcs( file ); rel_filename = str2wcs( file );
abs_filename = wrealpath( rel_filename, 0 ); abs_filename = wrealpath( rel_filename, 0 );
if( !abs_filename ) if( !abs_filename )
{ {
abs_filename = wcsdup(rel_filename); abs_filename = wcsdup(rel_filename);
} }
reader_push_current_filename( intern( abs_filename ) ); reader_push_current_filename( intern( abs_filename ) );
free( rel_filename ); free( rel_filename );
free( abs_filename ); free( abs_filename );
res = reader_read( fd, empty_ios ); res = reader_read( fd, empty_ios );
if( res ) if( res )
{ {
debug( 1, debug( 1,
_(L"Error while reading file %ls\n"), _(L"Error while reading file %ls\n"),
reader_current_filename()?reader_current_filename(): _(L"Standard input") ); reader_current_filename()?reader_current_filename(): _(L"Standard input") );
} }
reader_pop_current_filename(); reader_pop_current_filename();
} }
} }
} }
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res ); proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
history_destroy(); restore_term_foreground_process_group();
proc_destroy(); history_destroy();
builtin_destroy(); proc_destroy();
reader_destroy(); builtin_destroy();
parser.destroy(); reader_destroy();
wutil_destroy(); parser.destroy();
event_destroy(); wutil_destroy();
event_destroy();
env_destroy(); env_destroy();
if (g_log_forks) if (g_log_forks)
printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); 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();
} }

1385
proc.cpp

File diff suppressed because it is too large Load Diff

3009
reader.cpp

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/** \file reader.h /** \file reader.h
Prototypes for functions for reading data from stdin and passing Prototypes for functions for reading data from stdin and passing
to the parser. If stdin is a keyboard, it supplies a killring, to the parser. If stdin is a keyboard, it supplies a killring,
history, syntax highlighting, tab-completion and various other history, syntax highlighting, tab-completion and various other
features. features.
*/ */
#ifndef FISH_READER_H #ifndef FISH_READER_H
@ -177,6 +177,10 @@ void reader_set_left_prompt( const wcstring &prompt );
*/ */
void reader_set_right_prompt( const wcstring &prompt ); void reader_set_right_prompt( const wcstring &prompt );
/** Sets whether autosuggesting is allowed. */
void reader_set_allow_autosuggesting(bool flag);
/** /**
Returns true if the shell is exiting, 0 otherwise. Returns true if the shell is exiting, 0 otherwise.
*/ */

View File

@ -120,7 +120,7 @@ function __fish_config_interactive -d "Initializations that should be performed
# Pager colors # Pager colors
set_default fish_pager_color_prefix cyan set_default fish_pager_color_prefix cyan
set_default fish_pager_color_completion normal set_default fish_pager_color_completion normal
set_default fish_pager_color_description normal set_default fish_pager_color_description 555 yellow
set_default fish_pager_color_progress cyan set_default fish_pager_color_progress cyan
# #

File diff suppressed because it is too large Load Diff