1308265Sgjb# Check tz tables for consistency.
2308265Sgjb
3308265Sgjb# Contributed by Paul Eggert.  This file is in the public domain.
4308265Sgjb
5308265SgjbBEGIN {
6308265Sgjb	FS = "\t"
7308265Sgjb
8308265Sgjb	if (!iso_table) iso_table = "iso3166.tab"
9308265Sgjb	if (!zone_table) zone_table = "zone1970.tab"
10308265Sgjb	if (!want_warnings) want_warnings = -1
11308265Sgjb
12308265Sgjb	while (getline <iso_table) {
13308265Sgjb		iso_NR++
14308265Sgjb		if ($0 ~ /^#/) continue
15308265Sgjb		if (NF != 2) {
16308265Sgjb			printf "%s:%d: wrong number of columns\n", \
17308265Sgjb				iso_table, iso_NR >>"/dev/stderr"
18308265Sgjb			status = 1
19308265Sgjb		}
20308265Sgjb		cc = $1
21308265Sgjb		name = $2
22308265Sgjb		if (cc !~ /^[A-Z][A-Z]$/) {
23308265Sgjb			printf "%s:%d: invalid country code '%s'\n", \
24308265Sgjb				iso_table, iso_NR, cc >>"/dev/stderr"
25308265Sgjb			status = 1
26308265Sgjb		}
27308265Sgjb		if (cc <= cc0) {
28308265Sgjb			if (cc == cc0) {
29308265Sgjb				s = "duplicate";
30308265Sgjb			} else {
31308265Sgjb				s = "out of order";
32308265Sgjb			}
33308265Sgjb
34308265Sgjb			printf "%s:%d: country code '%s' is %s\n", \
35308265Sgjb				iso_table, iso_NR, cc, s \
36308265Sgjb				>>"/dev/stderr"
37308265Sgjb			status = 1
38308265Sgjb		}
39308265Sgjb		cc0 = cc
40308265Sgjb		if (name2cc[name]) {
41308265Sgjb			printf "%s:%d: '%s' and '%s' have the same name\n", \
42308265Sgjb				iso_table, iso_NR, name2cc[name], cc \
43308265Sgjb				>>"/dev/stderr"
44308265Sgjb			status = 1
45308265Sgjb		}
46308265Sgjb		name2cc[name] = cc
47308265Sgjb		cc2name[cc] = name
48308265Sgjb		cc2NR[cc] = iso_NR
49308265Sgjb	}
50308265Sgjb
51308265Sgjb	cc0 = ""
52308265Sgjb
53308265Sgjb	while (getline <zone_table) {
54308265Sgjb		zone_NR++
55308265Sgjb		if ($0 ~ /^#/) continue
56308265Sgjb		if (NF != 3 && NF != 4) {
57308265Sgjb			printf "%s:%d: wrong number of columns\n", \
58308265Sgjb				zone_table, zone_NR >>"/dev/stderr"
59308265Sgjb			status = 1
60308265Sgjb		}
61308265Sgjb		split($1, cca, /,/)
62308265Sgjb		cc = cca[1]
63308265Sgjb		coordinates = $2
64308265Sgjb		tz = $3
65308265Sgjb		comments = $4
66308265Sgjb		if (cc < cc0) {
67308265Sgjb			printf "%s:%d: country code '%s' is out of order\n", \
68308265Sgjb				zone_table, zone_NR, cc >>"/dev/stderr"
69308265Sgjb			status = 1
70308265Sgjb		}
71308265Sgjb		cc0 = cc
72308265Sgjb		tztab[tz] = 1
73308265Sgjb		tz2comments[tz] = comments
74308265Sgjb		tz2NR[tz] = zone_NR
75308265Sgjb		for (i in cca) {
76308265Sgjb		    cc = cca[i]
77308265Sgjb		    cctz = cc tz
78308265Sgjb		    cctztab[cctz] = 1
79308265Sgjb		    if (cc2name[cc]) {
80308265Sgjb			cc_used[cc]++
81308265Sgjb		    } else {
82308265Sgjb			printf "%s:%d: %s: unknown country code\n", \
83308265Sgjb				zone_table, zone_NR, cc >>"/dev/stderr"
84308265Sgjb			status = 1
85308265Sgjb		    }
86308265Sgjb		}
87308265Sgjb		if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
88308265Sgjb		    && 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]$/) {
89308265Sgjb			printf "%s:%d: %s: invalid coordinates\n", \
90308265Sgjb				zone_table, zone_NR, coordinates >>"/dev/stderr"
91308265Sgjb			status = 1
92308265Sgjb		}
93308265Sgjb	}
94308265Sgjb
95308265Sgjb	for (cctz in cctztab) {
96308265Sgjb		cc = substr (cctz, 1, 2)
97308265Sgjb		tz = substr (cctz, 3)
98308265Sgjb		if (1 < cc_used[cc]) {
99308265Sgjb			comments_needed[tz] = cc
100308265Sgjb		}
101308265Sgjb	}
102308265Sgjb	for (cctz in cctztab) {
103308265Sgjb	  cc = substr (cctz, 1, 2)
104308265Sgjb	  tz = substr (cctz, 3)
105308265Sgjb	  if (!comments_needed[tz] && tz2comments[tz]) {
106308265Sgjb	    printf "%s:%d: unnecessary comment '%s'\n", \
107308265Sgjb		zone_table, tz2NR[tz], tz2comments[tz] \
108308265Sgjb		>>"/dev/stderr"
109308265Sgjb	    tz2comments[tz] = 0
110308265Sgjb	    status = 1
111308265Sgjb	  } else if (comments_needed[tz] && !tz2comments[tz]) {
112308265Sgjb	    printf "%s:%d: missing comment for %s\n", \
113308265Sgjb	      zone_table, tz2NR[tz], comments_needed[tz] \
114308265Sgjb	      >>"/dev/stderr"
115308265Sgjb	    tz2comments[tz] = 1
116308265Sgjb	    status = 1
117308265Sgjb	  }
118308265Sgjb	}
119308265Sgjb	FS = " "
120308265Sgjb}
121308265Sgjb
122308265Sgjb$1 ~ /^#/ { next }
123308265Sgjb
124308265Sgjb{
125308265Sgjb	tz = rules = ""
126308265Sgjb	if ($1 == "Zone") {
127308265Sgjb		tz = $2
128308265Sgjb		ruleUsed[$4] = 1
129331663Sphilip		if ($5 ~ /%/) rulePercentUsed[$4] = 1
130308265Sgjb	} else if ($1 == "Link" && zone_table == "zone.tab") {
131308265Sgjb		# Ignore Link commands if source and destination basenames
132308265Sgjb		# are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
133308265Sgjb		src = $2
134308265Sgjb		dst = $3
135308265Sgjb		while ((i = index(src, "/"))) src = substr(src, i+1)
136308265Sgjb		while ((i = index(dst, "/"))) dst = substr(dst, i+1)
137308265Sgjb		if (src != dst) tz = $3
138308265Sgjb	} else if ($1 == "Rule") {
139308265Sgjb		ruleDefined[$2] = 1
140331663Sphilip		if ($10 != "-") ruleLetters[$2] = 1
141308265Sgjb	} else {
142308265Sgjb		ruleUsed[$2] = 1
143331663Sphilip		if ($3 ~ /%/) rulePercentUsed[$2] = 1
144308265Sgjb	}
145308265Sgjb	if (tz && tz ~ /\//) {
146308265Sgjb		if (!tztab[tz]) {
147308265Sgjb			printf "%s: no data for '%s'\n", zone_table, tz \
148308265Sgjb				>>"/dev/stderr"
149308265Sgjb			status = 1
150308265Sgjb		}
151308265Sgjb		zoneSeen[tz] = 1
152308265Sgjb	}
153308265Sgjb}
154308265Sgjb
155308265SgjbEND {
156308265Sgjb	for (tz in ruleDefined) {
157308265Sgjb		if (!ruleUsed[tz]) {
158308265Sgjb			printf "%s: Rule never used\n", tz
159308265Sgjb			status = 1
160308265Sgjb		}
161308265Sgjb	}
162331663Sphilip	for (tz in ruleLetters) {
163331663Sphilip		if (!rulePercentUsed[tz]) {
164331663Sphilip			printf "%s: Rule contains letters never used\n", tz
165331663Sphilip			status = 1
166331663Sphilip		}
167331663Sphilip	}
168308265Sgjb	for (tz in tztab) {
169308265Sgjb		if (!zoneSeen[tz]) {
170308265Sgjb			printf "%s:%d: no Zone table for '%s'\n", \
171308265Sgjb				zone_table, tz2NR[tz], tz >>"/dev/stderr"
172308265Sgjb			status = 1
173308265Sgjb		}
174308265Sgjb	}
175308265Sgjb	if (0 < want_warnings) {
176308265Sgjb		for (cc in cc2name) {
177308265Sgjb			if (!cc_used[cc]) {
178308265Sgjb				printf "%s:%d: warning: " \
179308265Sgjb					"no Zone entries for %s (%s)\n", \
180308265Sgjb					iso_table, cc2NR[cc], cc, cc2name[cc]
181308265Sgjb			}
182308265Sgjb		}
183308265Sgjb	}
184308265Sgjb
185308265Sgjb	exit status
186308265Sgjb}
187