[BZ #3137]
[jlayton/glibc.git] / timezone / checktab.awk
1 # Check tz tables for consistency.
2
3 # @(#)checktab.awk      8.1
4
5 # Contributed by Paul Eggert.
6
7 BEGIN {
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                         if (cc == cc0) {
31                                 s = "duplicate";
32                         } else {
33                                 s = "out of order";
34                         }
35
36                         printf "%s:%d: country code `%s' is %s\n", \
37                                 iso_table, iso_NR, cc, s \
38                                 >>"/dev/stderr"
39                         status = 1
40                 }
41                 cc0 = cc
42                 if (name2cc[name]) {
43                         printf "%s:%d: `%s' and `%s' have the sname name\n", \
44                                 iso_table, iso_NR, name2cc[name], cc \
45                                 >>"/dev/stderr"
46                         status = 1
47                 }
48                 name2cc[name] = cc
49                 cc2name[cc] = name
50                 cc2NR[cc] = iso_NR
51         }
52
53         zone_table = "zone.tab"
54         cc0 = ""
55
56         while (getline <zone_table) {
57                 zone_NR++
58                 if ($0 ~ /^#/) continue
59                 if (NF != 3 && NF != 4) {
60                         printf "%s:%d: wrong number of columns\n", \
61                                 zone_table, zone_NR >>"/dev/stderr"
62                         status = 1
63                 }
64                 cc = $1
65                 coordinates = $2
66                 tz = $3
67                 comments = $4
68                 if (cc < cc0) {
69                         printf "%s:%d: country code `%s' is out of order\n", \
70                                 zone_table, zone_NR, cc >>"/dev/stderr"
71                         status = 1
72                 }
73                 cc0 = cc
74                 if (tz2cc[tz]) {
75                         printf "%s:%d: %s: duplicate TZ column\n", \
76                                 zone_table, zone_NR, tz >>"/dev/stderr"
77                         status = 1
78                 }
79                 tz2cc[tz] = cc
80                 tz2comments[tz] = 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 (tz in tz2cc) {
98                 if (cc_used[tz2cc[tz]] == 1) {
99                         if (tz2comments[tz]) {
100                                 printf "%s:%d: unnecessary comment `%s'\n", \
101                                         zone_table, tz2NR[tz], tz2comments[tz] \
102                                         >>"/dev/stderr"
103                                 status = 1
104                         }
105                 } else {
106                         if (!tz2comments[tz]) {
107                                 printf "%s:%d: missing comment\n", \
108                                         zone_table, tz2NR[tz] >>"/dev/stderr"
109                                 status = 1
110                         }
111                 }
112         }
113
114         FS = " "
115 }
116
117 {
118         tz = ""
119         if ($1 == "Zone") tz = $2
120         if ($1 == "Link") {
121                 # Ignore Link commands if source and destination basenames
122                 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
123                 src = $2
124                 dst = $3
125                 while ((i = index(src, "/"))) src = substr(src, i+1)
126                 while ((i = index(dst, "/"))) dst = substr(dst, i+1)
127                 if (src != dst) tz = $3
128         }
129         if (tz && tz ~ /\//) {
130                 if (!tz2cc[tz]) {
131                         printf "%s: no data for `%s'\n", zone_table, tz \
132                                 >>"/dev/stderr"
133                         status = 1
134                 }
135                 zoneSeen[tz] = 1
136         }
137 }
138
139 END {
140         for (tz in tz2cc) {
141                 if (!zoneSeen[tz]) {
142                         printf "%s:%d: no Zone table for `%s'\n", \
143                                 zone_table, tz2NR[tz], tz >>"/dev/stderr"
144                         status = 1
145                 }
146         }
147
148         if (0 < want_warnings) {
149                 for (cc in cc2name) {
150                         if (!cc_used[cc]) {
151                                 printf "%s:%d: warning: " \
152                                         "no Zone entries for %s (%s)\n", \
153                                         iso_table, cc2NR[cc], cc, cc2name[cc]
154                         }
155                 }
156         }
157
158         exit status
159 }