+ } else if (!strchr("%#:-=+?"+3, exp_op)) {
+#if ENABLE_HUSH_BASH_COMPAT
+ /* exp_op is ':' and next char isn't a subst operator.
+ * Assuming it's ${var:[N][:M]} bashism.
+ * TODO: N, M can be expressions similar to $((EXPR)): 2+2, 2+var etc
+ */
+ char *end;
+ unsigned len = INT_MAX;
+ unsigned beg = 0;
+ end = --exp_word;
+ if (*exp_word != ':') /* not ${var::...} */
+ beg = bb_strtou(exp_word, &end, 0);
+ //bb_error_msg("beg:'%s'=%u end:'%s'", exp_word, beg, end);
+ if (*end == ':') {
+ if (end[1] != '\0') /* not ${var:NUM:} */
+ len = bb_strtou(end + 1, &end, 0);
+ else {
+ len = 0;
+ end++;
+ }
+ //bb_error_msg("len:%u end:'%s'", len, end);
+ }
+ if (*end == '\0') {
+ //bb_error_msg("from val:'%s'", val);
+ if (len == 0 || !val || beg >= strlen(val))
+ val = "";
+ else
+ val = to_be_freed = xstrndup(val + beg, len);
+ //bb_error_msg("val:'%s'", val);
+ } else
+#endif
+ {
+ die_if_script("malformed ${%s...}", var);
+ val = "";
+ }
+ } else { /* one of "-=+?" */
+ /* Standard-mandated substitution ops:
+ * ${var?word} - indicate error if unset
+ * If var is unset, word (or a message indicating it is unset
+ * if word is null) is written to standard error
+ * and the shell exits with a non-zero exit status.
+ * Otherwise, the value of var is substituted.
+ * ${var-word} - use default value
+ * If var is unset, word is substituted.
+ * ${var=word} - assign and use default value
+ * If var is unset, word is assigned to var.
+ * In all cases, final value of var is substituted.
+ * ${var+word} - use alternative value
+ * If var is unset, null is substituted.
+ * Otherwise, word is substituted.
+ *
+ * Word is subjected to tilde expansion, parameter expansion,
+ * command substitution, and arithmetic expansion.
+ * If word is not needed, it is not expanded.
+ *
+ * Colon forms (${var:-word}, ${var:=word} etc) do the same,
+ * but also treat null var as if it is unset.
+ */
+ int use_word = (!val || ((exp_save == ':') && !val[0]));