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

View File

@ -276,7 +276,7 @@ static int builtin_jobs( wchar_t **argv )
*/ */
for( j=first_job; j; j=j->next ) 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 ); builtin_jobs_print( j, mode, !found );
return 0; return 0;
@ -330,7 +330,7 @@ static int builtin_jobs( wchar_t **argv )
/* /*
Ignore unconstructed jobs, i.e. ourself. 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 ); builtin_jobs_print( j, mode, !found );
found = 1; 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; int res = 0;
if( j->job_control ) if( job_get_flag( j, JOB_CONTROL ) )
{ {
if (!j->pgid) if (!j->pgid)
{ {
@ -638,7 +638,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
j->pgid = getpid(); 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 ) if( tcsetpgrp (0, j->pgid) && print_errors )
{ {
@ -735,7 +735,7 @@ void exec( job_t *j )
} }
else else
{ {
j->constructed=1; job_set_flag( j, JOB_CONSTRUCTED, 1 );
j->first_process->completed=1; j->first_process->completed=1;
return; return;
} }
@ -767,7 +767,7 @@ void exec( job_t *j )
inside a pipeline. inside a pipeline.
*/ */
if( j->job_control ) if( job_get_flag( j, JOB_CONTROL ) )
{ {
for( p=j->first_process; p; p = p->next ) 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_out_redirect = has_fd( j->io, 1 );
builtin_err_redirect = has_fd( j->io, 2 ); builtin_err_redirect = has_fd( j->io, 2 );
fg = j->fg; fg = job_get_flag( j, JOB_FOREGROUND );
j->fg = 0; job_set_flag( j, JOB_FOREGROUND, 0 );
signal_unblock(); signal_unblock();
@ -1005,7 +1005,7 @@ void exec( job_t *j )
false during builtin execution so as not to confuse false during builtin execution so as not to confuse
some job-handling builtins. some job-handling builtins.
*/ */
j->fg = fg; job_set_flag( j, JOB_FOREGROUND, fg );
} }
if( close_stdin ) if( close_stdin )
@ -1041,7 +1041,7 @@ void exec( job_t *j )
*/ */
if( p->next == 0 ) 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; p->completed = 1;
break; break;
@ -1091,7 +1091,7 @@ void exec( job_t *j )
{ {
if( p->next == 0 ) 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; 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 ); 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; break;
@ -1316,9 +1316,9 @@ void exec( job_t *j )
for( tmp = block_io; tmp; tmp=tmp->next ) for( tmp = block_io; tmp; tmp=tmp->next )
j->io = io_remove( j->io, tmp ); 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; proc_last_bg_pid = j->pgid;
} }

View File

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

59
proc.c
View File

@ -211,8 +211,10 @@ job_t *job_create()
res->job_id = free_id; res->job_id = free_id;
first_job = res; first_job = res;
res->job_control = (job_control_mode==JOB_CONTROL_ALL) || job_set_flag( res,
((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive)); JOB_CONTROL,
(job_control_mode==JOB_CONTROL_ALL) ||
((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive)) );
// if( res->job_id > 2 ) // if( res->job_id > 2 )
// fwprintf( stderr, L"Create job %d\n", res->job_id ); // 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. Store the status of the process pid that was returned by waitpid.
Return 0 if all went well, nonzero otherwise. Return 0 if all went well, nonzero otherwise.
@ -521,7 +537,7 @@ int job_reap( int interactive )
sent to the console, do not consider reaping jobs that need sent to the console, do not consider reaping jobs that need
status messages 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; continue;
} }
@ -549,8 +565,8 @@ int job_reap( int interactive )
{ {
int proc_is_job = ((p==j->first_process) && (p->next == 0)); int proc_is_job = ((p==j->first_process) && (p->next == 0));
if( proc_is_job ) if( proc_is_job )
j->notified = 1; job_set_flag( j, JOB_NOTIFIED, 1 );
if( !j->skip_notification ) if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
{ {
if( proc_is_job ) if( proc_is_job )
fwprintf( stdout, fwprintf( stdout,
@ -589,30 +605,27 @@ int job_reap( int interactive )
*/ */
if( job_is_completed( j ) ) 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_EXIT, -j->pgid, 0 );
proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 ); proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );
job_free(j); 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. 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" ) ); format_job_info( j, _( L"stopped" ) );
found=1; 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 ); job_remove( j );
j->next = first_job; j->next = first_job;
first_job = j; first_job = j;
j->notified = 0; job_set_flag( j, JOB_NOTIFIED, 0 );
debug( 4, debug( 4,
L"Continue job %d (%ls), %ls, %ls", 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( !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. */ /* Put the job into the foreground. */
signal_block(); signal_block();
@ -893,7 +906,7 @@ void job_continue (job_t *j, int cont)
for( p=j->first_process; p; p=p->next ) for( p=j->first_process; p; p=p->next )
p->stopped=0; p->stopped=0;
if( j->job_control ) if( job_get_flag( j, JOB_CONTROL ) )
{ {
if( killpg( j->pgid, SIGCONT ) ) 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; 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 )) if( job_is_completed( j ))
@ -986,14 +999,14 @@ void job_continue (job_t *j, int cont)
if( p->pid ) if( p->pid )
{ {
debug( 3, L"Set status of %ls to %d", j->command, WEXITSTATUS(p->status) ); 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. 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(); signal_block();
if( tcsetpgrp (0, getpid()) ) if( tcsetpgrp (0, getpid()) )
@ -1037,7 +1050,7 @@ void proc_sanity_check()
{ {
process_t *p; process_t *p;
if( !j->constructed ) if( !job_get_flag( j, JOB_CONSTRUCTED ) )
continue; continue;
@ -1054,7 +1067,7 @@ void proc_sanity_check()
/* /*
More than one foreground job? 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 ) if( fg_job != 0 )
{ {

96
proc.h
View File

@ -146,6 +146,64 @@ typedef struct process
} }
process_t; 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. */ /** A pipeline of one or more processes. */
typedef struct job typedef struct job
@ -156,45 +214,22 @@ typedef struct job
process_t *first_process; process_t *first_process;
/** process group ID */ /** process group ID */
pid_t pgid; pid_t pgid;
/** true if user was told about stopped job */
int notified;
/** saved terminal modes */ /** saved terminal modes */
struct termios tmodes; struct termios tmodes;
/** The job id of the job*/ /** The job id of the job*/
int job_id; 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 */ /** List of IO redrections for the job */
io_data_t *io; 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 */ /** Pointer to the next job */
struct job *next; struct job *next;
/**
Bitset containing information about the job. A combination of the JOB_* constants.
*/
int flags;
} }
job_t; job_t;
@ -260,6 +295,9 @@ extern int job_control_mode;
*/ */
extern int no_exec; 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 Sets the status of the last process to exit