checktab.awk revision 1.2.6.1 1 # $NetBSD: checktab.awk,v 1.2.6.1 1999/12/27 18:29:55 wrstuden Exp $
2
3 # Check tz tables for consistency.
4
5 # @(#)checktab.awk 1.6
6
7 # Contributed by Paul Eggert <eggert (at] twinsun.com>.
8
9 BEGIN {
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
141 END {
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