5b0a6ee34390fe279d9671abd691efe17d0c215b — Simon Ser a month ago 009263d
shell/arithm: implement variables

Closes: https://github.com/emersion/mrsh/issues/85
2 files changed, 35 insertions(+), 19 deletions(-)

M shell/arithm.c
M test/arithm.sh
M shell/arithm.c => shell/arithm.c +27 -19
@@ 2,6 2,28 @@ #include <mrsh/shell.h>
  #include <stdlib.h>
  
+ static bool run_variable(struct mrsh_state *state, const char *name, long *val,
+ 		uint32_t *attribs) {
+ 	const char *str = mrsh_env_get(state, name, attribs);
+ 	if (str == NULL) {
+ 		if ((state->options & MRSH_OPT_NOUNSET)) {
+ 			fprintf(stderr, "%s: %s: unbound variable\n",
+ 					state->frame->argv[0], name);
+ 			return false;
+ 		}
+ 		*val = 0; // POSIX is not clear what to do in this case
+ 	} else {
+ 		char *end;
+ 		*val = strtod(str, &end);
+ 		if (end == str || end[0] != '\0') {
+ 			fprintf(stderr, "%s: %s: not a number: %s\n",
+ 					state->frame->argv[0], name, str);
+ 			return false;
+ 		}
+ 	}
+ 	return true;
+ }
+ 
  static bool run_arithm_binop(struct mrsh_state *state,
  		struct mrsh_arithm_binop *binop, long *result) {
  	long left, right;


@@ 149,22 171,8 @@ long cur = 0;
  	uint32_t attribs = MRSH_VAR_ATTRIB_NONE;
  	if (assign->op != MRSH_ARITHM_ASSIGN_NONE) {
- 		const char *cur_str = mrsh_env_get(state, assign->name, &attribs);
- 		if (cur_str == NULL) {
- 			if ((state->options & MRSH_OPT_NOUNSET)) {
- 				fprintf(stderr, "%s: %s: unbound variable\n",
- 						state->frame->argv[0], assign->name);
- 				return false;
- 			}
- 			cur = 0; // POSIX is not clear what to do in this case
- 		} else {
- 			char *end;
- 			cur = strtod(cur_str, &end);
- 			if (end == cur_str || end[0] != '\0') {
- 				fprintf(stderr, "%s: %s: not a number: %s\n",
- 						state->frame->argv[0], assign->name, cur_str);
- 				return false;
- 			}
+ 		if (!run_variable(state, assign->name, &cur, &attribs)) {
+ 			return false;
  		}
  	}
  	*result = run_arithm_assign_op(assign->op, cur, val);


@@ 185,9 193,9 @@ *result = literal->value;
  		return true;
  	case MRSH_ARITHM_VARIABLE:;
- 		//struct mrsh_arithm_variable *variable =
- 		//	(struct mrsh_arithm_variable *)expr;
- 		assert(false); // TODO
+ 		struct mrsh_arithm_variable *variable =
+ 			(struct mrsh_arithm_variable *)expr;
+ 		return run_variable(state, variable->name, result, NULL);
  	case MRSH_ARITHM_BINOP:;
  		struct mrsh_arithm_binop *binop =
  			(struct mrsh_arithm_binop *)expr;

M test/arithm.sh => test/arithm.sh +8 -0
@@ 34,6 34,14 @@ echo "2|1||1" $((2|1||1)) # 1
  echo "1||1|2" $((1||1|2)) # 1
  
+ # Variables
+ a=42
+ echo "a =" $((a))
+ echo "a+2 =" $((a+2))
+ echo "2*a-10 =" $((2*a-10))
+ echo "\$a =" $(($a))
+ echo "\$a+2 =" $(($a+2))
+ 
  # Assignments
  echo "(a=42) =" $((a=42)) "->" $a
  echo "(a+=1) =" $((a+=1)) "->" $a