f1342b124da2cf87e57f70bd8f1a9c221bca47fe — Simon Ser a month ago bb31b46
shell/task/word: implement parameter minus operator
2 files changed, 51 insertions(+), 6 deletions(-)

M shell/task/word.c
M test/word.sh
M shell/task/word.c => shell/task/word.c +48 -5
@@ 138,6 138,33 @@ return mrsh_env_get(state, name, NULL);
  }
  
+ /* Fill either result_str or result_word */
+ static int apply_parameter_op(struct mrsh_word_parameter *wp, const char *str,
+ 		char **result_str, struct mrsh_word **result_word) {
+ 	switch (wp->op) {
+ 	case MRSH_PARAM_NONE:
+ 		*result_str = str != NULL ? strdup(str) : NULL;
+ 		return 0;
+ 	case MRSH_PARAM_MINUS: // Use Default Values
+ 		if (str == NULL || (str[0] == '\0' && wp->colon)) {
+ 			*result_word = wp->arg;
+ 		} else {
+ 			*result_str = strdup(str);
+ 		}
+ 		return 0;
+ 	case MRSH_PARAM_EQUAL: // Assign Default Values
+ 	case MRSH_PARAM_QMARK: // Indicate Error if Null or Unset
+ 	case MRSH_PARAM_PLUS: // Use Alternative Value
+ 	case MRSH_PARAM_LEADING_HASH: // String Length
+ 	case MRSH_PARAM_PERCENT: // Remove Smallest Suffix Pattern
+ 	case MRSH_PARAM_DPERCENT: // Remove Largest Suffix Pattern
+ 	case MRSH_PARAM_HASH: // Remove Smallest Prefix Pattern
+ 	case MRSH_PARAM_DHASH: // Remove Largest Prefix Pattern
+ 		assert(false); // TODO
+ 	}
+ 	assert(false);
+ }
+ 
  int run_word(struct context *ctx, struct mrsh_word **word_ptr,
  		enum tilde_expansion tilde_expansion) {
  	struct mrsh_word *word = *word_ptr;


@@ 163,17 190,33 @@   			value = lineno;
  		}
- 		if (value == NULL) {
+ 		char *result_str = NULL;
+ 		struct mrsh_word *result_word = NULL;
+ 		ret = apply_parameter_op(wp, value, &result_str, &result_word);
+ 		if (ret < 0) {
+ 			return ret;
+ 		}
+ 		assert(result_str == NULL || result_word == NULL);
+ 		if (result_str == NULL && result_word == NULL) {
  			if ((ctx->state->options & MRSH_OPT_NOUNSET)) {
  				fprintf(stderr, "%s: %s: unbound variable\n",
  						ctx->state->frame->argv[0], wp->name);
  				return TASK_STATUS_ERROR;
  			}
- 			value = "";
+ 			result_str = strdup("");
+ 		}
+ 		if (result_word != NULL) {
+ 			result_word = mrsh_word_copy(result_word);
+ 			ret = run_word(ctx, &result_word, tilde_expansion);
+ 			if (ret < 0) {
+ 				return ret;
+ 			}
+ 		} else if (result_str != NULL) {
+ 			struct mrsh_word_string *ws =
+ 				mrsh_word_string_create(result_str, false);
+ 			result_word = &ws->word;
  		}
- 		struct mrsh_word_string *replacement =
- 			mrsh_word_string_create(strdup(value), false);
- 		swap_words(word_ptr, &replacement->word);
+ 		swap_words(word_ptr, result_word);
  		return 0;
  	case MRSH_WORD_COMMAND:
  		return run_word_command(ctx, word_ptr);

M test/word.sh => test/word.sh +3 -1
@@ 12,9 12,11 @@ a=a
  b=B
  hello=hello
+ null=""
  echo $a ${b} ">$a<"
  echo \$a '$a'
- #echo ${a:-BAD} ${idontexist:-GOOD}
+ echo ${a:-BAD} ${idontexist:-GOOD} ${null:-GOOD}
+ echo ${a-BAD} ${idontexist-GOOD} ${null-BAD}
  #echo ${#hello}
  
  echo ""