Gentoo Archives: gentoo-dev

From: Steven J Long <slong@××××××××××××××××××.uk>
To: gentoo-dev@l.g.o
Subject: [gentoo-dev] Re: estack_{push,pop}: cool new helpers or over engineering?
Date: Fri, 16 Dec 2011 07:22:30
Message-Id: jcerhf$t8v$1@dough.gmane.org
In Reply to: Re: [gentoo-dev] estack_{push,pop}: cool new helpers or over engineering? by Mike Frysinger
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 ;-)

Replies