mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
Make the validator show the help for a block command missing an 'end'
darcs-hash:20060616125616-ac50b-b895cc14ce9f26ec99ac90523b2a52d0dce66dd9.gz
This commit is contained in:
parent
d2869d5140
commit
907b2f8462
1 changed files with 150 additions and 71 deletions
221
parser.c
221
parser.c
|
@ -177,78 +177,78 @@ The fish parser. Contains functions for parsing code.
|
||||||
/**
|
/**
|
||||||
While block description
|
While block description
|
||||||
*/
|
*/
|
||||||
#define WHILE_BLOCK _( L"'while' block" )
|
#define WHILE_BLOCK N_( L"'while' block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
For block description
|
For block description
|
||||||
*/
|
*/
|
||||||
#define FOR_BLOCK _( L"'for' block" )
|
#define FOR_BLOCK N_( L"'for' block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
If block description
|
If block description
|
||||||
*/
|
*/
|
||||||
#define IF_BLOCK _( L"'if' conditional block" )
|
#define IF_BLOCK N_( L"'if' conditional block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Function definition block description
|
Function definition block description
|
||||||
*/
|
*/
|
||||||
#define FUNCTION_DEF_BLOCK _( L"function definition block" )
|
#define FUNCTION_DEF_BLOCK N_( L"function definition block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Function invocation block description
|
Function invocation block description
|
||||||
*/
|
*/
|
||||||
#define FUNCTION_CALL_BLOCK _( L"function invocation block" )
|
#define FUNCTION_CALL_BLOCK N_( L"function invocation block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Switch block description
|
Switch block description
|
||||||
*/
|
*/
|
||||||
#define SWITCH_BLOCK _( L"'switch' block" )
|
#define SWITCH_BLOCK N_( L"'switch' block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Fake block description
|
Fake block description
|
||||||
*/
|
*/
|
||||||
#define FAKE_BLOCK _( L"unexecutable block" )
|
#define FAKE_BLOCK N_( L"unexecutable block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Top block description
|
Top block description
|
||||||
*/
|
*/
|
||||||
#define TOP_BLOCK _( L"global root block" )
|
#define TOP_BLOCK N_( L"global root block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Command substitution block description
|
Command substitution block description
|
||||||
*/
|
*/
|
||||||
#define SUBST_BLOCK _( L"command substitution block" )
|
#define SUBST_BLOCK N_( L"command substitution block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Begin block description
|
Begin block description
|
||||||
*/
|
*/
|
||||||
#define BEGIN_BLOCK _( L"'begin' unconditional block" )
|
#define BEGIN_BLOCK N_( L"'begin' unconditional block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Source block description
|
Source block description
|
||||||
*/
|
*/
|
||||||
#define SOURCE_BLOCK _( L"Block created by the . builtin" )
|
#define SOURCE_BLOCK N_( L"Block created by the . builtin" )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Source block description
|
Source block description
|
||||||
*/
|
*/
|
||||||
#define EVENT_BLOCK _( L"event handler block" )
|
#define EVENT_BLOCK N_( L"event handler block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Unknown block description
|
Unknown block description
|
||||||
*/
|
*/
|
||||||
#define UNKNOWN_BLOCK _( L"unknown/invalid block" )
|
#define UNKNOWN_BLOCK N_( L"unknown/invalid block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -256,6 +256,71 @@ The fish parser. Contains functions for parsing code.
|
||||||
*/
|
*/
|
||||||
#define ERR_STR_SZ 1024
|
#define ERR_STR_SZ 1024
|
||||||
|
|
||||||
|
struct block_lookup_entry
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
const wchar_t *name;
|
||||||
|
const wchar_t *desc;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
const static struct block_lookup_entry block_lookup[]=
|
||||||
|
{
|
||||||
|
{
|
||||||
|
WHILE, L"while", WHILE_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
FOR, L"for", FOR_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
IF, L"if", IF_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
FUNCTION_DEF, L"function", FUNCTION_DEF_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
FUNCTION_CALL, 0, FUNCTION_CALL_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
SWITCH, L"switch", SWITCH_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
FAKE, 0, FAKE_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
TOP, 0, TOP_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
SUBST, 0, SUBST_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
BEGIN, L"begin", BEGIN_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
SOURCE, L".", SOURCE_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
EVENT, 0, EVENT_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
0,0,0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/** Last error code */
|
/** Last error code */
|
||||||
static int error_code;
|
static int error_code;
|
||||||
|
|
||||||
|
@ -393,48 +458,16 @@ void parser_pop_block()
|
||||||
|
|
||||||
const wchar_t *parser_get_block_desc( int block )
|
const wchar_t *parser_get_block_desc( int block )
|
||||||
{
|
{
|
||||||
switch( block )
|
int i;
|
||||||
|
|
||||||
|
for( i=0; block_lookup[i].desc; i++ )
|
||||||
{
|
{
|
||||||
case WHILE:
|
if( block_lookup[i].type == block )
|
||||||
return WHILE_BLOCK;
|
{
|
||||||
|
return _( block_lookup[i].desc );
|
||||||
case FOR:
|
}
|
||||||
return FOR_BLOCK;
|
|
||||||
|
|
||||||
case IF:
|
|
||||||
return IF_BLOCK;
|
|
||||||
|
|
||||||
case FUNCTION_DEF:
|
|
||||||
return FUNCTION_DEF_BLOCK;
|
|
||||||
|
|
||||||
case FUNCTION_CALL:
|
|
||||||
return FUNCTION_CALL_BLOCK;
|
|
||||||
|
|
||||||
case SWITCH:
|
|
||||||
return SWITCH_BLOCK;
|
|
||||||
|
|
||||||
case FAKE:
|
|
||||||
return FAKE_BLOCK;
|
|
||||||
|
|
||||||
case TOP:
|
|
||||||
return TOP_BLOCK;
|
|
||||||
|
|
||||||
case SUBST:
|
|
||||||
return SUBST_BLOCK;
|
|
||||||
|
|
||||||
case BEGIN:
|
|
||||||
return BEGIN_BLOCK;
|
|
||||||
|
|
||||||
case SOURCE:
|
|
||||||
return SOURCE_BLOCK;
|
|
||||||
|
|
||||||
case EVENT:
|
|
||||||
return EVENT_BLOCK;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return UNKNOWN_BLOCK;
|
|
||||||
}
|
}
|
||||||
|
return _(UNKNOWN_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1769,6 +1802,9 @@ static int parse_job( process_t *p,
|
||||||
while( al_get_count( args ) == 0 )
|
while( al_get_count( args ) == 0 )
|
||||||
{
|
{
|
||||||
wchar_t *nxt=0;
|
wchar_t *nxt=0;
|
||||||
|
int consumed = 0; // Set to one if the command requires a second command, like e.g. while does
|
||||||
|
int mark; // Use to save the position of the beginning of the token
|
||||||
|
|
||||||
switch( tok_last_type( tok ))
|
switch( tok_last_type( tok ))
|
||||||
{
|
{
|
||||||
case TOK_STRING:
|
case TOK_STRING:
|
||||||
|
@ -1835,11 +1871,13 @@ static int parse_job( process_t *p,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mark = tok_get_pos( tok );
|
mark = tok_get_pos( tok );
|
||||||
|
|
||||||
int consumed = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if this command is one of the many special builtins
|
||||||
|
that work directly on the parser, like e.g. 'not', that
|
||||||
|
simply flips the status inversion flag in the job.
|
||||||
|
*/
|
||||||
if( wcscmp( L"command", nxt )==0 )
|
if( wcscmp( L"command", nxt )==0 )
|
||||||
{
|
{
|
||||||
tok_next( tok );
|
tok_next( tok );
|
||||||
|
@ -1973,8 +2011,14 @@ static int parse_job( process_t *p,
|
||||||
consumed=1;
|
consumed=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if we need another command
|
||||||
|
*/
|
||||||
if( consumed )
|
if( consumed )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Yes we do, around in the loop for another lap, then!
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2624,25 +2668,39 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\return the block type created by the specified builtin, or -1 on error.
|
\return the block type created by the specified builtin, or -1 on error.
|
||||||
*/
|
*/
|
||||||
static int parser_get_block_type( const wchar_t *cmd )
|
static int parser_get_block_type( const wchar_t *cmd )
|
||||||
{
|
{
|
||||||
if( wcscmp( cmd, L"while") == 0 )
|
int i;
|
||||||
return WHILE;
|
|
||||||
else if( wcscmp( cmd, L"for") == 0 )
|
for( i=0; block_lookup[i].desc; i++ )
|
||||||
return FOR;
|
{
|
||||||
else if( wcscmp( cmd, L"switch") == 0 )
|
if( block_lookup[i].name && (wcscmp( block_lookup[i].name, cmd ) == 0) )
|
||||||
return SWITCH;
|
{
|
||||||
else if( wcscmp( cmd, L"if") == 0 )
|
return block_lookup[i].type;
|
||||||
return IF;
|
}
|
||||||
else if( wcscmp( cmd, L"function") == 0 )
|
}
|
||||||
return FUNCTION_DEF;
|
return -1;
|
||||||
else if( wcscmp( cmd, L"begin") == 0 )
|
}
|
||||||
return BEGIN;
|
|
||||||
else
|
/**
|
||||||
return -1;
|
\return the block type created by the specified builtin, or -1 on error.
|
||||||
|
*/
|
||||||
|
static const wchar_t *parser_get_block_command( int type )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i=0; block_lookup[i].desc; i++ )
|
||||||
|
{
|
||||||
|
if( block_lookup[i].type == type )
|
||||||
|
{
|
||||||
|
return block_lookup[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3167,10 +3225,15 @@ int parser_test( const wchar_t * buff,
|
||||||
err = 1;
|
err = 1;
|
||||||
if( out )
|
if( out )
|
||||||
{
|
{
|
||||||
|
char *h;
|
||||||
|
|
||||||
error( SYNTAX_ERROR,
|
error( SYNTAX_ERROR,
|
||||||
tok_get_pos( &tok ),
|
tok_get_pos( &tok ),
|
||||||
INVALID_END_ERR_MSG );
|
INVALID_END_ERR_MSG );
|
||||||
print_errors( out, prefix );
|
print_errors( out, prefix );
|
||||||
|
h = builtin_help_get( L"end" );
|
||||||
|
if( h )
|
||||||
|
sb_printf( out, L"%s", h );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3373,10 +3436,26 @@ int parser_test( const wchar_t * buff,
|
||||||
|
|
||||||
if( out && count>0 )
|
if( out && count>0 )
|
||||||
{
|
{
|
||||||
|
const char *h;
|
||||||
|
const wchar_t *cmd;
|
||||||
|
|
||||||
error( SYNTAX_ERROR,
|
error( SYNTAX_ERROR,
|
||||||
block_pos[count-1],
|
block_pos[count-1],
|
||||||
BLOCK_END_ERR_MSG );
|
BLOCK_END_ERR_MSG );
|
||||||
|
|
||||||
print_errors( out, prefix );
|
print_errors( out, prefix );
|
||||||
|
|
||||||
|
cmd = parser_get_block_command( block_type[count -1] );
|
||||||
|
if( cmd )
|
||||||
|
{
|
||||||
|
h = builtin_help_get( cmd );
|
||||||
|
if( cmd )
|
||||||
|
{
|
||||||
|
sb_printf( out, L"%s", h );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tok_destroy( &tok );
|
tok_destroy( &tok );
|
||||||
|
|
Loading…
Reference in a new issue