File: format_source_files.sh

package info (click to toggle)
kbibtex 0.9.90-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 23,072 kB
  • sloc: cpp: 40,314; python: 450; xml: 372; sh: 150; makefile: 12
file content (135 lines) | stat: -rwxr-xr-x 4,510 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/sh

export LC_ALL=en_US.utf8
export LANG=C
MY_NAME="$(basename "$0")"

SET_VERBOSE=0
ALL_FILES=0
HEAD_COMMIT=0

function parsearguments {
	local ARGS=$(getopt -o "h" -l "verbose,all,head,help" -n "${MY_NAME}" -- "$@")
	local PRINT_HELP=0

	#Bad arguments
	if [ $? -ne 0 ] ; then
		exit 1
	fi

	# A little magic
	eval set -- "$ARGS"

	while true ; do
		case "$1" in
		-h|--help)
			PRINT_HELP=1
			shift
		;;
		--verbose )
			SET_VERBOSE=1
			shift
		;;
		--all )
			ALL_FILES=1
			HEAD_COMMIT=0
			shift
		;;
		--head )
			HEAD_COMMIT=1
			ALL_FILES=0
			shift
		;;
		--)
			shift
			break
		esac
	done

	if [[ ${PRINT_HELP} -ne 0 ]] ; then
		echo "Usage: ${MY_NAME} [--all|--head] [--verbose]" >&2
		echo "Format C++ source code and headers in a git-controlled directory structure." >&2
		echo >&2
		echo "Options:" >&2
		echo " --help" >&2
		echo "    Show this help" >&2
		echo " --verbose" >&2
		echo "    Show verbose (more) output" >&2
		echo " --head" >&2
		echo "    Format .cpp/.h files changed in current HEAD commit">&2
		echo " --all" >&2
		echo "    Format all .cpp/.h files, not just those marked by git as added or modified">&2
		exit 1
	fi
}

parsearguments "$@"

if [[ ${HEAD_COMMIT} -eq 1 ]] ; then
	git diff-tree --no-commit-id --name-only -r HEAD | grep -E '[.](cpp|h)$'
elif [[ ${ALL_FILES} -eq 0 ]] ; then
	# Format only files seen by git as added or modified,
	# filter for .cpp or .h files.
	# Trying to handle filenames with spaces correctly (not tested)
	git status --untracked-files=no --porcelain | awk '/^\s*[AM]+\s+.*[.](cpp|h)$/ {for(i=2;i<NF;++i){printf $i" "};printf $NF"\n"}'
else
	# Format all .cpp or .h files; using "find" to located those files
	find . -type f -name '*.cpp' -o -name '*.h'
fi | \
# Sort files alphabetically, omit duplicates
sort -u | \
grep --color=NEVER -vE 'src/config/preferences.(cpp|h)$' | \
while read filename ; do
	if [[ ! -s "${filename}" ]] ; then
		echo "${MY_NAME}: File not found: \"${filename}\"" >&2
		continue
	fi

	TEMPFILE=$(mktemp -t 'kbibtex_formatted_source_XXXXXXXXXXX.cpp')

	echo "Processing \"${filename}\""
	astyle -n --align-reference=name --align-pointer=name --indent=spaces=4 --indent-labels --pad-oper --unpad-paren --pad-header --keep-one-line-statements --convert-tabs --indent-preprocessor <"${filename}" >${TEMPFILE}

	# Astyle has problem with 'foreach' statements
	sed -i -e 's/\bforeach(/foreach (/g' ${TEMPFILE}

	# normalize SIGNAL statements as recommended at
	# http://marcmutz.wordpress.com/effective-qt/prefer-to-use-normalised-signalslot-signatures/
	# astyle would insert spaces etc
	grep -Po '(SIGNAL|SLOT)\([^(]+\([^)]*\)\)' "${TEMPFILE}" | while read original ; do
		normalized="$(sed -e 's/const //g;s/&//g;s/ //g;s/\//\\\//g' <<<${original})"
		originalregexpized="$(sed -e 's/\*/\\*/g;s/\//\\\//g' <<<${original})"
		sed -i -e 's/'"${originalregexpized}"'/'"${normalized}"'/g' ${TEMPFILE}
	done

	# correct some astyle mis-formattings
	if [[ "${filename}" != "${filename/%.h/}" ]] ; then
		sed -i -e 's/^\([ ]*\)\(:[ ][a-zA-Z]\)/\1    \2/g' ${TEMPFILE}
	elif [[ "${filename}" != "${filename/%.cpp/}" ]] ; then
		sed -i -e  's/^\([ ]*\)\(:[ ][a-zA-Z]\)/\1    \2/g;s/\(foreach([^)]*\) \([&*]\) /\1 \2/g' ${TEMPFILE}
	fi

	# In const_cast operations, ensure space before ampersand
	sed -i -r 's!( : const_cast<[^(;]+[^ ])&>[(]!\1 \&>(!g' ${TEMPFILE}

	# Remove superfluous empty lines at file's end
	#  http://unix.stackexchange.com/a/81687
        #  http://sed.sourceforge.net/sed1line.txt
	sed -i -e :a -e '/^\n*$/{$d;N;};/\n$/ba' ${TEMPFILE}

	# Check if copyright year is up to date
	head -n 5 ${TEMPFILE} | grep -Eo --color=NEVER '20[0-9][0-9] by ' | head -n 1 | while read year rest ; do
		[ "${year}" = $(date '+%Y') ] || echo "File '${filename}' has an outdated copyright year: ${year}"
	done

	# only change/touch original file if it has been changed
	diff -q ${TEMPFILE} "${filename}" >/dev/null || { echo "Updating \"${filename}\"" ; cp -p ${TEMPFILE} "${filename}" || echo "Cannot copy \"${TEMPFILE}\" \"${filename}\"" ; }

	rm -f ${TEMPFILE}
done

year=$(date '+%Y')
test -s README && { grep -q "2004-${year} Thomas Fischer" README || echo "README should have current year in copyright: ${year}" ; }
for copyrightfile in src/program/program.cpp src/test/main.cpp src/parts/partfactory.cpp ; do
    test -s "${copyrightfile}" && { grep -q "\"Copyright 2004-${year} Thomas Fischer" "${copyrightfile}" || echo "'${copyrightfile}' should have current year in copyright: ${year}" ; }
done