1# Check tz tables for consistency. 2 3# Contributed by Paul Eggert. This file is in the public domain. 4 5BEGIN { 6 FS = "\t" 7 8 if (!iso_table) iso_table = "iso3166.tab" 9 if (!zone_table) zone_table = "zone1970.tab" 10 if (!want_warnings) want_warnings = -1 11 12 while (getline <iso_table) { 13 iso_NR++ 14 if ($0 ~ /^#/) continue 15 if (NF != 2) { 16 printf "%s:%d: wrong number of columns\n", \ 17 iso_table, iso_NR >>"/dev/stderr" 18 status = 1 19 } 20 cc = $1 21 name = $2 22 if (cc !~ /^[A-Z][A-Z]$/) { 23 printf "%s:%d: invalid country code '%s'\n", \ 24 iso_table, iso_NR, cc >>"/dev/stderr" 25 status = 1 26 } 27 if (cc <= cc0) { 28 if (cc == cc0) { 29 s = "duplicate"; 30 } else { 31 s = "out of order"; 32 } 33 34 printf "%s:%d: country code '%s' is %s\n", \ 35 iso_table, iso_NR, cc, s \ 36 >>"/dev/stderr" 37 status = 1 38 } 39 cc0 = cc 40 if (name2cc[name]) { 41 printf "%s:%d: '%s' and '%s' have the same name\n", \ 42 iso_table, iso_NR, name2cc[name], cc \ 43 >>"/dev/stderr" 44 status = 1 45 } 46 name2cc[name] = cc 47 cc2name[cc] = name 48 cc2NR[cc] = iso_NR 49 } 50 51 cc0 = "" 52 53 while (getline <zone_table) { 54 zone_NR++ 55 if ($0 ~ /^#/) continue 56 if (NF != 3 && NF != 4) { 57 printf "%s:%d: wrong number of columns\n", \ 58 zone_table, zone_NR >>"/dev/stderr" 59 status = 1 60 } 61 split($1, cca, /,/) 62 cc = cca[1] 63 coordinates = $2 64 tz = $3 65 comments = $4 66 67 # Don't complain about a special case for Crimea in zone.tab. 68 # FIXME: zone.tab should be removed, since it is obsolete. 69 # Or at least put just "XX" in its country-code column. 70 if (cc < cc0 \ 71 && !(zone_table == "zone.tab" \ 72 && tz0 == "Europe/Simferopol")) { 73 printf "%s:%d: country code '%s' is out of order\n", \ 74 zone_table, zone_NR, cc >>"/dev/stderr" 75 status = 1 76 } 77 cc0 = cc 78 tz0 = tz 79 tztab[tz] = 1 80 tz2comments[tz] = comments 81 tz2NR[tz] = zone_NR 82 for (i in cca) { 83 cc = cca[i] 84 cctz = cc tz 85 cctztab[cctz] = 1 86 if (cc2name[cc]) { 87 cc_used[cc]++ 88 } else { 89 printf "%s:%d: %s: unknown country code\n", \ 90 zone_table, zone_NR, cc >>"/dev/stderr" 91 status = 1 92 } 93 } 94 if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ 95 && 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]$/) { 96 printf "%s:%d: %s: invalid coordinates\n", \ 97 zone_table, zone_NR, coordinates >>"/dev/stderr" 98 status = 1 99 } 100 } 101 102 for (cctz in cctztab) { 103 cc = substr (cctz, 1, 2) 104 tz = substr (cctz, 3) 105 if (1 < cc_used[cc]) { 106 comments_needed[tz] = cc 107 } 108 } 109 for (cctz in cctztab) { 110 cc = substr (cctz, 1, 2) 111 tz = substr (cctz, 3) 112 if (!comments_needed[tz] && tz2comments[tz]) { 113 printf "%s:%d: unnecessary comment '%s'\n", \ 114 zone_table, tz2NR[tz], tz2comments[tz] \ 115 >>"/dev/stderr" 116 tz2comments[tz] = 0 117 status = 1 118 } else if (comments_needed[tz] && !tz2comments[tz]) { 119 printf "%s:%d: missing comment for %s\n", \ 120 zone_table, tz2NR[tz], comments_needed[tz] \ 121 >>"/dev/stderr" 122 tz2comments[tz] = 1 123 status = 1 124 } 125 } 126 FS = " " 127} 128 129$1 ~ /^#/ { next } 130 131{ 132 tz = rules = "" 133 if ($1 == "Zone") { 134 tz = $2 135 ruleUsed[$4] = 1 136 if ($5 ~ /%/) rulePercentUsed[$4] = 1 137 } else if ($1 == "Link" && zone_table == "zone.tab") { 138 # Ignore Link commands if source and destination basenames 139 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 140 src = $2 141 dst = $3 142 while ((i = index(src, "/"))) src = substr(src, i+1) 143 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 144 if (src != dst) tz = $3 145 } else if ($1 == "Rule") { 146 ruleDefined[$2] = 1 147 if ($10 != "-") ruleLetters[$2] = 1 148 } else { 149 ruleUsed[$2] = 1 150 if ($3 ~ /%/) rulePercentUsed[$2] = 1 151 } 152 if (tz && tz ~ /\//) { 153 if (!tztab[tz]) { 154 printf "%s: no data for '%s'\n", zone_table, tz \ 155 >>"/dev/stderr" 156 status = 1 157 } 158 zoneSeen[tz] = 1 159 } 160} 161 162END { 163 for (tz in ruleDefined) { 164 if (!ruleUsed[tz]) { 165 printf "%s: Rule never used\n", tz 166 status = 1 167 } 168 } 169 for (tz in ruleLetters) { 170 if (!rulePercentUsed[tz]) { 171 printf "%s: Rule contains letters never used\n", tz 172 status = 1 173 } 174 } 175 for (tz in tztab) { 176 if (!zoneSeen[tz]) { 177 printf "%s:%d: no Zone table for '%s'\n", \ 178 zone_table, tz2NR[tz], tz >>"/dev/stderr" 179 status = 1 180 } 181 } 182 if (0 < want_warnings) { 183 for (cc in cc2name) { 184 if (!cc_used[cc]) { 185 printf "%s:%d: warning: " \ 186 "no Zone entries for %s (%s)\n", \ 187 iso_table, cc2NR[cc], cc, cc2name[cc] 188 } 189 } 190 } 191 192 exit status 193} 194