Skip to content

Commit b5060ff

Browse files
berrangeAlon Levy
authored and
Alon Levy
committed
Add a 'syntax-check' make target
The 'make syntax-check' target is used to perform various code style sanity checks, as well as to detect certain trivial error patterns. The target is placed in GNUmakefile, instead of Makefile.am since it relies on GNU specific make extensions. The actual GNUmakefile and maint.mk files are taken from the GNULIB project, unchanged The cfg.mk file is used to configure which of the syntax checks are activated, to allow addition of new project specific syntax checks, and to blacklist certain files which should not be checked * .mailmap: Add mapping for various broken email addrs in commit log, to stop complaints about AUTHORS file missing entries * GNUmakefile: define the 'syntax-check' rule * maint.mk: definition of standard syntax checks * cfg.mk: configuration for checks
1 parent 68c2897 commit b5060ff

File tree

6 files changed

+2117
-0
lines changed

6 files changed

+2117
-0
lines changed

.mailmap

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
3+
4+
<[email protected]> <Larsson@.(none)>

GNUmakefile

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Having a separate GNUmakefile lets me `include' the dynamically
2+
# generated rules created via cfg.mk (package-local configuration)
3+
# as well as maint.mk (generic maintainer rules).
4+
# This makefile is used only if you run GNU Make.
5+
# It is necessary if you want to build targets usually of interest
6+
# only to the maintainer.
7+
8+
# Copyright (C) 2001, 2003, 2006-2011 Free Software Foundation, Inc.
9+
10+
# This program is free software: you can redistribute it and/or modify
11+
# it under the terms of the GNU General Public License as published by
12+
# the Free Software Foundation, either version 3 of the License, or
13+
# (at your option) any later version.
14+
15+
# This program is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License for more details.
19+
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
23+
# Systems where /bin/sh is not the default shell need this. The $(shell)
24+
# command below won't work with e.g. stock DOS/Windows shells.
25+
ifeq ($(wildcard /bin/s[h]),/bin/sh)
26+
SHELL = /bin/sh
27+
else
28+
# will be used only with the next shell-test line, then overwritten
29+
# by a configured-in value
30+
SHELL = sh
31+
endif
32+
33+
# If the user runs GNU make but has not yet run ./configure,
34+
# give them a diagnostic.
35+
_have-Makefile := $(shell test -f Makefile && echo yes)
36+
ifeq ($(_have-Makefile),yes)
37+
38+
# Make tar archive easier to reproduce.
39+
export TAR_OPTIONS = --owner=0 --group=0 --numeric-owner
40+
41+
# Allow the user to add to this in the Makefile.
42+
ALL_RECURSIVE_TARGETS =
43+
44+
include Makefile
45+
46+
# Some projects override e.g., _autoreconf here.
47+
-include $(srcdir)/cfg.mk
48+
49+
# Allow cfg.mk to override these.
50+
_build-aux ?= build-aux
51+
_autoreconf ?= autoreconf -v
52+
53+
include $(srcdir)/maint.mk
54+
55+
# Ensure that $(VERSION) is up to date for dist-related targets, but not
56+
# for others: rerunning autoreconf and recompiling everything isn't cheap.
57+
_have-git-version-gen := \
58+
$(shell test -f $(srcdir)/$(_build-aux)/git-version-gen && echo yes)
59+
ifeq ($(_have-git-version-gen)0,yes$(MAKELEVEL))
60+
_is-dist-target ?= $(filter-out %clean, \
61+
$(filter maintainer-% dist% alpha beta stable,$(MAKECMDGOALS)))
62+
_is-install-target ?= $(filter-out %check, $(filter install%,$(MAKECMDGOALS)))
63+
ifneq (,$(_is-dist-target)$(_is-install-target))
64+
_curr-ver := $(shell cd $(srcdir) \
65+
&& $(_build-aux)/git-version-gen \
66+
.tarball-version \
67+
$(git-version-gen-tag-sed-script))
68+
ifneq ($(_curr-ver),$(VERSION))
69+
ifeq ($(_curr-ver),UNKNOWN)
70+
$(info WARNING: unable to verify if $(VERSION) is the correct version)
71+
else
72+
ifneq (,$(_is-install-target))
73+
# GNU Coding Standards state that 'make install' should not cause
74+
# recompilation after 'make all'. But as long as changing the version
75+
# string alters config.h, the cost of having 'make all' always have an
76+
# up-to-date version is prohibitive. So, as a compromise, we merely
77+
# warn when installing a version string that is out of date; the user
78+
# should run 'autoreconf' (or something like 'make distcheck') to
79+
# fix the version, 'make all' to propagate it, then 'make install'.
80+
$(info WARNING: version string $(VERSION) is out of date;)
81+
$(info run '$(MAKE) _version' to fix it)
82+
else
83+
$(info INFO: running autoreconf for new version string: $(_curr-ver))
84+
GNUmakefile: _version
85+
touch GNUmakefile
86+
endif
87+
endif
88+
endif
89+
endif
90+
endif
91+
92+
.PHONY: _version
93+
_version:
94+
cd $(srcdir) && rm -rf autom4te.cache .version && $(_autoreconf)
95+
$(MAKE) $(AM_MAKEFLAGS) Makefile
96+
97+
else
98+
99+
.DEFAULT_GOAL := abort-due-to-no-makefile
100+
srcdir = .
101+
102+
# The package can override .DEFAULT_GOAL to run actions like autoreconf.
103+
-include ./cfg.mk
104+
include ./maint.mk
105+
106+
ifeq ($(.DEFAULT_GOAL),abort-due-to-no-makefile)
107+
$(MAKECMDGOALS): abort-due-to-no-makefile
108+
endif
109+
110+
abort-due-to-no-makefile:
111+
@echo There seems to be no Makefile in this directory. 1>&2
112+
@echo "You must run ./configure before running \`make'." 1>&2
113+
@exit 1
114+
115+
endif
116+
117+
# Tell version 3.79 and up of GNU make to not build goals in this
118+
# directory in parallel, in case someone tries to build multiple
119+
# targets, and one of them can cause a recursive target to be invoked.
120+
121+
# Only set this if Automake doesn't provide it.
122+
AM_RECURSIVE_TARGETS ?= $(RECURSIVE_TARGETS:-recursive=) \
123+
$(RECURSIVE_CLEAN_TARGETS:-recursive=) \
124+
dist distcheck tags ctags
125+
126+
ALL_RECURSIVE_TARGETS += $(AM_RECURSIVE_TARGETS)
127+
128+
ifneq ($(word 2, $(MAKECMDGOALS)), )
129+
ifneq ($(filter $(ALL_RECURSIVE_TARGETS), $(MAKECMDGOALS)), )
130+
.NOTPARALLEL:
131+
endif
132+
endif

build-aux/useless-if-before-free

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
eval '(exit $?0)' && eval 'exec perl -wST "$0" ${1+"$@"}'
2+
& eval 'exec perl -wST "$0" $argv:q'
3+
if 0;
4+
# Detect instances of "if (p) free (p);".
5+
# Likewise "if (p != 0)", "if (0 != p)", or with NULL; and with braces.
6+
7+
my $VERSION = '2011-04-20 13:43'; # UTC
8+
# The definition above must lie within the first 8 lines in order
9+
# for the Emacs time-stamp write hook (at end) to update it.
10+
# If you change this file with Emacs, please let the write hook
11+
# do its job. Otherwise, update this string manually.
12+
13+
# Copyright (C) 2008-2011 Free Software Foundation, Inc.
14+
15+
# This program is free software: you can redistribute it and/or modify
16+
# it under the terms of the GNU General Public License as published by
17+
# the Free Software Foundation, either version 3 of the License, or
18+
# (at your option) any later version.
19+
20+
# This program is distributed in the hope that it will be useful,
21+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
# GNU General Public License for more details.
24+
25+
# You should have received a copy of the GNU General Public License
26+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
27+
28+
# Written by Jim Meyering
29+
30+
use strict;
31+
use warnings;
32+
use Getopt::Long;
33+
34+
(my $ME = $0) =~ s|.*/||;
35+
36+
# use File::Coda; # http://meyering.net/code/Coda/
37+
END {
38+
defined fileno STDOUT or return;
39+
close STDOUT and return;
40+
warn "$ME: failed to close standard output: $!\n";
41+
$? ||= 1;
42+
}
43+
44+
sub usage ($)
45+
{
46+
my ($exit_code) = @_;
47+
my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
48+
if ($exit_code != 0)
49+
{
50+
print $STREAM "Try `$ME --help' for more information.\n";
51+
}
52+
else
53+
{
54+
print $STREAM <<EOF;
55+
Usage: $ME [OPTIONS] FILE...
56+
57+
Detect any instance in FILE of a useless "if" test before a free call, e.g.,
58+
"if (p) free (p);". Any such test may be safely removed without affecting
59+
the semantics of the C code in FILE. Use --name=FOO --name=BAR to also
60+
detect free-like functions named FOO and BAR.
61+
62+
OPTIONS:
63+
64+
--list print only the name of each matching FILE (\\0-terminated)
65+
--name=N add name N to the list of \`free\'-like functions to detect;
66+
may be repeated
67+
68+
--help display this help and exit
69+
--version output version information and exit
70+
71+
Exit status:
72+
73+
0 one or more matches
74+
1 no match
75+
2 an error
76+
77+
EXAMPLE:
78+
79+
For example, this command prints all removable "if" tests before "free"
80+
and "kfree" calls in the linux kernel sources:
81+
82+
git ls-files -z |xargs -0 $ME --name=kfree
83+
84+
EOF
85+
}
86+
exit $exit_code;
87+
}
88+
89+
sub is_NULL ($)
90+
{
91+
my ($expr) = @_;
92+
return ($expr eq 'NULL' || $expr eq '0');
93+
}
94+
95+
{
96+
sub EXIT_MATCH {0}
97+
sub EXIT_NO_MATCH {1}
98+
sub EXIT_ERROR {2}
99+
my $err = EXIT_NO_MATCH;
100+
101+
my $list;
102+
my @name = qw(free);
103+
GetOptions
104+
(
105+
help => sub { usage 0 },
106+
version => sub { print "$ME version $VERSION\n"; exit },
107+
list => \$list,
108+
'name=s@' => \@name,
109+
) or usage 1;
110+
111+
# Make sure we have the right number of non-option arguments.
112+
# Always tell the user why we fail.
113+
@ARGV < 1
114+
and (warn "$ME: missing FILE argument\n"), usage EXIT_ERROR;
115+
116+
my $or = join '|', @name;
117+
my $regexp = qr/(?:$or)/;
118+
119+
# Set the input record separator.
120+
# Note: this makes it impractical to print line numbers.
121+
$/ = '"';
122+
123+
my $found_match = 0;
124+
FILE:
125+
foreach my $file (@ARGV)
126+
{
127+
open FH, '<', $file
128+
or (warn "$ME: can't open `$file' for reading: $!\n"),
129+
$err = EXIT_ERROR, next;
130+
while (defined (my $line = <FH>))
131+
{
132+
while ($line =~
133+
/\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*([^)]+?))?\s*\)
134+
# 1 2 3
135+
(?: \s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;|
136+
\s*\{\s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;\s*\}))/sxg)
137+
{
138+
my $all = $1;
139+
my ($lhs, $rhs) = ($2, $3);
140+
my ($free_opnd, $braced_free_opnd) = ($4, $5);
141+
my $non_NULL;
142+
if (!defined $rhs) { $non_NULL = $lhs }
143+
elsif (is_NULL $rhs) { $non_NULL = $lhs }
144+
elsif (is_NULL $lhs) { $non_NULL = $rhs }
145+
else { next }
146+
147+
# Compare the non-NULL part of the "if" expression and the
148+
# free'd expression, without regard to white space.
149+
$non_NULL =~ tr/ \t//d;
150+
my $e2 = defined $free_opnd ? $free_opnd : $braced_free_opnd;
151+
$e2 =~ tr/ \t//d;
152+
if ($non_NULL eq $e2)
153+
{
154+
$found_match = 1;
155+
$list
156+
and (print "$file\0"), next FILE;
157+
print "$file: $all\n";
158+
}
159+
}
160+
}
161+
}
162+
continue
163+
{
164+
close FH;
165+
}
166+
167+
$found_match && $err == EXIT_NO_MATCH
168+
and $err = EXIT_MATCH;
169+
170+
exit $err;
171+
}
172+
173+
my $foo = <<'EOF';
174+
# The above is to *find* them.
175+
# This adjusts them, removing the unnecessary "if (p)" part.
176+
177+
# FIXME: do something like this as an option (doesn't do braces):
178+
free=xfree
179+
git grep -l -z "$free *(" \
180+
| xargs -0 useless-if-before-free -l --name="$free" \
181+
| xargs -0 perl -0x3b -pi -e \
182+
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s+('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\)\s*;)/$2/s'
183+
184+
# Use the following to remove redundant uses of kfree inside braces.
185+
# Note that -0777 puts perl in slurp-whole-file mode;
186+
# but we have plenty of memory, these days...
187+
free=kfree
188+
git grep -l -z "$free *(" \
189+
| xargs -0 useless-if-before-free -l --name="$free" \
190+
| xargs -0 perl -0777 -pi -e \
191+
's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*(?:0|NULL))?\s*\)\s*\{\s*('"$free"'\s*\((?:\s*\([^)]+\))?\s*\1\s*\);)\s*\}[^\n]*$/$2/gms'
192+
193+
Be careful that the result of the above transformation is valid.
194+
If the matched string is followed by "else", then obviously, it won't be.
195+
196+
When modifying files, refuse to process anything other than a regular file.
197+
EOF
198+
199+
## Local Variables:
200+
## mode: perl
201+
## indent-tabs-mode: nil
202+
## eval: (add-hook 'write-file-hooks 'time-stamp)
203+
## time-stamp-start: "my $VERSION = '"
204+
## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
205+
## time-stamp-time-zone: "UTC"
206+
## time-stamp-end: "'; # UTC"
207+
## End:

0 commit comments

Comments
 (0)