Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

   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
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 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
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 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
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 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
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 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
 524
 525
 526
 527
 528
 529
 530
 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
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
# -*-Makefile-*-
# This Makefile fragment tries to be general-purpose enough to be
# used by many projects via the gnulib maintainer-makefile module.

## Copyright (C) 2001-2012 Free Software Foundation, Inc.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.

# This is reported not to work with make-3.79.1
# ME := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
ME := maint.mk

# Diagnostic for continued use of deprecated variable.
# Remove in 2013
ifneq ($(build_aux),)
 $(error "$(ME): \
set $$(_build-aux) relative to $$(srcdir) instead of $$(build_aux)")
endif

# 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 \
    && printf %s --rsyncable)
GZIP_ENV = '--no-name --best $(gzip_rsyncable)'

GIT = git
VC = $(GIT)

VC_LIST = $(srcdir)/$(_build-aux)/vc-list-files -C $(srcdir)

# You can override this variable in cfg.mk to set your own regexp
# matching files to ignore.
VC_LIST_ALWAYS_EXCLUDE_REGEX ?= ^$$

# This is to preprocess robustly the output of $(VC_LIST), so that even
# when $(srcdir) is a pathological name like "....", the leading sed command
# removes only the intended prefix.
_dot_escaped_srcdir = $(subst .,\.,$(srcdir))

# Post-process $(VC_LIST) output, prepending $(srcdir)/, but only
# when $(srcdir) is not ".".
ifeq ($(srcdir),.)
_prepend_srcdir_prefix =
else
_prepend_srcdir_prefix = | sed 's|^|$(srcdir)/|'
endif

# In order to be able to consistently filter "."-relative names,
# (i.e., with no $(srcdir) prefix), this definition is careful to
# remove any $(srcdir) prefix, and to restore what it removes.
_sc_excl = \
  $(if $(exclude_file_name_regexp--$@),$(exclude_file_name_regexp--$@),^$$)
VC_LIST_EXCEPT = \
  $(VC_LIST) | sed 's|^$(_dot_escaped_srcdir)/||' \
	| if test -f $(srcdir)/.x-$@; then grep -vEf $(srcdir)/.x-$@; \
	  else grep -Ev -e "$${VC_LIST_EXCEPT_DEFAULT-ChangeLog}"; fi \
	| grep -Ev -e '($(VC_LIST_ALWAYS_EXCLUDE_REGEX)|$(_sc_excl))' \
	$(_prepend_srcdir_prefix)

ifeq ($(origin prev_version_file), undefined)
  prev_version_file = $(srcdir)/.prev-version
endif

PREV_VERSION := $(shell cat $(prev_version_file) 2>/dev/null)
VERSION_REGEXP = $(subst .,\.,$(VERSION))
PREV_VERSION_REGEXP = $(subst .,\.,$(PREV_VERSION))

ifeq ($(VC),$(GIT))
this-vc-tag = v$(VERSION)
this-vc-tag-regexp = v$(VERSION_REGEXP)
else
tag-package = $(shell echo "$(PACKAGE)" | tr '[:lower:]' '[:upper:]')
tag-this-version = $(subst .,_,$(VERSION))
this-vc-tag = $(tag-package)-$(tag-this-version)
this-vc-tag-regexp = $(this-vc-tag)
endif
my_distdir = $(PACKAGE)-$(VERSION)

# Old releases are stored here.
release_archive_dir ?= ../release

# Override gnu_rel_host and url_dir_list in cfg.mk if these are not right.
# Use alpha.gnu.org for alpha and beta releases.
# Use ftp.gnu.org for stable releases.
gnu_ftp_host-alpha = alpha.gnu.org
gnu_ftp_host-beta = alpha.gnu.org
gnu_ftp_host-stable = ftp.gnu.org
gnu_rel_host ?= $(gnu_ftp_host-$(RELEASE_TYPE))

ifeq ($(gnu_rel_host),ftp.gnu.org)
url_dir_list ?= http://ftpmirror.gnu.org/$(PACKAGE)
else
url_dir_list ?= ftp://$(gnu_rel_host)/gnu/$(PACKAGE)
endif

# Override this in cfg.mk if you are using a different format in your
# NEWS file.
today = $(shell date +%Y-%m-%d)

# Select which lines of NEWS are searched for $(news-check-regexp).
# This is a sed line number spec.  The default says that we search
# lines 1..10 of NEWS for $(news-check-regexp).
# If you want to search only line 3 or only lines 20-22, use "3" or "20,22".
news-check-lines-spec ?= 1,10
news-check-regexp ?= '^\*.* $(VERSION_REGEXP) \($(today)\)'

# 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

## --------------- ##
## Sanity checks.  ##
## --------------- ##

_cfg_mk := $(shell test -f $(srcdir)/cfg.mk && echo '$(srcdir)/cfg.mk')

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

ifeq ($(shell $(VC_LIST) >/dev/null 2>&1; echo $$?),0)
local-checks-available += $(syntax-check-rules)
else
local-checks-available += no-vc-detected
no-vc-detected:
	@echo "No version control files detected; skipping syntax check"
endif
.PHONY: $(local-checks-available)

# Arrange to print the name of each syntax-checking rule just before running it.
$(syntax-check-rules): %: %.m
sc_m_rules_ = $(patsubst %, %.m, $(syntax-check-rules))
.PHONY: $(sc_m_rules_)
$(sc_m_rules_):
	@echo $(patsubst sc_%.m, %, $@)
	@date +%s.%N > .sc-start-$(basename $@)

# Compute and print the elapsed time for each syntax-check rule.
sc_z_rules_ = $(patsubst %, %.z, $(syntax-check-rules))
.PHONY: $(sc_z_rules_)
$(sc_z_rules_): %.z: %
	@end=$$(date +%s.%N);						\
	start=$$(cat .sc-start-$*);					\
	rm -f .sc-start-$*;						\
	awk -v s=$$start -v e=$$end					\
	  'END {printf "%.2f $(patsubst sc_%,%,$*)\n", e - s}' < /dev/null

# The patsubst here is to replace each sc_% rule with its sc_%.z wrapper
# that computes and prints elapsed time.
local-check :=								\
  $(patsubst sc_%, sc_%.z,						\
    $(filter-out $(local-checks-to-skip), $(local-checks-available)))

syntax-check: $(local-check)

# _sc_search_regexp
#
# This macro searches for a given construct in the selected files and
# then takes some action.
#
# Parameters (shell variables):
#
#  prohibit | require
#
#     Regular expression (ERE) denoting either a forbidden construct
#     or a required construct.  Those arguments are exclusive.
#
#  exclude
#
#     Regular expression (ERE) denoting lines to ignore that matched
#     a prohibit construct.  For example, this can be used to exclude
#     comments that mention why the nearby code uses an alternative
#     construct instead of the simpler prohibited construct.
#
#  in_vc_files | in_files
#
#     grep-E-style regexp denoting the files to check.  If no files
#     are specified the default are all the files that are under
#     version control.
#
#  containing | non_containing
#
#     Select the files (non) containing strings matching this regexp.
#     If both arguments are specified then CONTAINING takes
#     precedence.
#
#  with_grep_options
#
#     Extra options for grep.
#
#  ignore_case
#
#     Ignore case.
#
#  halt
#
#     Message to display before to halting execution.
#
# Finally, you may exempt files based on an ERE matching file names.
# For example, to exempt from the sc_space_tab check all files with the
# .diff suffix, set this Make variable:
#
# exclude_file_name_regexp--sc_space_tab = \.diff$
#
# Note that while this functionality is mostly inherited via VC_LIST_EXCEPT,
# when filtering by name via in_files, we explicitly filter out matching
# names here as well.

# Initialize each, so that envvar settings cannot interfere.
export require =
export prohibit =
export exclude =
export in_vc_files =
export in_files =
export containing =
export non_containing =
export halt =
export with_grep_options =

# By default, _sc_search_regexp does not ignore case.
export ignore_case =
_ignore_case = $$(test -n "$$ignore_case" && printf %s -i || :)

define _sc_say_and_exit
   dummy=; : so we do not need a semicolon before each use;		\
   { printf '%s\n' "$(ME): $$msg" 1>&2; exit 1; };
endef

define _sc_search_regexp
   dummy=; : so we do not need a semicolon before each use;		\
									\
   : Check arguments;							\
   test -n "$$prohibit" && test -n "$$require"				\
     && { msg='Cannot specify both prohibit and require'		\
          $(_sc_say_and_exit) } || :;					\
   test -z "$$prohibit" && test -z "$$require"				\
     && { msg='Should specify either prohibit or require'		\
          $(_sc_say_and_exit) } || :;					\
   test -z "$$prohibit" && test -n "$$exclude"				\
     && { msg='Use of exclude requires a prohibit pattern'		\
          $(_sc_say_and_exit) } || :;					\
   test -n "$$in_vc_files" && test -n "$$in_files"			\
     && { msg='Cannot specify both in_vc_files and in_files'		\
          $(_sc_say_and_exit) } || :;					\
   test "x$$halt" != x							\
     || { msg='halt not defined' $(_sc_say_and_exit) };			\
									\
   : Filter by file name;						\
   if test -n "$$in_files"; then					\
     files=$$(find $(srcdir) | grep -E "$$in_files"			\
              | grep -Ev '$(exclude_file_name_regexp--$@)');		\
   else									\
     files=$$($(VC_LIST_EXCEPT));					\
     if test -n "$$in_vc_files"; then					\
       files=$$(echo "$$files" | grep -E "$$in_vc_files");		\
     fi;								\
   fi;									\
									\
   : Filter by content;							\
   test -n "$$files" && test -n "$$containing"				\
     && { files=$$(grep -l "$$containing" $$files); } || :;		\
   test -n "$$files" && test -n "$$non_containing"			\
     && { files=$$(grep -vl "$$non_containing" $$files); } || :;	\
									\
   : Check for the construct;						\
   if test -n "$$files"; then						\
     if test -n "$$prohibit"; then					\
       grep $$with_grep_options $(_ignore_case) -nE "$$prohibit" $$files \
         | grep -vE "$${exclude:-^$$}"					\
         && { msg="$$halt" $(_sc_say_and_exit) } || :;			\
     else								\
       grep $$with_grep_options $(_ignore_case) -LE "$$require" $$files \
           | grep .							\
         && { msg="$$halt" $(_sc_say_and_exit) } || :;			\
     fi									\
   else :;								\
   fi || :;
endef

sc_avoid_if_before_free:
	@$(srcdir)/$(_build-aux)/useless-if-before-free			\
		$(useless_free_options)					\
	    $$($(VC_LIST_EXCEPT) | grep -v useless-if-before-free) &&	\
	  { echo '$(ME): found useless "if" before "free" above' 1>&2;	\
	    exit 1; } || :

sc_cast_of_argument_to_free:
	@prohibit='\<free *\( *\(' halt="don't cast free argument"	\
	  $(_sc_search_regexp)

sc_cast_of_x_alloc_return_value:
	@prohibit='\*\) *x(m|c|re)alloc\>'				\
	halt="don't cast x*alloc return value"				\
	  $(_sc_search_regexp)

sc_cast_of_alloca_return_value:
	@prohibit='\*\) *alloca\>'					\
	halt="don't cast alloca return value"				\
	  $(_sc_search_regexp)

sc_space_tab:
	@prohibit='[ ]	'						\
	halt='found SPACE-TAB sequence; remove the SPACE'		\
	  $(_sc_search_regexp)

# 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:
	@prohibit='\<([fs]?scanf|ato([filq]|ll)) *\('				\
	halt='do not use *scan''f, ato''f, ato''i, ato''l, ato''ll or ato''q'	\
	  $(_sc_search_regexp)

# Use STREQ rather than comparing strcmp == 0, or != 0.
sp_ = strcmp *\(.+\)
sc_prohibit_strcmp:
	@prohibit='! *strcmp *\(|\<$(sp_) *[!=]=|[!=]= *$(sp_)'		\
	exclude=':# *define STRN?EQ\('					\
	halt='$(ME): replace strcmp calls above with STREQ/STRNEQ'	\
	  $(_sc_search_regexp)

# Pass EXIT_*, not number, to usage, exit, and error (when exiting)
# Convert all uses automatically, via these two commands:
# git grep -l '\<exit *(1)' \
#  | grep -vEf .x-sc_prohibit_magic_number_exit \
#  | xargs --no-run-if-empty \
#      perl -pi -e 's/(^|[^.])\b(exit ?)\(1\)/$1$2(EXIT_FAILURE)/'
# git grep -l '\<exit *(0)' \
#  | grep -vEf .x-sc_prohibit_magic_number_exit \
#  | xargs --no-run-if-empty \
#      perl -pi -e 's/(^|[^.])\b(exit ?)\(0\)/$1$2(EXIT_SUCCESS)/'
sc_prohibit_magic_number_exit:
	@prohibit='(^|[^.])\<(usage|exit) ?\([0-9]|\<error ?\([1-9][0-9]*,'	\
	halt='use EXIT_* values rather than magic number'			\
	  $(_sc_search_regexp)

# 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:
	@prohibit='error *\(EXIT_SUCCESS,'				\
	in_vc_files='\.[chly]$$'					\
	halt='found error (EXIT_SUCCESS'				\
	 $(_sc_search_regexp)

# "FATAL:" should be fully upper-cased in error messages
# "WARNING:" should be fully upper-cased, or fully lower-cased
sc_error_message_warn_fatal:
	@grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))		\
	    | grep -E '"Warning|"Fatal|"fatal' &&			\
	  { echo '$(ME): use FATAL, WARNING or warning'	1>&2;		\
	    exit 1; } || :

# Error messages should not start with a capital letter
sc_error_message_uppercase:
	@grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))		\
	    | grep -E '"[A-Z]'						\
	    | grep -vE '"FATAL|"WARNING|"Java|"C#|PRIuMAX' &&		\
	  { echo '$(ME): found capitalized error message' 1>&2;		\
	    exit 1; } || :

# Error messages should not end with a period
sc_error_message_period:
	@grep -nEA2 '[^rp]error *\(' $$($(VC_LIST_EXCEPT))		\
	    | grep -E '[^."]\."' &&					\
	  { echo '$(ME): found error message ending in period' 1>&2;	\
	    exit 1; } || :

sc_file_system:
	@prohibit=file''system						\
	ignore_case=1							\
	halt='found use of "file''system"; spell it "file system"'	\
	  $(_sc_search_regexp)

# Don't use cpp tests of this symbol.  All code assumes config.h is included.
sc_prohibit_have_config_h:
	@prohibit='^# *if.*HAVE''_CONFIG_H'				\
	halt='found use of HAVE''_CONFIG_H; remove'			\
	  $(_sc_search_regexp)

# Nearly all .c files must include <config.h>.  However, we also permit this
# via inclusion of a package-specific header, if cfg.mk specified one.
# config_h_header must be suitable for grep -E.
config_h_header ?= <config\.h>
sc_require_config_h:
	@require='^# *include $(config_h_header)'			\
	in_vc_files='\.c$$'						\
	halt='the above files do not include <config.h>'		\
	  $(_sc_search_regexp)

# You must include <config.h> before including any other header file.
# This can possibly be via a package-specific header, if given by cfg.mk.
sc_require_config_h_first:
	@if $(VC_LIST_EXCEPT) | grep -l '\.c$$' > /dev/null; then	\
	  fail=0;							\
	  for i in $$($(VC_LIST_EXCEPT) | grep '\.c$$'); do		\
	    grep '^# *include\>' $$i | sed 1q				\
		| grep -E '^# *include $(config_h_header)' > /dev/null	\
	      || { echo $$i; fail=1; };					\
	  done;								\
	  test $$fail = 1 &&						\
	    { echo '$(ME): the above files include some other header'	\
		'before <config.h>' 1>&2; exit 1; } || :;		\
	else :;								\
	fi

sc_prohibit_HAVE_MBRTOWC:
	@prohibit='\bHAVE_MBRTOWC\b'					\
	halt="do not use $$prohibit; it is always defined"		\
	  $(_sc_search_regexp)

# To use this "command" macro, you must first define two shell variables:
# h: the header name, with no enclosing <> or ""
# re: a regular expression that matches IFF something provided by $h is used.
define _sc_header_without_use
  dummy=; : so we do not need a semicolon before each use;		\
  h_esc=`echo '[<"]'"$$h"'[">]'|sed 's/\./\\\\./g'`;			\
  if $(VC_LIST_EXCEPT) | grep -l '\.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

# Prohibit the inclusion of assert.h without an actual use of assert.
sc_prohibit_assert_without_use:
	@h='assert.h' re='\<assert *\(' $(_sc_header_without_use)

# Prohibit the inclusion of close-stream.h without an actual use.
sc_prohibit_close_stream_without_use:
	@h='close-stream.h' re='\<close_stream *\(' $(_sc_header_without_use)

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

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

# Don't include quote.h unless you use one of its functions.
sc_prohibit_quote_without_use:
	@h='quote.h' re='\<quote((_n)? *\(|_quoting_options\>)' \
	  $(_sc_header_without_use)

# Don't include this header unless you use one of its functions.
sc_prohibit_long_options_without_use:
	@h='long-options.h' re='\<parse_long_options *\(' \
	  $(_sc_header_without_use)

# Don't include this header unless you use one of its functions.
sc_prohibit_inttostr_without_use:
	@h='inttostr.h' re='\<(off|[iu]max|uint)tostr *\(' \
	  $(_sc_header_without_use)

# Don't include this header unless you use one of its functions.
sc_prohibit_ignore_value_without_use:
	@h='ignore-value.h' re='\<ignore_(value|ptr) *\(' \
	  $(_sc_header_without_use)

# Don't include this header unless you use one of its functions.
sc_prohibit_error_without_use:
	@h='error.h' \
	re='\<error(_at_line|_print_progname|_one_per_line|_message_count)? *\('\
	  $(_sc_header_without_use)

# Don't include xalloc.h unless you use one of its functions.
# Consider these symbols:
# perl -lne '/^# *define (\w+)\(/ and print $1' lib/xalloc.h|grep -v '^__';
# perl -lne '/^(?:extern )?(?:void|char) \*?(\w+) *\(/ and print $1' lib/xalloc.h
# Divide into two sets on case, and filter each through this:
# | sort | perl -MRegexp::Assemble -le \
#  'print Regexp::Assemble->new(file => "/dev/stdin")->as_string'|sed 's/\?://g'
# Note this was produced by the above:
# _xa1 = \
#x(((2n?)?re|c(har)?|n(re|m)|z)alloc|alloc_(oversized|die)|m(alloc|emdup)|strdup)
# But we can do better, in at least two ways:
# 1) take advantage of two "dup"-suffixed strings:
# x(((2n?)?re|c(har)?|n(re|m)|[mz])alloc|alloc_(oversized|die)|(mem|str)dup)
# 2) notice that "c(har)?|[mz]" is equivalent to the shorter and more readable
# "char|[cmz]"
# x(((2n?)?re|char|n(re|m)|[cmz])alloc|alloc_(oversized|die)|(mem|str)dup)
_xa1 = x(((2n?)?re|char|n(re|m)|[cmz])alloc|alloc_(oversized|die)|(mem|str)dup)
_xa2 = X([CZ]|N?M)ALLOC
sc_prohibit_xalloc_without_use:
	@h='xalloc.h' \
	re='\<($(_xa1)|$(_xa2)) *\('\
	  $(_sc_header_without_use)

# Extract function names:
# perl -lne '/^(?:extern )?(?:void|char) \*?(\w+) *\(/ and print $1' lib/hash.h
_hash_re = \
clear|delete|free|get_(first|next)|insert|lookup|print_statistics|reset_tuning
_hash_fn = \<($(_hash_re)) *\(
_hash_struct = (struct )?\<[Hh]ash_(table|tuning)\>
sc_prohibit_hash_without_use:
	@h='hash.h' \
	re='$(_hash_fn)|$(_hash_struct)'\
	  $(_sc_header_without_use)

sc_prohibit_cloexec_without_use:
	@h='cloexec.h' re='\<(set_cloexec_flag|dup_cloexec) *\(' \
	  $(_sc_header_without_use)

sc_prohibit_posixver_without_use:
	@h='posixver.h' re='\<posix2_version *\(' $(_sc_header_without_use)

sc_prohibit_same_without_use:
	@h='same.h' re='\<same_name *\(' $(_sc_header_without_use)

sc_prohibit_hash_pjw_without_use:
	@h='hash-pjw.h' \
	re='\<hash_pjw\>' \
	  $(_sc_header_without_use)

sc_prohibit_safe_read_without_use:
	@h='safe-read.h' re='(\<SAFE_READ_ERROR\>|\<safe_read *\()' \
	  $(_sc_header_without_use)

sc_prohibit_argmatch_without_use:
	@h='argmatch.h' \
	re='(\<(ARRAY_CARDINALITY|X?ARGMATCH(|_TO_ARGUMENT|_VERIFY))\>|\<(invalid_arg|argmatch(_exit_fn|_(in)?valid)?) *\()' \
	  $(_sc_header_without_use)

sc_prohibit_canonicalize_without_use:
	@h='canonicalize.h' \
	re='CAN_(EXISTING|ALL_BUT_LAST|MISSING)|canonicalize_(mode_t|filename_mode|file_name)' \
	  $(_sc_header_without_use)

sc_prohibit_root_dev_ino_without_use:
	@h='root-dev-ino.h' \
	re='(\<ROOT_DEV_INO_(CHECK|WARN)\>|\<get_root_dev_ino *\()' \
	  $(_sc_header_without_use)

sc_prohibit_openat_without_use:
	@h='openat.h' \
	re='\<(openat_(permissive|needs_fchdir|(save|restore)_fail)|l?(stat|ch(own|mod))at|(euid)?accessat)\>' \
	  $(_sc_header_without_use)

# Prohibit the inclusion of c-ctype.h without an actual use.
ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
|isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper
sc_prohibit_c_ctype_without_use:
	@h='c-ctype.h' re='\<c_($(ctype_re)) *\(' \
	  $(_sc_header_without_use)

_empty =
_sp = $(_empty) $(_empty)
# The following list was generated by running:
# man signal.h|col -b|perl -ne '/bsd_signal.*;/.../sigwaitinfo.*;/ and print' \
#   | perl -lne '/^\s+(?:int|void).*?(\w+).*/ and print $1' | fmt
_sig_functions = \
  bsd_signal kill killpg pthread_kill pthread_sigmask raise sigaction \
  sigaddset sigaltstack sigdelset sigemptyset sigfillset sighold sigignore \
  siginterrupt sigismember signal sigpause sigpending sigprocmask sigqueue \
  sigrelse sigset sigsuspend sigtimedwait sigwait sigwaitinfo
_sig_function_re = $(subst $(_sp),|,$(strip $(_sig_functions)))
# The following were extracted from "man signal.h" manually.
_sig_types_and_consts =							\
  MINSIGSTKSZ SA_NOCLDSTOP SA_NOCLDWAIT SA_NODEFER SA_ONSTACK		\
  SA_RESETHAND SA_RESTART SA_SIGINFO SIGEV_NONE SIGEV_SIGNAL		\
  SIGEV_THREAD SIGSTKSZ SIG_BLOCK SIG_SETMASK SIG_UNBLOCK SS_DISABLE	\
  SS_ONSTACK mcontext_t pid_t sig_atomic_t sigevent siginfo_t sigset_t	\
  sigstack sigval stack_t ucontext_t
# generated via this:
# perl -lne '/^#ifdef (SIG\w+)/ and print $1' lib/sig2str.c|sort -u|fmt -70
_sig_names =								\
  SIGABRT SIGALRM SIGALRM1 SIGBUS SIGCANCEL SIGCHLD SIGCLD SIGCONT	\
  SIGDANGER SIGDIL SIGEMT SIGFPE SIGFREEZE SIGGRANT SIGHUP SIGILL	\
  SIGINFO SIGINT SIGIO SIGIOT SIGKAP SIGKILL SIGKILLTHR SIGLOST SIGLWP	\
  SIGMIGRATE SIGMSG SIGPHONE SIGPIPE SIGPOLL SIGPRE SIGPROF SIGPWR	\
  SIGQUIT SIGRETRACT SIGSAK SIGSEGV SIGSOUND SIGSTKFLT SIGSTOP SIGSYS	\
  SIGTERM SIGTHAW SIGTRAP SIGTSTP SIGTTIN SIGTTOU SIGURG SIGUSR1	\
  SIGUSR2 SIGVIRT SIGVTALRM SIGWAITING SIGWINCH SIGWIND SIGWINDOW	\
  SIGXCPU SIGXFSZ
_sig_syms_re = $(subst $(_sp),|,$(strip $(_sig_names) $(_sig_types_and_consts)))

# Prohibit the inclusion of signal.h without an actual use.
sc_prohibit_signal_without_use:
	@h='signal.h'							\
	re='\<($(_sig_function_re)) *\(|\<($(_sig_syms_re))\>'		\
	  $(_sc_header_without_use)

# Don't include stdio--.h unless you use one of its functions.
sc_prohibit_stdio--_without_use:
	@h='stdio--.h' re='\<((f(re)?|p)open|tmpfile) *\('		\
	  $(_sc_header_without_use)

# Don't include stdio-safer.h unless you use one of its functions.
sc_prohibit_stdio-safer_without_use:
	@h='stdio-safer.h' re='\<((f(re)?|p)open|tmpfile)_safer *\('	\
	  $(_sc_header_without_use)

# Prohibit the inclusion of strings.h without a sensible use.
# Using the likes of bcmp, bcopy, bzero, index or rindex is not sensible.
sc_prohibit_strings_without_use:
	@h='strings.h'							\
	re='\<(strn?casecmp|ffs(ll)?)\>'				\
	  $(_sc_header_without_use)

# Get the list of symbol names with this:
# perl -lne '/^# *define ([A-Z]\w+)\(/ and print $1' lib/intprops.h|fmt
_intprops_names =							\
  TYPE_IS_INTEGER TYPE_TWOS_COMPLEMENT TYPE_ONES_COMPLEMENT		\
  TYPE_SIGNED_MAGNITUDE TYPE_SIGNED TYPE_MINIMUM TYPE_MAXIMUM		\
  INT_BITS_STRLEN_BOUND INT_STRLEN_BOUND INT_BUFSIZE_BOUND		\
  INT_ADD_RANGE_OVERFLOW INT_SUBTRACT_RANGE_OVERFLOW			\
  INT_NEGATE_RANGE_OVERFLOW INT_MULTIPLY_RANGE_OVERFLOW			\
  INT_DIVIDE_RANGE_OVERFLOW INT_REMAINDER_RANGE_OVERFLOW		\
  INT_LEFT_SHIFT_RANGE_OVERFLOW INT_ADD_OVERFLOW INT_SUBTRACT_OVERFLOW	\
  INT_NEGATE_OVERFLOW INT_MULTIPLY_OVERFLOW INT_DIVIDE_OVERFLOW		\
  INT_REMAINDER_OVERFLOW INT_LEFT_SHIFT_OVERFLOW
_intprops_syms_re = $(subst $(_sp),|,$(strip $(_intprops_names)))
# Prohibit the inclusion of intprops.h without an actual use.
sc_prohibit_intprops_without_use:
	@h='intprops.h'							\
	re='\<($(_intprops_syms_re)) *\('				\
	  $(_sc_header_without_use)

_stddef_syms_re = NULL|offsetof|ptrdiff_t|size_t|wchar_t
# Prohibit the inclusion of stddef.h without an actual use.
sc_prohibit_stddef_without_use:
	@h='stddef.h'							\
	re='\<($(_stddef_syms_re))\>'					\
	  $(_sc_header_without_use)

_de1 = dirfd|(close|(fd)?open|read|rewind|seek|tell)dir(64)?(_r)?
_de2 = (versionsort|struct dirent|getdirentries|alphasort|scandir(at)?)(64)?
_de3 = MAXNAMLEN|DIR|ino_t|d_ino|d_fileno|d_namlen
_dirent_syms_re = $(_de1)|$(_de2)|$(_de3)
# Prohibit the inclusion of dirent.h without an actual use.
sc_prohibit_dirent_without_use:
	@h='dirent.h'							\
	re='\<($(_dirent_syms_re))\>'					\
	  $(_sc_header_without_use)

# Prohibit the inclusion of verify.h without an actual use.
sc_prohibit_verify_without_use:
	@h='verify.h'							\
	re='\<(verify(true|expr)?|static_assert) *\('			\
	  $(_sc_header_without_use)

# Don't include xfreopen.h unless you use one of its functions.
sc_prohibit_xfreopen_without_use:
	@h='xfreopen.h' re='\<xfreopen *\(' $(_sc_header_without_use)

sc_obsolete_symbols:
	@prohibit='\<(HAVE''_FCNTL_H|O''_NDELAY)\>'			\
	halt='do not use HAVE''_FCNTL_H or O'_NDELAY			\
	  $(_sc_search_regexp)

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

# Each nonempty ChangeLog line must start with a year number, or a TAB.
sc_changelog:
	@prohibit='^[^12	]'					\
	in_vc_files='^ChangeLog$$'					\
	halt='found unexpected prefix in a ChangeLog'			\
	  $(_sc_search_regexp)

# Ensure that each .c file containing a "main" function also
# calls set_program_name.
sc_program_name:
	@require='set_program_name *\(m?argv\[0\]\);'			\
	in_vc_files='\.c$$'						\
	containing='\<main *('						\
	halt='the above files do not call set_program_name'		\
	  $(_sc_search_regexp)

# Ensure that each .c file containing a "main" function also
# calls bindtextdomain.
sc_bindtextdomain:
	@require='bindtextdomain *\('					\
	in_vc_files='\.c$$'						\
	containing='\<main *('						\
	halt='the above files do not call bindtextdomain'		\
	  $(_sc_search_regexp)

# Require that the final line of each test-lib.sh-using test be this one:
# Exit $fail
# Note: this test requires GNU grep's --label= option.
Exit_witness_file ?= tests/test-lib.sh
Exit_base := $(notdir $(Exit_witness_file))
sc_require_test_exit_idiom:
	@if test -f $(srcdir)/$(Exit_witness_file); then		\
	  die=0;							\
	  for i in $$(grep -l -F 'srcdir/$(Exit_base)'			\
		$$($(VC_LIST) tests)); do				\
	    tail -n1 $$i | grep '^Exit .' > /dev/null			\
	      && : || { die=1; echo $$i; }				\
	  done;								\
	  test $$die = 1 &&						\
	    { echo 1>&2 '$(ME): the final line in each of the above is not:'; \
	      echo 1>&2 'Exit something';				\
	      exit 1; } || :;						\
	fi

sc_trailing_blank:
	@prohibit='[	 ]$$'						\
	halt='found trailing blank(s)'					\
	  $(_sc_search_regexp)

# 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:
	@prohibit='^   *(-[A-Za-z],)? $(longopt_re) [^ ].*\\$$'		\
	halt='help2man requires at least two spaces between an option and its description'\
	  $(_sc_search_regexp)

# A regexp matching function names like "error" that may be used
# to emit translatable messages.
_gl_translatable_diag_func_re ?= error

# 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.
sc_unmarked_diagnostics:
	@prohibit='\<$(_gl_translatable_diag_func_re) *\([^"]*"[^"]*[a-z]{3}' \
	exclude='(_|ngettext ?)\('					\
	halt='$(ME): found unmarked diagnostic(s)'			\
	  $(_sc_search_regexp)

# Avoid useless parentheses like those in this example:
# #if defined (SYMBOL) || defined (SYM2)
sc_useless_cpp_parens:
	@prohibit='^# *if .*defined *\('				\
	halt='found useless parentheses in cpp directive'		\
	  $(_sc_search_regexp)

# List headers for which HAVE_HEADER_H is always true, assuming you are
# using the appropriate gnulib module.  CAUTION: for each "unnecessary"
# #if HAVE_HEADER_H that you remove, be sure that your project explicitly
# requires the gnulib module that guarantees the usability of that header.
gl_assured_headers_ = \
  cd $(gnulib_dir)/lib && echo *.in.h|sed 's/\.in\.h//g'

# Convert the list of names to upper case, and replace each space with "|".
az_ = abcdefghijklmnopqrstuvwxyz
AZ_ = ABCDEFGHIJKLMNOPQRSTUVWXYZ
gl_header_upper_case_or_ =						\
  $$($(gl_assured_headers_)						\
    | tr $(az_)/.- $(AZ_)___						\
    | tr -s ' ' '|'							\
    )
sc_prohibit_always_true_header_tests:
	@or=$(gl_header_upper_case_or_);				\
	re="HAVE_($$or)_H";						\
	prohibit='\<'"$$re"'\>'						\
	halt=$$(printf '%s\n'						\
	'do not test the above HAVE_<header>_H symbol(s);'		\
	'  with the corresponding gnulib module, they are always true')	\
	  $(_sc_search_regexp)

# ==================================================================
gl_other_headers_ ?= \
  intprops.h	\
  openat.h	\
  stat-macros.h

# Perl -lne code to extract "significant" cpp-defined symbols from a
# gnulib header file, eliminating a few common false-positives.
# The exempted names below are defined only conditionally in gnulib,
# and hence sometimes must/may be defined in application code.
gl_extract_significant_defines_ = \
  /^\# *define ([^_ (][^ (]*)(\s*\(|\s+\w+)/\
    && $$2 !~ /(?:rpl_|_used_without_)/\
    && $$1 !~ /^(?:NSIG|ENODATA)$$/\
    && $$1 !~ /^(?:SA_RESETHAND|SA_RESTART)$$/\
    and print $$1

# Create a list of regular expressions matching the names
# of macros that are guaranteed to be defined by parts of gnulib.
define def_sym_regex
	gen_h=$(gl_generated_headers_);					\
	(cd $(gnulib_dir)/lib;						\
	  for f in *.in.h $(gl_other_headers_); do			\
	    test -f $$f							\
	      && perl -lne '$(gl_extract_significant_defines_)' $$f;	\
	  done;								\
	) | sort -u							\
	  | sed 's/^/^ *# *(define|undef)  */;s/$$/\\>/'
endef

# Don't define macros that we already get from gnulib header files.
sc_prohibit_always-defined_macros:
	@if test -d $(gnulib_dir); then					\
	  case $$(echo all: | grep -l -f - Makefile) in Makefile);; *)	\
	    echo '$(ME): skipping $@: you lack GNU grep' 1>&2; exit 0;;	\
	  esac;								\
	  $(def_sym_regex) | grep -E -f - $$($(VC_LIST_EXCEPT))		\
	    && { echo '$(ME): define the above via some gnulib .h file'	\
		  1>&2;  exit 1; } || :;				\
	fi
# ==================================================================

# Prohibit checked in backup files.
sc_prohibit_backup_files:
	@$(VC_LIST) | grep '~$$' &&				\
	  { echo '$(ME): found version controlled backup file' 1>&2;	\
	    exit 1; } || :

# Require the latest GPL.
sc_GPL_version:
	@prohibit='either ''version [^3]'				\
	halt='GPL vN, N!=3'						\
	  $(_sc_search_regexp)

# Require the latest GFDL.  Two regexp, since some .texi files end up
# line wrapping between 'Free Documentation License,' and 'Version'.
_GFDL_regexp = (Free ''Documentation.*Version 1\.[^3]|Version 1\.[^3] or any)
sc_GFDL_version:
	@prohibit='$(_GFDL_regexp)'					\
	halt='GFDL vN, N!=3'						\
	  $(_sc_search_regexp)

# Don't use Texinfo's @acronym{}.
# http://lists.gnu.org/archive/html/bug-gnulib/2010-03/msg00321.html
texinfo_suffix_re_ ?= \.(txi|texi(nfo)?)$$
sc_texinfo_acronym:
	@prohibit='@acronym\{'						\
	in_vc_files='$(texinfo_suffix_re_)'				\
	halt='found use of Texinfo @acronym{}'				\
	  $(_sc_search_regexp)

cvs_keywords = \
  Author|Date|Header|Id|Name|Locker|Log|RCSfile|Revision|Source|State

sc_prohibit_cvs_keyword:
	@prohibit='\$$($(cvs_keywords))\$$'				\
	halt='do not use CVS keyword expansion'				\
	  $(_sc_search_regexp)

# This Perl code is slightly obfuscated.  Not only is each "$" doubled
# because it's in a Makefile, but the $$c's are comments;  we cannot
# use "#" due to the way the script ends up concatenated onto one line.
# It would be much more concise, and would produce better output (including
# counts) if written as:
#   perl -ln -0777 -e '/\n(\n+)$/ and print "$ARGV: ".length $1' ...
# but that would be far less efficient, reading the entire contents
# of each file, rather than just the last two bytes of each.
# In addition, while the code below detects both blank lines and a missing
# newline at EOF, the above detects only the former.
#
# This is a perl script that is expected to be the single-quoted argument
# to a command-line "-le".  The remaining arguments are file names.
# Print the name of each file that does not end in exactly one newline byte.
# I.e., warn if there are blank lines (2 or more newlines), or if the
# last byte is not a newline.  However, currently we don't complain
# about any file that contains exactly one byte.
# Exit nonzero if at least one such file is found, otherwise, exit 0.
# Warn about, but otherwise ignore open failure.  Ignore seek/read failure.
#
# Use this if you want to remove trailing empty lines from selected files:
#   perl -pi -0777 -e 's/\n\n+$/\n/' files...
#
require_exactly_one_NL_at_EOF_ =					\
  foreach my $$f (@ARGV)						\
    {									\
      open F, "<", $$f or (warn "failed to open $$f: $$!\n"), next;	\
      my $$p = sysseek (F, -2, 2);					\
      my $$c = "seek failure probably means file has < 2 bytes; ignore"; \
      my $$last_two_bytes;						\
      defined $$p and $$p = sysread F, $$last_two_bytes, 2;		\
      close F;								\
      $$c = "ignore read failure";					\
      $$p && ($$last_two_bytes eq "\n\n"				\
              || substr ($$last_two_bytes,1) ne "\n")			\
          and (print $$f), $$fail=1;					\
    }									\
  END { exit defined $$fail }
sc_prohibit_empty_lines_at_EOF:
	@perl -le '$(require_exactly_one_NL_at_EOF_)' $$($(VC_LIST_EXCEPT)) \
	  || { echo '$(ME): empty line(s) or no newline at EOF'		\
		1>&2; exit 1; } || :

# Make sure we don't use st_blocks.  Use ST_NBLOCKS instead.
# This is a bit of a kludge, since it prevents use of the string
# even in comments, but for now it does the job with no false positives.
sc_prohibit_stat_st_blocks:
	@prohibit='[.>]st_blocks'					\
	halt='do not use st_blocks; use ST_NBLOCKS'			\
	  $(_sc_search_regexp)

# Make sure we don't define any S_IS* macros in src/*.c files.
# They're already defined via gnulib's sys/stat.h replacement.
sc_prohibit_S_IS_definition:
	@prohibit='^ *# *define  *S_IS'					\
	halt='do not define S_IS* macros; include <sys/stat.h>'		\
	  $(_sc_search_regexp)

# Perl block to convert a match to FILE_NAME:LINENO:TEST,
# that is shared by two definitions below.
perl_filename_lineno_text_ =						\
    -e '  {'								\
    -e '    $$n = ($$` =~ tr/\n/\n/ + 1);'				\
    -e '    ($$v = $$&) =~ s/\n/\\n/g;'					\
    -e '    print "$$ARGV:$$n:$$v\n";'					\
    -e '  }'

prohibit_doubled_word_RE_ ?= \
  /\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b/gims
prohibit_doubled_word_ =						\
    -e 'while ($(prohibit_doubled_word_RE_))'				\
    $(perl_filename_lineno_text_)

# Define this to a regular expression that matches
# any filename:dd:match lines you want to ignore.
# The default is to ignore no matches.
ignore_doubled_word_match_RE_ ?= ^$$

sc_prohibit_doubled_word:
	@perl -n -0777 $(prohibit_doubled_word_) $$($(VC_LIST_EXCEPT))	\
	  | grep -vE '$(ignore_doubled_word_match_RE_)'			\
	  | grep . && { echo '$(ME): doubled words' 1>&2; exit 1; } || :

# A regular expression matching undesirable combinations of words like
# "can not"; this matches them even when the two words appear on different
# lines, but not when there is an intervening delimiter like "#" or "*".
# Similarly undesirable, "See @xref{...}", since an @xref should start
# a sentence.  Explicitly prohibit any prefix of "see" or "also".
# Also prohibit a prefix matching "\w+ +".
# @pxref gets the same see/also treatment and should be parenthesized;
# presume it must *not* start a sentence.
bad_xref_re_ ?= (?:[\w,:;] +|(?:see|also)\s+)\@xref\{
bad_pxref_re_ ?= (?:[.!?]|(?:see|also))\s+\@pxref\{
prohibit_undesirable_word_seq_RE_ ?=					\
  /(?:\bcan\s+not\b|$(bad_xref_re_)|$(bad_pxref_re_))/gims
prohibit_undesirable_word_seq_ =					\
    -e 'while ($(prohibit_undesirable_word_seq_RE_))'			\
    $(perl_filename_lineno_text_)
# Define this to a regular expression that matches
# any filename:dd:match lines you want to ignore.
# The default is to ignore no matches.
ignore_undesirable_word_sequence_RE_ ?= ^$$

sc_prohibit_undesirable_word_seq:
	@perl -n -0777 $(prohibit_undesirable_word_seq_)		\
	     $$($(VC_LIST_EXCEPT))					\
	  | grep -vE '$(ignore_undesirable_word_sequence_RE_)' | grep .	\
	  && { echo '$(ME): undesirable word sequence' >&2; exit 1; } || :

_ptm1 = use "test C1 && test C2", not "test C1 -''a C2"
_ptm2 = use "test C1 || test C2", not "test C1 -''o C2"
# Using test's -a and -o operators is not portable.
# We prefer test over [, since the latter is spelled [[ in configure.ac.
sc_prohibit_test_minus_ao:
	@prohibit='(\<test| \[+) .+ -[ao] '				\
	halt='$(_ptm1); $(_ptm2)'					\
	  $(_sc_search_regexp)

# Avoid a test bashism.
sc_prohibit_test_double_equal:
	@prohibit='(\<test| \[+) .+ == '				\
	containing='#! */bin/[a-z]*sh'					\
	halt='use "test x = x", not "test x =''= x"'			\
	  $(_sc_search_regexp)

# Each program that uses proper_name_utf8 must link with one of the
# ICONV libraries.  Otherwise, some ICONV library must appear in LDADD.
# The perl -0777 invocation below extracts the possibly-multi-line
# definition of LDADD from the appropriate Makefile.am and exits 0
# when it contains "ICONV".
sc_proper_name_utf8_requires_ICONV:
	@progs=$$(grep -l 'proper_name_utf8 ''("' $$($(VC_LIST_EXCEPT)));\
	if test "x$$progs" != x; then					\
	  fail=0;							\
	  for p in $$progs; do						\
	    dir=$$(dirname "$$p");					\
	    perl -0777							\
	      -ne 'exit !(/^LDADD =(.+?[^\\]\n)/ms && $$1 =~ /ICONV/)'	\
	      $$dir/Makefile.am && continue;				\
	    base=$$(basename "$$p" .c);					\
	    grep "$${base}_LDADD.*ICONV)" $$dir/Makefile.am > /dev/null	\
	      || { fail=1; echo 1>&2 "$(ME): $$p uses proper_name_utf8"; }; \
	  done;								\
	  test $$fail = 1 &&						\
	    { echo 1>&2 '$(ME): the above do not link with any ICONV library'; \
	      exit 1; } || :;						\
	fi

# Warn about "c0nst struct Foo const foo[]",
# but not about "char const *const foo" or "#define const const".
sc_redundant_const:
	@prohibit='\bconst\b[[:space:][:alnum:]]{2,}\bconst\b'		\
	halt='redundant "const" in declarations'			\
	  $(_sc_search_regexp)

sc_const_long_option:
	@prohibit='^ *static.*struct option '				\
	exclude='const struct option|struct option const'		\
	halt='$(ME): add "const" to the above declarations'		\
	  $(_sc_search_regexp)

NEWS_hash =								\
  $$(sed -n '/^\*.* $(PREV_VERSION_REGEXP) ([0-9-]*)/,$$p'		\
       $(srcdir)/NEWS							\
     | perl -0777 -pe							\
	's/^Copyright.+?Free\sSoftware\sFoundation,\sInc\.\n//ms'	\
     | md5sum -								\
     | sed 's/ .*//')

# Ensure that we don't accidentally insert an entry into an old NEWS block.
sc_immutable_NEWS:
	@if test -f $(srcdir)/NEWS; then				\
	  test "$(NEWS_hash)" = '$(old_NEWS_hash)' && : ||		\
	    { echo '$(ME): you have modified old NEWS' 1>&2; exit 1; };	\
	fi

# Update the hash stored above.  Do this after each release and
# for any corrections to old entries.
update-NEWS-hash: NEWS
	perl -pi -e 's/^(old_NEWS_hash[ \t]+:?=[ \t]+).*/$${1}'"$(NEWS_hash)/" \
	  $(srcdir)/cfg.mk

# 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.
# However, there is still one case in which @VAR@ use is not just
# legitimate, but actually required: when augmenting an automake-defined
# variable with a prefix.  For example, gettext uses this:
# MAKEINFO = env LANG= LC_MESSAGES= LC_ALL= LANGUAGE= @MAKEINFO@
# otherwise, makeinfo would put German or French (current locale)
# navigation hints in the otherwise-English documentation.
#
# Allow the package to add exceptions via a hook in cfg.mk;
# for example, @PRAGMA_SYSTEM_HEADER@ can be permitted by
# setting this to ' && !/PRAGMA_SYSTEM_HEADER/'.
_makefile_at_at_check_exceptions ?=
sc_makefile_at_at_check:
	@perl -ne '/\@\w+\@/'						\
          -e ' && !/(\w+)\s+=.*\@\1\@$$/'				\
          -e ''$(_makefile_at_at_check_exceptions)			\
	  -e 'and (print "$$ARGV:$$.: $$_"), $$m=1; END {exit !$$m}'	\
	    $$($(VC_LIST_EXCEPT) | grep -E '(^|/)(Makefile\.am|[^/]+\.mk)$$') \
	  && { echo '$(ME): use $$(...), not @...@' 1>&2; exit 1; } || :

news-check: NEWS
	if sed -n $(news-check-lines-spec)p $(srcdir)/NEWS		\
	    | grep -E $(news-check-regexp) >/dev/null; then		\
	  :;								\
	else								\
	  echo 'NEWS: $$(news-check-regexp) failed to match' 1>&2;	\
	  exit 1;							\
	fi

sc_makefile_TAB_only_indentation:
	@prohibit='^	[ ]{8}'						\
	in_vc_files='akefile|\.mk$$'					\
	halt='found TAB-8-space indentation'				\
	  $(_sc_search_regexp)

sc_m4_quote_check:
	@prohibit='(AC_DEFINE(_UNQUOTED)?|AC_DEFUN)\([^[]'		\
	in_vc_files='(^configure\.ac|\.m4)$$'				\
	halt='quote the first arg to AC_DEF*'				\
	  $(_sc_search_regexp)

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

# Verify that all source files using _() are listed in po/POTFILES.in.
po_file ?= $(srcdir)/po/POTFILES.in
generated_files ?= $(srcdir)/lib/*.[ch]
sc_po_check:
	@if test -f $(po_file); then					\
	  grep -E -v '^(#|$$)' $(po_file)				\
	    | grep -v '^src/false\.c$$' | sort > $@-1;			\
	  files=;							\
	  for file in $$($(VC_LIST_EXCEPT)) $(generated_files); do	\
	    test -r $$file || continue;					\
	    case $$file in						\
	      *.m4|*.mk) continue ;;					\
	      *.?|*.??) ;;						\
	      *) continue;;						\
	    esac;							\
	    case $$file in						\
	    *.[ch])							\
	      base=`expr " $$file" : ' \(.*\)\..'`;			\
	      { test -f $$base.l || test -f $$base.y; } && continue;;	\
	    esac;							\
	    files="$$files $$file";					\
	  done;								\
	  grep -E -l '\b(N?_|gettext *)\([^)"]*("|$$)' $$files		\
	    | sed 's|^$(_dot_escaped_srcdir)/||' | sort -u > $@-2;	\
	  diff -u -L $(po_file) -L $(po_file) $@-1 $@-2			\
	    || { printf '$(ME): '$(fix_po_file_diag) 1>&2; exit 1; };	\
	  rm -f $@-1 $@-2;						\
	fi

# 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)'.
msg = '$(ME): Do not use ":" above; use $$(PATH_SEPARATOR) instead'
sc_makefile_path_separator_check:
	@prohibit='PATH[=].*:'						\
	in_vc_files='akefile|\.mk$$'					\
	halt=$(msg)							\
	  $(_sc_search_regexp)

# Check that 'make alpha' will not fail at the end of the process,
# i.e., when pkg-M.N.tar.xz already exists (either in "." or in ../release)
# and is read-only.
writable-files:
	if test -d $(release_archive_dir); then				\
	  for file in $(DIST_ARCHIVES); do				\
	    for p in ./ $(release_archive_dir)/; do			\
	      test -e $$p$$file || continue;				\
	      test -w $$p$$file						\
		|| { echo ERROR: $$p$$file is not writable; fail=1; };	\
	    done;							\
	  done;								\
	  test "$$fail" && exit 1 || : ;				\
	else :;								\
	fi

v_etc_file = $(gnulib_dir)/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.
sc_copyright_check:
	@require='enum { COPYRIGHT_YEAR = '$$(date +%Y)' };'		\
	in_files=$(v_etc_file)						\
	halt='out of date copyright in $(v_etc_file); update it'	\
	  $(_sc_search_regexp)
	@require='# Copyright \(C\) '$$(date +%Y)' Free'		\
	in_vc_files=$(sample-test)					\
	halt='out of date copyright in $(sample-test); update it'	\
	  $(_sc_search_regexp)
	@require='Copyright @copyright\{\} .*'$$(date +%Y)' Free'	\
	in_vc_files=$(texi)						\
	halt='out of date copyright in $(texi); update it'		\
	  $(_sc_search_regexp)

# If tests/help-version exists and seems to be new enough, assume that its
# use of init.sh and path_prepend_ is correct, and ensure that every other
# use of init.sh is identical.
# This is useful because help-version cross-checks prog --version
# with $(VERSION), which verifies that its path_prepend_ invocation
# sets PATH correctly.  This is an inexpensive way to ensure that
# the other init.sh-using tests also get it right.
_hv_file ?= $(srcdir)/tests/help-version
_hv_regex_weak ?= ^ *\. .*/init\.sh"
# Fix syntax-highlighters "
_hv_regex_strong ?= ^ *\. "\$${srcdir=\.}/init\.sh"
sc_cross_check_PATH_usage_in_tests:
	@if test -f $(_hv_file); then					\
	  grep -l 'VERSION mismatch' $(_hv_file) >/dev/null		\
	    || { echo "$@: skipped: no such file: $(_hv_file)" 1>&2;	\
		 exit 0; };						\
	  grep -lE '$(_hv_regex_strong)' $(_hv_file) >/dev/null		\
	    || { echo "$@: $(_hv_file) lacks conforming use of init.sh" 1>&2; \
		 exit 1; };						\
	  good=$$(grep -E '$(_hv_regex_strong)' $(_hv_file));		\
	  grep -LFx "$$good"						\
		$$(grep -lE '$(_hv_regex_weak)' $$($(VC_LIST_EXCEPT)))	\
	      | grep . &&						\
	    { echo "$(ME): the above files use path_prepend_ inconsistently" \
		1>&2; exit 1; } || :;					\
	fi

# BRE regex of file contents to identify a test script.
_test_script_regex ?= \<init\.sh\>

# In tests, use "compare expected actual", not the reverse.
sc_prohibit_reversed_compare_failure:
	@prohibit='\<compare [^ ]+ ([^ ]*exp|/dev/null)'		\
	containing='$(_test_script_regex)'				\
	halt='reversed compare arguments'				\
	  $(_sc_search_regexp)

# #if HAVE_... will evaluate to false for any non numeric string.
# That would be flagged by using -Wundef, however gnulib currently
# tests many undefined macros, and so we can't enable that option.
# So at least preclude common boolean strings as macro values.
sc_Wundef_boolean:
	@prohibit='^#define.*(yes|no|true|false)$$'			\
	in_files='$(CONFIG_INCLUDE)'					\
	halt='Use 0 or 1 for macro values'				\
	  $(_sc_search_regexp)

# Even if you use pathmax.h to guarantee that PATH_MAX is defined, it might
# not be constant, or might overflow a stack.  In general, use PATH_MAX as
# a limit, not an array or alloca size.
sc_prohibit_path_max_allocation:
	@prohibit='(\balloca *\([^)]*|\[[^]]*)PATH_MAX'			\
	halt='Avoid stack allocations of size PATH_MAX'			\
	  $(_sc_search_regexp)

sc_vulnerable_makefile_CVE-2009-4029:
	@prohibit='perm -777 -exec chmod a\+rwx|chmod 777 \$$\(distdir\)' \
	in_files=$$(find $(srcdir) -name Makefile.in)			\
	halt=$$(printf '%s\n'						\
	  'the above files are vulnerable; beware of running'		\
	  '  "make dist*" rules, and upgrade to fixed automake'		\
	  '  see http://bugzilla.redhat.com/542609 for details')	\
	  $(_sc_search_regexp)

vc-diff-check:
	(unset CDPATH; cd $(srcdir) && $(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

rel-files = $(DIST_ARCHIVES)

gnulib_dir ?= $(srcdir)/gnulib
gnulib-version = $$(cd $(gnulib_dir) && git describe)
bootstrap-tools ?= autoconf,automake,gnulib

# If it's not already specified, derive the GPG key ID from
# the signed tag we've just applied to mark this release.
gpg_key_ID ?= \
  $$(git cat-file tag v$(VERSION) \
     | gpgv --status-fd 1 --keyring /dev/null - - 2>/dev/null \
     | sed -n '/^\[GNUPG:\] ERRSIG /{s///;s/ .*//p;q}')

translation_project_ ?= coordinator@translationproject.org

# Make info-gnu the default only for a stable release.
ifeq ($(RELEASE_TYPE),stable)
  announcement_Cc_ ?= $(translation_project_), $(PACKAGE_BUGREPORT)
  announcement_mail_headers_ ?=						\
    To: info-gnu@gnu.org						\
    Cc: $(announcement_Cc_)						\
    Mail-Followup-To: $(PACKAGE_BUGREPORT)
else
  announcement_Cc_ ?= $(translation_project_)
  announcement_mail_headers_ ?=						\
    To: $(PACKAGE_BUGREPORT)						\
    Cc: $(announcement_Cc_)
endif

announcement: NEWS ChangeLog $(rel-files)
	@$(srcdir)/$(_build-aux)/announce-gen				\
	    --mail-headers='$(announcement_mail_headers_)'		\
	    --release-type=$(RELEASE_TYPE)				\
	    --package=$(PACKAGE)					\
	    --prev=$(PREV_VERSION)					\
	    --curr=$(VERSION)						\
	    --gpg-key-id=$(gpg_key_ID)					\
	    --news=$(srcdir)/NEWS					\
	    --bootstrap-tools=$(bootstrap-tools)			\
	    $$(case ,$(bootstrap-tools), in (*,gnulib,*)		\
	       echo --gnulib-version=$(gnulib-version);; esac)		\
	    --no-print-checksums					\
	    $(addprefix --url-dir=, $(url_dir_list))

## ---------------- ##
## Updating files.  ##
## ---------------- ##

ftp-gnu = ftp://ftp.gnu.org/gnu
www-gnu = http://www.gnu.org

upload_dest_dir_ ?= $(PACKAGE)
emit_upload_commands:
	@echo =====================================
	@echo =====================================
	@echo "$(srcdir)/$(_build-aux)/gnupload $(GNUPLOADFLAGS) \\"
	@echo "    --to $(gnu_rel_host):$(upload_dest_dir_) \\"
	@echo "  $(rel-files)"
	@echo '# send the ~/announce-$(my_distdir) e-mail'
	@echo =====================================
	@echo =====================================

define emit-commit-log
  printf '%s\n' 'maint: post-release administrivia' ''			\
    '* NEWS: Add header line for next release.'				\
    '* .prev-version: Record previous version.'				\
    '* cfg.mk (old_NEWS_hash): Auto-update.'
endef

.PHONY: no-submodule-changes
no-submodule-changes:
	if test -d $(srcdir)/.git; then					\
	  diff=$$(cd $(srcdir) && git submodule -q foreach		\
		  git diff-index --name-only HEAD)			\
	    || exit 1;							\
	  case $$diff in '') ;;						\
	    *) echo '$(ME): submodule files are locally modified:';	\
		echo "$$diff"; exit 1;; esac;				\
	else								\
	  : ;								\
	fi

submodule-checks ?= no-submodule-changes public-submodule-commit

# Ensure that each sub-module commit we're using is public.
# Without this, it is too easy to tag and release code that
# cannot be built from a fresh clone.
.PHONY: public-submodule-commit
public-submodule-commit:
	$(AM_V_GEN)if test -d $(srcdir)/.git; then			\
	  cd $(srcdir) &&						\
	  git submodule --quiet foreach test '$$(git rev-parse $$sha1)'	\
	      = '$$(git merge-base origin $$sha1)'			\
	    || { echo '$(ME): found non-public submodule commit' >&2;	\
		 exit 1; };						\
	else								\
	  : ;								\
	fi
# This rule has a high enough utility/cost ratio that it should be a
# dependent of "check" by default.  However, some of us do occasionally
# commit a temporary change that deliberately points to a non-public
# submodule commit, and want to be able to use rules like "make check".
# In that case, run e.g., "make check gl_public_submodule_commit="
# to disable this test.
gl_public_submodule_commit ?= public-submodule-commit
check: $(gl_public_submodule_commit)

.PHONY: alpha beta stable
ALL_RECURSIVE_TARGETS += alpha beta stable
alpha beta stable: $(local-check) writable-files $(submodule-checks)
	test $@ = stable						\
	  && { echo $(VERSION) | grep -E '^[0-9]+(\.[0-9]+)+$$'		\
	       || { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\
	  || :
	$(MAKE) vc-diff-check
	$(MAKE) news-check
	$(MAKE) distcheck
	$(MAKE) dist
	$(MAKE) $(release-prep-hook) RELEASE_TYPE=$@
	$(MAKE) -s emit_upload_commands RELEASE_TYPE=$@

# Override this in cfg.mk if you follow different procedures.
release-prep-hook ?= release-prep

gl_noteworthy_news_ = * Noteworthy changes in release ?.? (????-??-??) [?]
.PHONY: release-prep
release-prep:
	case $$RELEASE_TYPE in alpha|beta|stable) ;; \
	  *) echo "invalid RELEASE_TYPE: $$RELEASE_TYPE" 1>&2; exit 1;; esac
	$(MAKE) --no-print-directory -s announcement > ~/announce-$(my_distdir)
	if test -d $(release_archive_dir); then			\
	  ln $(rel-files) $(release_archive_dir);		\
	  chmod a-w $(rel-files);				\
	fi
	echo $(VERSION) > $(prev_version_file)
	$(MAKE) update-NEWS-hash
	perl -pi -e '$$. == 3 and print "$(gl_noteworthy_news_)\n\n\n"' NEWS
	$(emit-commit-log) > .ci-msg
	$(VC) commit -F .ci-msg -a
	rm .ci-msg

# Override this with e.g., -s $(srcdir)/some_other_name.texi
# if the default $(PACKAGE)-derived name doesn't apply.
gendocs_options_ ?=

.PHONY: web-manual
web-manual:
	@test -z "$(manual_title)" \
	  && { echo define manual_title in cfg.mk 1>&2; exit 1; } || :
	@cd '$(srcdir)/doc'; \
	  $(SHELL) ../$(_build-aux)/gendocs.sh $(gendocs_options_) \
	     -o '$(abs_builddir)/doc/manual' \
	     --email $(PACKAGE_BUGREPORT) $(PACKAGE) \
	    "$(PACKAGE_NAME) - $(manual_title)"
	@echo " *** Upload the doc/manual directory to web-cvs."

# Code Coverage

init-coverage:
	$(MAKE) $(AM_MAKEFLAGS) clean
	lcov --directory . --zerocounters

COVERAGE_CCOPTS ?= "-g --coverage"
COVERAGE_OUT ?= doc/coverage

build-coverage:
	$(MAKE) $(AM_MAKEFLAGS) CFLAGS=$(COVERAGE_CCOPTS) CXXFLAGS=$(COVERAGE_CCOPTS)
	$(MAKE) $(AM_MAKEFLAGS) CFLAGS=$(COVERAGE_CCOPTS) CXXFLAGS=$(COVERAGE_CCOPTS) check
	mkdir -p $(COVERAGE_OUT)
	lcov --directory . --output-file $(COVERAGE_OUT)/$(PACKAGE).info \
		--capture

gen-coverage:
	genhtml --output-directory $(COVERAGE_OUT) \
		$(COVERAGE_OUT)/$(PACKAGE).info \
		--highlight --frames --legend \
		--title "$(PACKAGE_NAME)"

coverage: init-coverage build-coverage gen-coverage

# Update gettext files.
PACKAGE ?= $(shell basename $(PWD))
PO_DOMAIN ?= $(PACKAGE)
POURL = http://translationproject.org/latest/$(PO_DOMAIN)/
PODIR ?= po
refresh-po:
	rm -f $(PODIR)/*.po && \
	echo "$(ME): getting translations into po (please ignore the robots.txt ERROR 404)..." && \
	wget --no-verbose --directory-prefix $(PODIR) --no-directories --recursive --level 1 --accept .po --accept .po.1 $(POURL) && \
	echo 'en@boldquot' > $(PODIR)/LINGUAS && \
	echo 'en@quot' >> $(PODIR)/LINGUAS && \
	ls $(PODIR)/*.po | sed 's/\.po//' | sed 's,$(PODIR)/,,' | sort >> $(PODIR)/LINGUAS

 # Running indent once is not idempotent, but running it twice is.
INDENT_SOURCES ?= $(C_SOURCES)
.PHONY: indent
indent:
	indent $(INDENT_SOURCES)
	indent $(INDENT_SOURCES)

# If you want to set UPDATE_COPYRIGHT_* environment variables,
# put the assignments in this variable.
update-copyright-env ?=

# Run this rule once per year (usually early in January)
# to update all FSF copyright year lists in your project.
# If you have an additional project-specific rule,
# add it in cfg.mk along with a line 'update-copyright: prereq'.
# By default, exclude all variants of COPYING; you can also
# add exemptions (such as ChangeLog..* for rotated change logs)
# in the file .x-update-copyright.
.PHONY: update-copyright
update-copyright:
	grep -l -w Copyright                                             \
	  $$(export VC_LIST_EXCEPT_DEFAULT=COPYING && $(VC_LIST_EXCEPT)) \
	  | $(update-copyright-env) xargs $(srcdir)/$(_build-aux)/$@

# This tight_scope test is skipped with a warning if $(_gl_TS_headers) is not
# overridden and $(_gl_TS_dir)/Makefile.am does not mention noinst_HEADERS.

# NOTE: to override any _gl_TS_* default value, you must
# define the variable(s) using "export" in cfg.mk.
_gl_TS_dir ?= src

ALL_RECURSIVE_TARGETS += sc_tight_scope
sc_tight_scope: tight-scope.mk
	@fail=0;							\
	if ! grep '^ *export _gl_TS_headers *=' $(srcdir)/cfg.mk	\
		> /dev/null						\
	   && ! grep -w noinst_HEADERS $(srcdir)/$(_gl_TS_dir)/Makefile.am \
		> /dev/null 2>&1; then					\
	    echo '$(ME): skipping $@';					\
	else								\
	    $(MAKE) -s -C $(_gl_TS_dir)					\
		-f Makefile						\
		-f $(abs_top_srcdir)/cfg.mk				\
		-f $(abs_top_builddir)/$<				\
	      _gl_tight_scope						\
		|| fail=1;						\
	fi;								\
	rm -f $<;							\
	exit $$fail

tight-scope.mk: $(ME)
	@rm -f $@ $@-t
	@perl -ne '/^# TS-start/.../^# TS-end/ and print' $(srcdir)/$(ME) > $@-t
	@chmod a=r $@-t && mv $@-t $@

ifeq (a,b)
# TS-start

# Most functions should have static scope.
# Any that don't must be marked with 'extern', but 'main'
# and 'usage' are exceptions: they're always extern, but
# do not need to be marked.  Symbols matching '__.*' are
# reserved by the compiler, so are automatically excluded below.
_gl_TS_unmarked_extern_functions ?= main usage
_gl_TS_function_match ?= /^(?:$(_gl_TS_extern)) +.*?(\S+) *\(/

# If your project uses a macro like "XTERN", then put
# the following in cfg.mk to override this default:
# export _gl_TS_extern = extern|XTERN
_gl_TS_extern ?= extern

# The second nm|grep checks for file-scope variables with 'extern' scope.
# Without gnulib's progname module, you might put program_name here.
# Symbols matching '__.*' are reserved by the compiler,
# so are automatically excluded below.
_gl_TS_unmarked_extern_vars ?=

# NOTE: the _match variables are perl expressions -- not mere regular
# expressions -- so that you can extend them to match other patterns
# and easily extract matched variable names.
# For example, if your project declares some global variables via
# a macro like this: GLOBAL(type, var_name, initializer), then you
# can override this definition to automatically extract those names:
# export _gl_TS_var_match = \
#   /^(?:$(_gl_TS_extern)) .*?\**(\w+)(\[.*?\])?;/ || /\bGLOBAL\(.*?,\s*(.*?),/
_gl_TS_var_match ?= /^(?:$(_gl_TS_extern)) .*?(\w+)(\[.*?\])?;/

# The names of object files in (or relative to) $(_gl_TS_dir).
_gl_TS_obj_files ?= *.$(OBJEXT)

# Files in which to search for the one-line style extern declarations.
# $(_gl_TS_dir)-relative.
_gl_TS_headers ?= $(noinst_HEADERS)

.PHONY: _gl_tight_scope
_gl_tight_scope: $(bin_PROGRAMS)
	t=exceptions-$$$$;						\
	trap 's=$$?; rm -f $$t; exit $$s' 0;				\
	for sig in 1 2 3 13 15; do					\
	  eval "trap 'v=`expr $$sig + 128`; (exit $$v); exit $$v' $$sig"; \
	done;								\
	src=`for f in $(SOURCES); do					\
	       test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`;	\
	hdr=`for f in $(_gl_TS_headers); do				\
	       test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`;	\
	( printf '^%s$$\n' '__.*' $(_gl_TS_unmarked_extern_functions);	\
	  grep -h -A1 '^extern .*[^;]$$' $$src				\
	    | grep -vE '^(extern |--)' | sed 's/ .*//';			\
	  perl -lne							\
	     '$(_gl_TS_function_match) and print "^$$1\$$"' $$hdr;	\
	) | sort -u > $$t;						\
	nm -e $(_gl_TS_obj_files) | sed -n 's/.* T //p'|grep -Ev -f $$t	\
	  && { echo the above functions should have static scope >&2;	\
	       exit 1; } || : ;						\
	( printf '^%s$$\n' '__.*' $(_gl_TS_unmarked_extern_vars);	\
	  perl -lne '$(_gl_TS_var_match) and print "^$$1\$$"' $$hdr *.h	\
	) | sort -u > $$t;						\
	nm -e $(_gl_TS_obj_files) | sed -n 's/.* [BCDGRS] //p'		\
            | sort -u | grep -Ev -f $$t					\
	  && { echo the above variables should have static scope >&2;	\
	       exit 1; } || :
# TS-end
endif