2005-09-20 23:26:39 +10:00
/** \file parser.h
The fish parser .
*/
2005-10-05 01:11:39 +10:00
# ifndef FISH_PARSER_H
# define FISH_PARSER_H
# include <wchar.h>
# include "proc.h"
# include "util.h"
# include "parser.h"
2006-02-02 01:49:11 +10:00
# include "event.h"
2005-10-05 01:11:39 +10:00
2006-10-02 02:02:58 +10:00
# define PARSER_TEST_ERROR 1
# define PARSER_TEST_INCOMPLETE 2
2006-01-24 06:40:14 +10:00
/**
event_block_t represents a block on events of the specified type
*/
2005-12-12 08:21:01 +10:00
typedef struct event_block
{
/**
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 .
*/
int type ;
/**
The next event_block struct
*/
struct event_block * next ;
}
event_block_t ;
2005-09-20 23:26:39 +10:00
/**
block_t represents a block of commands .
*/
typedef struct block
{
int type ; /**< Type of block. Can be one of WHILE, FOR, IF and FUNCTION */
int skip ; /**< Whether execution of the commands in this block should be skipped */
int tok_pos ; /**< The start index of the block */
/**
2005-12-12 08:21:01 +10:00
Status for the current loop block . Can be any of the values from the loop_status enum .
2005-09-20 23:26:39 +10:00
*/
int loop_status ;
2005-10-15 10:51:26 +10:00
/**
2005-12-12 08:21:01 +10:00
The job that is currently evaluated in the specified block .
2005-10-15 10:51:26 +10:00
*/
job_t * job ;
2006-09-09 00:12:41 +10:00
/**
Block type - specific data
*/
void * data ;
2005-10-15 10:51:26 +10:00
2005-09-20 23:26:39 +10:00
/**
First block type specific variable
*/
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 */
2006-09-09 00:12:41 +10:00
int if_state ; /**< The state of the if block, can be one of IF_STATE_UNTESTED, IF_STATE_FALSE, IF_STATE_TRUE */
2005-09-20 23:26:39 +10:00
wchar_t * switch_value ; /**< The value to test in a switch block */
2006-02-03 01:23:56 +10:00
const wchar_t * source_dest ; /**< The name of the file to source*/
2006-02-02 01:49:11 +10:00
event_t * event ; /**<The event that triggered this block */
2006-09-09 00:12:41 +10:00
wchar_t * function_call_name ;
2005-10-12 05:31:16 +10:00
} param1 ;
2005-09-20 23:26:39 +10:00
/**
Second block type specific variable
*/
union
{
array_list_t for_vars ; /**< List of values for a for block */
int switch_taken ; /**< Whether a switch match has already been found */
2006-02-02 01:49:11 +10:00
process_t * function_call_process ; /**< The process representing this function call */
2005-10-12 05:31:16 +10:00
} param2 ;
2005-09-20 23:26:39 +10:00
2006-02-02 01:49:11 +10:00
/**
Name of file that created this block
*/
2006-02-03 01:23:56 +10:00
const wchar_t * src_filename ;
2006-02-02 01:49:11 +10:00
/**
Line number where this block was created
*/
int src_lineno ;
2005-10-06 08:37:08 +10:00
2005-12-12 08:21:01 +10:00
/**
Some naming confusion . This is a pointer to the first element in the list of all event blocks .
*/
event_block_t * first_event_block ;
2005-09-20 23:26:39 +10:00
/**
Next outer block
*/
struct block * outer ;
} block_t ;
/**
Types of blocks
*/
enum block_type
{
WHILE , /**< While loop block */
FOR , /**< For loop block */
IF , /**< If block */
FUNCTION_DEF , /**< Function definition block */
FUNCTION_CALL , /**< Function invocation block */
SWITCH , /**< Switch block */
FAKE , /**< Fake block */
SUBST , /**< Command substitution scope */
TOP , /**< Outermost block */
BEGIN , /**< Unconditional block */
2006-01-28 21:34:40 +10:00
SOURCE , /**< Block created by the . (source) builtin */
2006-02-02 01:49:11 +10:00
EVENT , /**< Block created on event notifier invocation */
2005-09-20 23:26:39 +10:00
}
;
/**
Possible states for a loop
*/
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 */
} ;
/**
Possible states for a while block
*/
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 */
}
;
/**
Errors that can be generated by the parser
*/
enum parser_error
{
2005-12-04 02:43:56 +10:00
/**
No error
*/
2005-09-20 23:26:39 +10:00
NO_ERR = 0 ,
2005-12-04 02:43:56 +10:00
/**
An error in the syntax
*/
2005-09-20 23:26:39 +10:00
SYNTAX_ERROR ,
2005-12-04 02:43:56 +10:00
/**
Error occured while evaluating commands
*/
2005-09-20 23:26:39 +10:00
EVAL_ERROR ,
2005-12-04 02:43:56 +10:00
/**
2006-08-23 00:38:31 +10:00
Error while evaluating cmdsubst
2005-12-04 02:43:56 +10:00
*/
2006-08-23 00:38:31 +10:00
CMDSUBST_ERROR ,
2005-09-20 23:26:39 +10:00
}
;
/** The current innermost block */
extern block_t * current_block ;
2005-12-12 08:21:01 +10:00
/** Global event blocks */
extern event_block_t * global_event_block ;
2005-09-20 23:26:39 +10:00
/**
2005-10-03 23:09:37 +10:00
Current block level io redirections
2005-09-20 23:26:39 +10:00
*/
extern io_data_t * block_io ;
/**
Finds the full path of an executable in a newly allocated string .
\ param cmd The name of the executable .
2006-06-13 00:12:33 +10:00
\ param context the halloc context to use for memory allocations
2005-09-20 23:26:39 +10:00
\ return 0 if the command can not be found , the path of the command otherwise .
*/
2006-06-13 00:12:33 +10:00
wchar_t * parser_get_filename ( void * context , const wchar_t * cmd ) ;
2005-09-20 23:26:39 +10:00
/**
Evaluate the expressions contained in cmd .
\ param cmd the string to evaluate
2006-01-24 06:40:14 +10:00
\ param io io redirections to perform on all started jobs
2005-09-20 23:26:39 +10:00
\ param block_type The type of block to push on the block stack
2006-01-24 06:40:14 +10:00
\ return 0 on success , 1 otherwise
2005-09-20 23:26:39 +10:00
*/
int eval ( const wchar_t * cmd , io_data_t * io , int block_type ) ;
/**
2006-08-23 00:38:31 +10:00
Evaluate line as a list of parameters , i . e . tokenize it and perform parameter expansion and cmdsubst execution on the tokens .
2005-09-20 23:26:39 +10:00
The output is inserted into output , and should be freed by the caller .
\ param line Line to evaluate
\ param output List to insert output to
*/
int eval_args ( const wchar_t * line ,
array_list_t * output ) ;
/**
Sets the current error
\ param ec The new error code
\ param p The character offset at which the error occured
2005-12-08 02:06:47 +10:00
\ param str The printf - style error message filter
2005-09-20 23:26:39 +10:00
*/
2005-12-08 02:06:47 +10:00
void error ( int ec , int p , const wchar_t * str , . . . ) ;
2005-09-20 23:26:39 +10:00
/**
Tests if the specified commands parameters should be interpreted as another command , which will be true if the command is either ' command ' , ' exec ' , ' if ' , ' while ' or ' builtin ' .
\ param cmd The command name to test
\ return 1 of the command parameter is a command , 0 otherwise
*/
int parser_is_subcommand ( const wchar_t * cmd ) ;
/**
Tests if the specified command is a reserved word , i . e . if it is
the name of one of the builtin functions that change the block or
command scope , like ' for ' , ' end ' or ' command ' or ' exec ' . These
functions may not be overloaded , so their names are reserved .
2006-01-24 06:40:14 +10:00
\ param word The command name to test
2005-09-20 23:26:39 +10:00
\ return 1 of the command parameter is a command , 0 otherwise
*/
2006-02-08 20:22:03 +10:00
int parser_is_reserved ( const wchar_t * word ) ;
2005-09-20 23:26:39 +10:00
2006-03-30 07:29:42 +10:00
/**
Test if the specified string is command that opens a new block
*/
int parser_is_block ( const wchar_t * word ) ;
2005-09-20 23:26:39 +10:00
/**
Returns a string describing the current parser pisition in the format ' FILENAME ( line LINE_NUMBER ) : LINE ' .
Example :
init . fish ( line 127 ) : ls | grep pancake
*/
wchar_t * parser_current_line ( ) ;
2006-01-27 00:48:10 +10:00
/**
Returns the current line number
*/
int parser_get_lineno ( ) ;
2005-09-20 23:26:39 +10:00
/**
Returns the current position in the latest string of the tokenizer .
*/
int parser_get_pos ( ) ;
/**
Returns the position where the current job started in the latest string of the tokenizer .
*/
int parser_get_job_pos ( ) ;
/**
Set the current position in the latest string of the tokenizer .
*/
void parser_set_pos ( int p ) ;
/**
Get the string currently parsed
*/
const wchar_t * parser_get_buffer ( ) ;
/**
Create block of specified type
*/
void parser_push_block ( int type ) ;
/**
Remove the outermost block namespace
*/
void parser_pop_block ( ) ;
/**
Return a description of the given blocktype
*/
2006-01-04 22:51:02 +10:00
const wchar_t * parser_get_block_desc ( int block ) ;
2005-09-20 23:26:39 +10:00
/**
2006-05-22 05:25:24 +10:00
Test if the specified string can be parsed , or if more bytes need
to be read first . The result has the first bit set if the string
contains errors , and the second bit is set if the string contains
an unclosed block .
2005-09-20 23:26:39 +10:00
*/
2006-06-02 12:15:17 +10:00
int parser_test ( const wchar_t * buff , string_buffer_t * out , const wchar_t * prefix ) ;
2006-05-22 05:25:24 +10:00
/**
Test if the specified string can be parsed as an argument list ,
e . g . sent to eval_args . The result has the first bit set if the
string contains errors , and the second bit is set if the string
contains an unclosed block .
*/
2006-06-02 12:15:17 +10:00
int parser_test_args ( const wchar_t * buff , string_buffer_t * out , const wchar_t * prefix ) ;
2005-09-20 23:26:39 +10:00
/**
Returns the full path of the specified directory . If the \ c in is a
full path to an existing directory , a copy of the string is
returned . If \ c in is a directory relative to one of the
directories i the CDPATH , the full path is returned . If no
directory can be found , 0 is returned .
*/
2006-06-13 00:12:33 +10:00
wchar_t * parser_cdpath_get ( void * context , wchar_t * in ) ;
2005-09-20 23:26:39 +10:00
/**
Tell the parser that the specified function may not be run if not
inside of a conditional block . This is to remove some possibilities
of infinite recursion .
*/
void parser_forbid_function ( wchar_t * function ) ;
/**
Undo last call to parser_forbid_function ( ) .
*/
void parser_allow_function ( ) ;
/**
2005-12-15 23:59:02 +10:00
Initialize static parser data
2005-09-20 23:26:39 +10:00
*/
void parser_init ( ) ;
/**
2005-12-15 23:59:02 +10:00
Destroy static parser data
2005-09-20 23:26:39 +10:00
*/
void parser_destroy ( ) ;
/**
This function checks if the specified string is a help option .
\ param s the string to test
\ param min_match is the minimum number of characters that must match in a long style option , i . e . the longest common prefix between - - help and any other option . If less than 3 , 3 will be assumed .
*/
int parser_is_help ( wchar_t * s , int min_match ) ;
2006-01-27 01:47:22 +10:00
/**
Returns the file currently evaluated by the parser . This can be
different than reader_current_filename , e . g . if we are evaulating a
function defined in a different file than the one curently read .
*/
const wchar_t * parser_current_filename ( ) ;
2006-01-31 03:54:26 +10:00
/**
Write a stack trace starting at the specified block to the specified string_buffer_t
*/
void parser_stack_trace ( block_t * b , string_buffer_t * buff ) ;
2006-09-06 06:43:47 +10:00
int parser_get_block_type ( const wchar_t * cmd ) ;
const wchar_t * parser_get_block_command ( int type ) ;
2006-01-27 01:47:22 +10:00
2005-10-05 01:11:39 +10:00
# endif