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