1# $NetBSD: checktab.awk,v 1.6 2013/09/20 19:06:54 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{ 121 tz = "" 122 if ($1 == "Zone") tz = $2 123 if ($1 == "Link") { 124 # Ignore Link commands if source and destination basenames 125 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 126 src = $2 127 dst = $3 128 while ((i = index(src, "/"))) src = substr(src, i+1) 129 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 130 if (src != dst) tz = $3 131 } 132 if (tz && tz ~ /\//) { 133 if (!tztab[tz]) { 134 printf "%s: no data for `%s'\n", zone_table, tz \ 135 >>"/dev/stderr" 136 status = 1 137 } 138 zoneSeen[tz] = 1 139 } 140} 141 142END { 143 for (tz in tz2cc) { 144 if (!zoneSeen[tz]) { 145 printf "%s:%d: no Zone table for `%s'\n", \ 146 zone_table, tz2NR[tz], tz >>"/dev/stderr" 147 status = 1 148 } 149 } 150 151 if (0 < want_warnings) { 152 for (cc in cc2name) { 153 if (!cc_used[cc]) { 154 printf "%s:%d: warning: " \ 155 "no Zone entries for %s (%s)\n", \ 156 iso_table, cc2NR[cc], cc, cc2name[cc] 157 } 158 } 159 } 160 161 exit status 162} 163