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