checktab.awk 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. # Check tz tables for consistency.
  2. # Contributed by Paul Eggert.
  3. BEGIN {
  4. FS = "\t"
  5. if (!iso_table) iso_table = "iso3166.tab"
  6. if (!zone_table) zone_table = "zone1970.tab"
  7. if (!want_warnings) want_warnings = -1
  8. while (getline <iso_table) {
  9. iso_NR++
  10. if ($0 ~ /^#/) continue
  11. if (NF != 2) {
  12. printf "%s:%d: wrong number of columns\n", \
  13. iso_table, iso_NR >>"/dev/stderr"
  14. status = 1
  15. }
  16. cc = $1
  17. name = $2
  18. if (cc !~ /^[A-Z][A-Z]$/) {
  19. printf "%s:%d: invalid country code '%s'\n", \
  20. iso_table, iso_NR, cc >>"/dev/stderr"
  21. status = 1
  22. }
  23. if (cc <= cc0) {
  24. if (cc == cc0) {
  25. s = "duplicate";
  26. } else {
  27. s = "out of order";
  28. }
  29. printf "%s:%d: country code '%s' is %s\n", \
  30. iso_table, iso_NR, cc, s \
  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. cc0 = ""
  46. while (getline <zone_table) {
  47. zone_NR++
  48. if ($0 ~ /^#/) continue
  49. if (NF != 3 && NF != 4) {
  50. printf "%s:%d: wrong number of columns\n", \
  51. zone_table, zone_NR >>"/dev/stderr"
  52. status = 1
  53. }
  54. split($1, cca, /,/)
  55. cc = cca[1]
  56. coordinates = $2
  57. tz = $3
  58. comments = $4
  59. if (cc < cc0) {
  60. printf "%s:%d: country code '%s' is out of order\n", \
  61. zone_table, zone_NR, cc >>"/dev/stderr"
  62. status = 1
  63. }
  64. cc0 = cc
  65. tztab[tz] = 1
  66. tz2comments[tz] = comments
  67. tz2NR[tz] = zone_NR
  68. for (i in cca) {
  69. cc = cca[i]
  70. cctz = cc tz
  71. cctztab[cctz] = 1
  72. if (cc2name[cc]) {
  73. cc_used[cc]++
  74. } else {
  75. printf "%s:%d: %s: unknown country code\n", \
  76. zone_table, zone_NR, cc >>"/dev/stderr"
  77. status = 1
  78. }
  79. }
  80. if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
  81. && 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]$/) {
  82. printf "%s:%d: %s: invalid coordinates\n", \
  83. zone_table, zone_NR, coordinates >>"/dev/stderr"
  84. status = 1
  85. }
  86. }
  87. for (cctz in cctztab) {
  88. cc = substr (cctz, 1, 2)
  89. tz = substr (cctz, 3)
  90. if (1 < cc_used[cc]) {
  91. comments_needed[tz] = cc
  92. }
  93. }
  94. for (cctz in cctztab) {
  95. cc = substr (cctz, 1, 2)
  96. tz = substr (cctz, 3)
  97. if (!comments_needed[tz] && tz2comments[tz]) {
  98. printf "%s:%d: unnecessary comment '%s'\n", \
  99. zone_table, tz2NR[tz], tz2comments[tz] \
  100. >>"/dev/stderr"
  101. tz2comments[tz] = 0
  102. status = 1
  103. } else if (comments_needed[tz] && !tz2comments[tz]) {
  104. printf "%s:%d: missing comment for %s\n", \
  105. zone_table, tz2NR[tz], comments_needed[tz] \
  106. >>"/dev/stderr"
  107. status = 1
  108. }
  109. }
  110. FS = " "
  111. }
  112. $1 ~ /^#/ { next }
  113. {
  114. tz = rules = ""
  115. if ($1 == "Zone") {
  116. tz = $2
  117. ruleUsed[$4] = 1
  118. } else if ($1 == "Link" && zone_table == "zone.tab") {
  119. # Ignore Link commands if source and destination basenames
  120. # are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
  121. src = $2
  122. dst = $3
  123. while ((i = index(src, "/"))) src = substr(src, i+1)
  124. while ((i = index(dst, "/"))) dst = substr(dst, i+1)
  125. if (src != dst) tz = $3
  126. } else if ($1 == "Rule") {
  127. ruleDefined[$2] = 1
  128. } else {
  129. ruleUsed[$2] = 1
  130. }
  131. if (tz && tz ~ /\//) {
  132. if (!tztab[tz]) {
  133. printf "%s: no data for '%s'\n", zone_table, tz \
  134. >>"/dev/stderr"
  135. status = 1
  136. }
  137. zoneSeen[tz] = 1
  138. }
  139. }
  140. END {
  141. for (tz in ruleDefined) {
  142. if (!ruleUsed[tz]) {
  143. printf "%s: Rule never used\n", tz
  144. status = 1
  145. }
  146. }
  147. for (tz in tztab) {
  148. if (!zoneSeen[tz]) {
  149. printf "%s:%d: no Zone table for '%s'\n", \
  150. zone_table, tz2NR[tz], tz >>"/dev/stderr"
  151. status = 1
  152. }
  153. }
  154. if (0 < want_warnings) {
  155. for (cc in cc2name) {
  156. if (!cc_used[cc]) {
  157. printf "%s:%d: warning: " \
  158. "no Zone entries for %s (%s)\n", \
  159. iso_table, cc2NR[cc], cc, cc2name[cc]
  160. }
  161. }
  162. }
  163. exit status
  164. }