checktab.awk revision 1.7.2.1 1 1.7.2.1 martin # $NetBSD: checktab.awk,v 1.7.2.1 2015/01/25 09:11:03 martin Exp $
2 1.2 perry
3 1.1 jtc # Check tz tables for consistency.
4 1.1 jtc
5 1.4 mlelstv # Contributed by Paul Eggert.
6 1.1 jtc
7 1.1 jtc BEGIN {
8 1.1 jtc FS = "\t"
9 1.1 jtc
10 1.1 jtc if (!iso_table) iso_table = "iso3166.tab"
11 1.7.2.1 martin if (!zone_table) zone_table = "zone1970.tab"
12 1.1 jtc if (!want_warnings) want_warnings = -1
13 1.1 jtc
14 1.6 christos # A special (and we hope temporary) case.
15 1.6 christos tztab["America/Montreal"] = 1
16 1.6 christos
17 1.7.2.1 martin # Some more special cases; these are zones that should probably
18 1.7.2.1 martin # be turned into links.
19 1.7.2.1 martin if (zone_table == "zone1970.tab") {
20 1.7.2.1 martin tztab["Africa/Addis_Ababa"] = 1
21 1.7.2.1 martin tztab["Africa/Asmara"] = 1
22 1.7.2.1 martin tztab["Africa/Bangui"] = 1
23 1.7.2.1 martin tztab["Africa/Blantyre"] = 1
24 1.7.2.1 martin tztab["Africa/Brazzaville"] = 1
25 1.7.2.1 martin tztab["Africa/Bujumbura"] = 1
26 1.7.2.1 martin tztab["Africa/Dar_es_Salaam"] = 1
27 1.7.2.1 martin tztab["Africa/Djibouti"] = 1
28 1.7.2.1 martin tztab["Africa/Douala"] = 1
29 1.7.2.1 martin tztab["Africa/Gaborone"] = 1
30 1.7.2.1 martin tztab["Africa/Harare"] = 1
31 1.7.2.1 martin tztab["Africa/Kampala"] = 1
32 1.7.2.1 martin tztab["Africa/Kigali"] = 1
33 1.7.2.1 martin tztab["Africa/Kinshasa"] = 1
34 1.7.2.1 martin tztab["Africa/Libreville"] = 1
35 1.7.2.1 martin tztab["Africa/Luanda"] = 1
36 1.7.2.1 martin tztab["Africa/Lubumbashi"] = 1
37 1.7.2.1 martin tztab["Africa/Lusaka"] = 1
38 1.7.2.1 martin tztab["Africa/Malabo"] = 1
39 1.7.2.1 martin tztab["Africa/Maseru"] = 1
40 1.7.2.1 martin tztab["Africa/Mbabane"] = 1
41 1.7.2.1 martin tztab["Africa/Mogadishu"] = 1
42 1.7.2.1 martin tztab["Africa/Niamey"] = 1
43 1.7.2.1 martin tztab["Africa/Porto-Novo"] = 1
44 1.7.2.1 martin tztab["America/Antigua"] = 1
45 1.7.2.1 martin tztab["America/Cayman"] = 1
46 1.7.2.1 martin tztab["Asia/Aden"] = 1
47 1.7.2.1 martin tztab["Asia/Bahrain"] = 1
48 1.7.2.1 martin tztab["Asia/Ho_Chi_Minh"] = 1
49 1.7.2.1 martin tztab["Asia/Kuwait"] = 1
50 1.7.2.1 martin tztab["Asia/Muscat"] = 1
51 1.7.2.1 martin tztab["Asia/Phnom_Penh"] = 1
52 1.7.2.1 martin tztab["Asia/Vientiane"] = 1
53 1.7.2.1 martin tztab["Indian/Antananarivo"] = 1
54 1.7.2.1 martin tztab["Indian/Comoro"] = 1
55 1.7.2.1 martin tztab["Indian/Mayotte"] = 1
56 1.7.2.1 martin tztab["Pacific/Midway"] = 1
57 1.7.2.1 martin tztab["Pacific/Saipan"] = 1
58 1.7.2.1 martin }
59 1.7.2.1 martin
60 1.1 jtc while (getline <iso_table) {
61 1.1 jtc iso_NR++
62 1.1 jtc if ($0 ~ /^#/) continue
63 1.1 jtc if (NF != 2) {
64 1.3 kleink printf "%s:%d: wrong number of columns\n", \
65 1.1 jtc iso_table, iso_NR >>"/dev/stderr"
66 1.1 jtc status = 1
67 1.1 jtc }
68 1.1 jtc cc = $1
69 1.1 jtc name = $2
70 1.1 jtc if (cc !~ /^[A-Z][A-Z]$/) {
71 1.7.2.1 martin printf "%s:%d: invalid country code '%s'\n", \
72 1.1 jtc iso_table, iso_NR, cc >>"/dev/stderr"
73 1.1 jtc status = 1
74 1.1 jtc }
75 1.1 jtc if (cc <= cc0) {
76 1.3 kleink if (cc == cc0) {
77 1.3 kleink s = "duplicate";
78 1.3 kleink } else {
79 1.3 kleink s = "out of order";
80 1.3 kleink }
81 1.3 kleink
82 1.7.2.1 martin printf "%s:%d: country code '%s' is %s\n", \
83 1.3 kleink iso_table, iso_NR, cc, s \
84 1.1 jtc >>"/dev/stderr"
85 1.1 jtc status = 1
86 1.1 jtc }
87 1.1 jtc cc0 = cc
88 1.1 jtc if (name2cc[name]) {
89 1.7.2.1 martin printf "%s:%d: '%s' and '%s' have the sname name\n", \
90 1.1 jtc iso_table, iso_NR, name2cc[name], cc \
91 1.1 jtc >>"/dev/stderr"
92 1.1 jtc status = 1
93 1.1 jtc }
94 1.1 jtc name2cc[name] = cc
95 1.1 jtc cc2name[cc] = name
96 1.1 jtc cc2NR[cc] = iso_NR
97 1.1 jtc }
98 1.1 jtc
99 1.1 jtc cc0 = ""
100 1.1 jtc
101 1.1 jtc while (getline <zone_table) {
102 1.1 jtc zone_NR++
103 1.1 jtc if ($0 ~ /^#/) continue
104 1.1 jtc if (NF != 3 && NF != 4) {
105 1.3 kleink printf "%s:%d: wrong number of columns\n", \
106 1.1 jtc zone_table, zone_NR >>"/dev/stderr"
107 1.1 jtc status = 1
108 1.1 jtc }
109 1.7.2.1 martin split($1, cca, /,/)
110 1.7.2.1 martin cc = cca[1]
111 1.1 jtc coordinates = $2
112 1.1 jtc tz = $3
113 1.1 jtc comments = $4
114 1.1 jtc if (cc < cc0) {
115 1.7.2.1 martin printf "%s:%d: country code '%s' is out of order\n", \
116 1.1 jtc zone_table, zone_NR, cc >>"/dev/stderr"
117 1.1 jtc status = 1
118 1.1 jtc }
119 1.1 jtc cc0 = cc
120 1.6 christos tztab[tz] = 1
121 1.7.2.1 martin tz2comments[tz] = comments
122 1.1 jtc tz2NR[tz] = zone_NR
123 1.7.2.1 martin for (i in cca) {
124 1.7.2.1 martin cc = cca[i]
125 1.7.2.1 martin cctz = cc tz
126 1.7.2.1 martin cctztab[cctz] = 1
127 1.7.2.1 martin if (cc2name[cc]) {
128 1.1 jtc cc_used[cc]++
129 1.7.2.1 martin } else {
130 1.1 jtc printf "%s:%d: %s: unknown country code\n", \
131 1.1 jtc zone_table, zone_NR, cc >>"/dev/stderr"
132 1.1 jtc status = 1
133 1.7.2.1 martin }
134 1.1 jtc }
135 1.1 jtc if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
136 1.1 jtc && 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]$/) {
137 1.1 jtc printf "%s:%d: %s: invalid coordinates\n", \
138 1.1 jtc zone_table, zone_NR, coordinates >>"/dev/stderr"
139 1.1 jtc status = 1
140 1.1 jtc }
141 1.1 jtc }
142 1.1 jtc
143 1.6 christos for (cctz in cctztab) {
144 1.6 christos cc = substr (cctz, 1, 2)
145 1.6 christos tz = substr (cctz, 3)
146 1.7.2.1 martin if (1 < cc_used[cc]) {
147 1.7.2.1 martin comments_needed[tz] = cc
148 1.1 jtc }
149 1.1 jtc }
150 1.7.2.1 martin for (cctz in cctztab) {
151 1.7.2.1 martin cc = substr (cctz, 1, 2)
152 1.7.2.1 martin tz = substr (cctz, 3)
153 1.7.2.1 martin if (!comments_needed[tz] && tz2comments[tz]) {
154 1.7.2.1 martin printf "%s:%d: unnecessary comment '%s'\n", \
155 1.7.2.1 martin zone_table, tz2NR[tz], tz2comments[tz] \
156 1.7.2.1 martin >>"/dev/stderr"
157 1.7.2.1 martin tz2comments[tz] = 0
158 1.7.2.1 martin status = 1
159 1.7.2.1 martin } else if (comments_needed[tz] && !tz2comments[tz]) {
160 1.7.2.1 martin printf "%s:%d: missing comment for %s\n", \
161 1.7.2.1 martin zone_table, tz2NR[tz], comments_needed[tz] \
162 1.7.2.1 martin >>"/dev/stderr"
163 1.7.2.1 martin status = 1
164 1.7.2.1 martin }
165 1.7.2.1 martin }
166 1.1 jtc FS = " "
167 1.1 jtc }
168 1.1 jtc
169 1.7 christos $1 ~ /^#/ { next }
170 1.7 christos
171 1.1 jtc {
172 1.7 christos tz = rules = ""
173 1.7 christos if ($1 == "Zone") {
174 1.7 christos tz = $2
175 1.7 christos ruleUsed[$4] = 1
176 1.7.2.1 martin } else if ($1 == "Link" && zone_table == "zone.tab") {
177 1.1 jtc # Ignore Link commands if source and destination basenames
178 1.1 jtc # are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
179 1.1 jtc src = $2
180 1.1 jtc dst = $3
181 1.1 jtc while ((i = index(src, "/"))) src = substr(src, i+1)
182 1.1 jtc while ((i = index(dst, "/"))) dst = substr(dst, i+1)
183 1.1 jtc if (src != dst) tz = $3
184 1.7 christos } else if ($1 == "Rule") {
185 1.7 christos ruleDefined[$2] = 1
186 1.7 christos } else {
187 1.7 christos ruleUsed[$2] = 1
188 1.1 jtc }
189 1.1 jtc if (tz && tz ~ /\//) {
190 1.6 christos if (!tztab[tz]) {
191 1.7.2.1 martin printf "%s: no data for '%s'\n", zone_table, tz \
192 1.1 jtc >>"/dev/stderr"
193 1.1 jtc status = 1
194 1.1 jtc }
195 1.1 jtc zoneSeen[tz] = 1
196 1.1 jtc }
197 1.1 jtc }
198 1.1 jtc
199 1.1 jtc END {
200 1.7 christos for (tz in ruleDefined) {
201 1.7 christos if (!ruleUsed[tz]) {
202 1.7 christos printf "%s: Rule never used\n", tz
203 1.7 christos status = 1
204 1.7 christos }
205 1.7 christos }
206 1.7.2.1 martin for (tz in tztab) {
207 1.1 jtc if (!zoneSeen[tz]) {
208 1.7.2.1 martin printf "%s:%d: no Zone table for '%s'\n", \
209 1.1 jtc zone_table, tz2NR[tz], tz >>"/dev/stderr"
210 1.1 jtc status = 1
211 1.1 jtc }
212 1.1 jtc }
213 1.1 jtc if (0 < want_warnings) {
214 1.1 jtc for (cc in cc2name) {
215 1.1 jtc if (!cc_used[cc]) {
216 1.3 kleink printf "%s:%d: warning: " \
217 1.3 kleink "no Zone entries for %s (%s)\n", \
218 1.1 jtc iso_table, cc2NR[cc], cc, cc2name[cc]
219 1.1 jtc }
220 1.1 jtc }
221 1.1 jtc }
222 1.1 jtc
223 1.1 jtc exit status
224 1.1 jtc }
225