1 |
Just to point out that arithmetic context can be more efficient; no bugs, |
2 |
except for a /minor/ possibility (second last comment.) |
3 |
|
4 |
Mike Frysinger wrote: |
5 |
> --- eutils.eclass 14 Dec 2011 17:36:18 -0000 1.372 |
6 |
> +++ eutils.eclass 14 Dec 2011 23:46:37 -0000 |
7 |
> @@ -100,6 +100,54 @@ esvn_clean() { |
8 |
> find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf |
9 |
> } |
10 |
> |
11 |
> +# @FUNCTION: estack_push |
12 |
> +# @USAGE: <stack> [items to push] |
13 |
> +# @DESCRIPTION: |
14 |
> +# Push any number of items onto the specified stack. Pick a name that |
15 |
> +# is a valid variable (i.e. stick to alphanumerics), and push as many |
16 |
> +# items as you like onto the stack at once. |
17 |
> +# |
18 |
> +# The following code snippet will echo 5, then 4, then 3, then ... |
19 |
> +# @CODE |
20 |
> +# estack_push mystack 1 2 3 4 5 |
21 |
> +# while estack_pop mystack i ; do |
22 |
> +# echo ${i} |
23 |
A minor #bash point in passing: although these values of i are safe, for |
24 |
tutorial code, I really would recommend quoting: echo "$i" (or "${i}"). It's |
25 |
better to get people used to quoting by default, and only not quoting iff |
26 |
they need field-splitting on parameter expansions (eg for a variable used |
27 |
for command options.) |
28 |
|
29 |
> +# done |
30 |
> +# @CODE |
31 |
> +estack_push() { |
32 |
> + [[ $# -eq 0 ]] && die "estack_push: incorrect # of arguments" |
33 |
> + local stack_name="__ESTACK_$1__" ; shift |
34 |
> + eval ${stack_name}+=\( \"\$@\" \) |
35 |
> +} |
36 |
((..)) is quicker than [[ .. ]] for arithmetic stuff, and usually easier to |
37 |
grok swiftly. |
38 |
(($#)) || die .. is how this would normally be done. |
39 |
|
40 |
> + |
41 |
> +# @FUNCTION: estack_pop |
42 |
> +# @USAGE: <stack> [variable] |
43 |
> +# @DESCRIPTION: |
44 |
> +# Pop a single item off the specified stack. If a variable is specified, |
45 |
> +# the popped item is stored there. If no more items are available, |
46 |
> return |
47 |
> +# 1, else return 0. See estack_push for more info. |
48 |
> +estack_pop() { |
49 |
> + ( [[ $# -eq 0 ]] || [[ $# -gt 2 ]] ) && die "estack_pop: incorrect |
50 |
# of arguments" |
51 |
|
52 |
(($# == 0 || $# > 2)) && die.. # does it in one command, with no subshell. |
53 |
[[ $# -eq 0 || $# -gt 2 ]] && die .. would work too, but more slowly. |
54 |
In general if you want to do complex chains without a subshell, you would |
55 |
use: { } && .. instead of: ( ) && .. |
56 |
|
57 |
TBH I would type (($#==0||$#>2)) in bash, though I space in C, where it |
58 |
doesn't affect execution time. But it's not as clear, especially if you're |
59 |
not in a highlighting editor. |
60 |
|
61 |
> + # We use the fugly __estack_xxx var names to avoid collision with |
62 |
> + # passing back the return value. If we used "local i" and the |
63 |
> + # caller ran `estack_pop ... i`, we'd end up setting the local |
64 |
> + # copy of "i" rather than the caller's copy. The __estack_xxx |
65 |
> + # garbage is preferable to using $1/$2 everywhere as that is a |
66 |
> + # bit harder to read. |
67 |
> + local __estack_name="__ESTACK_$1__" ; shift |
68 |
> + local __estack_retvar=$1 ; shift |
69 |
> + eval local __estack_i=\${#${__estack_name}[@]} |
70 |
> + # Don't warn -- let the caller interpret this as a failure |
71 |
> + # or as normal behavior (akin to `shift`) |
72 |
> + [[ $(( --__estack_i )) -eq -1 ]] && return 1 |
73 |
((--__estack_i == -1)) && .. |
74 |
|
75 |
> + |
76 |
> + if [[ -n ${__estack_retvar} ]] ; then |
77 |
> + eval ${__estack_retvar}=\"\${${__estack_name} |
78 |
[${__estack_i}]}\" |
79 |
> + fi |
80 |
> + eval unset ${__estack_name}[${__estack_i}] |
81 |
> +} |
82 |
> + |
83 |
> # @FUNCTION: eshopts_push |
84 |
> # @USAGE: [options to `set` or `shopt`] |
85 |
> # @DESCRIPTION: |
86 |
> @@ -126,15 +174,14 @@ esvn_clean() { |
87 |
> eshopts_push() { |
88 |
> # have to assume __ESHOPTS_SAVE__ isn't screwed with |
89 |
> # as a `declare -a` here will reset its value |
90 |
> - local i=${#__ESHOPTS_SAVE__[@]} |
91 |
> if [[ $1 == -[su] ]] ; then |
92 |
> - __ESHOPTS_SAVE__[$i]=$(shopt -p) |
93 |
> + estack_push eshopts "$(shopt -p)" |
94 |
> [[ $# -eq 0 ]] && return 0 |
95 |
I'm not sure how this will ever match, given that $1 has been checked above? |
96 |
(($#==1)) && return 0 # if that applies (might be a 'bug'.) |
97 |
|
98 |
> shopt "$@" || die "eshopts_push: bad options to shopt: $*" |
99 |
> else |
100 |
> - __ESHOPTS_SAVE__[$i]=$- |
101 |
> + estack_push eshopts $- |
102 |
> [[ $# -eq 0 ]] && return 0 |
103 |
(($#)) || return 0 |
104 |
|
105 |
> set "$@" || die "eshopts_push: bad options to set: $*" |
106 |
> fi |
107 |
> } |
108 |
> |
109 |
|
110 |
HTH, |
111 |
Steve. |
112 |
-- |
113 |
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-) |