Makefile.maint 22.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
# This is reported not to work with make-3.79.1
# ME := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
ME := Makefile.maint

# Do not save the original name or timestamp in the .tar.gz file.
# Use --rsyncable if available.
gzip_rsyncable := \
  $(shell gzip --help 2>/dev/null|grep rsyncable >/dev/null && echo --rsyncable)
GZIP_ENV = '--no-name --best $(gzip_rsyncable)'

11
VC_LIST = build-aux/vc-list-files
12

13 14
VC_LIST_EXCEPT = \
  $(VC_LIST) | if test -f .x-$@; then grep -vEf .x-$@; else grep -v ChangeLog; fi
15 16 17 18 19 20

# Prevent programs like 'sort' from considering distinct strings to be equal.
# Doing it here saves us from having to set LC_ALL elsewhere in this file.
export LC_ALL = C

# Collect the names of rules starting with `sc_'.
21 22
syntax-check-rules := $(shell sed -n 's/^\(sc_[a-zA-Z0-9_-]*\):.*/\1/p' \
                        $(srcdir)/$(ME))
23 24 25 26
.PHONY: $(syntax-check-rules)

local-checks-available = \
  po-check copyright-check m4-check author_mark_check \
27
  patch-check strftime-check $(syntax-check-rules) \
28 29 30 31 32 33 34
  makefile_path_separator_check \
  makefile-check check-AUTHORS
.PHONY: $(local-checks-available)

local-check := $(filter-out $(local-checks-to-skip), $(local-checks-available))

syntax-check: $(local-check)
35 36 37 38
#	@grep -nE '#  *include <(limits|std(def|arg|bool))\.h>'		\
#	    $$(find -type f -name '*.[chly]') &&			\
#	  { echo '$(ME): found conditional include' 1>&2;		\
#	    exit 1; } || :
39

40 41 42 43 44
#	grep -nE '^#  *include <(string|stdlib)\.h>'			\
#	    $(srcdir)/{lib,src}/*.[chy] &&				\
#	  { echo '$(ME): FIXME' 1>&2;					\
#	    exit 1; } || :
# FIXME: don't allow `#include .strings\.h' anywhere
45 46

sc_avoid_if_before_free:
47 48
	@$(srcdir)/build-aux/useless-if-before-free			\
		$(useless_free_options)					\
49
	    $$($(VC_LIST_EXCEPT)) &&					\
50 51 52
	  { echo '$(ME): found useless "if" before "free" above' 1>&2;	\
	    exit 1; } || :

53 54 55
# Avoid uses of write(2).  Either switch to streams (fwrite), or use
# the safewrite wrapper.
sc_avoid_write:
56 57
	@if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then		\
	  grep '\<write *(' $$($(VC_LIST_EXCEPT) | grep '\.c$$') &&	\
58 59 60 61 62 63
	    { echo "$(ME): the above files use write;"			\
	      " consider using the safewrite wrapper instead"		\
		  1>&2; exit 1; } || :;					\
	else :;								\
	fi

64
sc_cast_of_argument_to_free:
65
	@grep -nE '\<free \(\(' $$($(VC_LIST_EXCEPT)) &&		\
66 67 68 69
	  { echo '$(ME): don'\''t cast free argument' 1>&2;		\
	    exit 1; } || :

sc_cast_of_x_alloc_return_value:
70
	@grep -nE '\*\) *x(m|c|re)alloc\>' $$($(VC_LIST_EXCEPT)) &&	\
71 72 73 74
	  { echo '$(ME): don'\''t cast x*alloc return value' 1>&2;	\
	    exit 1; } || :

sc_cast_of_alloca_return_value:
75
	@grep -nE '\*\) *alloca\>' $$($(VC_LIST_EXCEPT)) &&		\
76 77 78 79
	  { echo '$(ME): don'\''t cast alloca return value' 1>&2;	\
	    exit 1; } || :

sc_space_tab:
80
	@grep -n '[ ]	' $$($(VC_LIST_EXCEPT)) &&			\
81 82 83 84 85 86 87
	  { echo '$(ME): found SPACE-TAB sequence; remove the SPACE'	\
		1>&2; exit 1; } || :

# Don't use *scanf or the old ato* functions in `real' code.
# They provide no error checking mechanism.
# Instead, use strto* functions.
sc_prohibit_atoi_atof:
88
	@grep -nE '\<([fs]?scanf|ato([filq]|ll))\>' $$($(VC_LIST_EXCEPT)) && \
89 90 91 92
	  { echo '$(ME): do not use *scan''f, ato''f, ato''i, ato''l, ato''ll, ato''q, or ss''canf'	\
		1>&2; exit 1; } || :

# Use STREQ rather than comparing strcmp == 0, or != 0.
93
# Similarly, use STREQLEN or STRPREFIX rather than strncmp.
94
sc_prohibit_strcmp:
95
	@grep -nE '! *str''n?cmp *\(|\<str''n?cmp *\([^)]+\) *=='	\
96
	    $$($(VC_LIST_EXCEPT)) &&					\
97 98 99 100 101 102 103 104 105 106 107 108
	  { echo '$(ME): use STREQ in place of the above uses of str''cmp' \
		1>&2; exit 1; } || :

# Using EXIT_SUCCESS as the first argument to error is misleading,
# since when that parameter is 0, error does not exit.  Use `0' instead.
sc_error_exit_success:
	@grep -nF 'error (EXIT_SUCCESS,'				\
	    $$(find -type f -name '*.[chly]') &&			\
	  { echo '$(ME): found error (EXIT_SUCCESS' 1>&2;		\
	    exit 1; } || :

sc_file_system:
109
	@grep -ni 'file''system' $$($(VC_LIST_EXCEPT)) &&		\
110 111 112 113 114
	  { echo '$(ME): found use of "file''system";'			\
	    'rewrite to use "file system"' 1>&2;			\
	    exit 1; } || :

sc_no_have_config_h:
115
	@grep -n '^# *if.*HAVE''_CONFIG_H' $$($(VC_LIST_EXCEPT)) &&	\
116 117 118 119 120
	  { echo '$(ME): found use of HAVE''_CONFIG_H; remove'		\
		1>&2; exit 1; } || :

# Nearly all .c files must include <config.h>.
sc_require_config_h:
121
	@if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then		\
122
	  grep -L '^# *include <config\.h>'				\
123
		$$($(VC_LIST_EXCEPT) | grep '\.c$$')			\
124 125 126 127 128 129
	      | grep . &&						\
	  { echo '$(ME): the above files do not include <config.h>'	\
		1>&2; exit 1; } || :;					\
	else :;								\
	fi

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
# To use this "command" macro, you must first define two shell variables:
# h: the header, enclosed in <> or ""
# re: a regular expression that matches IFF something provided by $h is used.
define _header_without_use
  h_esc=`echo "$$h"|sed 's/\./\\./'`;					\
  if $(VC_LIST_EXCEPT) | grep '\.c$$' > /dev/null; then			\
    files=$$(grep -l '^# *include '"$$h_esc"				\
	     $$($(VC_LIST_EXCEPT) | grep '\.c$$')) &&			\
    grep -LE "$$re" $$files | grep . &&					\
      { echo "$(ME): the above files include $$h but don't use it"	\
	1>&2; exit 1; } || :;						\
  else :;								\
  fi
endef

145 146
# Prohibit the inclusion of assert.h without an actual use of assert.
sc_prohibit_assert_without_use:
147 148 149 150 151
	@h='<assert.h>' re='\<assert *\(' $(_header_without_use)

# Prohibit the inclusion of getopt.h without an actual use.
sc_prohibit_getopt_without_use:
	@h='<getopt.h>' re='\<getopt(_long)? *\(' $(_header_without_use)
152 153 154

# Don't include quotearg.h unless you use one of its functions.
sc_prohibit_quotearg_without_use:
155
	@h='"quotearg.h"' re='\<quotearg(_[^ ]+)? *\(' $(_header_without_use)
156 157 158

# Don't include quote.h unless you use one of its functions.
sc_prohibit_quote_without_use:
159
	@h='"quote.h"' re='\<quote(_n)? *\(' $(_header_without_use)
160

161 162 163 164 165 166 167 168 169 170
# Prohibit the inclusion of c-ctype.h without an actual use.
sc_prohibit_c_ctype_without_use:
	@h='[<"]c-ctype.h[">]' re='\<c_($(ctype_re)) *\(' $(_header_without_use)

# Prohibit the inclusion of <ctype.h>.
sc_prohibit_ctype_h:
	@grep -E '^# *include  *<ctype\.h>' $$($(VC_LIST_EXCEPT)) &&	\
	  { echo "$(ME): don't use ctype.h; instead, use c-ctype.h"	\
		1>&2; exit 1; } || :

171 172
sc_obsolete_symbols:
	@grep -nE '\<(HAVE''_FCNTL_H|O''_NDELAY)\>'			\
173
	     $$($(VC_LIST_EXCEPT)) &&					\
174 175 176 177 178 179
	  { echo '$(ME): do not use HAVE''_FCNTL_H or O''_NDELAY'	\
		1>&2; exit 1; } || :

# FIXME: warn about definitions of EXIT_FAILURE, EXIT_SUCCESS, STREQ

# Each nonempty line must start with a year number, or a TAB.
180 181 182
# Or day-of-week+space.
changelog_entry_header_regexp = \
  ([12][0-9][0-9][0-9]|	.|(Mon|Tue|Wed|Thu|Fri|Sat|Sun) )
183
sc_changelog:
184 185
	@grep -Evn '(^$$|^$(changelog_entry_header_regexp))'		\
	  $$(find . -maxdepth 2 -name ChangeLog) &&			\
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
	  { echo '$(ME): found unexpected prefix in a ChangeLog' 1>&2;	\
	    exit 1; } || :

# Ensure that dd's definition of LONGEST_SYMBOL stays in sync
# with the strings from the two affected variables.
dd_c = $(srcdir)/src/dd.c
sc_dd_max_sym_length:
ifneq ($(wildcard $(dd_c)),)
	@len=$$( (sed -n '/conversions\[\] =$$/,/^};/p' $(dd_c);\
		 sed -n '/flags\[\] =$$/,/^};/p' $(dd_c) )	\
		|sed -n '/"/s/^[^"]*"\([^"]*\)".*/\1/p'		\
	      | wc --max-line-length);				\
	max=$$(sed -n '/^#define LONGEST_SYMBOL /s///p' $(dd_c)	\
	      |tr -d '"' | wc --max-line-length);		\
	if test "$$len" = "$$max"; then :; else			\
	  echo 'dd.c: LONGEST_SYMBOL is not longest' 1>&2;	\
	  exit 1;						\
	fi
endif

# Many m4 macros names once began with `jm_'.
# On 2004-04-13, they were all changed to start with gl_ instead.
# Make sure that none are inadvertently reintroduced.
sc_prohibit_jm_in_m4:
	@grep -nE 'jm_[A-Z]'					\
211
		$$($(VC_LIST) m4 |grep '\.m4$$'; echo /dev/null) && \
212 213 214 215 216 217 218
	    { echo '$(ME): do not use jm_ in m4 macro names'	\
	      1>&2; exit 1; } || :

sc_root_tests:
	@if test -d tests \
	      && grep check-root tests/Makefile.am>/dev/null 2>&1; then \
	t1=sc-root.expected; t2=sc-root.actual;				\
219 220
	grep -nl '^require_root_$$'					\
	  $$($(VC_LIST) tests) |sed s,tests,., |sort > $$t1;		\
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	sed -n 's,	cd \([^ ]*\) .*MAKE..check TESTS=\(.*\),./\1/\2,p' \
	  $(srcdir)/tests/Makefile.am |sort > $$t2;			\
	diff -u $$t1 $$t2 || diff=1;					\
	rm -f $$t1 $$t2;						\
	test "$$diff"							\
	  && { echo 'tests/Makefile.am: missing check-root action'>&2;	\
	       exit 1; } || :;						\
	fi

headers_with_interesting_macro_defs = \
  exit.h	\
  fcntl_.h	\
  fnmatch_.h	\
  intprops.h	\
  inttypes_.h	\
  lchown.h	\
  openat.h	\
  stat-macros.h	\
  stdint_.h

# Create a list of regular expressions matching the names
# of macros that are guaranteed by parts of gnulib to be defined.
.re-defmac:
	@(cd $(srcdir)/lib;						\
	  for f in $(headers_with_interesting_macro_defs); do		\
	    test -f $$f &&						\
	      sed -n '/^# *define \([^_ (][^ (]*\)[ (].*/s//\1/p' $$f;	\
	   done;							\
	 ) | sort -u							\
	   | grep -Ev 'ATTRIBUTE_NORETURN|SIZE_MAX'			\
	   | sed 's/^/^# *define /'					\
	  > $@-t
	@mv $@-t $@

# Don't define macros that we already get from gnulib header files.
sc_always_defined_macros: .re-defmac
	@if test -f $(srcdir)/src/system.h; then			\
	  trap 'rc=$$?; rm -f .re-defmac; exit $$rc' 0 1 2 3 15;	\
259
	  grep -f .re-defmac $$($(VC_LIST))				\
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
	    && { echo '$(ME): define the above via some gnulib .h file'	\
		  1>&2;  exit 1; } || :;				\
	fi

# Create a list of regular expressions matching the names
# of files included from system.h.  Exclude a couple.
.re-list:
	@sed -n '/^# *include /s///p' $(srcdir)/src/system.h \
	  | grep -Ev 'sys/(param|file)\.h' \
	  | sed 's/ .*//;;s/^["<]/^# *include [<"]/;s/\.h[">]$$/\\.h[">]/' \
	  > $@-t
	@mv $@-t $@

# Files in src/ should not include directly any of
# the headers already included via system.h.
sc_system_h_headers: .re-list
	@if test -f $(srcdir)/src/system.h; then			\
	  trap 'rc=$$?; rm -f .re-list; exit $$rc' 0 1 2 3 15;		\
	  grep -nE -f .re-list						\
279
	      $$($(VC_LIST) src |					\
280 281 282 283 284 285 286 287
		 grep -Ev '((copy|system)\.h|parse-gram\.c)$$')		\
	    && { echo '$(ME): the above are already included via system.h'\
		  1>&2;  exit 1; } || :;				\
	fi

sc_sun_os_names:
	@grep -nEi \
	    'solaris[^[:alnum:]]*2\.(7|8|9|[1-9][0-9])|sunos[^[:alnum:]][6-9]' \
288
	    $$($(VC_LIST_EXCEPT)) &&					\
289 290 291 292
	  { echo '$(ME): found misuse of Sun OS version numbers' 1>&2;	\
	    exit 1; } || :

sc_the_the:
293
	@grep -ni '\<the ''the\>' $$($(VC_LIST_EXCEPT)) &&		\
294 295 296 297 298 299 300
	  { echo '$(ME): found use of "the ''the";' 1>&2;		\
	    exit 1; } || :

sc_tight_scope:
	$(MAKE) -C src $@

sc_trailing_blank:
301
	@grep -n '[	 ]$$' $$($(VC_LIST_EXCEPT)) &&			\
302 303 304
	  { echo '$(ME): found trailing blank(s)'			\
		1>&2; exit 1; } || :

305 306 307 308 309 310 311 312 313 314 315
# Ensure that no C source file uses TABs for indentation.
# Also match *.h.in files, to get libvirt.h.in.
# Exclude files in gnulib, since they're imported.
sc_TAB_in_indentation:
	@grep -lE '^ *	' /dev/null					\
	     $$($(VC_LIST_EXCEPT)					\
	        | grep -E '\.[ch](\.in)?$$'				\
	        | grep -v '^gnulib/') &&				\
	  { echo '$(ME): found TAB(s) use for indentation; use spaces'	\
		1>&2; exit 1; } || :

316 317 318
ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper

319
sc_avoid_ctype_macros:
320
	@grep -E '\b($(ctype_re)) *\(' /dev/null			\
321 322
	     $$($(VC_LIST_EXCEPT)) &&					\
	  { echo "$(ME): don't use ctype macros (use c-ctype.h)"	\
323 324
		1>&2; exit 1; } || :

325 326 327 328 329 330
# Match lines like the following, but where there is only one space
# between the options and the description:
#   -D, --all-repeated[=delimit-method]  print all duplicate lines\n
longopt_re = --[a-z][0-9A-Za-z-]*(\[?=[0-9A-Za-z-]*\]?)?
sc_two_space_separator_in_usage:
	@grep -nE '^   *(-[A-Za-z],)? $(longopt_re) [^ ].*\\$$'		\
331
	    $$($(VC_LIST_EXCEPT)) &&					\
332 333 334 335
	  { echo "$(ME): help2man requires at least two spaces between"; \
	    echo "$(ME): an option and its description"; \
		1>&2; exit 1; } || :

336 337 338 339 340 341 342 343 344 345 346 347 348 349
msg_gen_function =
msg_gen_function += DISABLE_fprintf
msg_gen_function += virXendError
msg_gen_function += virXMLError
msg_gen_function += virHashError
msg_gen_function += virConfError
msg_gen_function += virTestError
msg_gen_function += virLibConnError
msg_gen_function += virStorageReportError
msg_gen_function += virxmlRpcError
msg_gen_function += virLog
msg_gen_function += qemudLog
msg_gen_function += remoteDispatchError
msg_gen_function += virStorageLog
350
msg_gen_function += xenXMError
351
msg_gen_function += ReportError
352
msg_gen_function += qemudReportError
353
msg_gen_function += openvzLog
D
Daniel Veillard 已提交
354
msg_gen_function += openvzError
355
msg_gen_function += virDomainReportError
356 357
msg_gen_function += virReportErrorHelper
msg_gen_function += lxcError
358
msg_gen_function += umlError
359

360 361 362
# Uncomment the following and run "make syntax-check" to see diagnostics
# that are not yet marked for translation, but that need to be rewritten
# so that they are translatable.
363
# msg_gen_function += error
364 365 366 367 368
# msg_gen_function += virXenError
# msg_gen_function += testError

func_or := $(shell printf '$(msg_gen_function)'|tr -s '[[:space:]]' '|')
func_re := ($(func_or))
369

370 371
# Look for diagnostics that aren't marked for translation.
# This won't find any for which error's format string is on a separate line.
372 373 374
# The sed filters eliminate false-positives like these:
#    _("...: "
#    "%s", _("no storage vol w..."
375 376
sc_unmarked_diagnostics:
	@grep -nE							\
377
            '\<$(func_re) \([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT))	\
378 379 380
	  | grep -v '_''(' &&						\
	  { echo '$(ME): found unmarked diagnostic(s)' 1>&2;		\
	    exit 1; } || :
381 382
	@{ grep     -nE '\<$(func_re) *\(.*;$$' $$($(VC_LIST_EXCEPT));   \
	   grep -A1 -nE '\<$(func_re) *\(.*,$$' $$($(VC_LIST_EXCEPT)); } \
383 384
	   | sed 's/_("[^"][^"]*"//;s/[	 ]"%s"//'			\
	   | grep '[	 ]"' &&						\
385 386
	  { echo '$(ME): found unmarked diagnostic(s)' 1>&2;		\
	    exit 1; } || :
387

388
sc_prohibit_virBufferAdd_with_string_literal:
389
	@grep -nE '\<virBufferAdd *\([^,]+, *"[^"]' $$($(VC_LIST_EXCEPT)) && \
390 391 392
	  { echo '$(ME): use virBufferAddLit, not virBufferAdd,' \
	      'with a string literal' 1>&2; exit 1; } || :

393 394 395
# Avoid useless parentheses like those in this example:
# #if defined (SYMBOL) || defined (SYM2)
sc_useless_cpp_parens:
396
	@grep -n '^# *if .*defined *(' $$($(VC_LIST_EXCEPT)) &&		\
397 398 399 400 401
	  { echo '$(ME): found useless parentheses in cpp directive'	\
		1>&2; exit 1; } || :

# Require the latest GPL.
sc_GPL_version:
402
	@grep -n 'either ''version [^3]' $$($(VC_LIST_EXCEPT)) &&	\
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
	  { echo '$(ME): GPL vN, N!=3' 1>&2; exit 1; } || :

# Ensure that the c99-to-c89 patch applies cleanly.
patch-check:
	rm -rf src-c89 $@.1 $@.2
	cp -a src src-c89
	(cd src-c89; patch -p1 -V never --fuzz=0) < src/c99-to-c89.diff \
	  > $@.1 2>&1
	if test "$$REGEN_PATCH" = yes; then \
	  diff -upr src src-c89 | sed 's,src-c89/,src/,' \
	    | grep -v '^Only in' > new-diff || : ; fi
	grep -v '^patching file ' $@.1 > $@.2 || :
	msg=ok; test -s $@.2 && msg='fuzzy patch' || : ;	\
	rm -f src-c89/*.o || msg='rm failed';			\
	$(MAKE) -C src-c89 CFLAGS='-Wdeclaration-after-statement -Werror' \
	  || msg='compile failure with extra options';		\
	test "$$msg" = ok && rm -rf src-c89 $@.1 $@.2 || echo "$$msg" 1>&2; \
	test "$$msg" = ok

# Ensure that date's --help output stays in sync with the info
# documentation for GNU strftime.  The only exception is %N,
# which date accepts but GNU strftime does not.
extract_char = sed 's/^[^%][^%]*%\(.\).*/\1/'
strftime-check:
J
Jim Meyering 已提交
427
	@if test -f $(srcdir)/src/date.c; then				\
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
	  grep '^  %.  ' $(srcdir)/src/date.c | sort			\
	    | $(extract_char) > $@-src;					\
	  { echo N;							\
	    info libc date calendar format | grep '^    `%.'\'		\
	      | $(extract_char); } | sort > $@-info;			\
	  diff -u $@-src $@-info || exit 1;				\
	  rm -f $@-src $@-info;						\
	fi

check-AUTHORS:
	$(MAKE) -C src $@

# Ensure that we use only the standard $(VAR) notation,
# not @...@ in Makefile.am, now that we can rely on automake
# to emit a definition for each substituted variable.
makefile-check:
	grep -nE '@[A-Z_0-9]+@' `find . -name Makefile.am` \
	  && { echo 'Makefile.maint: use $$(...), not @...@' 1>&2; exit 1; } || :

news-date-check: NEWS
	today=`date +%Y-%m-%d`;						\
	if head NEWS | grep '^\*.* $(VERSION_REGEXP) ('$$today')'	\
	    >/dev/null; then						\
	  :;								\
	else								\
	  echo "version or today's date is not in NEWS" 1>&2;		\
	  exit 1;							\
	fi

changelog-check:
	if head ChangeLog | grep 'Version $(VERSION_REGEXP)\.$$'	\
	    >/dev/null; then						\
	  :;								\
	else								\
	  echo "$(VERSION) not in ChangeLog" 1>&2;			\
	  exit 1;							\
	fi

m4-check:
	@grep -n 'AC_DEFUN([^[]' m4/*.m4 \
	  && { echo 'Makefile.maint: quote the first arg to AC_DEFUN' 1>&2; \
	       exit 1; } || :

471 472 473 474
fix_po_file_diag = \
'you have changed the set of files with translatable diagnostics;\n\
apply the above patch\n'

475
# Verify that all source files using _() are listed in po/POTFILES.in.
476
po_file = po/POTFILES.in
477
po-check:
J
Jim Meyering 已提交
478
	@if test -f po/POTFILES.in; then					\
479 480 481
	  grep -E -v '^(#|$$)' po/POTFILES.in				\
	    | grep -v '^src/false\.c$$' | sort > $@-1;			\
	  files=;							\
482 483 484 485 486
	  for file in $$($(VC_LIST_EXCEPT)); do				\
	    case $$file in						\
	    djgpp/* | man/*) continue;;					\
	    */c99-to-c89.diff) continue;;				\
	    esac;							\
487 488 489 490
	    case $$file in						\
	    *.[ch])							\
	      base=`expr " $$file" : ' \(.*\)\..'`;			\
	      { test -f $$base.l || test -f $$base.y; } && continue;;	\
491
	    *) continue;;						\
492 493 494 495 496
	    esac;							\
	    files="$$files $$file";					\
	  done;								\
	  grep -E -l '\b(N?_|gettext *)\([^)"]*("|$$)' $$files		\
	    | sort -u > $@-2;						\
497 498
	  diff -u -L $(po_file) -L $(po_file) $@-1 $@-2			\
	    || { printf '$(ME): '$(fix_po_file_diag) 1>&2; exit 1; };	\
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
	  rm -f $@-1 $@-2;						\
	fi

# In a definition of #define AUTHORS "... and ..." where the RHS contains
# the English word `and', the string must be marked with `N_ (...)' so that
# gettext recognizes it as a string requiring translation.
author_mark_check:
	@grep -n '^# *define AUTHORS "[^"]* and ' src/*.c |grep -v ' N_ (' && \
	  { echo 'Makefile.maint: enclose the above strings in N_ (...)' 1>&2; \
	    exit 1; } || :

# Sometimes it is useful to change the PATH environment variable
# in Makefiles.  When doing so, it's better not to use the Unix-centric
# path separator of `:', but rather the automake-provided `@PATH_SEPARATOR@'.
# It'd be better to use `find -print0 ...|xargs -0 ...', but less portable,
# and there probably aren't many projects with so many Makefile.am files
# that we'd have to worry about limits on command line length.
msg = 'Makefile.maint: Do not use `:'\'' above; use @PATH_SEPARATOR@ instead'
makefile_path_separator_check:
	@grep -n 'PATH=.*:' `find $(srcdir) -name Makefile.am` \
	  && { echo $(msg) 1>&2; exit 1; } || :

# Check that `make alpha' will not fail at the end of the process.
writable-files:
	if test -d $(release_archive_dir); then :; else			\
524 525 526 527 528 529 530
	  for file in $(distdir).tar.gz					\
	              $(release_archive_dir)/$(distdir).tar.gz; do	\
	    test -e $$file || continue;					\
	    test -w $$file						\
	      || { echo ERROR: $$file is not writable; fail=1; };	\
	  done;								\
	  test "$$fail" && exit 1 || :
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
	fi

v_etc_file = lib/version-etc.c
sample-test = tests/sample-test
texi = doc/$(PACKAGE).texi
# Make sure that the copyright date in $(v_etc_file) is up to date.
# Do the same for the $(sample-test) and the main doc/.texi file.
copyright-check:
	@if test -f $(v_etc_file); then \
	  grep 'enum { COPYRIGHT_YEAR = '$$(date +%Y)' };' $(v_etc_file) \
	    >/dev/null \
	  || { echo 'out of date copyright in $(v_etc_file); update it' 1>&2; \
	       exit 1; }; \
	fi
	@if test -f $(sample-test); then \
	  grep '# Copyright (C) '$$(date +%Y)' Free' $(sample-test) \
	    >/dev/null \
	  || { echo 'out of date copyright in $(sample-test); update it' 1>&2; \
	       exit 1; }; \
	fi
	@if test -f $(texi); then \
	  grep 'Copyright @copyright{} .*'$$(date +%Y)' Free' $(texi) \
	    >/dev/null \
	  || { echo 'out of date copyright in $(texi); update it' 1>&2; \
	       exit 1; }; \
	fi

vc-diff-check:
	$(VC) diff > vc-diffs || :
	if test -s vc-diffs; then				\
	  cat vc-diffs;						\
	  echo "Some files are locally modified:" 1>&2;		\
	  exit 1;						\
	else							\
	  rm vc-diffs;						\
	fi

cvs-check: vc-diff-check

maintainer-distcheck:
	$(MAKE) distcheck
	$(MAKE) my-distcheck

# Use -Wformat -Werror to detect format-string/arg-list mismatches.
# Also, check for shadowing problems with -Wshadow, and for pointer
# arithmetic problems with -Wpointer-arith.
# These CFLAGS are pretty strict.  If you build this target, you probably
# have to have a recent version of gcc and glibc headers.
# The for-loop below ensures that there is a bin/ directory full of all
# of the programs under test (except the few that are required for basic
# Makefile rules), all symlinked to the just-built "false" program.
# This is to ensure that if ever a test neglects to make PATH include
# the build srcdir, these always-failing programs will run.
# Otherwise, it is too easy to test the wrong programs.
# Note that "false" itself is a symlink to true, so it too will malfunction.
TMPDIR ?= /tmp
t=$(TMPDIR)/$(PACKAGE)/test
my-distcheck: $(local-check) check
	-rm -rf $(t)
	mkdir -p $(t)
	GZIP=$(GZIP_ENV) $(AMTAR) -C $(t) -zxf $(distdir).tar.gz
	cd $(t)/$(distdir)				\
	  && ./configure --disable-nls			\
	  && $(MAKE) CFLAGS='$(warn_cflags)'		\
	      AM_MAKEFLAGS='$(null_AM_MAKEFLAGS)'	\
	  && $(MAKE) dvi				\
	  && $(MAKE) distclean
	(cd $(t) && mv $(distdir) $(distdir).old	\
	  && $(AMTAR) -zxf - ) < $(distdir).tar.gz
	diff -ur $(t)/$(distdir).old $(t)/$(distdir)
	if test -f $(srcdir)/src/c99-to-c89.diff; then			\
	  cd $(t)/$(distdir)						\
	    && (cd src && patch -V never --fuzz=0 <c99-to-c89.diff)	\
	    && ./configure --disable-largefile				\
	         CFLAGS='-Werror -ansi -Wno-long-long'			\
	    && $(MAKE);							\
	fi
	-rm -rf $(t)
	@echo "========================"; \
	echo "$(distdir).tar.gz is ready for distribution"; \
	echo "========================"
612

613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
cvs-to-git = '\#!/usr/bin/perl\n\
use warnings;\n\
use strict;\n\
use File::Find;\n\
use File::Copy;\n\
\n\
find ({wanted =>\n\
       sub {$$_ eq q/.cvsignore/ or return;\n\
	    my $$gi = q/.gitignore/;\n\
	    unlink $$gi;\n\
	    copy($$_, $$gi) or die qq/copy failed: $$_->$$gi: $$!\\n/;\n\
	    chmod 0444, $$gi;\n\
	    }},\n\
      q!.!);\n'

.PHONY: sync-vcs-ignore-files
c2g = cvs-to-git
630
sync-vcs-ignore-files:
631 632 633 634 635 636
	rm -f $(c2g)-t $(c2g)
	printf $(cvs-to-git) > $(c2g)-t
	chmod a+x-w $(c2g)-t
	mv $(c2g)-t $(c2g)
	perl $(c2g)
	rm -f $(c2g)