arm, objdump: print obsolote warning when 26-bit set in instructions
[binutils-gdb.git] / gdb / contrib / spellcheck.sh
blob1b3e88e259b7b4ae8f9448187fd971acf9af5cdd
1 #!/bin/bash
3 # Copyright (C) 2024 Free Software Foundation, Inc.
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 # Script to auto-correct common spelling mistakes.
19 # Example usage:
20 # $ ./gdb/contrib/spellcheck.sh gdb*
22 scriptdir=$(cd "$(dirname "$0")" || exit; pwd -P)
23 this_script=$scriptdir/$(basename "$0")
25 url=https://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines
26 cache_dir=$scriptdir/../../.git
27 cache_file=wikipedia-common-misspellings.txt
28 dictionary=$cache_dir/$cache_file
29 local_dictionary=$scriptdir/common-misspellings.txt
30 cache_file2=spell-check.pat1
32 # Separators: space, slash, tab, colon, comma.
33 declare -a grep_separators
34 grep_separators=(
35 " "
36 "/"
37 " "
38 ":"
39 ","
41 declare -a sed_separators
42 sed_separators=(
43 " "
44 "/"
45 "\t"
46 ":"
47 ","
50 join ()
52 local or
53 or="$1"
54 shift
56 local res
57 res=""
59 local first
60 first=true
62 for item in "$@"; do
63 if $first; then
64 first=false
65 res="$item"
66 else
67 res="$res$or$item"
69 done
71 echo "$res"
74 grep_or="|"
75 sed_or="\|"
77 grep_join ()
79 local res
80 res=$(join $grep_or "$@")
81 echo "($res)"
84 sed_join ()
86 local res
87 res=$(join $sed_or "$@")
88 echo "\($res\)"
91 usage ()
93 echo "usage: $(basename "$0") [--check] <file|dir>+"
96 make_absolute ()
98 local arg
99 arg="$1"
101 case "$arg" in
105 arg=$(pwd -P)/"$arg"
107 esac
109 echo "$arg"
112 parse_args ()
114 local files
115 files=$(mktemp)
116 trap 'rm -f "$files"' EXIT
118 while true; do
119 case " $1 " in
120 " --check ")
121 check=true
122 shift
125 break
127 esac
128 done
130 if [ $# -eq -0 ]; then
131 usage
132 exit 1
135 local arg
136 for arg in "$@"; do
137 if [ -f "$arg" ]; then
138 arg=$(make_absolute "$arg")
139 readlink -e "$arg" \
140 >> "$files"
141 elif [ -d "$arg" ]; then
142 arg=$(make_absolute "$arg")
143 local f
144 find "$arg" -type f -exec readlink -e {} \; \
145 >> "$files"
146 else
147 echo "Not a file or directory: $arg"
148 exit 1
150 done
152 mapfile -t unique_files \
153 < <(sort -u "$files" \
154 | grep -v ChangeLog)
156 rm -f "$files"
157 trap "" EXIT
160 get_dictionary ()
162 if [ -f "$dictionary" ]; then
163 return
166 local webpage
167 webpage=$(mktemp)
168 trap 'rm -f "$webpage"' EXIT
170 # Download web page containing table.
171 wget $url -O "$webpage"
173 # Extract table from web page.
174 awk '/<pre>/,/<\/pre>/' "$webpage" \
175 | sed 's/<pre>//;s/<\/pre>//' \
176 | grep -E -v "^$" \
177 > "$dictionary"
179 rm -f "$webpage"
180 trap "" EXIT
183 output_local_dictionary ()
185 # Filter out comments and empty lines.
186 grep -E -v \
187 "^#|^$" \
188 "$local_dictionary"
191 output_dictionaries ()
193 output_local_dictionary
194 cat "$dictionary"
197 parse_dictionary ()
199 # Parse dictionary.
200 mapfile -t words \
201 < <(awk -F '->' '{print $1}' <(output_dictionaries))
202 mapfile -t replacements \
203 < <(awk -F '->' '{print $2}' <(output_dictionaries))
206 find_files_matching_words ()
208 local cache_id
209 cache_id=$(cat "$local_dictionary" "$dictionary" "$this_script" \
210 | md5sum \
211 | awk '{print $1}')
213 local patfile
214 patfile="$cache_dir/$cache_file2".$cache_id
216 local pat
217 if [ -f "$patfile" ]; then
218 pat=$(cat "$patfile")
219 else
220 rm -f "$cache_dir/$cache_file2".*
222 pat=$(grep_join "${words[@]}")
224 local before after
225 before=$(grep_join \
226 "^" \
227 "${grep_separators[@]}")
228 after=$(grep_join \
229 "${grep_separators[@]}" \
230 "\." \
231 "$")
233 pat="$before$pat$after"
235 echo "$pat" \
236 > "$patfile"
239 grep -E \
240 -l \
241 "$pat" \
242 "$@"
245 find_files_matching_word ()
247 local pat
248 pat="$1"
249 shift
251 local before after
252 before=$(grep_join \
253 "^" \
254 "${grep_separators[@]}")
255 after=$(grep_join \
256 "${grep_separators[@]}" \
257 "\." \
258 "$")
260 pat="$before$pat$after"
262 grep -E \
263 -l \
264 "$pat" \
265 "$@"
268 replace_word_in_file ()
270 local word
271 word="$1"
273 local replacement
274 replacement="$2"
276 local file
277 file="$3"
279 local before after
280 before=$(sed_join \
281 "^" \
282 "${sed_separators[@]}")
283 after=$(sed_join \
284 "${sed_separators[@]}" \
285 "\." \
286 "$")
288 local repl
289 repl="s%$before$word$after%\1$replacement\2%g"
291 sed -i \
292 "$repl" \
293 "$file"
296 replace_word_in_files ()
298 local word
299 word="$1"
301 local replacement
302 replacement="$2"
304 shift 2
306 local id
307 id="$word -> $replacement"
309 # Reduce set of files for sed to operate on.
310 local files_matching_word
311 declare -a files_matching_word
312 mapfile -t files_matching_word \
313 < <(find_files_matching_word "$word" "$@")
315 if [ ${#files_matching_word[@]} -eq 0 ]; then
316 return
319 if echo "$replacement"| grep -q ","; then
320 echo "TODO: $id"
321 return
324 declare -A md5sums
326 local changed f before after
327 changed=false
328 for f in "${files_matching_word[@]}"; do
329 if [ "${md5sums[$f]}" = "" ]; then
330 md5sums[$f]=$(md5sum "$f")
333 before="${md5sums[$f]}"
335 replace_word_in_file \
336 "$word" \
337 "$replacement" \
338 "$f"
340 after=$(md5sum "$f")
342 if [ "$after" != "$before" ]; then
343 md5sums[$f]="$after"
344 changed=true
346 done
348 if $changed; then
349 echo "$id"
352 find_files_matching_word "$word" "${files_matching_word[@]}" \
353 | awk "{ printf \"TODO: $id: replacement failed: %s\n\", \$0}"
356 main ()
358 declare -a unique_files
359 check=false
360 parse_args "$@"
362 get_dictionary
364 declare -a words
365 declare -a replacements
366 parse_dictionary
368 # Reduce set of files for sed to operate on.
369 local files_matching_words
370 declare -a files_matching_words
371 mapfile -t files_matching_words \
372 < <(find_files_matching_words "${unique_files[@]}")
374 if [ ${#files_matching_words[@]} -eq 0 ]; then
375 return
378 if $check; then
379 exit 1
382 declare -A words_done
383 local i word replacement
385 for word in "${words[@]}"; do
386 replacement=${replacements[$i]}
387 i=$((i + 1))
389 # Skip words that are already handled. This ensures that the local
390 # dictionary overrides the wiki dictionary.
391 if [ "${words_done[$word]}" == 1 ]; then
392 continue
394 words_done[$word]=1
396 replace_word_in_files \
397 "$word" \
398 "$replacement" \
399 "${files_matching_words[@]}"
400 done
403 main "$@"