1# Check tz tables for consistency. 2 3# Contributed by Paul Eggert. 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 sname 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 status = 1 116 } 117 } 118 FS = " " 119} 120 121$1 ~ /^#/ { next } 122 123{ 124 tz = rules = "" 125 if ($1 == "Zone") { 126 tz = $2 127 ruleUsed[$4] = 1 128 } else if ($1 == "Link" && zone_table == "zone.tab") { 129 # Ignore Link commands if source and destination basenames 130 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 131 src = $2 132 dst = $3 133 while ((i = index(src, "/"))) src = substr(src, i+1) 134 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 135 if (src != dst) tz = $3 136 } else if ($1 == "Rule") { 137 ruleDefined[$2] = 1 138 } else { 139 ruleUsed[$2] = 1 140 } 141 if (tz && tz ~ /\//) { 142 if (!tztab[tz]) { 143 printf "%s: no data for '%s'\n", zone_table, tz \ 144 >>"/dev/stderr" 145 status = 1 146 } 147 zoneSeen[tz] = 1 148 } 149} 150 151END { 152 for (tz in ruleDefined) { 153 if (!ruleUsed[tz]) { 154 printf "%s: Rule never used\n", tz 155 status = 1 156 } 157 } 158 for (tz in tztab) { 159 if (!zoneSeen[tz]) { 160 printf "%s:%d: no Zone table for '%s'\n", \ 161 zone_table, tz2NR[tz], tz >>"/dev/stderr" 162 status = 1 163 } 164 } 165 if (0 < want_warnings) { 166 for (cc in cc2name) { 167 if (!cc_used[cc]) { 168 printf "%s:%d: warning: " \ 169 "no Zone entries for %s (%s)\n", \ 170 iso_table, cc2NR[cc], cc, cc2name[cc] 171 } 172 } 173 } 174 175 exit status 176} 177