Commits

Steven! Ragnarök committed 005dafe

Parse and interpret negated commands.

Comments (0)

Files changed (6)

features/exit_statuses.feature

 	Scenario: Get the exit status of the last run program
 		When I run `sh142` interactively
 		And I type "exitwith 3"
-		And I type "echo exit code was $?1"
+		And I type "echo exit code was $?0"
 		And I exit
 		Then the stdout should contain "exit code was 3"
 
 		And I type "exitwith 7"
 		And I type "exitwith 8"
 		And I type "exitwith 9"
-		And I type "echo exit codes were $?1 $?2 $?3 $?4 $?5 $?6 $?7 $?8 $?9"
+		And I type "echo exit codes were $?0 $?1 $?2 $?3 $?4 $?5 $?6 $?7 $?8"
 		And I exit
 		Then the stdout should contain "exit codes were 9 8 7 6 5 4 3 2 1"
 

include/interpreter.h

 /* The interpreter for the sh142 command shell. Works on a tree of ASTNodes */
 
 void interpret(ast_node *root);
+int interpret_command_seq(ast_node *command_seq);
 int interpret_command(ast_node *command);
+int interpret_negated_command(ast_node *command);
 int interpret_var_assign(ast_node *var_assign);
 char *interpret_variable(ast_node *variable);
 char *interpret_value(ast_node *value);
 /* The parser takes an input array of tokens and builds an
  * Abstract Syntax Tree for the following Grammar
  * Start ::= Command | VarAssign
- * Command ::= Command [Arglist] | NegatedCommand | BackgroundCommand | BooleanCommand | PipedCommand
- * NegatedCommand ::= ! Command
- * BackgroundCommand ::= Command &
+ * CommandSequence ::= Command [Arglist] | NegatedCommand | BackgroundCommand | BooleanCommand | PipedCommand
+ * Command
+ * NegatedCommand ::= ! CommandSequence
+ * BackgroundCommand ::= CommandSequence &
  * BooleanCommand ::= AndedCommand | OrredCommand
- * AndedCommand ::= Command && Command
- * OrredCommand ::= Command || Commmand
+ * AndedCommand ::= CommandSequence && CommandSequence
+ * OrredCommand ::= CommandSequence || CommandSequence
  * Arglist ::= Arg [ Arglist ]
  * Arg ::= Variable | Value
  * Variable ::= $Value
 
 /* Actual parsing functions */
 ast_node *parse(void);
+ast_node *parse_command_seq(void);
 ast_node *parse_var_assign(int eqlidx);
 ast_node *parse_command(void);
+ast_node *parse_negated_command(void);
 ast_nodelist *parse_arglist(void);
 ast_node *parse_arg(void);
 ast_node *parse_variable(void);

include/sh142types.h

 #define MAX_SAVED_EXITSTATUSES 10
 
 /* Different types of tokens!!!! */
-typedef enum { COMMAND, VARASSIGN, VALUE, VARIABLE } node_type;
+typedef enum {
+	VARASSIGN, VALUE, VARIABLE, COMMAND, NEGATED_COMMAND
+} node_type;
 
 /* Since we have mutually recursive structures, we need to use forward
  * declaration and thus, cannot omit the struct name.

src/interpreter.c

 
 void interpret(ast_node *root) {
 	int exit_status;
-	if (root->type == COMMAND) {
-		exit_status = interpret_command(root);
-	} else if (root->type == VARASSIGN) {
+	if (root->type == VARASSIGN) {
 		exit_status = interpret_var_assign(root);
+	} else {
+		exit_status = interpret_command_seq(root);
 	}
 
 	fifo_push(MAX_SAVED_EXITSTATUSES, exitstatuses, exitstatus_head, exit_status);
 	return;
 }
 
+int interpret_command_seq(ast_node *command_seq) {
+	int exit_status = 99;
+	switch (command_seq->type) {
+		case NEGATED_COMMAND:
+			exit_status = interpret_negated_command(command_seq);
+			break;
+		case COMMAND:
+			exit_status = interpret_command(command_seq);
+			break;
+	}
+	return exit_status;
+}
+
 int interpret_command(ast_node* command) {
 	int cmdstats, argc = 0, execerr;
 	pid_t cmdpid;
 	return WEXITSTATUS(cmdstats);
 }
 
+int interpret_negated_command(ast_node *command) {
+	int command_status;
+	command_status = interpret_command(command);
+	if (command_status == 0) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 int interpret_var_assign(ast_node *var_assign) {
 	char *varname, *value;
 	varname = var_assign->children->node->token;
 	if ((eql = contains_eql(tokens->str)) != -1) {
 		return parse_var_assign(eql);
 	} else {
+		return parse_command_seq();
+	}
+}
+
+ast_node *parse_command_seq() {
+	if (strcmp(tokens->str, "!") == 0) {
+		return parse_negated_command();
+	} else {
 		return parse_command();
 	}
 }
 	return command;
 }
 
+ast_node *parse_negated_command() {
+	ast_node *negated_command;
+	strip_head();
+	negated_command = parse_command();
+	negated_command->type = NEGATED_COMMAND;
+	return negated_command;
+}
+
+
+
 ast_nodelist *parse_arglist() {
 	ast_nodelist *head, *tail;
 	ast_node *arg_node;