1# $NetBSD: checktab.awk,v 1.7 2014/05/13 16:33:56 christos Exp $ 2 3# Check tz tables for consistency. 4 5# Contributed by Paul Eggert. 6 7BEGIN { 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 # A special (and we hope temporary) case. 15 tztab["America/Montreal"] = 1 16 17 while (getline <iso_table) { 18 iso_NR++ 19 if ($0 ~ /^#/) continue 20 if (NF != 2) { 21 printf "%s:%d: wrong number of columns\n", \ 22 iso_table, iso_NR >>"/dev/stderr" 23 status = 1 24 } 25 cc = $1 26 name = $2 27 if (cc !~ /^[A-Z][A-Z]$/) { 28 printf "%s:%d: invalid country code `%s'\n", \ 29 iso_table, iso_NR, cc >>"/dev/stderr" 30 status = 1 31 } 32 if (cc <= cc0) { 33 if (cc == cc0) { 34 s = "duplicate"; 35 } else { 36 s = "out of order"; 37 } 38 39 printf "%s:%d: country code `%s' is %s\n", \ 40 iso_table, iso_NR, cc, s \ 41 >>"/dev/stderr" 42 status = 1 43 } 44 cc0 = cc 45 if (name2cc[name]) { 46 printf "%s:%d: `%s' and `%s' have the sname name\n", \ 47 iso_table, iso_NR, name2cc[name], cc \ 48 >>"/dev/stderr" 49 status = 1 50 } 51 name2cc[name] = cc 52 cc2name[cc] = name 53 cc2NR[cc] = iso_NR 54 } 55 56 zone_table = "zone.tab" 57 cc0 = "" 58 59 while (getline <zone_table) { 60 zone_NR++ 61 if ($0 ~ /^#/) continue 62 if (NF != 3 && NF != 4) { 63 printf "%s:%d: wrong number of columns\n", \ 64 zone_table, zone_NR >>"/dev/stderr" 65 status = 1 66 } 67 cc = $1 68 coordinates = $2 69 tz = $3 70 comments = $4 71 if (cc < cc0) { 72 printf "%s:%d: country code `%s' is out of order\n", \ 73 zone_table, zone_NR, cc >>"/dev/stderr" 74 status = 1 75 } 76 cc0 = cc 77 cctz = cc tz 78 cctztab[cctz] = 1 79 tztab[tz] = 1 80 tz2comments[cctz] = 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 (cctz in cctztab) { 98 cc = substr (cctz, 1, 2) 99 tz = substr (cctz, 3) 100 if (cc_used[cc] == 1) { 101 if (tz2comments[cctz]) { 102 printf "%s:%d: unnecessary comment `%s'\n", \ 103 zone_table, tz2NR[tz], \ 104 tz2comments[cctz] \ 105 >>"/dev/stderr" 106 status = 1 107 } 108 } else { 109 if (!tz2comments[cctz]) { 110 printf "%s:%d: missing comment\n", \ 111 zone_table, tz2NR[tz] >>"/dev/stderr" 112 status = 1 113 } 114 } 115 } 116 117 FS = " " 118} 119 120$1 ~ /^#/ { next } 121 122{ 123 tz = rules = "" 124 if ($1 == "Zone") { 125 tz = $2 126 ruleUsed[$4] = 1 127 } else if ($1 == "Link") { 128 # Ignore Link commands if source and destination basenames 129 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 130 src = $2 131 dst = $3 132 while ((i = index(src, "/"))) src = substr(src, i+1) 133 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 134 if (src != dst) tz = $3 135 } else if ($1 == "Rule") { 136 ruleDefined[$2] = 1 137 } else { 138 ruleUsed[$2] = 1 139 } 140 if (tz && tz ~ /\//) { 141 if (!tztab[tz]) { 142 printf "%s: no data for `%s'\n", zone_table, tz \ 143 >>"/dev/stderr" 144 status = 1 145 } 146 zoneSeen[tz] = 1 147 } 148} 149 150END { 151 for (tz in ruleDefined) { 152 if (!ruleUsed[tz]) { 153 printf "%s: Rule never used\n", tz 154 status = 1 155 } 156 } 157 for (tz in tz2cc) { 158 if (!zoneSeen[tz]) { 159 printf "%s:%d: no Zone table for `%s'\n", \ 160 zone_table, tz2NR[tz], tz >>"/dev/stderr" 161 status = 1 162 } 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