xref: /netbsd-src/lib/libc/time/checktab.awk (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1#	$NetBSD: checktab.awk,v 1.4 2009/12/31 22:49:16 mlelstv Exp $
2
3# Check tz tables for consistency.
4
5# @(#)checktab.awk	8.1
6
7# Contributed by Paul Eggert.
8
9BEGIN {
10	FS = "\t"
11
12	if (!iso_table) iso_table = "iso3166.tab"
13	if (!zone_table) zone_table = "zone.tab"
14	if (!want_warnings) want_warnings = -1
15
16	while (getline <iso_table) {
17		iso_NR++
18		if ($0 ~ /^#/) continue
19		if (NF != 2) {
20			printf "%s:%d: wrong number of columns\n", \
21				iso_table, iso_NR >>"/dev/stderr"
22			status = 1
23		}
24		cc = $1
25		name = $2
26		if (cc !~ /^[A-Z][A-Z]$/) {
27			printf "%s:%d: invalid country code `%s'\n", \
28				iso_table, iso_NR, cc >>"/dev/stderr"
29			status = 1
30		}
31		if (cc <= cc0) {
32			if (cc == cc0) {
33				s = "duplicate";
34			} else {
35				s = "out of order";
36			}
37
38			printf "%s:%d: country code `%s' is %s\n", \
39				iso_table, iso_NR, cc, s \
40				>>"/dev/stderr"
41			status = 1
42		}
43		cc0 = cc
44		if (name2cc[name]) {
45			printf "%s:%d: `%s' and `%s' have the sname name\n", \
46				iso_table, iso_NR, name2cc[name], cc \
47				>>"/dev/stderr"
48			status = 1
49		}
50		name2cc[name] = cc
51		cc2name[cc] = name
52		cc2NR[cc] = iso_NR
53	}
54
55	zone_table = "zone.tab"
56	cc0 = ""
57
58	while (getline <zone_table) {
59		zone_NR++
60		if ($0 ~ /^#/) continue
61		if (NF != 3 && NF != 4) {
62			printf "%s:%d: wrong number of columns\n", \
63				zone_table, zone_NR >>"/dev/stderr"
64			status = 1
65		}
66		cc = $1
67		coordinates = $2
68		tz = $3
69		comments = $4
70		if (cc < cc0) {
71			printf "%s:%d: country code `%s' is out of order\n", \
72				zone_table, zone_NR, cc >>"/dev/stderr"
73			status = 1
74		}
75		cc0 = cc
76		if (tz2cc[tz]) {
77			printf "%s:%d: %s: duplicate TZ column\n", \
78				zone_table, zone_NR, tz >>"/dev/stderr"
79			status = 1
80		}
81		tz2cc[tz] = cc
82		tz2comments[tz] = comments
83		tz2NR[tz] = zone_NR
84		if (cc2name[cc]) {
85			cc_used[cc]++
86		} else {
87			printf "%s:%d: %s: unknown country code\n", \
88				zone_table, zone_NR, cc >>"/dev/stderr"
89			status = 1
90		}
91		if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
92		    && coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) {
93			printf "%s:%d: %s: invalid coordinates\n", \
94				zone_table, zone_NR, coordinates >>"/dev/stderr"
95			status = 1
96		}
97	}
98
99	for (tz in tz2cc) {
100		if (cc_used[tz2cc[tz]] == 1) {
101			if (tz2comments[tz]) {
102				printf "%s:%d: unnecessary comment `%s'\n", \
103					zone_table, tz2NR[tz], tz2comments[tz] \
104					>>"/dev/stderr"
105				status = 1
106			}
107		} else {
108			if (!tz2comments[tz]) {
109				printf "%s:%d: missing comment\n", \
110					zone_table, tz2NR[tz] >>"/dev/stderr"
111				status = 1
112			}
113		}
114	}
115
116	FS = " "
117}
118
119{
120	tz = ""
121	if ($1 == "Zone") tz = $2
122	if ($1 == "Link") {
123		# Ignore Link commands if source and destination basenames
124		# are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
125		src = $2
126		dst = $3
127		while ((i = index(src, "/"))) src = substr(src, i+1)
128		while ((i = index(dst, "/"))) dst = substr(dst, i+1)
129		if (src != dst) tz = $3
130	}
131	if (tz && tz ~ /\//) {
132		if (!tz2cc[tz]) {
133			printf "%s: no data for `%s'\n", zone_table, tz \
134				>>"/dev/stderr"
135			status = 1
136		}
137		zoneSeen[tz] = 1
138	}
139}
140
141END {
142	for (tz in tz2cc) {
143		if (!zoneSeen[tz]) {
144			printf "%s:%d: no Zone table for `%s'\n", \
145				zone_table, tz2NR[tz], tz >>"/dev/stderr"
146			status = 1
147		}
148	}
149
150	if (0 < want_warnings) {
151		for (cc in cc2name) {
152			if (!cc_used[cc]) {
153				printf "%s:%d: warning: " \
154					"no Zone entries for %s (%s)\n", \
155					iso_table, cc2NR[cc], cc, cc2name[cc]
156			}
157		}
158	}
159
160	exit status
161}
162