1# Check tz tables for consistency. 2 3# Contributed by Paul Eggert <eggert@twinsun.com>. 4 5BEGIN { 6 FS = "\t" 7 8 if (!iso_table) iso_table = "iso3166.tab" 9 if (!zone_table) zone_table = "zone.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 printf "%s:%d: country code `%s' is %s\n", \ 29 iso_table, iso_NR, cc, \ 30 cc==cc0 ? "duplicate" : "out of order" \ 31 >>"/dev/stderr" 32 status = 1 33 } 34 cc0 = cc 35 if (name2cc[name]) { 36 printf "%s:%d: `%s' and `%s' have the sname name\n", \ 37 iso_table, iso_NR, name2cc[name], cc \ 38 >>"/dev/stderr" 39 status = 1 40 } 41 name2cc[name] = cc 42 cc2name[cc] = name 43 cc2NR[cc] = iso_NR 44 } 45 46 zone_table = "zone.tab" 47 cc0 = "" 48 49 while (getline <zone_table) { 50 zone_NR++ 51 if ($0 ~ /^#/) continue 52 if (NF != 3 && NF != 4) { 53 printf "%s:%d: wrong number of columns\n", 54 zone_table, zone_NR >>"/dev/stderr" 55 status = 1 56 } 57 cc = $1 58 coordinates = $2 59 tz = $3 60 comments = $4 61 if (cc < cc0) { 62 printf "%s:%d: country code `%s' is out of order\n", \ 63 zone_table, zone_NR, cc >>"/dev/stderr" 64 status = 1 65 } 66 cc0 = cc 67 if (tz2cc[tz]) { 68 printf "%s:%d: %s: duplicate TZ column\n", \ 69 zone_table, zone_NR, tz >>"/dev/stderr" 70 status = 1 71 } 72 tz2cc[tz] = cc 73 tz2comments[tz] = comments 74 tz2NR[tz] = zone_NR 75 if (cc2name[cc]) { 76 cc_used[cc]++ 77 } else { 78 printf "%s:%d: %s: unknown country code\n", \ 79 zone_table, zone_NR, cc >>"/dev/stderr" 80 status = 1 81 } 82 if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ 83 && 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]$/) { 84 printf "%s:%d: %s: invalid coordinates\n", \ 85 zone_table, zone_NR, coordinates >>"/dev/stderr" 86 status = 1 87 } 88 } 89 90 for (tz in tz2cc) { 91 if (cc_used[tz2cc[tz]] == 1) { 92 if (tz2comments[tz]) { 93 printf "%s:%d: unnecessary comment `%s'\n", \ 94 zone_table, tz2NR[tz], tz2comments[tz] \ 95 >>"/dev/stderr" 96 status = 1 97 } 98 } else { 99 if (!tz2comments[tz]) { 100 printf "%s:%d: missing comment\n", \ 101 zone_table, tz2NR[tz] >>"/dev/stderr" 102 status = 1 103 } 104 } 105 } 106 107 FS = " " 108} 109 110{ 111 tz = "" 112 if ($1 == "Zone") tz = $2 113 if ($1 == "Link") { 114 # Ignore Link commands if source and destination basenames 115 # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. 116 src = $2 117 dst = $3 118 while ((i = index(src, "/"))) src = substr(src, i+1) 119 while ((i = index(dst, "/"))) dst = substr(dst, i+1) 120 if (src != dst) tz = $3 121 } 122 if (tz && tz ~ /\//) { 123 if (!tz2cc[tz]) { 124 printf "%s: no data for `%s'\n", zone_table, tz \ 125 >>"/dev/stderr" 126 status = 1 127 } 128 zoneSeen[tz] = 1 129 } 130} 131 132END { 133 for (tz in tz2cc) { 134 if (!zoneSeen[tz]) { 135 printf "%s:%d: no Zone table for `%s'\n", \ 136 zone_table, tz2NR[tz], tz >>"/dev/stderr" 137 status = 1 138 } 139 } 140 141 if (0 < want_warnings) { 142 for (cc in cc2name) { 143 if (!cc_used[cc]) { 144 printf "%s:%d: warning:" \ 145 "no Zone entries for %s (%s)\n", 146 iso_table, cc2NR[cc], cc, cc2name[cc] 147 } 148 } 149 } 150 151 exit status 152} 153