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 if (cc < cc0) { 67 printf "%s:%d: country code '%s' is out of order\n", \ 68 zone_table, zone_NR, cc >>"/dev/stderr" 69 status = 1 70 } 71 cc0 = cc 72 tztab[tz] = 1 73 tz2comments[tz] = comments 74 tz2NR[tz] = zone_NR 75 for (i in cca) { 76 cc = cca[i] 77 cctz = cc tz 78 cctztab[cctz] = 1 79 if (cc2name[cc]) { 80 cc_used[cc]++ 81 } else { 82 printf "%s:%d: %s: unknown country code\n", \ 83 zone_table, zone_NR, cc >>"/dev/stderr" 84 status = 1 85 } 86 } 87 if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ 88 && 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]$/) { 89 printf "%s:%d: %s: invalid coordinates\n", \ 90 zone_table, zone_NR, coordinates >>"/dev/stderr" 91 status = 1 92 } 93 } 94 95 for (cctz in cctztab) { 96 cc = substr (cctz, 1, 2) 97 tz = substr (cctz, 3) 98 if (1 < cc_used[cc]) { 99 comments_needed[tz] = cc 100 } 101 } 102 for (cctz in cctztab) { 103 cc = substr (cctz, 1, 2) 104 tz = substr (cctz, 3) 105 if (!comments_needed[tz] && tz2comments[tz]) { 106 printf "%s:%d: unnecessary comment '%s'\n", \ 107 zone_table, tz2NR[tz], tz2comments[tz] \ 108 >>"/dev/stderr" 109 tz2comments[tz] = 0 110 status = 1 111 } else if (comments_needed[tz] && !tz2comments[tz]) { 112 printf "%s:%d: missing comment for %s\n", \ 113 zone_table, tz2NR[tz], comments_needed[tz] \ 114 >>"/dev/stderr" 115 tz2comments[tz] = 1 116 status = 1 117 } 118 } 119 FS = " " 120} 121 122$1 ~ /^#/ { next } 123 124{ 125 tz = rules = "" 126 if ($1 == "Zone") { 127 tz = $2 128 ruleUsed[$4] = 1 129 if ($5 ~ /%/) rulePercentUsed[$4] = 1 130 } else if ($1 == "Link" && zone_table == "zone.tab") { 131 # Ignore Link commands if source and destination basenames 132 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 133 src = $2 134 dst = $3 135 while ((i = index(src, "/"))) src = substr(src, i+1) 136 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 137 if (src != dst) tz = $3 138 } else if ($1 == "Rule") { 139 ruleDefined[$2] = 1 140 if ($10 != "-") ruleLetters[$2] = 1 141 } else { 142 ruleUsed[$2] = 1 143 if ($3 ~ /%/) rulePercentUsed[$2] = 1 144 } 145 if (tz && tz ~ /\//) { 146 if (!tztab[tz]) { 147 printf "%s: no data for '%s'\n", zone_table, tz \ 148 >>"/dev/stderr" 149 status = 1 150 } 151 zoneSeen[tz] = 1 152 } 153} 154 155END { 156 for (tz in ruleDefined) { 157 if (!ruleUsed[tz]) { 158 printf "%s: Rule never used\n", tz 159 status = 1 160 } 161 } 162 for (tz in ruleLetters) { 163 if (!rulePercentUsed[tz]) { 164 printf "%s: Rule contains letters never used\n", tz 165 status = 1 166 } 167 } 168 for (tz in tztab) { 169 if (!zoneSeen[tz]) { 170 printf "%s:%d: no Zone table for '%s'\n", \ 171 zone_table, tz2NR[tz], tz >>"/dev/stderr" 172 status = 1 173 } 174 } 175 if (0 < want_warnings) { 176 for (cc in cc2name) { 177 if (!cc_used[cc]) { 178 printf "%s:%d: warning: " \ 179 "no Zone entries for %s (%s)\n", \ 180 iso_table, cc2NR[cc], cc, cc2name[cc] 181 } 182 } 183 } 184 185 exit status 186} 187