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 ccs = input_ccs[zone_NR] = $1 62 coordinates = $2 63 tz = $3 64 comments = input_comments[zone_NR] = $4 65 split(ccs, cca, /,/) 66 cc = cca[1] 67 68 # Don't complain about a special case for Crimea in zone.tab. 69 # FIXME: zone.tab should be removed, since it is obsolete. 70 # Or at least put just "XX" in its country-code column. 71 if (cc < cc0 \ 72 && !(zone_table == "zone.tab" \ 73 && tz0 == "Europe/Simferopol")) { 74 printf "%s:%d: country code '%s' is out of order\n", \ 75 zone_table, zone_NR, cc >>"/dev/stderr" 76 status = 1 77 } 78 cc0 = cc 79 tz0 = tz 80 tztab[tz] = 1 81 tz2NR[tz] = zone_NR 82 for (i in cca) { 83 cc = cca[i] 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 } 92 if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ 93 && 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]$/) { 94 printf "%s:%d: %s: invalid coordinates\n", \ 95 zone_table, zone_NR, coordinates >>"/dev/stderr" 96 status = 1 97 } 98 } 99 100 for (i = 1; i <= zone_NR; i++) { 101 ccs = input_ccs[i] 102 if (!ccs) continue 103 comments = input_comments[i] 104 split(ccs, cca, /,/) 105 used_max = 0 106 for (j in cca) { 107 cc = cca[j] 108 if (used_max < cc_used[cc]) { 109 used_max = cc_used[cc] 110 } 111 } 112 if (used_max <= 1 && comments) { 113 printf "%s:%d: unnecessary comment '%s'\n", \ 114 zone_table, i, comments \ 115 >>"/dev/stderr" 116 status = 1 117 } else if (1 < cc_used[cc] && !comments) { 118 printf "%s:%d: missing comment for %s\n", \ 119 zone_table, i, cc \ 120 >>"/dev/stderr" 121 status = 1 122 } 123 } 124 FS = " " 125} 126 127$1 ~ /^#/ { next } 128 129{ 130 tz = rules = "" 131 if ($1 == "Zone") { 132 tz = $2 133 ruleUsed[$4] = 1 134 if ($5 ~ /%/) rulePercentUsed[$4] = 1 135 } else if ($1 == "Link" && zone_table == "zone.tab") { 136 # Ignore Link commands if source and destination basenames 137 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 138 src = $2 139 dst = $3 140 while ((i = index(src, "/"))) src = substr(src, i+1) 141 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 142 if (src != dst) tz = $3 143 } else if ($1 == "Rule") { 144 ruleDefined[$2] = 1 145 if ($10 != "-") ruleLetters[$2] = 1 146 } else { 147 ruleUsed[$2] = 1 148 if ($3 ~ /%/) rulePercentUsed[$2] = 1 149 } 150 if (tz && tz ~ /\// && tz !~ /^Etc\//) { 151 if (!tztab[tz] && FILENAME != "backward") { 152 printf "%s: no data for '%s'\n", zone_table, tz \ 153 >>"/dev/stderr" 154 status = 1 155 } 156 zoneSeen[tz] = 1 157 } 158} 159 160END { 161 for (tz in ruleDefined) { 162 if (!ruleUsed[tz]) { 163 printf "%s: Rule never used\n", tz 164 status = 1 165 } 166 } 167 for (tz in ruleLetters) { 168 if (!rulePercentUsed[tz]) { 169 printf "%s: Rule contains letters never used\n", tz 170 status = 1 171 } 172 } 173 for (tz in tztab) { 174 if (!zoneSeen[tz] && tz !~ /^Etc\//) { 175 printf "%s:%d: no Zone table for '%s'\n", \ 176 zone_table, tz2NR[tz], tz >>"/dev/stderr" 177 status = 1 178 } 179 } 180 if (0 < want_warnings) { 181 for (cc in cc2name) { 182 if (!cc_used[cc]) { 183 printf "%s:%d: warning: " \ 184 "no Zone entries for %s (%s)\n", \ 185 iso_table, cc2NR[cc], cc, cc2name[cc] 186 } 187 } 188 } 189 190 exit status 191} 192