#ifndef __PARSER_H #define __PARSER_H /* Include this header to use the parser. For an example of the usage see CUseParser.c UseParser.cpp For an example of the build run make and see the commands it executes (see README for details) If you want to see the structure of the generated parse tree, run ./DisplayStructure */ #ifdef _WIN32 # ifndef WIN32 # define WIN32 # endif #endif #ifdef __cplusplus #else /* use this to simulate the bool type in C++; e.g.: bool flag = false; if (flag) ... else ... */ typedef enum { false, true } bool; #endif /* a string literal list string literals can be made up of multiple strings (next_part points to the next part of a string or is NULL if there are no more parts) Some parts might need environment variable expansion (expand == true); if that is the case, "string" points to the environment variable name The next string literal is pointed to by next_word (NULL if there are no more list elements) The parser guarantees that '=' will be a single part of a string (e.g. "name=value" will contain three parts: "name" "=" "value" (except for quoted strings in the original command line)) this can ease implementing an internal command similar to export, although the parser does not provide full functionality for this. You are not required to implement export. To tell if a string literal represents an internal command, first concatenate all its parts (expanding them if necessary) and then compare the result using string comparison. */ typedef struct word_t { const char * string; bool expand; struct word_t * next_part; struct word_t * next_word; } word_t; /* Describes a simple command aux can be used to point to additional information you might need; freeing the memory aux points to is your responsibility. aux will be initialized to NULL. Do not modify these structures, please use aux. verb points to a single string literal (possibly made up of parts) that is the executable name or the internal command name. params points to a list of parameters (possibly none) in the order they were entered in the command line. in out and err point to the names of the redirections for the command; they can point to a single literal, no literal (the command does not have that redirection) or multiple literals (the user entered multiple redirections for a command; e.g. cat >out1 >out2). You can handle the latter as you wish (e.g. only consider the first redirection). Within any of these lists, the literals are in the original order. Some string literals can be found in both the out list and the err list (those entered as "command &> out"). up points to the command_t structure that points to this simple_command_t (up != NULL) */ typedef struct { word_t * verb; word_t * params; word_t * in; word_t * out; word_t * err; struct command_t * up; void * aux; } simple_command_t; /* operators OP_NONE means no operator (the scmd field points to a simple command and cmd1 == cmd2 == NULL) the rest of the operators mean scmd == NULL OP_DUMMY is a dummy value that can be used to count the number of operators */ typedef enum { OP_NONE, OP_SEQUENTIAL, OP_PARALLEL, OP_CONDITIONAL_ZERO, OP_CONDITIONAL_NZERO, OP_PIPE, OP_DUMMY } operator_t; /* describes a command tree (a node of the parse tree) if (op == OP_NONE) scmd != NULL cmd1 == cmd2 == NULL scmd points to a command to be executed else scmd == NULL cmd1 != NULL cmd2 != NULL cmd1 op cmd2 must be executed, according to the rules for op You can use aux the same way as for simple_command_t up points to the command_t that points to this structure (the father of the current node in the parse tree) The root of the tree has up == NULL The parsed expressions do not contain parantheses, this means that the following holds: for any op_lower that has a lower priority than op, there is no parent in the tree with op == op_lower In particular, if op == OP_PIPE descendants can only have OP_PIPE or OP_NONE */ typedef struct command_t { struct command_t * up; struct command_t * cmd1; struct command_t * cmd2; operator_t op; simple_command_t * scmd; void * aux; } command_t; #ifdef __cplusplus extern "C" { #endif /* You must define this function; it will be called by the parser when a parse error occurs; str describes the error (not a useful description) and where points to some location before the error was discovered (the character number, starting at 0) */ void parse_error(const char * str, const int where); /* Call this to parse a line line must point to a string containig a single line The line must end with "\r\n\0" or "\n\0" or "\0" (*root) must point to NULL ((*root) == NULL) parse_line returns true if there was no error parsing the line and false if there was an error parsing or the arguments were invalid if parse_line returns true: if line was empty (or contained just blanks) (*root) is NULL else (*root) points to the root of the parse tree */ bool parse_line(const char * line, command_t ** root); /* should be called to free the parse tree call this even if parse_line() returned false */ void free_parse_memory(); #ifdef __cplusplus } #endif #ifdef __PARSER_H_INTERNAL_INCLUDE /* parser and lexer common internal stuff */ typedef void * GenericPointer; typedef struct { word_t * red_i; word_t * red_o; word_t * red_e; } redirect_t; #ifdef __cplusplus extern "C" { #endif int yylex(); void globalParseAnotherString(const char * str); void globalEndParsing(); void pointerToMallocMemory(const void * ptr); #ifdef __cplusplus } #endif #endif /* Parser written by Maximilian Machedon, based on a previous version. */ #endif