Skip to content

Commit 3579d63

Browse files
committed
bugfix: circular ref. when caller passes a nameref named like the local var holding the ref
1 parent 92d34a5 commit 3579d63

1 file changed

Lines changed: 18 additions & 21 deletions

File tree

bash-args.sh

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function args:flag() {
2424
local required="false"; [[ "${1:-}" == "-r" || "${1:-}" == "--required" ]] && required="true" && shift;
2525
local bundle="false"; [[ "${1:-}" == "-b" || "${1:-}" == "--bundle" ]] && bundle="true" && shift;
2626
local count="false"; [[ "${1:-}" == "--count" ]] && count="true" && shift;
27-
local -n value="${1//[^_0-9a-zA-Z]/_}";
27+
local -n __value_="${1//[^_0-9a-zA-Z]/_}";
2828
local long="${1?ERROR: args:flag requires <long>}"; shift;
2929
local short="${1?ERROR: args:flag requires <short>}"; shift;
3030

@@ -45,8 +45,8 @@ function args:flag() {
4545
fi
4646

4747
# Flag when --count value=$hits otherwise value=true
48-
((hits > 0)) && value="true";
49-
[[ "$count" == "true" ]] && value="$hits";
48+
((hits > 0)) && __value_="true";
49+
[[ "$count" == "true" ]] && __value_="$hits";
5050

5151
# Flag found or optional and absent.
5252
((hits > 0)) || [[ "$required" == "false" ]] && return 0;
@@ -79,7 +79,7 @@ function args:opt() {
7979
local err=""; (($# >= 2)) && [[ "${*: -2:1}" == "--err" ]] && err="${*: -1}" && set -- "${@:1:$#-2}";
8080
local required="false"; [[ "${1:-}" == "-r" || "${1:-}" == "--required" ]] && required="true" && shift;
8181
local accumulate="false"; [[ "${1:-}" == "-a" || "${1:-}" == "--accumulate" ]] && accumulate="true" && shift;
82-
local -n value="${1?ERROR: args:opt requires <long>}";
82+
local -n __value_="${1?ERROR: args:opt requires <long>}";
8383
local long="${1}"; shift;
8484
local short="${1?ERROR: args:opt requires <short>}"; shift;
8585
local pattern="${1:-(.*)}"; shift || true;
@@ -89,19 +89,16 @@ function args:opt() {
8989

9090
# Scan all args and accumulate $values
9191
local rc=0 captured values=();
92-
while true; do
93-
args::capture captured "$scan" "$pattern";
94-
rc=$?;
95-
((rc == 0)) || break;
92+
while args::capture captured "$scan" "$pattern" || { rc=$?; false; }; do
9693
values+=("$captured");
9794
done
9895

9996
# Option was found but didn't match $pattern
10097
((rc == 2)) && { [[ -n "$err" ]] && echo "$err" >&2; return 1; };
10198

10299
# Opt when --accumulate value=$values otherwise value=$values[0]
103-
((${#values[@]} > 0)) && value="${values[0]}";
104-
[[ "$accumulate" == "true" ]] && value=("${values[@]}");
100+
((${#values[@]} > 0)) && __value_="${values[0]}";
101+
[[ "$accumulate" == "true" ]] && __value_=("${values[@]}");
105102

106103
# Option found and matches, or absent and optional.
107104
((${#values[@]} > 0)) || [[ "$required" == "false" ]] && return 0;
@@ -132,7 +129,7 @@ function args:arg() {
132129

133130
local optional="false"; [[ "${1:-}" == "-o" || "${1:-}" == "--optional" ]] && optional="true" && shift;
134131
# shellcheck disable=SC2178 # nameref is a string, points to an array
135-
local -n value="${1?ERROR: args:arg requires <name>}"; shift;
132+
local -n __value_="${1?ERROR: args:arg requires <name>}"; shift;
136133
local pattern="${1:-(.*)}"; shift || true;
137134

138135
[[ "${TOKENS[0]:-}" == "--" ]] && TOKENS=("${TOKENS[@]:1}");
@@ -151,7 +148,7 @@ function args:arg() {
151148
fi
152149

153150
# shellcheck disable=SC2178 # nameref assigned a string
154-
value="${BASH_REMATCH[1]:-$captured}";
151+
__value_="${BASH_REMATCH[1]:-$captured}";
155152

156153
# rewrite the $TOKENS array without the captured tokens
157154
TOKENS=("${TOKENS[@]:1}");
@@ -177,7 +174,7 @@ function args:varg() {
177174
local err=""; (($# >= 2)) && [[ "${*: -2:1}" == "--err" ]] && err="${*: -1}" && set -- "${@:1:$#-2}";
178175
local optional="false"; [[ "${1:-}" == "-o" || "${1:-}" == "--optional" ]] && optional="true" && shift;
179176
# shellcheck disable=SC2178 # nameref is a string, points to an array
180-
local -n value="${1?ERROR: args:varg requires <name>}"; shift;
177+
local -n __value_="${1?ERROR: args:varg requires <name>}"; shift;
181178

182179
[[ "${TOKENS[0]:-}" == "--" ]] && TOKENS=("${TOKENS[@]:1}");
183180

@@ -187,7 +184,7 @@ function args:varg() {
187184
return 1;
188185
fi
189186

190-
value=("${TOKENS[@]}");
187+
__value_=("${TOKENS[@]}");
191188

192189
# rewrite the $TOKENS array without the captured tokens
193190
TOKENS=();
@@ -215,8 +212,8 @@ function args:sub() {
215212
local err=""; (($# >= 2)) && [[ "${*: -2:1}" == "--err" ]] && err="${*: -1}" && set -- "${@:1:$#-2}";
216213
local optional="false"; [[ "${1:-}" == "-o" || "${1:-}" == "--optional" ]] && optional="true" && shift;
217214
# shellcheck disable=SC2178 # nameref is a string, points to an array
218-
local -n value="${1?ERROR: args:sub requires <name>}"; shift;
219-
local -n rest="${1?ERROR: args:sub requires <rest>}"; shift;
215+
local -n __value_="${1?ERROR: args:sub requires <name>}"; shift;
216+
local -n __rest_="${1?ERROR: args:sub requires <rest>}"; shift;
220217
local pattern="${1?ERROR: args:sub requires <pattern>}"; shift;
221218

222219
local i captured;
@@ -226,8 +223,8 @@ function args:sub() {
226223
[[ ! "$captured" =~ $pattern ]] && continue;
227224

228225
# shellcheck disable=SC2178 # nameref assigned a string
229-
value="${BASH_REMATCH[1]:-$captured}";
230-
rest=("${TOKENS[@]:i+1}");
226+
__value_="${BASH_REMATCH[1]:-$captured}";
227+
__rest_=("${TOKENS[@]:i+1}");
231228
TOKENS=("${TOKENS[@]:0:i}");
232229
return 0;
233230
done
@@ -254,7 +251,7 @@ function args::capture() {
254251
# shellcheck disable=SC2178 # nameref is a string, points to an array
255252
local -n TOKENS="ARGS";
256253

257-
local -n ref="${1}"; shift;
254+
local -n __ref_="${1}"; shift;
258255
local tok="${1}"; shift;
259256
local pat="${1:-}"; shift
260257

@@ -270,7 +267,7 @@ function args::capture() {
270267

271268
# Flag matched (no value pattern provided)
272269
# shellcheck disable=SC2034 # ref is a nameref, assigned for the caller
273-
[[ -z "$pat" ]] && ref="$token" && TOKENS=("${tokens[@]}" "${TOKENS[@]:i+1}") && return 0;
270+
[[ -z "$pat" ]] && __ref_="$token" && TOKENS=("${tokens[@]}" "${TOKENS[@]:i+1}") && return 0;
274271

275272
# Value attached to option -o123 or --opt=123
276273
value="${BASH_REMATCH[1]:-${BASH_REMATCH[2]:-}}";
@@ -279,7 +276,7 @@ function args::capture() {
279276

280277
# Value must match this pattern.
281278
# shellcheck disable=SC2034 # ref is a nameref, assigned for the caller
282-
[[ "$value" =~ $pat ]] && ref="${BASH_REMATCH[1]:-$value}" && TOKENS=("${tokens[@]}" "${TOKENS[@]:i+1}") && return 0;
279+
[[ "$value" =~ $pat ]] && __ref_="${BASH_REMATCH[1]:-$value}" && TOKENS=("${tokens[@]}" "${TOKENS[@]:i+1}") && return 0;
283280

284281
# Value found but didn't match pattern.
285282
TOKENS=("${tokens[@]}" "${TOKENS[@]:i+1}");

0 commit comments

Comments
 (0)