/* See LICENSE file for copyright and license details. */ #include #include #include "config.h" enum argument_type { /* .text and .length */ QUOTED, /* \ or '…' or $'…' */ UNQUOTED, /* normal */ /* .child */ QUOTE_EXPRESSION, /* "…" */ BACKQUOTE_EXPRESSION, /* `…` */ ARITHMETIC_EXPRESSION, /* $((…)) */ VARIABLE_SUBSTITUTION, /* ${…} */ SUBSHELL_SUBSTITUTION, /* $(…) */ PROCESS_SUBSTITUTION_INPUT, /* >(…) */ PROCESS_SUBSTITUTION_OUTPUT, /* <(…) */ PROCESS_SUBSTITUTION_INPUT_OUTPUT, /* <>(…) */ SUBSHELL, /* (…) ## if non-first argument: format shell code into a string (can be used for a clean subshell) */ ARITHMETIC_SUBSHELL, /* ((…)) ## if non-first argument: format shell code into a string */ /* (none) */ REDIRECTION, /* at beginning of argument, use next redirection and use reminder of argument as right-hand side */ FUNCTION_MARK /* () */ }; enum redirection_type { REDIRECT_INPUT, REDIRECT_INPUT_TO_FD, REDIRECT_OUTPUT, REDIRECT_OUTPUT_APPEND, REDIRECT_OUTPUT_CLOBBER, REDIRECT_OUTPUT_TO_FD, REDIRECT_OUTPUT_AND_STDERR, REDIRECT_OUTPUT_AND_STDERR_APPEND, REDIRECT_OUTPUT_AND_STDERR_CLOBBER, REDIRECT_OUTPUT_AND_STDERR_TO_FD, REDIRECT_INPUT_OUTPUT, REDIRECT_INPUT_OUTPUT_TO_FD, HERE_STRING, HERE_DOCUMENT, HERE_DOCUMENT_INDENTED }; enum tokeniser_mode { NORMAL_MODE, COMMENT_MODE, BQ_QUOTE_MODE, DQ_QUOTE_MODE, RRB_QUOTE_MODE, RB_QUOTE_MODE, SB_QUOTE_MODE, CB_QUOTE_MODE, HERE_DOCUMENT_MODE }; enum command_terminal { DOUBLE_SEMICOLON, SEMICOLON, AMPERSAND, SOCKET_PIPE, PIPE, PIPE_AMPERSAND, AND, OR }; struct parser_state; struct argument { enum argument_type type; union { struct { char *text; size_t length; }; struct parser_state *child; }; size_t line_number; struct argument *next_part; }; struct redirection { enum redirection_type type; struct argument *left_hand_side; }; struct command { enum command_terminal terminal; struct argument **arguments; size_t narguments; struct redirection **redirections; size_t nredirections; }; struct parser_state { struct parser_state *parent; struct command **commands; size_t ncommands; struct argument **arguments; size_t narguments; struct redirection **redirections; size_t nredirections; struct argument *current_argument; struct argument *current_argument_end; char need_right_hand_side; }; struct here_document { struct redirection *redirection; struct argument *argument; struct here_document *next; }; struct mode_stack { enum tokeniser_mode mode; int she_is_comment; struct mode_stack *previous; }; struct parser_context { int tty_input; int end_of_file_reached; int premature_end_of_file; size_t preparser_offset; size_t preparser_line_number; size_t line_continuations; size_t tokeniser_line_number; struct mode_stack *mode_stack; struct parser_state *parser_state; struct here_document *here_documents_first; struct here_document **here_documents_next; }; /* apsh.c */ void initialise_parser_context(struct parser_context *ctx); /* preparser.c */ size_t parse(struct parser_context *ctx, char *code, size_t code_len, size_t *nremovedp); /* tokeniser.c */ void push_mode(struct parser_context *ctx, enum tokeniser_mode mode); void pop_mode(struct parser_context *ctx); size_t parse_preparsed(struct parser_context *ctx, char *code, size_t code_len); /* parser.c */ void push_end_of_file(struct parser_context *ctx); void push_whitespace(struct parser_context *ctx, int strict); void push_semicolon(struct parser_context *ctx, int maybe); size_t push_symbol(struct parser_context *ctx, char *token, size_t token_len); void push_quoted(struct parser_context *ctx, char *text, size_t text_len); void push_escaped(struct parser_context *ctx, char *text, size_t text_len); void push_unquoted(struct parser_context *ctx, char *text, size_t text_len); void push_enter(struct parser_context *ctx, enum argument_type type); void push_leave(struct parser_context *ctx);