Skip to content

Commit 57a11b0

Browse files
committed
cc.sh: faster list operations
Signed-off-by: Harmen Stoppels <me@harmenstoppels.nl>
1 parent e9fb6c4 commit 57a11b0

3 files changed

Lines changed: 299 additions & 46 deletions

File tree

.github/workflows/shellcheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ jobs:
1111
steps:
1212
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1313
- name: Run shellcheck
14-
run: shellcheck cc.sh test/run.sh
14+
run: shellcheck cc.sh test/*.sh benchmark/*.sh
1515
- name: Run tests
1616
run: sh test/run.sh

cc.sh

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
# other separators, we set and reset it.
2525
unset IFS
2626

27+
# BEGIN list functions
28+
2729
# Separator for lists whose names end with `_list`.
2830
# We pick the alarm bell character, which is highly unlikely to
2931
# conflict with anything. This is a literal bell character (which
@@ -94,23 +96,6 @@ setsep() {
9496
esac
9597
}
9698

97-
# prepend LISTNAME ELEMENT
98-
#
99-
# Prepend ELEMENT to the list stored in the variable LISTNAME.
100-
# Handles empty lists and single-element lists.
101-
prepend() {
102-
varname="$1"
103-
elt="$2"
104-
105-
if empty "$varname"; then
106-
eval "$varname=\"\${elt}\""
107-
else
108-
# Get the appropriate separator for the list we're appending to.
109-
setsep "$varname"
110-
eval "$varname=\"\${elt}${sep}\${$varname}\""
111-
fi
112-
}
113-
11499
# append LISTNAME ELEMENT [SEP]
115100
#
116101
# Append ELEMENT to the list stored in the variable LISTNAME,
@@ -129,43 +114,76 @@ append() {
129114
fi
130115
}
131116

132-
# extend LISTNAME1 LISTNAME2 [PREFIX]
117+
# extend DST_LISTNAME SRC_LISTNAME [PREFIX]
133118
#
134-
# Append the elements stored in the variable LISTNAME2
135-
# to the list stored in LISTNAME1.
119+
# Append the elements stored in the variable SRC_LISTNAME
120+
# to the list stored in DST_LISTNAME.
136121
# If PREFIX is provided, prepend it to each element.
137122
extend() {
138-
# Figure out the appropriate IFS for the list we're reading.
139-
setsep "$2"
140-
if [ "$sep" != " " ]; then
141-
IFS="$sep"
142-
fi
143-
eval "for elt in \${$2}; do append $1 \"$3\${elt}\"; done"
123+
_dst="$1"
124+
_src="$2"
125+
_prefix="$3"
126+
127+
# Turn source list into positional parameters
128+
setsep "$_src"
129+
[ "$sep" != " " ] && IFS="$sep"
130+
eval "set -- \${$_src}"
144131
unset IFS
132+
133+
[ $# -eq 0 ] && return
134+
135+
setsep "$_dst"; _dst_sep="$sep"
136+
137+
if [ -z "$_prefix" ]; then
138+
# Fast concatenation when no prefix is needed
139+
IFS="$_dst_sep"; _ext_str="$*"; unset IFS
140+
else
141+
_ext_str="${_prefix}$1"
142+
shift
143+
for elt in "$@"; do
144+
_ext_str="${_ext_str}${_dst_sep}${_prefix}${elt}"
145+
done
146+
fi
147+
148+
eval "$_dst=\"\${$_dst:+\${$_dst}$_dst_sep}\${_ext_str}\""
145149
}
146150

147-
# preextend LISTNAME1 LISTNAME2 [PREFIX]
151+
# preextend DST_LISTNAME SRC_LISTNAME [PREFIX]
148152
#
149-
# Prepend the elements stored in the list at LISTNAME2
150-
# to the list at LISTNAME1, preserving order.
153+
# Prepend the elements stored in the list at SRC_LISTNAME
154+
# to the list at DST_LISTNAME, preserving order.
151155
# If PREFIX is provided, prepend it to each element.
152156
preextend() {
153-
# Figure out the appropriate IFS for the list we're reading.
154-
setsep "$2"
155-
if [ "$sep" != " " ]; then
156-
IFS="$sep"
157-
fi
157+
_dst="$1"
158+
_src="$2"
159+
_prefix="$3"
160+
161+
# Turn source list into positional parameters
162+
setsep "$_src"
163+
[ "$sep" != " " ] && IFS="$sep"
164+
eval "set -- \${$_src}"
165+
unset IFS
158166

159-
# first, reverse the list to prepend
160-
_reversed_list=""
161-
eval "for elt in \${$2}; do prepend _reversed_list \"$3\${elt}\"; done"
167+
[ $# -eq 0 ] && return
162168

163-
# prepend reversed list to preextend in order
164-
IFS="${lsep}"
165-
for elt in $_reversed_list; do prepend "$1" "$3${elt}"; done
166-
unset IFS
169+
setsep "$_dst"; _dst_sep="$sep"
170+
171+
if [ -z "$_prefix" ]; then
172+
# Fast concatenation when no prefix is needed
173+
IFS="$_dst_sep"; _ext_str="$*"; unset IFS
174+
else
175+
_ext_str="${_prefix}$1"
176+
shift
177+
for elt in "$@"; do
178+
_ext_str="${_ext_str}${_dst_sep}${_prefix}${elt}"
179+
done
180+
fi
181+
182+
eval "$_dst=\"\${_ext_str}\${$_dst:+$_dst_sep\${$_dst}}\""
167183
}
168184

185+
# END list functions
186+
169187
execute() {
170188
# dump the full command if the caller supplies SPACK_TEST_COMMAND=dump-args
171189
if [ -n "${SPACK_TEST_COMMAND=}" ]; then
@@ -977,7 +995,7 @@ esac
977995
if [ -n "$SPACK_CCACHE_BINARY" ]; then
978996
case "$lang_flags" in
979997
C|CXX) # ccache only supports C languages
980-
prepend full_command_list "${SPACK_CCACHE_BINARY}"
998+
full_command_list="${SPACK_CCACHE_BINARY}${lsep}${full_command_list}"
981999
# workaround for stage being a temp folder
9821000
# see #3761#issuecomment-294352232
9831001
export CCACHE_NOHASHDIR=yes

0 commit comments

Comments
 (0)