Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

parser.c File Reference

The fish parser. More...

#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <pwd.h>
#include <dirent.h>
#include <signal.h>
#include "fallback.h"
#include "util.h"
#include "common.h"
#include "wutil.h"
#include "proc.h"
#include "parser.h"
#include "parser_keywords.h"
#include "tokenizer.h"
#include "exec.h"
#include "wildcard.h"
#include "function.h"
#include "builtin.h"
#include "env.h"
#include "expand.h"
#include "reader.h"
#include "sanity.h"
#include "env_universal.h"
#include "event.h"
#include "intern.h"
#include "parse_util.h"
#include "halloc.h"
#include "halloc_util.h"
#include "path.h"

Data Structures

struct  block_lookup_entry
 Datastructure to describe a block type, like while blocks, command substitution blocks, etc. More...
struct  profile_element_t
 Struct used to keep track of profiling data for a command. More...

Defines

#define BLOCK_MAX_COUNT   64
 Maximum number of block levels in code.
#define MAX_RECURSION_DEPTH   128
 Maximum number of function calls, i.e.
#define UNKNOWN_BUILTIN_ERR_MSG   _(L"Unknown builtin '%ls'")
 Error message for unknown builtin.
#define EXEC_ERR_MSG   _(L"This command can not be used in a pipeline")
 Error message for improper use of the exec builtin.
#define TOK_ERR_MSG   _( L"Tokenizer error: '%ls'")
 Error message for tokenizer error.
#define COND_ERR_MSG   _( L"An additional command is required" )
 Error message for short circuit command error.
#define RECURSION_ERR_MSG   _( L"Maximum recursion depth reached. Accidental infinite loop?")
 Error message on reaching maximum recusrion depth.
#define BLOCK_END_ERR_MSG   _( L"Could not locate end of block. The 'end' command is missing, misspelled or a ';' is missing.")
 Error message used when the end of a block can't be located.
#define BLOCK_ERR_MSG   _( L"Maximum number of nested blocks reached.")
 Error message on reaching maximum number of block calls.
#define CMD_ERR_MSG   _( L"Expected a command name, got token of type '%ls'")
 Error message when a non-string token is found when expecting a command name.
#define CMD_OR_ERR_MSG   _( L"Expected a command name, got token of type '%ls'. Did you mean 'COMMAND; or COMMAND'? See the help section for the 'or' builtin command by typing 'help or'.")
 Error message when a non-string token is found when expecting a command name.
#define CMD_AND_ERR_MSG   _( L"Expected a command name, got token of type '%ls'. Did you mean 'COMMAND; and COMMAND'? See the help section for the 'and' builtin command by typing 'help and'.")
 Error message when a non-string token is found when expecting a command name.
#define ILLEGAL_CMD_ERR_MSG   _( L"Illegal command name '%ls'")
 Error message when encountering an illegal command name.
#define ILLEGAL_FD_ERR_MSG   _( L"Illegal file descriptor '%ls'")
 Error message when encountering an illegal file descriptor.
#define WILDCARD_ERR_MSG   _( L"Warning: No match for wildcard '%ls'. The command will not be executed.")
 Error message for wildcards with no matches.
#define INVALID_CASE_ERR_MSG   _( L"'case' builtin not inside of switch block")
 Error when using case builtin outside of switch block.
#define INVALID_LOOP_ERR_MSG   _( L"Loop control command while not inside of loop" )
 Error when using loop control builtins (break or continue) outside of loop.
#define INVALID_RETURN_ERR_MSG   _( L"'return' builtin command outside of function definition" )
 Error when using return builtin outside of function definition.
#define INVALID_ELSE_ERR_MSG   _( L"'else' builtin not inside of if block" )
 Error when using else builtin outside of if block.
#define INVALID_END_ERR_MSG   _( L"'end' command outside of block")
 Error when using end builtin outside of block.
#define COMMAND_ASSIGN_ERR_MSG   _( L"Unknown command '%ls'. Did you mean 'set %ls %ls'? For information on assigning values to variables, see the help section on the set command by typing 'help set'.")
 Error message for Posix-style assignment.
#define REDIRECT_TOKEN_ERR_MSG   _( L"Expected redirection specification, got token of type '%ls'")
 Error for invalid redirection token.
#define INVALID_REDIRECTION_ERR_MSG   _( L"Encountered redirection when expecting a command name. Fish does not allow a redirection operation before a command.")
 Error when encountering redirection without a command.
#define EVAL_NULL_ERR_MSG   _( L"Tried to evaluate null pointer." )
 Error for evaluating null pointer.
#define INVALID_SCOPE_ERR_MSG   _( L"Tried to evaluate commands using invalid block type '%ls'" )
 Error for evaluating in illegal scope.
#define UNEXPECTED_TOKEN_ERR_MSG   _( L"Unexpected token of type '%ls'")
 Error for wrong token type.
#define WHILE_BLOCK   N_( L"'while' block" )
 While block description.
#define FOR_BLOCK   N_( L"'for' block" )
 For block description.
#define BREAKPOINT_BLOCK   N_( L"Block created by breakpoint" )
 Breakpoint block.
#define IF_BLOCK   N_( L"'if' conditional block" )
 If block description.
#define FUNCTION_DEF_BLOCK   N_( L"function definition block" )
 Function definition block description.
#define FUNCTION_CALL_BLOCK   N_( L"function invocation block" )
 Function invocation block description.
#define FUNCTION_CALL_NO_SHADOW_BLOCK   N_( L"function invocation block with no variable shadowing" )
 Function invocation block description.
#define SWITCH_BLOCK   N_( L"'switch' block" )
 Switch block description.
#define FAKE_BLOCK   N_( L"unexecutable block" )
 Fake block description.
#define TOP_BLOCK   N_( L"global root block" )
 Top block description.
#define SUBST_BLOCK   N_( L"command substitution block" )
 Command substitution block description.
#define BEGIN_BLOCK   N_( L"'begin' unconditional block" )
 Begin block description.
#define SOURCE_BLOCK   N_( L"Block created by the . builtin" )
 Source block description.
#define EVENT_BLOCK   N_( L"event handler block" )
 Source block description.
#define UNKNOWN_BLOCK   N_( L"unknown/invalid block" )
 Unknown block description.

Functions

static int parse_job (process_t *p, job_t *j, tokenizer *tok)
 Fully parse a single job.
static int block_count (block_t *b)
 Return the current number of block nestings.
void parser_push_block (int type)
 Create block of specified type.
void parser_pop_block ()
 Remove the outermost block namespace.
const wchar_t * parser_get_block_desc (int block)
 Return a description of the given blocktype.
static int parser_is_pipe_forbidden (wchar_t *word)
 Returns 1 if the specified command is a builtin that may not be used in a pipeline.
static const wchar_t * parser_find_end (const wchar_t *buff)
 Search the text for the end of the current block.
void parser_forbid_function (wchar_t *function)
 Tell the parser that the specified function may not be run if not inside of a conditional block.
void parser_allow_function ()
 Undo last call to parser_forbid_function().
void error (int ec, int p, const wchar_t *str,...)
 Sets the current evaluation error.
void parser_init ()
 Initialize static parser data.
static void print_profile (array_list_t *p, int pos, FILE *out)
 Print profiling information to the specified stream.
void parser_destroy ()
 Destroy static parser data.
static void print_errors (string_buffer_t *target, const wchar_t *prefix)
 Print error message to string_buffer_t if an error has occured while parsing.
static void print_errors_stderr ()
 Print error message to stderr if an error has occured while parsing.
int eval_args (const wchar_t *line, array_list_t *args)
 Evaluate line as a list of parameters, i.e.
void parser_stack_trace (block_t *b, string_buffer_t *buff)
 Write a stack trace starting at the specified block to the specified string_buffer_t.
static const wchar_t * is_function ()
 Returns the name of the currently evaluated function if we are currently evaluating a function, null otherwise.
int parser_get_lineno ()
 Returns the current line number.
const wchar_t * parser_current_filename ()
 Returns the file currently evaluated by the parser.
static int printed_width (const wchar_t *str, int len)
 Calculates the on-screen width of the specified substring of the specified string.
wchar_t * parser_current_line ()
 Returns a string describing the current parser pisition in the format 'FILENAME (line LINE_NUMBER): LINE'.
int parser_get_pos ()
 Returns the current position in the latest string of the tokenizer.
int parser_get_job_pos ()
 Returns the position where the current job started in the latest string of the tokenizer.
void parser_set_pos (int p)
 Set the current position in the latest string of the tokenizer.
const wchar_t * parser_get_buffer ()
 Get the string currently parsed.
int parser_is_help (wchar_t *s, int min_match)
 This function checks if the specified string is a help option.
static void parse_job_argument_list (process_t *p, job_t *j, tokenizer *tok, array_list_t *args)
 Parse options for the specified job.
static void skipped_exec (job_t *j)
 Do skipped execution of command.
static void eval_job (tokenizer *tok)
 Evaluates a job from the specified tokenizer.
int eval (const wchar_t *cmd, io_data_t *io, int block_type)
 Evaluate the expressions contained in cmd.
int parser_get_block_type (const wchar_t *cmd)
const wchar_t * parser_get_block_command (int type)
static int parser_test_argument (const wchar_t *arg, string_buffer_t *out, const wchar_t *prefix, int offset)
 Test if this argument contains any errors.
int parser_test_args (const wchar_t *buff, string_buffer_t *out, const wchar_t *prefix)
 Test if the specified string can be parsed as an argument list, e.g.
int parser_test (const wchar_t *buff, int *block_level, string_buffer_t *out, const wchar_t *prefix)
 Test if the specified string can be parsed, or if more bytes need to be read first.

Variables

static const struct block_lookup_entry block_lookup []
 List of all legal block types.
static int error_code
 Last error code.
event_block_tglobal_event_block = 0
 Global event blocks.
io_data_tblock_io
 Current block level io redirections.
static int err_pos
 Position of last error.
static string_buffer_terr_buff = 0
 Description of last error.
static tokenizercurrent_tokenizer
 Pointer to the current tokenizer.
static string_buffer_tlineinfo = 0
 String for representing the current line.
static int current_tokenizer_pos
 This is the position of the beginning of the currently parsed command.
block_tcurrent_block = 0
 The current innermost block.
static array_list_tforbidden_function
 List of called functions, used to help prevent infinite recursion.
static int job_start_pos
 String index where the current job started.
static array_list_t profile_data
 List of all profiling data.
static int eval_level = -1
 Keeps track of how many recursive eval calls have been made.


Detailed Description

The fish parser.

Contains functions for parsing and evaluating code.


Define Documentation

#define BLOCK_MAX_COUNT   64
 

Maximum number of block levels in code.

This is not the same as maximum recursion depth, this only has to do with how many block levels are legal in the source code, not at evaluation.

#define MAX_RECURSION_DEPTH   128
 

Maximum number of function calls, i.e.

recursion depth.

#define TOK_ERR_MSG   _( L"Tokenizer error: '%ls'")
 

Error message for tokenizer error.

The tokenizer message is appended to this message.


Function Documentation

void error int  ec,
int  p,
const wchar_t *  str,
  ...
 

Sets the current evaluation error.

This function should only be used by libraries that are called by

Parameters:
ec The new error code
p The character offset at which the error occured
str The printf-style error message filter

int eval const wchar_t *  cmd,
io_data_t io,
int  block_type
 

Evaluate the expressions contained in cmd.

Parameters:
cmd the string to evaluate
io io redirections to perform on all started jobs
block_type The type of block to push on the block stack
Returns:
0 on success, 1 otherwise

int eval_args const wchar_t *  line,
array_list_t output
 

Evaluate line as a list of parameters, i.e.

tokenize it and perform parameter expansion and cmdsubst execution on the tokens. The output is inserted into output, and should be freed by the caller.

Parameters:
line Line to evaluate
output List to insert output to

static void eval_job tokenizer tok  )  [static]
 

Evaluates a job from the specified tokenizer.

First calls parse_job to parse the job and then calls exec to execute it.

Parameters:
tok The tokenizer to read tokens from

static const wchar_t* is_function  )  [static]
 

Returns the name of the currently evaluated function if we are currently evaluating a function, null otherwise.

This is tested by moving down the block-scope-stack, checking every block if it is of type FUNCTION_CALL.

static int parse_job process_t p,
job_t j,
tokenizer tok
[static]
 

Fully parse a single job.

Does not call exec on it, but any command substitutions in the job will be executed.

Parameters:
p The process structure that should be used to represent the first process in the job.
j The job structure to contain the parsed job
tok tokenizer to read from
Returns:
1 on success, 0 on error

static void parse_job_argument_list process_t p,
job_t j,
tokenizer tok,
array_list_t args
[static]
 

Parse options for the specified job.

Parameters:
p the process to parse options for
j the job to which the process belongs to
tok the tokenizer to read options from
args the argument list to insert options into

const wchar_t* parser_current_filename  ) 
 

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.

wchar_t* parser_current_line  ) 
 

Returns a string describing the current parser pisition in the format 'FILENAME (line LINE_NUMBER): LINE'.

If we are not going to print a stack trace, at least print the line number and filename

void parser_forbid_function wchar_t *  function  ) 
 

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.

const wchar_t* parser_get_block_command int  type  ) 
 

Returns:
the block command that createa the specified block type, or null on error.

int parser_get_block_type const wchar_t *  cmd  ) 
 

Returns:
the block type created by the specified builtin, or -1 on error.

int parser_is_help wchar_t *  s,
int  min_match
 

This function checks if the specified string is a help option.

Parameters:
s the string to test
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_test const wchar_t *  buff,
int *  block_level,
string_buffer_t out,
const wchar_t *  prefix
 

Test if the specified string can be parsed, or if more bytes need to be read first.

The result will have the PARSER_TEST_ERROR bit set if there is a syntax error in the code, and the PARSER_TEST_INCOMPLETE bit set if the code contains unclosed blocks.

Parameters:
buff the text buffer to test
block_level if non-null, the block nesting level will be filled out into this array
out if non-null, any errors in the command will be filled out into this buffer
prefix the prefix string to prepend to each error message written to the out buffer

int parser_test_args const wchar_t *  buff,
string_buffer_t out,
const wchar_t *  prefix
 

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.

static int parser_test_argument const wchar_t *  arg,
string_buffer_t out,
const wchar_t *  prefix,
int  offset
[static]
 

Test if this argument contains any errors.

Detected errors include syntax errors in command substitutions, improperly escaped characters and improper use of the variable expansion operator.

static void print_errors string_buffer_t target,
const wchar_t *  prefix
[static]
 

Print error message to string_buffer_t if an error has occured while parsing.

Parameters:
target the buffer to write to
prefix,: The string token to prefix the ech line with. Usually the name of the command trying to parse something.

static int printed_width const wchar_t *  str,
int  len
[static]
 

Calculates the on-screen width of the specified substring of the specified string.

This function takes into account the width and allignment of the tab character, but other wise behaves like repeatedly calling wcwidth.

static void skipped_exec job_t j  )  [static]
 

Do skipped execution of command.

This means that only limited execution of block level commands such as end and switch should be preformed.

Parameters:
j the job to execute


Variable Documentation

int eval_level = -1 [static]
 

Keeps track of how many recursive eval calls have been made.

Eval doesn't call itself directly, recursion happens on blocks and on command substitutions.


Generated on Sun Jan 13 02:53:01 2008 for fish by  doxygen 1.4.4