Remove trailing whitespaces and change tabs to spaces

This commit is contained in:
Łukasz Niemier 2012-11-18 11:23:22 +01:00
parent b79854ad1a
commit 47df1ae40a
140 changed files with 29549 additions and 29549 deletions

View file

@ -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

View file

@ -70,11 +70,11 @@ 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?
@ -105,16 +105,16 @@ int autoload_t::load( const wcstring &cmd, bool reload )
/* 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 );
}
@ -181,8 +181,8 @@ autoload_function_t *autoload_t::get_autoloaded_function_with_creation(const wcs
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. */
{

View file

@ -58,10 +58,10 @@ private:
/** 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 {

File diff suppressed because it is too large Load diff

View file

@ -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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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:
{
process_t *p;
switch( mode )
{
case JOBS_DEFAULT:
{
if( header )
{
/*
Print table header before first job
*/
stdout_buffer.append( _( L"Job\tGroup\t" ));
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;
}
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_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" ));
}
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;
}
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" ));
}
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;
}
}
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;
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;
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
}
}
;
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_index = 0;
int opt = wgetopt_long( argc,
argv,
L"pclgh",
long_options,
&opt_index );
if( opt == -1 )
break;
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;
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;
}
}
if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
return 0;
}
}
}
else
{
if( woptind < argc )
{
int i;
}
else
{
if( woptind < argc )
{
int i;
found = 1;
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;
}
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 );
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 && !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;
}
}
}
}
/*
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] );
}
if( !found )
{
append_format(stdout_buffer,
_( L"%ls: There are no jobs\n" ),
argv[0] );
}
return 0;
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -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 processs 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 processs 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;
int i;
for( i=0; resource_arr[i].desc; i++ )
{
if( resource_arr[i].resource == what )
{
return resource_arr[i].multiplier;
}
}
return -1;
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;
struct rlimit ls;
getrlimit( resource, &ls );
getrlimit( resource, &ls );
return hard ? ls.rlim_max:ls.rlim_cur;
return hard ? ls.rlim_max:ls.rlim_cur;
}
/**
@ -141,12 +141,12 @@ 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,39 +155,39 @@ static void print( int resource, int hard )
*/
static void print_all( int hard )
{
int i;
int w=0;
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++ )
{
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;
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, "));
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);
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) );
}
}
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;
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";
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 );
struct rlimit ls;
getrlimit( resource, &ls );
if( hard )
{
ls.rlim_max = value;
}
if( hard )
{
ls.rlim_max = value;
}
if( soft )
{
ls.rlim_cur = 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;
}
}
/*
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;
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 hard=0;
int soft=0;
int what = RLIMIT_FSIZE;
int report_all = 0;
int what = RLIMIT_FSIZE;
int report_all = 0;
int argc = builtin_count_args( argv );
int argc = builtin_count_args( argv );
woptind=0;
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
}
}
;
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_index = 0;
int opt = wgetopt_long( argc,
argv,
L"aHScdflmnstuvh",
long_options,
&opt_index );
if( opt == -1 )
break;
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;
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 L'a':
report_all=1;
break;
case L'a':
report_all=1;
break;
case L'H':
hard=1;
break;
case L'H':
hard=1;
break;
case L'S':
soft=1;
break;
case L'S':
soft=1;
break;
case L'c':
what=RLIMIT_CORE;
break;
case L'c':
what=RLIMIT_CORE;
break;
case L'd':
what=RLIMIT_DATA;
break;
case L'd':
what=RLIMIT_DATA;
break;
case L'f':
what=RLIMIT_FSIZE;
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;
case L'm':
what=RLIMIT_RSS;
break;
#endif
case L'n':
what=RLIMIT_NOFILE;
break;
case L'n':
what=RLIMIT_NOFILE;
break;
case L's':
what=RLIMIT_STACK;
break;
case L's':
what=RLIMIT_STACK;
break;
case L't':
what=RLIMIT_CPU;
break;
case L't':
what=RLIMIT_CPU;
break;
#ifdef RLIMIT_NPROC
case L'u':
what=RLIMIT_NPROC;
break;
case L'u':
what=RLIMIT_NPROC;
break;
#endif
#ifdef RLIMIT_AS
case L'v':
what=RLIMIT_AS;
break;
case L'v':
what=RLIMIT_AS;
break;
#endif
case L'h':
builtin_print_help( parser, argv[0], stdout_buffer );
return 0;
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;
}
}
case L'?':
builtin_unknown_option( parser, argv[0], argv[woptind-1] );
return 1;
}
}
if( report_all )
{
if( argc - woptind == 0 )
{
print_all( hard );
}
else
{
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;
}
builtin_print_help( parser, argv[0], stderr_buffer );
return 1;
}
return 0;
}
return 0;
}
switch( argc - woptind )
{
case 0:
{
/*
Show current limit value
*/
print( what, hard );
break;
}
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;
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;
}
/*
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 );
}
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 );
}
return set( what, hard, soft, new_limit );
}
default:
{
default:
{
stderr_buffer.append(argv[0]);
stderr_buffer.append(L": Too many arguments\n");
builtin_print_help( parser, argv[0], stderr_buffer );
return 1;
}
builtin_print_help( parser, argv[0], stderr_buffer );
return 1;
}
}
return 0;
}
return 0;
}

2146
common.cpp

File diff suppressed because it is too large Load diff

View file

@ -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
@ -85,7 +85,7 @@ typedef unsigned int escape_flags_t;
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;
@ -118,56 +118,56 @@ 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
@ -651,7 +651,7 @@ wcstring escape_string( const wcstring &in, escape_flags_t flags );
*/
wchar_t *unescape( const wchar_t * in,
int escape_special );
int escape_special );
bool unescape_string( wcstring &str,
int escape_special );
@ -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();

File diff suppressed because it is too large Load diff

View file

@ -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
@ -18,39 +18,39 @@
#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"
@ -109,30 +109,30 @@ 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); }
@ -142,9 +142,9 @@ public:
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 {
@ -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 );
/**

File diff suppressed because it is too large Load diff

1412
env.cpp

File diff suppressed because it is too large Load diff

6
env.h
View file

@ -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
}
;

View file

@ -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,85 +81,85 @@ static int is_dead()
*/
static int get_socket( int fork_ok )
{
int s, len;
struct sockaddr_un local;
int s, len;
struct sockaddr_un local;
char *name;
wchar_t *wdir;
wchar_t *wuname;
char *dir =0, *uname=0;
char *name;
wchar_t *wdir;
wchar_t *wuname;
char *dir =0, *uname=0;
get_socket_count++;
wdir = path;
wuname = user;
get_socket_count++;
wdir = path;
wuname = user;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
{
wperror(L"socket");
return -1;
}
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
{
wperror(L"socket");
return -1;
}
if( wdir )
dir = wcs2str(wdir );
else
dir = strdup("/tmp");
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 );
}
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 );
name = (char *)malloc( strlen(dir) +
strlen(uname) +
strlen(SOCK_FILENAME) +
2 );
strcpy( name, dir );
strcat( name, "/" );
strcat( name, SOCK_FILENAME );
strcat( name, uname );
strcpy( name, dir );
strcat( name, "/" );
strcat( name, SOCK_FILENAME );
strcat( name, uname );
free( dir );
free( uname );
free( dir );
free( uname );
debug( 3, L"Connect to socket %s at fd %2", name, s );
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);
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 );
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();
start_fishd();
return get_socket( 0 );
}
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;
}
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 );
if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) )
{
wperror( L"fcntl" );
close( s );
return -1;
}
return -1;
}
debug( 3, L"Connected to fd %d", s );
debug( 3, L"Connected to fd %d", s );
return s;
return s;
}
/**
@ -167,15 +167,15 @@ static int get_socket( int fork_ok )
*/
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( !init )
return;
if( env_universal_server.killme )
{
debug( 3, L"Lost connection to universal variable server." );
if( env_universal_server.killme )
{
debug( 3, L"Lost connection to universal variable server." );
if( close( env_universal_server.fd ) )
{
wperror( L"close" );
}
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();
}
env_universal_server.fd = -1;
env_universal_server.killme=0;
env_universal_server.input.clear();
env_universal_read_all();
}
}
/**
@ -208,17 +208,17 @@ static void check_connection()
*/
static void env_universal_remove_all()
{
size_t i;
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 );
}
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;
if( get_socket_count >= RECONNECT_COUNT )
return;
debug( 3, L"Get new fishd connection" );
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();
}
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 ))
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;
path=p;
user=u;
start_fishd=sf;
external_callback = cb;
connection_init( &env_universal_server, -1 );
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();
}
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 );
}
/*
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;
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( !init)
return 0;
if( env_universal_server.fd == -1 )
{
reconnect();
if( env_universal_server.fd == -1 )
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( 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;
if( !init)
return 0;
return env_universal_common_get_export( name );
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();
/*
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.unsent->empty() )
break;
if( env_universal_server.fd == -1 )
{
reconnect();
debug( 2, L"barrier interrupted, exiting" );
return;
}
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 );
}
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 );
/*
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;
message_t *msg;
if( !init )
return;
if( !init )
return;
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name.c_str(), value.c_str() );
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( 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;
}
if( !msg )
{
debug( 1, L"Could not create universal variable message" );
return;
}
msg->count=1;
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;
int res;
message_t *msg;
if( !init )
return 1;
message_t *msg;
if( !init )
return 1;
CHECK( name, 1 );
CHECK( name, 1 );
res = !env_universal_common_get( name );
debug( 3,
L"env_universal_remove( \"%ls\" )",
name );
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;
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();
}
env_universal_barrier();
}
return res;
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 );
}

View file

@ -1,5 +1,5 @@
/** \file env_universal.h
Universal variable client library.
Universal variable client library.
*/
#ifndef ENV_UNIVERSAL_H
@ -61,8 +61,8 @@ int env_universal_read_all();
\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

File diff suppressed because it is too large Load diff

View file

@ -42,11 +42,11 @@
*/
typedef enum
{
SET,
SET_EXPORT,
ERASE,
BARRIER,
BARRIER_REPLY,
SET,
SET_EXPORT,
ERASE,
BARRIER,
BARRIER_REPLY,
} fish_message_type_t;
/**
@ -59,15 +59,15 @@ typedef enum
*/
typedef struct
{
/**
Number of queues that contain this message. Once this reaches zero, the message should be deleted
*/
int count;
/**
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 body. The message must be allocated using enough memory to actually contain the message.
*/
std::string body;
} message_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;
/**
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];
/**
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 already been consumed.
*/
size_t buffer_consumed;
/**
Number of bytes that have been read into the buffer.
*/
size_t buffer_used;
/**
Number of bytes that have been read into the buffer.
*/
size_t buffer_used;
/**
Link to the next connection
*/
struct connection *next;
/**
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.

598
event.cpp
View file

@ -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
@ -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 == EVENT_ANY )
return 1;
if( classv->type != instance->type )
return 0;
if( classv->type != instance->type )
return 0;
switch( classv->type )
{
switch( classv->type )
{
case EVENT_SIGNAL:
if( classv->param1.signal == EVENT_ANY_SIGNAL )
return 1;
return classv->param1.signal == instance->param1.signal;
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_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_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_JOB_ID:
return classv->param1.job_id == instance->param1.job_id;
case EVENT_GENERIC:
return instance->str_param1 == classv->str_param1;
case EVENT_GENERIC:
return instance->str_param1 == classv->str_param1;
}
}
/**
This should never be reached
*/
return 0;
/**
This should never be reached
*/
return 0;
}
@ -144,12 +144,12 @@ 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 )
{
if( copy_arguments && event->arguments.get() != NULL )
{
*(e->arguments) = *(event->arguments);
}
}
return e;
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;
break;
case EVENT_VARIABLE:
result = format_string(_(L"handler for variable '%ls'"), e->str_param1.c_str() );
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 );
}
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;
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 );
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;
}
break;
}
case EVENT_GENERIC:
result = format_string(_(L"handler for generic event '%ls'"), e->str_param1.c_str() );
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;
default:
result = format_string(_(L"Unknown event type") );
break;
}
}
return result;
return result;
}
#if 0
@ -237,16 +237,16 @@ static void show_all_handlers(void) {
void event_add_handler( const event_t *event )
{
event_t *e;
event_t *e;
CHECK( event, );
CHECK( event, );
e = event_copy( event, 0 );
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();
@ -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;
size_t i;
event_list_t new_list;
CHECK( criterion, );
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.
*/
/*
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;
if( events.empty() )
return;
for( i=0; i<events.size(); i++ )
{
event_t *n = events.at(i);
if( event_match( criterion, n ) )
{
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;
size_t i;
int found = 0;
if( events.empty() )
return 0;
if( events.empty() )
return 0;
CHECK( criterion, 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 )
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)
@ -376,62 +376,62 @@ 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;
size_t i, j;
event_list_t fire;
/*
First we free all events that have been removed
*/
event_free_kills();
/*
First we free all events that have been removed
*/
event_free_kills();
if( events.empty() )
return;
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);
/*
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 ) )
{
/*
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;
/*
No matches. Time to return.
*/
if( fire.empty() )
return;
/*
Iterate over our list of matching events
*/
/*
Iterate over our list of matching events
*/
for( i=0; i<fire.size(); i++ )
{
event_t *criterion = fire.at(i);
int prev_status;
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;
/*
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;
/*
Fire event
*/
wcstring buffer = criterion->function_name;
if (event->arguments.get())
{
@ -443,28 +443,28 @@ static void event_fire_internal( const event_t *event )
}
}
// debug( 1, L"Event handler fires command '%ls'", buffer.c_str() );
// 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();
/*
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 );
}
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();
/*
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;
size_t i;
/*
If is_event is one, we are running the event-handler non-recursively.
/*
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;
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 ) )
{
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;
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;
/*
Switch signal lists
*/
sig_list[1-active_list].count=0;
sig_list[1-active_list].overflow=0;
active_list=1-active_list;
/*
Set up
*/
/*
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];
lst = &sig_list[1-active_list];
if( lst->overflow )
{
debug( 0, _( L"Signal list overflow. Signals have been ignored." ) );
}
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];
/*
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)
@ -566,32 +566,32 @@ 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();
/*
Fire events triggered by signals
*/
event_fire_delayed();
if( event )
{
if( event_is_blocked( event ) )
{
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--;
}
}
}
@ -611,29 +611,29 @@ void event_destroy()
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 );
}
va_end( va );
event_fire( &ev );
event_fire( &ev );
ev.arguments.reset(NULL);
}

54
event.h
View file

@ -1,11 +1,11 @@
/** \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.
*/
@ -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,14 +49,14 @@ enum
*/
struct event_t
{
/**
Type of event
*/
int type;
/**
Type of event
*/
int type;
/** The type-specific parameter. The int types are one of the following:
/** 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
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
*/
@ -73,16 +73,16 @@ struct event_t
*/
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() { }

1502
exec.cpp

File diff suppressed because it is too large Load diff

2
exec.h
View file

@ -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

1212
expand.cpp

File diff suppressed because it is too large Load diff

View file

@ -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. */

File diff suppressed because it is too large Load diff

View file

@ -63,14 +63,14 @@ typedef char tputs_arg_t;
*/
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;
}
;
@ -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
@ -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;
}
;
@ -411,8 +411,8 @@ char * textdomain( const char * domainname );
Fallback implementation of dcgettext. Just returns the original string.
*/
char * dcgettext ( const char * domainname,
const char * msgid,
int category );
const char * msgid,
int category );
#endif
@ -443,42 +443,42 @@ int killpg( int pgr, int sig );
*/
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);
char * const argv[],
const char *optstring,
const struct option *longopts,
int *longindex);
#endif

524
fish.cpp
View file

@ -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"
@ -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 );
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;
/*
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 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 );
}
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 )
{
int my_optind;
int force_interactive=0;
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
}
}
;
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_index = 0;
int opt = getopt_long( argc,
argv,
GETOPT_STRING,
long_options,
&opt_index );
int opt = getopt_long( argc,
argv,
GETOPT_STRING,
long_options,
&opt_index );
if( opt == -1 )
break;
if( opt == -1 )
break;
switch( opt )
{
case 0:
{
break;
}
switch( opt )
{
case 0:
{
break;
}
case 'c':
{
*cmd_ptr = optarg;
is_interactive_session = 0;
break;
}
case 'c':
{
*cmd_ptr = optarg;
is_interactive_session = 0;
break;
}
case 'd':
{
char *end;
long tmp;
case 'd':
{
char *end;
long tmp;
errno = 0;
tmp = strtol(optarg, &end, 10);
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;
}
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 'h':
{
*cmd_ptr = "__fish_print_help fish";
break;
}
case 'i':
{
force_interactive = 1;
break;
}
case 'i':
{
force_interactive = 1;
break;
}
case 'l':
{
is_login=1;
break;
}
case 'l':
{
is_login=1;
break;
}
case 'n':
{
no_exec=1;
break;
}
case 'n':
{
no_exec=1;
break;
}
case 'p':
{
profile = optarg;
break;
}
case 'p':
{
profile = optarg;
break;
}
case 'v':
{
fwprintf( stderr,
_(L"%s, version %s\n"),
PACKAGE_NAME,
PACKAGE_VERSION );
exit_without_destructors( 0 );
}
case 'v':
{
fwprintf( stderr,
_(L"%s, version %s\n"),
PACKAGE_NAME,
PACKAGE_VERSION );
exit_without_destructors( 0 );
}
case '?':
{
exit_without_destructors( 1 );
}
case '?':
{
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
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 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;
/*
We are also an interactive session if we have are forced-
*/
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 )
{
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 );
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;
}
/*
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]);
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();
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( 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( ( 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 );
}
env_set( L"argv", sb.c_str(), 0 );
}
rel_filename = str2wcs( file );
abs_filename = wrealpath( rel_filename, 0 );
rel_filename = str2wcs( file );
abs_filename = wrealpath( rel_filename, 0 );
if( !abs_filename )
{
abs_filename = wcsdup(rel_filename);
}
if( !abs_filename )
{
abs_filename = wcsdup(rel_filename);
}
reader_push_current_filename( intern( abs_filename ) );
free( rel_filename );
free( abs_filename );
reader_push_current_filename( intern( abs_filename ) );
free( rel_filename );
free( abs_filename );
res = reader_read( fd, empty_ios );
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();
}
}
}
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 );
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
history_destroy();
proc_destroy();
builtin_destroy();
reader_destroy();
parser.destroy();
wutil_destroy();
event_destroy();
history_destroy();
proc_destroy();
builtin_destroy();
reader_destroy();
parser.destroy();
wutil_destroy();
event_destroy();
env_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();
}

View file

@ -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);
}
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);
}
break;
}
b.push_back((wchar_t)c);
}
}
/**
@ -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;
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 );
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 );
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;
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( 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( do_indent && flags && prev_type != TOK_PIPE )
{
insert_tabs( out, indent );
}
append_format(out, L"%ls", last );
indent = next_indent;
indent = next_indent;
}
else
{
if ( prev_type != TOK_REDIRECT_FD )
out.append( L" " );
out.append( last );
}
}
else
{
if ( prev_type != TOK_REDIRECT_FD )
out.append( L" " );
out.append( last );
}
break;
}
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_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);
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;
}
}
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_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_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_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_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_BACKGROUND:
{
out.append( L"&\n" );
do_indent = 1;
is_command = 1;
break;
}
case TOK_COMMENT:
{
if( do_indent && flags)
{
insert_tabs( out, indent );
}
case TOK_COMMENT:
{
if( do_indent && flags)
{
insert_tabs( out, indent );
}
append_format( out, L"%ls", last );
do_indent = 1;
break;
}
append_format( out, L"%ls", last );
do_indent = 1;
break;
}
default:
{
debug( 0, L"Unknown token '%ls'", last );
exit(1);
}
}
default:
{
debug( 0, L"Unknown token '%ls'", last );
exit(1);
}
}
prev_prev_type = prev_type;
prev_type = type;
prev_prev_type = prev_type;
prev_type = type;
}
}
tok_destroy( &tok );
tok_destroy( &tok );
return res;
return res;
}
/**
@ -279,105 +279,105 @@ static void trim( wcstring &str )
*/
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";
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
}
}
;
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_index = 0;
int opt = getopt_long( argc,
argv,
GETOPT_STRING,
long_options,
&opt_index );
int opt = getopt_long( argc,
argv,
GETOPT_STRING,
long_options,
&opt_index );
if( opt == -1 )
break;
if( opt == -1 )
break;
switch( opt )
{
case 0:
{
break;
}
switch( opt )
{
case 0:
{
break;
}
case 'h':
{
print_help( "fish_indent", 1 );
exit( 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 'v':
{
fwprintf( stderr,
_(L"%ls, version %s\n"),
program_name,
PACKAGE_VERSION );
exit( 0 );
}
case 'i':
{
do_indent = 0;
break;
}
case 'i':
{
do_indent = 0;
break;
}
case '?':
{
exit( 1 );
}
case '?':
{
exit( 1 );
}
}
}
}
}
wcstring sb_in, sb_out;
read_file( stdin, sb_in );
read_file( stdin, sb_in );
wutil_init();
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() );
}
fwprintf( stdout, L"%ls", sb_out.c_str() );
}
else
{
/*
Indenting failed - print original input
*/
fwprintf( stdout, L"%ls", sb_in.c_str() );
}
wutil_destroy();
wutil_destroy();
return 0;
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -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++;
va_list va;
va_start( va, blah );
err_count++;
wprintf( L"Error: " );
vwprintf( blah, va );
va_end( va );
wprintf( L"\n" );
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;
int i;
wcstring sb;
say( L"Testing escaping and unescaping" );
say( L"Testing escaping and unescaping" );
for( i=0; i<ESCAPE_TEST_COUNT; i++ )
{
const wchar_t *o, *e, *u;
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" );
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 );
if( wcscmp(o, u) )
{
err( L"Escaping cycle of string %ls produced different string %ls", o, u );
}
free( (void *)e );
free( (void *)u );
}
free( (void *)e );
free( (void *)u );
}
}
}
static void test_format(void) {
@ -198,81 +198,81 @@ static void test_format(void) {
*/
static void test_convert()
{
/* char o[] =
{
-17, -128, -121, -68, 0
}
;
/* char o[] =
{
-17, -128, -121, -68, 0
}
;
wchar_t *w = str2wcs(o);
char *n = wcs2str(w);
wchar_t *w = str2wcs(o);
char *n = wcs2str(w);
int i;
int i;
for( i=0; o[i]; i++ )
{
bitprint(o[i]);;
//wprintf(L"%d ", o[i]);
}
wprintf(L"\n");
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; 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");
for( i=0; n[i]; i++ )
{
bitprint(n[i]);;
//wprintf(L"%d ", n[i]);
}
wprintf(L"\n");
return;
return;
*/
int i;
std::vector<char> sb;
int i;
std::vector<char> sb;
say( L"Testing wide/narrow string conversion" );
say( L"Testing wide/narrow string conversion" );
for( i=0; i<ESCAPE_TEST_COUNT; i++ )
{
wchar_t *w;
const char *o, *n;
for( i=0; i<ESCAPE_TEST_COUNT; i++ )
{
wchar_t *w;
const char *o, *n;
char c;
char c;
sb.clear();
sb.clear();
while( rand() % ESCAPE_TEST_LENGTH )
{
c = rand ();
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);
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( !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 );
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;
tokenizer t;
say( L"Testing tokenizer" );
say( L"Testing tokenizer" );
say( L"Testing invalid input" );
tok_init( &t, 0, 0 );
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" );
}
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" );
}
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" );
}
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 );
/*
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;
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" );
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 )) );
}
}
}
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) {
@ -397,73 +397,73 @@ static void test_fork(void) {
*/
static void test_parser()
{
say( L"Testing parser" );
say( L"Testing parser" );
parser_t parser(PARSER_TYPE_GENERAL, true);
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 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 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" );
}
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" );
}
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 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 {
@ -516,16 +516,16 @@ 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;
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( expand_string( in, output, flags) )
{
}
}
#if 0
for (size_t idx=0; idx < output.size(); idx++)
@ -534,27 +534,27 @@ static int expand_test( const wchar_t *in, int flags, ... )
}
#endif
va_start( va, flags );
va_start( va, flags );
while( (arg=va_arg(va, wchar_t *) )!= 0 )
{
if( output.size() == i )
{
res=0;
break;
}
while( (arg=va_arg(va, wchar_t *) )!= 0 )
{
if( output.size() == i )
{
res=0;
break;
}
if (output.at(i).completion != arg)
{
res=0;
break;
}
{
res=0;
break;
}
i++;
}
va_end( va );
i++;
}
va_end( va );
return res;
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" );
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"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{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( !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" );
}
}
@ -845,64 +845,64 @@ 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;
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" );
say( L"Testing completion performance" );
reader_push(L"");
say( L"Here we go" );
reader_push(L"");
say( L"Here we go" );
t1 = get_time();
t1 = get_time();
for( c=L'a'; c<=L'z'; c++ )
{
str[0]=c;
reader_set_buffer( str, 0 );
for( c=L'a'; c<=L'z'; c++ )
{
str[0]=c;
reader_set_buffer( str, 0 );
complete( str, out, COMPLETE_DEFAULT, NULL );
complete( str, out, COMPLETE_DEFAULT, NULL );
matches += out.size();
matches += out.size();
out.clear();
}
t2=get_time();
}
t2=get_time();
t = (double)(t2-t1)/(1000000*26);
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 );
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);
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 );
reader_set_buffer( str, 0 );
complete( str, out, COMPLETE_DEFAULT, NULL );
complete( str, out, COMPLETE_DEFAULT, NULL );
matches += out.size();
matches += out.size();
out.clear();
}
t2=get_time();
}
t2=get_time();
t = (double)(t2-t1)/(1000000*LAPS);
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 );
say( L"Two letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
reader_pop();
reader_pop();
}
@ -1212,33 +1212,33 @@ void history_tests_t::test_history_formats(void) {
*/
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)";
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();
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();
@ -1246,19 +1246,19 @@ int main( int argc, char **argv )
history_tests_t::test_history_merge();
history_tests_t::test_history_formats();
say( L"Encountered %d errors in low-level tests", err_count );
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();
/*
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();
env_destroy();
reader_destroy();
builtin_destroy();
wutil_destroy();
event_destroy();
proc_destroy();
}

1016
fishd.cpp

File diff suppressed because it is too large Load diff

View file

@ -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;
size_t i;
const env_var_t path_var_wstr = env_get_string( L"fish_function_path" );
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;
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;
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()
@ -182,12 +182,12 @@ 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 */
@ -197,16 +197,16 @@ void function_add( const function_data_t &data, const parser_t &parser )
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();
@ -214,8 +214,8 @@ int function_exists( const wcstring &cmd )
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);
}
@ -225,7 +225,7 @@ 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;
event_remove( &ev );
@ -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,19 +307,19 @@ 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) {

View file

@ -1,10 +1,10 @@
/** \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,31 +28,31 @@ 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 {
@ -69,20 +69,20 @@ public:
/** 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;
/** Line where definition started */
const int definition_offset;
/** List of all named arguments for this function */
/** 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;
};

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/** \file highlight.h
Prototypes for functions for syntax highlighting
Prototypes for functions for syntax highlighting
*/
#ifndef FISH_HIGHLIGHT_H

View file

@ -1,5 +1,5 @@
/** \file history.c
History functions, part of the user interface.
History functions, part of the user interface.
*/
#include "config.h"
@ -339,46 +339,46 @@ static size_t offset_of_next_item_fish_1_x(const char *begin, size_t mmap_length
if (mmap_length == 0 || *inout_cursor >= mmap_length)
return (size_t)(-1);
const char *end = begin + mmap_length;
const char *pos;
const char *end = begin + mmap_length;
const char *pos;
bool ignore_newline = false;
bool do_push = true;
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++ )
{
for( pos = begin + *inout_cursor; pos < end && ! all_done; pos++ )
{
if( do_push )
{
ignore_newline = (*pos == '#');
do_push = false;
}
if( do_push )
{
ignore_newline = (*pos == '#');
do_push = false;
}
switch( *pos )
{
case '\\':
{
pos++;
break;
}
switch( *pos )
{
case '\\':
{
pos++;
break;
}
case '\n':
{
if( ignore_newline )
{
ignore_newline = false;
}
else
{
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;
}
@ -453,7 +453,7 @@ void history_t::add(const history_item_t &item)
/* 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();
}
}
@ -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;
}
@ -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;
}
@ -835,9 +835,9 @@ bool history_t::load_old_if_needed(void)
// PCA not sure why signals were blocked here
//signal_block();
//signal_block();
bool ok = false;
bool ok = false;
if (map_file(name, &mmap_start, &mmap_length)) {
// Here we've mapped the file
ok = true;
@ -845,7 +845,7 @@ bool history_t::load_old_if_needed(void)
this->populate_from_mmap();
}
//signal_unblock();
//signal_unblock();
return ok;
}
@ -1022,11 +1022,11 @@ void history_t::save_internal()
/* Compact our new items so we don't have duplicates */
this->compact_new_items();
bool ok = true;
bool ok = true;
wcstring tmp_name = history_filename(name, L".tmp");
if( ! tmp_name.empty() )
{
if( ! tmp_name.empty() )
{
/* Make an LRU cache to save only the last N elements */
history_lru_cache_t lru(HISTORY_SAVE_MAX);
@ -1078,8 +1078,8 @@ void history_t::save_internal()
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;
@ -1089,20 +1089,20 @@ void history_t::save_internal()
}
}
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();
@ -1111,13 +1111,13 @@ void history_t::save_internal()
/* 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)
@ -1229,9 +1229,9 @@ 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) {

View file

@ -35,11 +35,11 @@ class history_item_t {
/** Attempts to merge two compatible history items together */
bool merge(const history_item_t &item);
/** The actual contents of the entry */
wcstring contents;
/** The actual contents of the entry */
wcstring contents;
/** Original creation time for the entry */
time_t creation_timestamp;
/** 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;
@ -91,23 +91,23 @@ private:
/** Internal function */
void clear_file_state();
/** The name of this list. Used for picking a suitable filename and for switching modes. */
const wcstring name;
/** 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;
/** 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,8 +115,8 @@ 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);

658
input.cpp
View file

@ -74,8 +74,8 @@
*/
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,8 +86,8 @@ 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,38 +141,38 @@ 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"
}
;
;
*/
/**
@ -180,43 +180,43 @@ static const wchar_t *desc_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;
@ -249,24 +249,24 @@ 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, );
size_t i;
CHECK( sequence, );
CHECK( command, );
// debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) );
// 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;
}
}
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 );
/*
Fire any pending events
*/
event_fire( NULL );
/*
Reap stray processes, including printing exit status messages
*/
if( job_reap( 1 ) )
reader_repaint_needed();
/*
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;
}
/*
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;
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;
if( is_init )
return 1;
is_init = 1;
is_init = 1;
input_common_init( &interrupt_handler );
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( 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() );
output_set_term( term.c_str() );
input_terminfo_init();
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" );
}
/* 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;
return 1;
}
void input_destroy()
{
if( !is_init )
return;
if( !is_init )
return;
is_init=0;
is_init=0;
input_common_destroy();
input_common_destroy();
if( del_curterm( cur_term ) == ERR )
{
debug( 0, _(L"Error while closing terminfo") );
}
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 )
{
wchar_t code = input_function_get_code( m.command );
if( code != -1 )
{
switch( code )
{
case R_SELF_INSERT:
{
return seq[0];
}
case R_SELF_INSERT:
{
return seq[0];
}
default:
{
return code;
}
default:
{
return code;
}
}
}
else
{
}
}
else
{
/*
This key sequence is bound to a command, which
is sent to the parser for evaluation.
*/
int last_status = proc_get_last_status();
/*
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 );
parser_t::principal_parser().eval( m.command.c_str(), io_chain_t(), TOP );
proc_set_last_status( last_status );
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.
/*
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.
*/
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;
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;
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 );
/*
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++)
@ -476,70 +476,70 @@ 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;
size_t i;
CHECK_BLOCK( R_NULL );
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;
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;
}
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
}
;
arr[0] = input_common_readch(0);
;
arr[0] = input_common_readch(0);
return input_exec_binding( *generic, arr );
}
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)
@ -551,13 +551,13 @@ wint_t input_readch()
void input_mapping_get_names( wcstring_list_t &lst )
{
size_t i;
size_t i;
for( i=0; i<mapping_list.size(); i++ )
{
const input_mapping_t &m = mapping_list.at(i);
for( i=0; i<mapping_list.size(); i++ )
{
const input_mapping_t &m = mapping_list.at(i);
lst.push_back(wcstring(m.seq));
}
}
}
@ -565,41 +565,41 @@ void input_mapping_get_names( wcstring_list_t &lst )
bool input_mapping_erase( const wchar_t *sequence )
{
ASSERT_IS_MAIN_THREAD();
bool result = false;
size_t i, sz = mapping_list.size();
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 ) )
{
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;
result = true;
break;
}
}
return result;
}
}
return result;
}
bool input_mapping_get( const wcstring &sequence, wcstring &cmd )
{
size_t i, sz = mapping_list.size();
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;
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),
@ -774,47 +774,47 @@ 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;
int err = ENOENT;
CHECK( name, 0 );
input_init();
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;
}
}
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;
}
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();
input_init();
for( size_t i=0; i<terminfo_mappings.size(); i++ )
{
terminfo_mapping_t &m = terminfo_mappings.at(i);
for( size_t i=0; i<terminfo_mappings.size(); i++ )
{
terminfo_mapping_t &m = terminfo_mappings.at(i);
if( !m.seq )
{
continue;
}
if( !m.seq )
{
continue;
}
const wcstring map_buf = format_string(L"%s", m.seq);
if (map_buf == seq) {
@ -823,7 +823,7 @@ bool input_terminfo_get_name( const wcstring &seq, wcstring &name )
}
}
return false;
return false;
}
wcstring_list_t input_terminfo_get_names( bool skip_null )
@ -831,18 +831,18 @@ wcstring_list_t input_terminfo_get_names( bool skip_null )
wcstring_list_t result;
result.reserve(terminfo_mappings.size());
input_init();
input_init();
for( size_t i=0; i<terminfo_mappings.size(); i++ )
{
terminfo_mapping_t &m = terminfo_mappings.at(i);
for( size_t i=0; i<terminfo_mappings.size(); i++ )
{
terminfo_mapping_t &m = terminfo_mappings.at(i);
if( skip_null && !m.seq )
{
continue;
}
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;
}

68
input.h
View file

@ -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
}
;

View file

@ -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))
@ -73,69 +73,69 @@ 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;
unsigned char arr[1];
bool do_loop;
do
{
do
{
/* Invoke any poll handler */
if (poll_handler)
poll_handler();
fd_set fdset;
int fd_max=0;
int ioport = iothread_port();
int res;
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;
}
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];
}
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
{
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;
@ -149,116 +149,116 @@ static wint_t readb()
}
}
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 );
do_loop = false;
}
}
}
while( do_loop );
return arr[0];
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
}
;
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);
FD_ZERO( &fds );
FD_SET( 0, &fds );
count = select(1, &fds, 0, 0, &tm);
switch( count )
{
case 0:
return WEOF;
switch( count )
{
case 0:
return WEOF;
case -1:
return WEOF;
break;
default:
break;
case -1:
return WEOF;
break;
default:
break;
}
}
}
}
wchar_t res;
static mbstate_t state;
wchar_t res;
static mbstate_t state;
while(1)
{
wint_t b = readb();
char bb;
while(1)
{
wint_t b = readb();
char bb;
size_t sz;
size_t sz;
if( (b >= R_NULL) && (b < R_NULL + 1000) )
return b;
if( (b >= R_NULL) && (b < R_NULL + 1000) )
return b;
bb=b;
bb=b;
sz = mbrtowc( &res, &bb, 1, &state );
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:
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 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];
}
return lookahead_arr[--lookahead_count];
}
}
void input_common_unreadch( wint_t ch )
{
lookahead_arr[lookahead_count++] = ch;
lookahead_arr[lookahead_count++] = ch;
}

View file

@ -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

View file

@ -45,10 +45,10 @@ 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;
if( !in )
return NULL;
// debug( 0, L"intern %ls", in );
// debug( 0, L"intern %ls", in );
scoped_lock lock(intern_lock);
const wchar_t *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);
}

152
io.cpp
View file

@ -53,76 +53,76 @@ Utilities for io redirection.
void io_buffer_read( io_data_t *d )
{
exec_close(d->param1.pipe_fd[1] );
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" );
}
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 );
}
}
}
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;
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( 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)
{
@ -130,28 +130,28 @@ io_data_t *io_buffer_create( bool is_input )
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] );
}
/**
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] );
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;
/*
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)

50
io.h
View file

@ -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,31 +24,31 @@ private:
void operator=(const io_data_t &rhs);
public:
/** Type of redirect */
int io_mode;
/** FD to redirect */
int fd;
/** 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;
/**
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;
/** 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;
@ -87,8 +87,8 @@ public:
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(),

View file

@ -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 sequenceNumber;
int (*handler)(void *);
void (*completionCallback)(void *, int);
void *context;
int handlerResult;
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;
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 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];
/* 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,67 +94,67 @@ 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;
assert(threadPtr != NULL);
struct WorkerThread_t *thread = (struct WorkerThread_t *)threadPtr;
/* Grab a request off of the queue */
struct ThreadedRequest_t *req = dequeue_request();
/* 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);
}
/* 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));
/* 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;
/* 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);
assert(err == 0);
/* Note that we are spawned another thread */
s_active_thread_count += 1;
/* 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();
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;
/* 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);
@ -168,38 +168,38 @@ int iothread_perform_base(int (*handler)(void *), void (*completionCallback)(voi
}
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);
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 WorkerThread_t *thread = &threads[threadIdx];
assert(thread->thread != 0);
struct ThreadedRequest_t *req = NULL;
VOMIT_ON_FAILURE(pthread_join(thread->thread, (void **)&req));
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;
/* Free up this thread */
thread->thread = 0;
assert(s_active_thread_count > 0);
s_active_thread_count -= 1;
/* Handle the request */
/* Handle the request */
if (req) {
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) {

View file

@ -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, "" );
setlocale( LC_ALL, "" );
if( argc == 2 )
{
static char term_buffer[2048];
char *termtype = getenv ("TERM");
char *tbuff = new char[9999];
char *res;
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 );
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;
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 */
struct termios modes, /* so we can change the modes */
savemodes; /* so we can reset the modes when we're done */
input_common_init(0);
input_common_init(0);
tcgetattr(0,&modes); /* get the current terminal modes */
savemodes = modes; /* save a copy so we can reset them */
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);
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();
}
input_common_destroy();
}
return 0;
return 0;
}

146
kill.cpp
View file

@ -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 )
@ -71,56 +71,56 @@ void kill_add( const wcstring &str )
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;
}
}
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 );
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
*/
}
if (! cmd.empty())
{
if( exec_subshell(cmd) == -1 )
{
/*
Do nothing on failiure
*/
}
free( cut_buffer );
free( cut_buffer );
cut_buffer = escaped_str;
}
cut_buffer = escaped_str;
}
}
/**
@ -138,8 +138,8 @@ static void kill_remove( const wcstring &s )
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()
@ -160,33 +160,33 @@ const wchar_t *kill_yank_rotate()
*/
static void kill_check_x_buffer()
{
if( !has_xsel() )
return;
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"";
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 )
{
if( exec_subshell( cmd, list ) != -1 )
{
for( i=0; i<list.size(); i++ )
{
wcstring next_line = escape_string( list.at(i), 0 );
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)
{
@ -194,15 +194,15 @@ static void kill_check_x_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 );
}

4
kill.h
View file

@ -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

1920
mimedb.cpp

File diff suppressed because it is too large Load diff

View file

@ -69,17 +69,17 @@ static int writeb_internal( char c );
*/
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) {
@ -212,177 +212,177 @@ void set_color(rgb_color_t c, rgb_color_t c2)
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;
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;
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;
}
if( !exit_attribute_mode )
{
return;
}
is_bold |= c.is_bold();
is_bold |= c2.is_bold();
is_bold |= c.is_bold();
is_bold |= c2.is_bold();
is_underline |= c.is_underline();
is_underline |= c2.is_underline();
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( 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;
}
writembs( exit_attribute_mode );
return;
}
if( was_bold && !is_bold )
{
/*
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;
}
writembs( exit_attribute_mode );
last_color = normal;
last_color2 = normal;
was_bold=0;
was_underline=0;
}
if( ! last_color2.is_normal() &&
if( ! last_color2.is_normal() &&
! last_color2.is_reset() &&
! last_color2.is_ignore() )
{
/*
{
/*
Background was set
*/
last_bg_set=1;
}
last_bg_set=1;
}
if( ! c2.is_normal() &&
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( 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 );
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() )
{
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;
last_color = c;
if( last_color2 != c2 )
{
if( c2.is_normal() )
{
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( (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( exit_underline_mode );
}
if( !was_underline && is_underline )
{
writembs( enter_underline_mode );
}
was_underline = is_underline;
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 );
CHECK( str, 1 );
return tputs(str,1,&writeb)==ERR?1:0;
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;
mbstate_t state;
size_t i;
char buff[MB_LEN_MAX+1];
size_t bytes;
if( ( ch >= ENCODE_DIRECT_BASE) &&
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 );
{
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;
}
}
}
switch( bytes )
{
case (size_t)(-1):
{
return 1;
}
}
}
for( i=0; i<bytes; i++ )
{
out( buff[i] );
}
return 0;
for( i=0; i<bytes; i++ )
{
out( buff[i] );
}
return 0;
}
void writestr( const wchar_t *str )
{
char *pos;
char *pos;
CHECK( str, );
CHECK( str, );
// while( *str )
// writech( *str++ );
// while( *str )
// writech( *str++ );
/*
/*
Check amount of needed space
*/
size_t len = wcstombs( 0, str, 0 );
size_t len = wcstombs( 0, str, 0 );
if( len == (size_t)-1 )
{
debug( 1, L"Tried to print invalid wide character string" );
return;
}
if( len == (size_t)-1 )
{
debug( 1, L"Tried to print invalid wide character string" );
return;
}
len++;
len++;
/*
/*
Convert
*/
char *buffer, static_buffer[256];
@ -473,17 +473,17 @@ void writestr( const wchar_t *str )
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;
int written=0;
int tot;
CHECK( str, );
CHECK( str, );
tot = my_wcswidth(str);
tot = my_wcswidth(str);
if( tot <= max_width )
{
writestr( str );
return;
}
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++) );
}
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 );
written += fish_wcwidth( ellipsis_char );
writech( ellipsis_char );
while( written < max_width )
{
written++;
writestr( L" " );
}
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;
wchar_t *out;
int i;
int len;
int written=0;
CHECK( str, 0 );
CHECK( str, 0 );
out = escape( str, 1 );
len = my_wcswidth( out );
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 );
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 );
}
for( i=written; i<max_len; i++ )
{
writech( L' ' );
written++;
}
}
else
{
written = len;
writestr( out );
}
free( out );
return written;
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;
int is_bold=0;
int is_underline=0;
if (val.empty())
return FISH_COLOR_NORMAL;
if (val.empty())
return FISH_COLOR_NORMAL;
wcstring_list_t el;
tokenize_variable_array( val, el );
tokenize_variable_array( val, el );
for(size_t j=0; j < el.size(); j++ ) {
for(size_t j=0; j < el.size(); j++ ) {
const wcstring &next = el.at(j);
wcstring color_name;
if (is_background) {
@ -608,21 +608,21 @@ 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 );
tokenize_variable_array( val, el );
for(size_t j=0; j < el.size(); j++ ) {
for(size_t j=0; j < el.size(); j++ ) {
const wcstring &next = el.at(j);
wcstring color_name;
if (is_background) {
@ -682,7 +682,7 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
void output_set_term( const wchar_t *term )
{
current_term = term;
current_term = term;
}
const wchar_t *output_get_term()

View file

@ -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.
@ -17,18 +17,18 @@
*/
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); \
} \
}
/**

File diff suppressed because it is too large Load diff

View file

@ -23,9 +23,9 @@
*/
int parse_util_locate_cmdsubst( const wchar_t *in,
wchar_t **begin,
wchar_t **end,
int flags );
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 );
/**

4670
parser.cpp

File diff suppressed because it is too large Load diff

214
parser.h
View file

@ -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.
/**
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;
Note that EVENT_ANY can be used to specify any event.
*/
unsigned int typemask;
};
typedef std::list<event_blockage_t> event_blockage_list_t;
@ -46,24 +46,24 @@ 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 */
}
;
@ -77,7 +77,7 @@ 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:
@ -86,53 +86,53 @@ struct block_t
/** 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 */
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;
/**
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;
/**
Name of file that created this block
*/
const wchar_t *src_filename;
/**
Line number where this block was created
*/
int src_lineno;
/**
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();
@ -213,9 +213,9 @@ struct breakpoint_block_t : public block_t
*/
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 */
}
;
@ -236,22 +236,22 @@ enum while_status
*/
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;
@ -390,11 +390,11 @@ 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

View file

@ -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" );
}

View file

@ -11,9 +11,9 @@ Functions having to do with parser keywords, like testing if a function is a blo
*/
enum
{
ARG_NON_SWITCH,
ARG_SWITCH,
ARG_SKIP
ARG_NON_SWITCH,
ARG_SWITCH,
ARG_SKIP
};

336
path.cpp
View file

@ -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;
int err = ENOENT;
debug( 3, L"path_get_path( '%ls' )", cmd.c_str() );
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 (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( 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
{
errno = EACCES;
return false;
}
}
else
{
struct stat buff;
wstat( cmd, &buff );
return false;
}
}
else
{
}
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;
return true;
}
err = EACCES;
}
else
{
switch( errno )
{
case ENOENT:
case ENAMETOOLONG:
case EACCES:
case ENOTDIR:
break;
default:
{
debug( 1,
}
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" );
}
}
}
}
}
wperror( L"access" );
}
}
}
}
}
errno = err;
return false;
errno = err;
return false;
}
bool path_get_path(const wcstring &cmd, wcstring *out_path, const env_vars_snapshot_t &vars)
@ -143,30 +143,30 @@ 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
{
err = ENOTDIR;
}
}
}
else
{
}
}
else
{
wcstring path = L".";
@ -186,44 +186,44 @@ bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env
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;
}
if( !success )
{
errno = err;
}
return res;
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)
{
@ -262,7 +262,7 @@ 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;
@ -275,26 +275,26 @@ bool path_get_cdpath(const wcstring &dir, wcstring *out, const wchar_t *wd, cons
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;
}
@ -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;
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;
}
}
}
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 )
{
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;
}
}

8
path.h
View file

@ -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

View file

@ -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,19 +44,19 @@ 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;
int res = 0;
if( job_get_flag( j, JOB_CONTROL ) )
{
if (!j->pgid)
{
j->pgid = p->pid;
}
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 )
{
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];
@ -67,38 +67,38 @@ int set_child_group( job_t *j, process_t *p, int print_errors )
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 );
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();
}
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 )
{
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. */
@ -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;
int tmp;
if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
{
continue;
}
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;
}
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" );
}
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);
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;
}
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);
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;
}
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:
{
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;
}
break;
}
}
}
}
}
return 0;
return 0;
}
int setup_child_process( job_t *j, process_t *p )
{
bool ok=true;
bool ok=true;
if( p )
{
ok = (0 == set_child_group( j, p, 1 ));
}
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 );
}
}
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();
}
/* Set the handling for job control signals back to the default. */
if( ok )
{
signal_reset_handlers();
}
/* Remove all signal blocks */
signal_unblock();
/* Remove all signal blocks */
signal_unblock();
return ok ? 0 : -1;
return ok ? 0 : -1;
}
int g_fork_count = 0;
@ -324,41 +324,41 @@ pid_t execute_fork(bool wait_for_threads_to_die)
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;
}
for( i=0; i<FORK_LAPS; i++ )
{
pid = fork();
if( pid >= 0)
{
return pid;
}
if( errno != EAGAIN )
{
break;
}
if( errno != EAGAIN )
{
break;
}
pollint.tv_sec = 0;
pollint.tv_nsec = FORK_SLEEP_TIME;
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 );
}
}
/*
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();
debug_safe( 0, FORK_ERROR );
wperror (L"fork");
FATAL_EXIT();
return 0;
}
@ -389,11 +389,11 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
desired_parent_group_id = j->pgid;
}
/* Set the handling for job control signals back to the default. */
bool reset_signal_handlers = 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;
/* Remove all signal blocks */
bool reset_sigmask = true;
/* Set our flags */
short flags = 0;
@ -440,17 +440,17 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
{
const io_data_t *io = j->io.at(idx);
if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
{
continue;
}
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->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:
@ -474,9 +474,9 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
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;
@ -484,19 +484,19 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
err = posix_spawn_file_actions_adddup2(actions, from_fd, to_fd);
if( write_pipe_idx > 0 )
{
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
{
}
else
{
if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]);
}
}
break;
}
}
@ -514,86 +514,86 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
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 );
debug_safe( 0, "Failed to execute process '%s'. Reason:", actual_cmd );
switch( err )
{
switch( err )
{
case E2BIG:
{
char sz1[128], sz2[128];
case E2BIG:
{
char sz1[128], sz2[128];
long arg_max = -1;
long arg_max = -1;
size_t sz = 0;
char **p;
for(p=argv; *p; p++)
{
sz += strlen(*p)+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;
}
for(p=envv; *p; p++)
{
sz += strlen(*p)+1;
}
format_size_safe(sz1, sz);
arg_max = sysconf( _SC_ARG_MAX );
arg_max = sysconf( _SC_ARG_MAX );
if( arg_max > 0 )
{
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);
}
}
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;
}
debug_safe(0, "Try running the command again with fewer arguments.");
break;
}
case ENOEXEC:
{
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;
}
}
}
}
}

View file

@ -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

View file

@ -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 );
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));
}
if( printed < CMD_LEN )
{
if( (system( cmd ) == -1) )
{
write_loop(2, HELP_ERR, strlen(HELP_ERR));
}
}
}
}

View file

@ -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 );

1384
proc.cpp

File diff suppressed because it is too large Load diff

260
proc.h
View file

@ -1,10 +1,10 @@
/** \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.
*/
@ -56,73 +56,73 @@
*/
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
@ -144,12 +144,12 @@ class 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 */
@ -180,41 +180,41 @@ class process_t
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,
@ -223,9 +223,9 @@ enum {
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,
@ -261,12 +261,12 @@ 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;
@ -298,68 +298,68 @@ class job_t
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;
/**
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;
/**
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 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;
/**
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;
/** 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;
/**
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;

3018
reader.cpp

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
/** \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

View file

@ -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();
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;
return insane;
}
void validate_pointer( const void *ptr, const wchar_t *err, int null_ok )
{
/*
Test if the pointer data crosses a segment boundary.
*/
/*
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( (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();
}
if((!null_ok) && (ptr==0))
{
debug( 0, _(L"The pointer '%ls' is null"), err );
sanity_lose();
}
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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 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 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
@ -135,21 +135,21 @@ class screen_t
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;
};
/**
@ -169,13 +169,13 @@ class screen_t
\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 );
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,

View file

@ -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;
static int is_init = 0;
if( is_init )
return;
is_init = 1;
setlocale( LC_ALL, "" );
bindtextdomain( PACKAGE_NAME, LOCALEDIR );
textdomain( PACKAGE_NAME );
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. */
@ -186,109 +186,109 @@ int main( int argc, char **argv )
if (argc <= 1)
return EXIT_FAILURE;
char *bgcolor=0;
char *fgcolor=0;
bool bold=false;
bool underline=false;
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
}
}
;
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_index = 0;
int opt = getopt_long( argc,
argv,
GETOPT_STRING,
long_options,
&opt_index );
int opt = getopt_long( argc,
argv,
GETOPT_STRING,
long_options,
&opt_index );
if( opt == -1 )
break;
if( opt == -1 )
break;
switch( opt )
{
case 0:
break;
switch( opt )
{
case 0:
break;
case 'b':
bgcolor = optarg;
break;
case 'h':
print_help( argv[0], 1 );
exit(0);
case 'b':
bgcolor = optarg;
break;
case 'h':
print_help( argv[0], 1 );
exit(0);
case 'o':
bold=true;
break;
case 'o':
bold=true;
break;
case 'u':
underline=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 'v':
check_locale_init();
fprintf( stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION );
exit( 0 );
case 'c':
print_colors();
exit(0);
case 'c':
print_colors();
exit(0);
case '?':
return 1;
case '?':
return 1;
}
}
}
}
switch( argc-optind)
{
case 0:
// printf( "no fg\n" );
break;
switch( argc-optind)
{
case 0:
// printf( "no fg\n" );
break;
case 1:
fgcolor=argv[optind];
// printf( "fg %s\n", fgcolor );
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;
}
default:
check_locale_init();
printf( _("%s: Too many arguments\n"), SET_COLOR );
return 1;
}
/* Infer term256 support */
char *fish_term256 = getenv("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;
}
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);
setupterm( 0, STDOUT_FILENO, 0);
if( bold )
{
if( enter_bold_mode )
putp( enter_bold_mode );
}
if( bold )
{
if( enter_bold_mode )
putp( enter_bold_mode );
}
if( underline )
{
if( enter_underline_mode )
putp( enter_underline_mode );
}
if( underline )
{
if( enter_underline_mode )
putp( enter_underline_mode );
}
if( bgcolor )
{
if( bg.is_normal() )
{
if( bgcolor )
{
if( bg.is_normal() )
{
write_background_color(0);
putp( tparm(exit_attribute_mode) );
}
}
putp( tparm(exit_attribute_mode) );
}
}
if( fgcolor )
{
if( fg.is_normal() )
{
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") );
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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
}
;
;
/**
@ -67,29 +67,29 @@ enum tokenizer_error
*/
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;
/** 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;
/** 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;

122
util.cpp
View file

@ -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 );
CHECK( a, 0 );
CHECK( b, 0 );
if( *a==0 )
{
if( *b==0)
return 0;
return -1;
}
if( *b==0 )
{
return 1;
}
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;
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 );
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 );
}
if( errno )
{
/*
Huuuuuuuuge numbers - fall back to regular string comparison
*/
return wcscmp( a, b );
}
diff = al - bl;
if( diff )
return diff > 0 ? 2 : -2;
diff = al - bl;
if( diff )
return diff > 0 ? 2 : -2;
secondary_diff = (aend-a) - (bend-b);
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;
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;
}
secondary_diff = *a-*b;
}
int res = wcsfilecmp( a+1, b+1 );
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;
}
}
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;
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;
}

18
util.h
View file

@ -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;

View file

@ -1,24 +1,24 @@
/** \file wgetopt.c
A version of the getopt library for use with wide character strings.
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.
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.
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.
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;
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. */
/* 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)
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
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 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;
}
/* 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. */
/* 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 (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;
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. */
/* 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] == '-'));
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 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])))))
if (woptind != argc && !wcscmp (argv[woptind], L"--"))
{
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;
woptind++;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
if (first_nonopt != last_nonopt && last_nonopt != woptind)
exchange ((wchar_t **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = woptind;
last_nonopt = argc;
/* 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 '?';
}
woptind = argc;
}
/* Look at and handle the next short option-character. */
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
{
wchar_t c = *nextchar++;
wchar_t *temp = const_cast<wchar_t*>(my_index (optstring, c));
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;
}
/* Increment `woptind' when we start to process its last character. */
if (*nextchar == '\0')
++woptind;
/* 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 (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;
}
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] == '-'));
}
/* 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);
}

110
wgetopt.h
View file

@ -1,24 +1,24 @@
/** \file wgetopt.h
A version of the getopt library for use with wide character strings.
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.
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.
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.
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,20 +141,20 @@ 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__ */
@ -162,48 +162,48 @@ extern int wgetopt (int argc, wchar_t *const *argv, const wchar_t *shortopts);
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);
const struct woption *longopts, int *longind);
/**
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 (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

File diff suppressed because it is too large Load diff

View file

@ -31,40 +31,40 @@ 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.
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

160
wutil.cpp
View file

@ -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"
@ -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;
char *buffc = (char *)malloc( sz*MAX_UTF8_BYTES);
char *res;
wchar_t *ret = 0;
if( !buffc )
{
errno = ENOMEM;
return 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;
}
}
res = getcwd( buffc, sz*MAX_UTF8_BYTES );
if( res )
{
if( (size_t)-1 != mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
{
ret = buff;
}
}
free( buffc );
free( buffc );
return ret;
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)
@ -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;
cstring tmp = wcs2string(pathname);
char *narrow_res = realpath( tmp.c_str(), 0 );
wchar_t *res;
if( !narrow_res )
return 0;
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 );
}
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;
char narrow_buff[PATH_MAX];
char *narrow_res = realpath( tmp.c_str(), narrow_buff );
wchar_t *res;
if( !narrow_res )
return 0;
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;
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,15 +367,15 @@ static void wgettext_init_if_necessary()
const wchar_t *wgettext( const wchar_t *in )
{
if( !in )
return in;
if( !in )
return in;
// preserve errno across this since this is often used in printing error messages
int err = errno;
// 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];
@ -384,14 +384,14 @@ const wchar_t *wgettext( const wchar_t *in )
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() );
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)

View file

@ -92,10 +92,10 @@ 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);

View file

@ -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;
{
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);
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;
}
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;
{
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 (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;
@ -520,9 +520,9 @@ 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)
@ -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,7 +571,7 @@ 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;
@ -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;
@ -636,7 +636,7 @@ xdg_mime_mime_type_subclass (const char *mime,
for (; parents && *parents; parents++)
{
if (xdg_mime_mime_type_subclass (*parents, ubase))
return 1;
return 1;
}
return 0;
@ -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->next)
list->next = list->prev;
if (list->prev)
list->prev->next = list->next;
else
callback_list = list->next;
if (list->prev)
list->prev->next = list->next;
else
callback_list = list->next;
/* invoke the destroy handler */
(list->destroy) (list->data);
free (list);
return;
}
/* invoke the destroy handler */
(list->destroy) (list->data);
free (list);
return;
}
}
}

View file

@ -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
@ -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

View file

@ -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 XdgAlias XdgAlias;
@ -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,25 +138,25 @@ _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->n_aliases * sizeof (XdgAlias));
fclose (file);
@ -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);
}
}
}

View file

@ -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__ */

View file

@ -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;
{
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;
}
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;
@ -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);

View file

@ -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
@ -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);

View file

@ -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;
}
{
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;
}
for ( bytelength --; bytelength > 0; bytelength -- )
{
result <<= 6;
result |= *source++ & 0x3F;
}
ucs32 = result;
}
}
return ucs32;
}

View file

@ -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;

View file

@ -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 ((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 (_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];

View file

@ -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__ */

View file

@ -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;
@ -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,54 +144,54 @@ _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->n_mimes * sizeof (XdgMimeParents));
fclose (file);
@ -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);
}
}
}

View file

@ -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__ */