Use bitset to implement flags for jobs instead of wasting a whole int for every flag

darcs-hash:20061025204759-ac50b-ea07caa30782a1ea02d2cd8aa7cbc94474047a10.gz
This commit is contained in:
axel 2006-10-26 06:47:59 +10:00
parent cdc52f7bde
commit 3a128e1484
6 changed files with 141 additions and 89 deletions

View file

@ -2216,8 +2216,8 @@ static int builtin_fg( wchar_t **argv )
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && (!job_is_completed(j)) &&
( (job_is_stopped(j) || !j->fg) && (j->job_control) ) )
if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) &&
( (job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND)) ) && job_get_flag( j, JOB_CONTROL) ) )
{
break;
}
@ -2288,7 +2288,7 @@ static int builtin_fg( wchar_t **argv )
else
{
j = job_get_from_pid( pid );
if( !j || !j->constructed || job_is_completed( j ))
if( !j || !job_get_flag( j, JOB_CONSTRUCTED ) || job_is_completed( j ))
{
sb_printf( sb_err,
_( L"%ls: No suitable job: %d\n" ),
@ -2297,7 +2297,7 @@ static int builtin_fg( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
j=0;
}
else if( !j->job_control )
else if( !job_get_flag( j, JOB_CONTROL) )
{
sb_printf( sb_err,
_( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
@ -2339,7 +2339,7 @@ static int builtin_fg( wchar_t **argv )
reader_write_title();
make_first( j );
j->fg=1;
job_set_flag( j, JOB_FOREGROUND, 1 );
job_continue( j, job_is_stopped(j) );
}
@ -2360,7 +2360,7 @@ static int send_to_bg( job_t *j, const wchar_t *name )
builtin_print_help( L"bg", sb_err );
return STATUS_BUILTIN_ERROR;
}
else if( !j->job_control )
else if( !job_get_flag( j, JOB_CONTROL ) )
{
sb_printf( sb_err,
_( L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n" ),
@ -2378,7 +2378,7 @@ static int send_to_bg( job_t *j, const wchar_t *name )
j->command );
}
make_first( j );
j->fg=0;
job_set_flag( j, JOB_FOREGROUND, 0 );
job_continue( j, job_is_stopped(j) );
return 0;
}
@ -2396,7 +2396,7 @@ static int builtin_bg( wchar_t **argv )
job_t *j;
for( j=first_job; j; j=j->next )
{
if( job_is_stopped(j) && j->job_control && (!job_is_completed(j)) )
if( job_is_stopped(j) && job_get_flag( j, JOB_CONTROL ) && (!job_is_completed(j)) )
{
break;
}
@ -2519,7 +2519,6 @@ static void builtin_end_add_function_def( function_data_t *d )
wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos,
parser_get_job_pos()-current_block->tok_pos );
function_add( d->name,
def,
d->description,

View file

@ -276,7 +276,7 @@ static int builtin_jobs( wchar_t **argv )
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && !job_is_completed(j) )
if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
return 0;
@ -330,7 +330,7 @@ static int builtin_jobs( wchar_t **argv )
/*
Ignore unconstructed jobs, i.e. ourself.
*/
if( j->constructed && !job_is_completed(j) )
if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
found = 1;

24
exec.c
View file

@ -609,7 +609,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
{
int res = 0;
if( j->job_control )
if( job_get_flag( j, JOB_CONTROL ) )
{
if (!j->pgid)
{
@ -638,7 +638,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
j->pgid = getpid();
}
if( j->terminal && j->fg )
if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
{
if( tcsetpgrp (0, j->pgid) && print_errors )
{
@ -735,7 +735,7 @@ void exec( job_t *j )
}
else
{
j->constructed=1;
job_set_flag( j, JOB_CONSTRUCTED, 1 );
j->first_process->completed=1;
return;
}
@ -767,7 +767,7 @@ void exec( job_t *j )
inside a pipeline.
*/
if( j->job_control )
if( job_get_flag( j, JOB_CONTROL ) )
{
for( p=j->first_process; p; p = p->next )
{
@ -991,8 +991,8 @@ void exec( job_t *j )
builtin_out_redirect = has_fd( j->io, 1 );
builtin_err_redirect = has_fd( j->io, 2 );
fg = j->fg;
j->fg = 0;
fg = job_get_flag( j, JOB_FOREGROUND );
job_set_flag( j, JOB_FOREGROUND, 0 );
signal_unblock();
@ -1005,7 +1005,7 @@ void exec( job_t *j )
false during builtin execution so as not to confuse
some job-handling builtins.
*/
j->fg = fg;
job_set_flag( j, JOB_FOREGROUND, fg );
}
if( close_stdin )
@ -1041,7 +1041,7 @@ void exec( job_t *j )
*/
if( p->next == 0 )
{
proc_set_last_status( j->negate?(!status):status);
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
}
p->completed = 1;
break;
@ -1091,7 +1091,7 @@ void exec( job_t *j )
{
if( p->next == 0 )
{
proc_set_last_status( j->negate?(!status):status);
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
}
p->completed = 1;
}
@ -1182,7 +1182,7 @@ void exec( job_t *j )
{
debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status );
proc_set_last_status( j->negate?(!p->status):p->status );
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!p->status):p->status );
}
break;
@ -1316,9 +1316,9 @@ void exec( job_t *j )
for( tmp = block_io; tmp; tmp=tmp->next )
j->io = io_remove( j->io, tmp );
j->constructed = 1;
job_set_flag( j, JOB_CONSTRUCTED, 1 );
if( !j->fg )
if( !job_get_flag( j, JOB_FOREGROUND ) )
{
proc_last_bg_pid = j->pgid;
}

View file

@ -1362,7 +1362,7 @@ static void parse_job_main_loop( process_t *p,
case TOK_BACKGROUND:
{
j->fg = 0;
job_set_flag( j, JOB_FOREGROUND, 0 );
}
case TOK_END:
@ -1381,7 +1381,7 @@ static void parse_job_main_loop( process_t *p,
{
int skip=0;
if( j->skip )
if( job_get_flag( j, JOB_SKIP ) )
{
skip = 1;
}
@ -1622,7 +1622,7 @@ static void parse_job_main_loop( process_t *p,
{
if( unmatched_wildcard && !matched_wildcard )
{
j->wildcard_error = 1;
job_set_flag( j, JOB_WILDCARD_ERROR, 1 );
proc_set_last_status( STATUS_UNMATCHED_WILDCARD );
if( is_interactive && !is_block )
{
@ -1783,7 +1783,7 @@ static int parse_job( process_t *p,
}
else
{
j->negate=1-j->negate;
job_set_flag( j, JOB_NEGATE, !job_get_flag( j, JOB_NEGATE ) );
consumed=1;
}
}
@ -1796,7 +1796,7 @@ static int parse_job( process_t *p,
}
else
{
j->skip = proc_get_last_status();
job_set_flag( j, JOB_SKIP, proc_get_last_status());
consumed=1;
}
}
@ -1809,7 +1809,7 @@ static int parse_job( process_t *p,
}
else
{
j->skip = !proc_get_last_status();
job_set_flag( j, JOB_SKIP, !proc_get_last_status());
consumed=1;
}
}
@ -2053,7 +2053,8 @@ static int parse_job( process_t *p,
fwprintf( stderr, L"%ls", parser_current_line() );
current_tokenizer_pos=tmp;
j->skip=1;
job_set_flag( j, JOB_SKIP, 1 );
proc_set_last_status( STATUS_UNKNOWN_COMMAND );
}
}
@ -2258,9 +2259,10 @@ static void eval_job( tokenizer *tok )
case TOK_STRING:
{
j = job_create();
j->fg=1;
j->terminal = j->job_control && (!is_subshell && !is_event);
j->skip_notification = is_subshell || is_block || is_event || (!is_interactive);
job_set_flag( j, JOB_FOREGROUND, 1 );
job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) );
job_set_flag( j, JOB_TERMINAL, job_get_flag( j, JOB_CONTROL ) && (!is_subshell && !is_event));
job_set_flag( j, JOB_SKIP_NOTIFICATION, is_subshell || is_block || is_event || (!is_interactive));
current_block->job = j;
@ -2303,11 +2305,11 @@ static void eval_job( tokenizer *tok )
p->cmd = wcsdup( j->command );
p->skipped=current_block->skip;
}
skip |= current_block->skip;
skip |= j->wildcard_error;
skip |= j->skip;
skip |= job_get_flag( j, JOB_WILDCARD_ERROR );
skip |= job_get_flag( j, JOB_SKIP );
if(!skip )
{
int was_builtin = 0;

59
proc.c
View file

@ -211,8 +211,10 @@ job_t *job_create()
res->job_id = free_id;
first_job = res;
res->job_control = (job_control_mode==JOB_CONTROL_ALL) ||
((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive));
job_set_flag( res,
JOB_CONTROL,
(job_control_mode==JOB_CONTROL_ALL) ||
((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive)) );
// if( res->job_id > 2 )
// fwprintf( stderr, L"Create job %d\n", res->job_id );
@ -287,6 +289,20 @@ int job_is_completed( const job_t *j )
}
void job_set_flag( job_t *j, int flag, int set )
{
if( set )
j->flags |= flag;
else
j->flags = j->flags & (0xffffffff ^ flag);
}
int job_get_flag( job_t *j, int flag )
{
return j->flags&flag?1:0;
}
/**
Store the status of the process pid that was returned by waitpid.
Return 0 if all went well, nonzero otherwise.
@ -521,7 +537,7 @@ int job_reap( int interactive )
sent to the console, do not consider reaping jobs that need
status messages
*/
if( (!j->skip_notification) && (!interactive) && (!j->fg))
if( (!job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) && (!interactive) && (!job_get_flag( j, JOB_FOREGROUND )))
{
continue;
}
@ -549,8 +565,8 @@ int job_reap( int interactive )
{
int proc_is_job = ((p==j->first_process) && (p->next == 0));
if( proc_is_job )
j->notified = 1;
if( !j->skip_notification )
job_set_flag( j, JOB_NOTIFIED, 1 );
if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
{
if( proc_is_job )
fwprintf( stdout,
@ -589,30 +605,27 @@ int job_reap( int interactive )
*/
if( job_is_completed( j ) )
{
if( !j->fg && !j->notified )
if( !job_get_flag( j, JOB_FOREGROUND) && !job_get_flag( j, JOB_NOTIFIED ) && !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
{
if( !j->skip_notification )
{
format_job_info( j, _( L"ended" ) );
found=1;
}
format_job_info( j, _( L"ended" ) );
found=1;
}
proc_fire_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 );
proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );
job_free(j);
}
else if( job_is_stopped( j ) && !j->notified )
else if( job_is_stopped( j ) && !job_get_flag( j, JOB_NOTIFIED ) )
{
/*
Notify the user about newly stopped jobs.
*/
if( !j->skip_notification )
if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
{
format_job_info( j, _( L"stopped" ) );
found=1;
}
j->notified = 1;
job_set_flag( j, JOB_NOTIFIED, 1 );
}
}
@ -843,7 +856,7 @@ void job_continue (job_t *j, int cont)
job_remove( j );
j->next = first_job;
first_job = j;
j->notified = 0;
job_set_flag( j, JOB_NOTIFIED, 0 );
debug( 4,
L"Continue job %d (%ls), %ls, %ls",
@ -854,7 +867,7 @@ void job_continue (job_t *j, int cont)
if( !job_is_completed( j ) )
{
if( j->terminal && j->fg )
if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
{
/* Put the job into the foreground. */
signal_block();
@ -893,7 +906,7 @@ void job_continue (job_t *j, int cont)
for( p=j->first_process; p; p=p->next )
p->stopped=0;
if( j->job_control )
if( job_get_flag( j, JOB_CONTROL ) )
{
if( killpg( j->pgid, SIGCONT ) )
{
@ -914,7 +927,7 @@ void job_continue (job_t *j, int cont)
}
}
if( j->fg )
if( job_get_flag( j, JOB_FOREGROUND ) )
{
int quit = 0;
@ -968,7 +981,7 @@ void job_continue (job_t *j, int cont)
}
}
if( j->fg )
if( job_get_flag( j, JOB_FOREGROUND ) )
{
if( job_is_completed( j ))
@ -986,14 +999,14 @@ void job_continue (job_t *j, int cont)
if( p->pid )
{
debug( 3, L"Set status of %ls to %d", j->command, WEXITSTATUS(p->status) );
proc_set_last_status( j->negate?(WEXITSTATUS(p->status)?0:1):WEXITSTATUS(p->status) );
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(WEXITSTATUS(p->status)?0:1):WEXITSTATUS(p->status) );
}
}
}
/*
Put the shell back in the foreground.
*/
if( j->terminal && j->fg )
if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
{
signal_block();
if( tcsetpgrp (0, getpid()) )
@ -1037,7 +1050,7 @@ void proc_sanity_check()
{
process_t *p;
if( !j->constructed )
if( !job_get_flag( j, JOB_CONSTRUCTED ) )
continue;
@ -1054,7 +1067,7 @@ void proc_sanity_check()
/*
More than one foreground job?
*/
if( j->fg && !(job_is_stopped(j) || job_is_completed(j) ) )
if( job_get_flag( j, JOB_FOREGROUND ) && !(job_is_stopped(j) || job_is_completed(j) ) )
{
if( fg_job != 0 )
{

96
proc.h
View file

@ -146,6 +146,64 @@ typedef struct process
}
process_t;
/**
Constant for the flag variable in the job struct
true if user was told about stopped job
*/
#define JOB_NOTIFIED 1
/**
Constant for the flag variable in the job struct
Whether this job is in the foreground
*/
#define JOB_FOREGROUND 2
/**
Constant for the flag variable in the job struct
Whether the specified job is completely constructed,
i.e. completely parsed, and every process in the job has been
forked, etc.
*/
#define JOB_CONSTRUCTED 4
/**
Constant for the flag variable in the job struct
Whether the specified job is a part of a subshell, event handler or some other form of special job that should not be reported
*/
#define JOB_SKIP_NOTIFICATION 8
/**
Constant for the flag variable in the job struct
Should the exit status be negated? This flag can only be set by the not builtin.
*/
#define JOB_NEGATE 16
/**
Constant for the flag variable in the job struct
This flag is set to one on wildcard expansion errors. It means that the current command should not be executed
*/
#define JOB_WILDCARD_ERROR 32
/**
Constant for the flag variable in the job struct
Skip executing this job. This flag is set by the short-circut builtins, i.e. and and or
*/
#define JOB_SKIP 64
/**
Constant for the flag variable in the job struct
Whether the job is under job control
*/
#define JOB_CONTROL 128
/**
Constant for the flag variable in the job struct
Whether the job wants to own the terminal when in the foreground
*/
#define JOB_TERMINAL 256
/** A pipeline of one or more processes. */
typedef struct job
@ -156,45 +214,22 @@ typedef struct job
process_t *first_process;
/** process group ID */
pid_t pgid;
/** true if user was told about stopped job */
int notified;
/** saved terminal modes */
struct termios tmodes;
/** The job id of the job*/
int job_id;
/** Whether this job is in the foreground */
int fg;
/**
Whether the specified job is completely constructed,
i.e. completely parsed, and every process in the job has been
forked, etc.
*/
int constructed;
/**
Whether the specified job is a part of a subshell, event handler or some other form of special job that should not be reported
*/
int skip_notification;
/** List of IO redrections for the job */
io_data_t *io;
/** Should the exit status be negated? This flag can only be set by the not builtin. */
int negate;
/** This flag is set to one on wildcard expansion errors. It means that the current command should not be executed */
int wildcard_error;
/** Skip executing this job. This flag is set by the short-circut builtins, i.e. and and or */
int skip;
/** Whether the job is under job control */
int job_control;
/** Whether the job wants to own the terminal when in the foreground */
int terminal;
/** Pointer to the next job */
struct job *next;
/**
Bitset containing information about the job. A combination of the JOB_* constants.
*/
int flags;
}
job_t;
@ -260,6 +295,9 @@ extern int job_control_mode;
*/
extern int no_exec;
void job_set_flag( job_t *j, int flag, int set );
int job_get_flag( job_t *j, int flag );
/**
Sets the status of the last process to exit