xref: /freebsd/contrib/kyua/admin/check-style.sh (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1#! /bin/sh
2# Copyright 2011 The Kyua Authors.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10#   notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above copyright
12#   notice, this list of conditions and the following disclaimer in the
13#   documentation and/or other materials provided with the distribution.
14# * Neither the name of Google Inc. nor the names of its contributors
15#   may be used to endorse or promote products derived from this software
16#   without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30# \file admin/check-style.sh
31#
32# Sanity checks the coding style of all source files in the project tree.
33
34ProgName="${0##*/}"
35
36
37# Prints an error message and exits.
38#
39# \param ... Parts of the error message; concatenated using a space as the
40#     separator.
41err() {
42    echo "${ProgName}:" "${@}" 1>&2
43    exit 1
44}
45
46
47# Locates all source files within the project directory.
48#
49# We require the project to have been configured in a directory that is separate
50# from the source tree.   This is to allow us to easily filter out build
51# artifacts from our search.
52#
53# \param srcdir Absolute path to the source directory.
54# \param builddir Absolute path to the build directory.
55# \param tarname Basename of the project's tar file, to skip possible distfile
56#     directories.
57find_sources() {
58    local srcdir="${1}"; shift
59    local builddir="${1}"; shift
60    local tarname="${1}"; shift
61
62    (
63        cd "${srcdir}"
64        find . -type f -a \
65                  \! -path "*/.git/*" \
66                  \! -path "*/.deps/*" \
67                  \! -path "*/autom4te.cache/*" \
68                  \! -path "*/${tarname}-[0-9]*/*" \
69                  \! -path "*/${builddir##*/}/*" \
70                  \! -name "Makefile.in" \
71                  \! -name "aclocal.m4" \
72                  \! -name "config.h.in" \
73                  \! -name "configure" \
74                  \! -name "testsuite"
75    )
76}
77
78
79# Prints the style rules applicable to a given file.
80#
81# \param file Path to the source file.
82guess_rules() {
83    local file="${1}"; shift
84
85    case "${file}" in
86        */ax_cxx_compile_stdcxx.m4) ;;
87        */ltmain.sh) ;;
88        *Makefile*) echo common make ;;
89        *.[0-9]) echo common man ;;
90        *.cpp|*.hpp) echo common cpp ;;
91        *.sh) echo common shell ;;
92        *) echo common ;;
93    esac
94}
95
96
97# Validates a given file against the rules that apply to it.
98#
99# \param srcdir Absolute path to the source directory.
100# \param file Name of the file to validate relative to srcdir.
101#
102# \return 0 if the file is valid; 1 otherwise, in which case the style
103# violations are printed to the output.
104check_file() {
105    local srcdir="${1}"; shift
106    local file="${1}"; shift
107
108    local err=0
109    for rule in $(guess_rules "${file}"); do
110        awk -f "${srcdir}/admin/check-style-${rule}.awk" \
111            "${srcdir}/${file}" || err=1
112    done
113
114    return ${err}
115}
116
117
118# Entry point.
119main() {
120    local builddir=.
121    local srcdir=.
122    local tarname=UNKNOWN
123
124    local arg
125    while getopts :b:s:t: arg; do
126        case "${arg}" in
127            b)
128                builddir="${OPTARG}"
129                ;;
130
131            s)
132                srcdir="${OPTARG}"
133                ;;
134
135            t)
136                tarname="${OPTARG}"
137                ;;
138
139            \?)
140                err "Unknown option -${OPTARG}"
141                ;;
142        esac
143    done
144    shift $(expr ${OPTIND} - 1)
145
146    srcdir="$(cd "${srcdir}" && pwd -P)"
147    builddir="$(cd "${builddir}" && pwd -P)"
148    [ "${srcdir}" != "${builddir}" ] || \
149        err "srcdir and builddir cannot match; reconfigure the package" \
150            "in a separate directory"
151
152    local sources
153    if [ ${#} -gt 0 ]; then
154        sources="${@}"
155    else
156        sources="$(find_sources "${srcdir}" "${builddir}" "${tarname}")"
157    fi
158
159    local ok=0
160    for file in ${sources}; do
161        local file="$(echo ${file} | sed -e "s,\\./,,")"
162
163        check_file "${srcdir}" "${file}" || ok=1
164    done
165
166    return "${ok}"
167}
168
169
170main "${@}"
171