xref: /freebsd/contrib/tzdata/ziguard.awk (revision e273650f2c538034b45f78e670a89cbf333ab6db)
146bee4edSPhilip Paeps# Convert tzdata source into vanguard or rearguard form.
246bee4edSPhilip Paeps
346bee4edSPhilip Paeps# Contributed by Paul Eggert.  This file is in the public domain.
446bee4edSPhilip Paeps
546bee4edSPhilip Paeps# This is not a general-purpose converter; it is designed for current tzdata.
6e7e2d659SPhilip Paeps# It just converts from current source to main, vanguard, and rearguard forms.
7e7e2d659SPhilip Paeps# Although it might be nice for it to be idempotent, or to be useful
8*e273650fSPhilip Paeps# for converting back and forth between formats,
9e7e2d659SPhilip Paeps# it does not do these nonessential tasks now.
10e7e2d659SPhilip Paeps#
11*e273650fSPhilip Paeps# This script can convert from main to vanguard form and vice versa.
129f9fc6bbSPhilip Paeps# There is no need to convert rearguard to other forms.
1346bee4edSPhilip Paeps#
149142a2a3SPhilip Paeps# When converting to vanguard form, the output can use the line
159142a2a3SPhilip Paeps# "Zone GMT 0 - GMT" which TZUpdater 2.3.2 mistakenly rejects.
169142a2a3SPhilip Paeps#
1746bee4edSPhilip Paeps# When converting to vanguard form, the output can use negative SAVE
1846bee4edSPhilip Paeps# values.
1946bee4edSPhilip Paeps#
2046bee4edSPhilip Paeps# When converting to rearguard form, the output uses only nonnegative
2146bee4edSPhilip Paeps# SAVE values.  The idea is for the output data to simulate the behavior
2246bee4edSPhilip Paeps# of the input data as best it can within the constraints of the
2346bee4edSPhilip Paeps# rearguard format.
2446bee4edSPhilip Paeps
259f9fc6bbSPhilip Paeps# Given a FIELD like "-0:30", return a minute count like -30.
269f9fc6bbSPhilip Paepsfunction get_minutes(field, \
279f9fc6bbSPhilip Paeps		     sign, hours, minutes)
289f9fc6bbSPhilip Paeps{
299f9fc6bbSPhilip Paeps  sign = field ~ /^-/ ? -1 : 1
309f9fc6bbSPhilip Paeps  hours = +field
319f9fc6bbSPhilip Paeps  if (field ~ /:/) {
329f9fc6bbSPhilip Paeps    minutes = field
339f9fc6bbSPhilip Paeps    sub(/[^:]*:/, "", minutes)
349f9fc6bbSPhilip Paeps  }
359f9fc6bbSPhilip Paeps  return 60 * hours + sign * minutes
369f9fc6bbSPhilip Paeps}
379f9fc6bbSPhilip Paeps
389f9fc6bbSPhilip Paeps# Given an OFFSET, which is a minute count like 300 or 330,
399f9fc6bbSPhilip Paeps# return a %z-style abbreviation like "+05" or "+0530".
409f9fc6bbSPhilip Paepsfunction offset_abbr(offset, \
419f9fc6bbSPhilip Paeps		     hours, minutes, sign)
429f9fc6bbSPhilip Paeps{
439f9fc6bbSPhilip Paeps  hours = int(offset / 60)
449f9fc6bbSPhilip Paeps  minutes = offset % 60
459f9fc6bbSPhilip Paeps  if (minutes) {
469f9fc6bbSPhilip Paeps    return sprintf("%+.4d", hours * 100 + minutes);
479f9fc6bbSPhilip Paeps  } else {
489f9fc6bbSPhilip Paeps    return sprintf("%+.2d", hours)
499f9fc6bbSPhilip Paeps  }
509f9fc6bbSPhilip Paeps}
519f9fc6bbSPhilip Paeps
529f9fc6bbSPhilip Paeps# Round TIMESTAMP (a +-hh:mm:ss.dddd string) to the nearest second.
539f9fc6bbSPhilip Paepsfunction round_to_second(timestamp, \
549f9fc6bbSPhilip Paeps			 hh, mm, ss, seconds, dot_dddd, subseconds)
559f9fc6bbSPhilip Paeps{
569f9fc6bbSPhilip Paeps  dot_dddd = timestamp
579f9fc6bbSPhilip Paeps  if (!sub(/^[+-]?[0-9]+:[0-9]+:[0-9]+\./, ".", dot_dddd))
589f9fc6bbSPhilip Paeps    return timestamp
599f9fc6bbSPhilip Paeps  hh = mm = ss = timestamp
609f9fc6bbSPhilip Paeps  sub(/^[-+]?[0-9]+:[0-9]+:/, "", ss)
619f9fc6bbSPhilip Paeps  sub(/^[-+]?[0-9]+:/, "", mm)
629f9fc6bbSPhilip Paeps  sub(/^[-+]?/, "", hh)
639f9fc6bbSPhilip Paeps  seconds = 3600 * hh + 60 * mm + ss
649f9fc6bbSPhilip Paeps  subseconds = +dot_dddd
659f9fc6bbSPhilip Paeps  seconds += 0.5 < subseconds || ((subseconds == 0.5) && (seconds % 2));
669f9fc6bbSPhilip Paeps  return sprintf("%s%d:%.2d:%.2d", timestamp ~ /^-/ ? "-" : "", \
679f9fc6bbSPhilip Paeps		 seconds / 3600, seconds / 60 % 60, seconds % 60)
689f9fc6bbSPhilip Paeps}
699f9fc6bbSPhilip Paeps
7046bee4edSPhilip PaepsBEGIN {
71d81c2dd9SPhilip Paeps  dataform_type["vanguard"] = 1
72d81c2dd9SPhilip Paeps  dataform_type["main"] = 1
73d81c2dd9SPhilip Paeps  dataform_type["rearguard"] = 1
7446bee4edSPhilip Paeps
759f9fc6bbSPhilip Paeps  if (PACKRATLIST) {
769f9fc6bbSPhilip Paeps    while (getline <PACKRATLIST) {
779f9fc6bbSPhilip Paeps      if ($0 ~ /^#/) continue
789f9fc6bbSPhilip Paeps      packratlist[$3] = 1
799f9fc6bbSPhilip Paeps    }
809f9fc6bbSPhilip Paeps  }
819f9fc6bbSPhilip Paeps
82d81c2dd9SPhilip Paeps  # The command line should set DATAFORM.
83d81c2dd9SPhilip Paeps  if (!dataform_type[DATAFORM]) exit 1
849f9fc6bbSPhilip Paeps}
859f9fc6bbSPhilip Paeps
869f9fc6bbSPhilip Paeps$1 == "#PACKRATLIST" && $2 == PACKRATLIST {
879f9fc6bbSPhilip Paeps  sub(/^#PACKRATLIST[\t ]+[^\t ]+[\t ]+/, "")
8846bee4edSPhilip Paeps}
8946bee4edSPhilip Paeps
9046bee4edSPhilip Paeps/^Zone/ { zone = $2 }
9146bee4edSPhilip Paeps
92d81c2dd9SPhilip PaepsDATAFORM != "main" {
935f33eb72SPhilip Paeps  in_comment = $0 ~ /^#/
94d81c2dd9SPhilip Paeps  uncomment = comment_out = 0
95d81c2dd9SPhilip Paeps
96e7e2d659SPhilip Paeps  # If this line should differ due to Czechoslovakia using negative SAVE values,
97d81c2dd9SPhilip Paeps  # uncomment the desired version and comment out the undesired one.
985f33eb72SPhilip Paeps  if (zone == "Europe/Prague" && $0 ~ /^#?[\t ]+[01]:00[\t ]/ \
995f33eb72SPhilip Paeps      && $0 ~ /1947 Feb 23/) {
1009f9fc6bbSPhilip Paeps    if (($(in_comment + 2) != "-") == (DATAFORM != "rearguard")) {
101d81c2dd9SPhilip Paeps      uncomment = in_comment
102d81c2dd9SPhilip Paeps    } else {
103d81c2dd9SPhilip Paeps      comment_out = !in_comment
104d81c2dd9SPhilip Paeps    }
105d81c2dd9SPhilip Paeps  }
10646bee4edSPhilip Paeps
10746bee4edSPhilip Paeps  # If this line should differ due to Ireland using negative SAVE values,
10846bee4edSPhilip Paeps  # uncomment the desired version and comment out the undesired one.
1095f33eb72SPhilip Paeps  Rule_Eire = $0 ~ /^#?Rule[\t ]+Eire[\t ]/
11046bee4edSPhilip Paeps  Zone_Dublin_post_1968 \
1115f33eb72SPhilip Paeps    = (zone == "Europe/Dublin" && $0 ~ /^#?[\t ]+[01]:00[\t ]/ \
11246bee4edSPhilip Paeps       && (!$(in_comment + 4) || 1968 < $(in_comment + 4)))
11346bee4edSPhilip Paeps  if (Rule_Eire || Zone_Dublin_post_1968) {
11446bee4edSPhilip Paeps    if ((Rule_Eire \
11546bee4edSPhilip Paeps	 || (Zone_Dublin_post_1968 && $(in_comment + 3) == "IST/GMT"))	\
1169f9fc6bbSPhilip Paeps	== (DATAFORM != "rearguard")) {
117d81c2dd9SPhilip Paeps      uncomment = in_comment
118d81c2dd9SPhilip Paeps    } else {
119d81c2dd9SPhilip Paeps      comment_out = !in_comment
12046bee4edSPhilip Paeps    }
12146bee4edSPhilip Paeps  }
122d81c2dd9SPhilip Paeps
1232c5e84ccSPhilip Paeps  # If this line should differ due to Namibia using negative SAVE values,
124d81c2dd9SPhilip Paeps  # uncomment the desired version and comment out the undesired one.
1255f33eb72SPhilip Paeps  Rule_Namibia = $0 ~ /^#?Rule[\t ]+Namibia[\t ]/
126d81c2dd9SPhilip Paeps  Zone_using_Namibia_rule \
1275f33eb72SPhilip Paeps    = (zone == "Africa/Windhoek" && $0 ~ /^#?[\t ]+[12]:00[\t ]/ \
128d81c2dd9SPhilip Paeps       && ($(in_comment + 2) == "Namibia" \
129e35a01eeSPhilip Paeps	   || ($(in_comment + 2) == "-" && $(in_comment + 3) == "CAT" \
130e35a01eeSPhilip Paeps	       && ((1994 <= $(in_comment + 4) && $(in_comment + 4) <= 2017) \
131e35a01eeSPhilip Paeps		   || in_comment + 3 == NF))))
132d81c2dd9SPhilip Paeps  if (Rule_Namibia || Zone_using_Namibia_rule) {
133d81c2dd9SPhilip Paeps    if ((Rule_Namibia \
1349f9fc6bbSPhilip Paeps	 ? ($9 ~ /^-/ || ($9 == 0 && $10 == "CAT")) \
135d81c2dd9SPhilip Paeps	 : $(in_comment + 1) == "2:00" && $(in_comment + 2) == "Namibia") \
1369f9fc6bbSPhilip Paeps	== (DATAFORM != "rearguard")) {
1379f9fc6bbSPhilip Paeps      uncomment = in_comment
1389f9fc6bbSPhilip Paeps    } else {
1399f9fc6bbSPhilip Paeps      comment_out = !in_comment
1409f9fc6bbSPhilip Paeps    }
1419f9fc6bbSPhilip Paeps  }
1429f9fc6bbSPhilip Paeps
1439f9fc6bbSPhilip Paeps  # If this line should differ due to Portugal benefiting from %z if supported,
144*e273650fSPhilip Paeps  # comment out the undesired version and uncomment the desired one.
145*e273650fSPhilip Paeps  if ($0 ~ /^#?[\t ]+-[12]:00[\t ]+((Port|W-Eur)[\t ]+[%+-]|-[\t ]+(%z|-01)[\t ]+1982 Mar 28)/) {
146*e273650fSPhilip Paeps    if (($0 ~ /%z/) == (DATAFORM == "rearguard")) {
147d81c2dd9SPhilip Paeps      comment_out = !in_comment
148*e273650fSPhilip Paeps    } else {
149*e273650fSPhilip Paeps      uncomment = in_comment
150d81c2dd9SPhilip Paeps    }
151d81c2dd9SPhilip Paeps  }
152d81c2dd9SPhilip Paeps
1539142a2a3SPhilip Paeps  # In vanguard form, use the line "Zone GMT 0 - GMT" instead of
1549142a2a3SPhilip Paeps  # "Zone Etc/GMT 0 - GMT" and adjust Link lines accordingly.
1559142a2a3SPhilip Paeps  # This works around a bug in TZUpdater 2.3.2.
1569142a2a3SPhilip Paeps  if (/^#?(Zone|Link)[\t ]+(Etc\/)?GMT[\t ]/) {
1579142a2a3SPhilip Paeps    if (($2 == "GMT") == (DATAFORM == "vanguard")) {
1589142a2a3SPhilip Paeps      uncomment = in_comment
1599142a2a3SPhilip Paeps    } else {
1609142a2a3SPhilip Paeps      comment_out = !in_comment
1619142a2a3SPhilip Paeps    }
1629142a2a3SPhilip Paeps  }
1639142a2a3SPhilip Paeps
164d81c2dd9SPhilip Paeps  if (uncomment) {
165d81c2dd9SPhilip Paeps    sub(/^#/, "")
166d81c2dd9SPhilip Paeps  }
167d81c2dd9SPhilip Paeps  if (comment_out) {
168d81c2dd9SPhilip Paeps    sub(/^/, "#")
169d81c2dd9SPhilip Paeps  }
170b9994124SPhilip Paeps
171*e273650fSPhilip Paeps  # Prefer explicit abbreviations in rearguard form, %z otherwise.
172*e273650fSPhilip Paeps  if (DATAFORM == "rearguard") {
1735f33eb72SPhilip Paeps    if ($0 ~ /^[^#]*%z/) {
1745f33eb72SPhilip Paeps      stdoff_column = 2 * ($0 ~ /^Zone/) + 1
1759f9fc6bbSPhilip Paeps      rules_column = stdoff_column + 1
1769f9fc6bbSPhilip Paeps      stdoff = get_minutes($stdoff_column)
1779f9fc6bbSPhilip Paeps      rules = $rules_column
1789f9fc6bbSPhilip Paeps      stdabbr = offset_abbr(stdoff)
1799f9fc6bbSPhilip Paeps      if (rules == "-") {
1809f9fc6bbSPhilip Paeps	abbr = stdabbr
1819f9fc6bbSPhilip Paeps      } else {
1829f9fc6bbSPhilip Paeps	dstabbr_only = rules ~ /^[+0-9-]/
1839f9fc6bbSPhilip Paeps	if (dstabbr_only) {
1849f9fc6bbSPhilip Paeps	  dstoff = get_minutes(rules)
1859f9fc6bbSPhilip Paeps	} else {
1869f9fc6bbSPhilip Paeps	  # The DST offset is normally an hour, but there are special cases.
1879f9fc6bbSPhilip Paeps	  if (rules == "Morocco" && NF == 3) {
1889f9fc6bbSPhilip Paeps	    dstoff = -60
1899f9fc6bbSPhilip Paeps	  } else if (rules == "NBorneo") {
1909f9fc6bbSPhilip Paeps	    dstoff = 20
1919f9fc6bbSPhilip Paeps	  } else if (((rules == "Cook" || rules == "LH") && NF == 3) \
1929f9fc6bbSPhilip Paeps		     || (rules == "Uruguay" \
1935f33eb72SPhilip Paeps			 && $0 ~ /[\t ](1942 Dec 14|1960|1970|1974 Dec 22)$/)) {
1949f9fc6bbSPhilip Paeps	    dstoff = 30
1955f33eb72SPhilip Paeps	  } else if (rules == "Uruguay" && $0 ~ /[\t ]1974 Mar 10$/) {
1969f9fc6bbSPhilip Paeps	    dstoff = 90
1979f9fc6bbSPhilip Paeps	  } else {
1989f9fc6bbSPhilip Paeps	    dstoff = 60
1999f9fc6bbSPhilip Paeps	  }
2009f9fc6bbSPhilip Paeps	}
2019f9fc6bbSPhilip Paeps	dstabbr = offset_abbr(stdoff + dstoff)
2029f9fc6bbSPhilip Paeps	if (dstabbr_only) {
2039f9fc6bbSPhilip Paeps	  abbr = dstabbr
2049f9fc6bbSPhilip Paeps	} else {
2059f9fc6bbSPhilip Paeps	  abbr = stdabbr "/" dstabbr
2069f9fc6bbSPhilip Paeps	}
2079f9fc6bbSPhilip Paeps      }
2089f9fc6bbSPhilip Paeps      sub(/%z/, abbr)
2099f9fc6bbSPhilip Paeps    }
210*e273650fSPhilip Paeps  } else {
211*e273650fSPhilip Paeps    sub(/^(Zone[\t ]+[^\t ]+)?[\t ]+[^\t ]+[\t ]+[^\t ]+[\t ]+[-+][^\t ]+/, \
212*e273650fSPhilip Paeps	"&CHANGE-TO-%z")
213*e273650fSPhilip Paeps    sub(/-00CHANGE-TO-%z/, "-00")
214*e273650fSPhilip Paeps    sub(/[-+][^\t ]+CHANGE-TO-/, "")
2159f9fc6bbSPhilip Paeps  }
2169f9fc6bbSPhilip Paeps
2179f9fc6bbSPhilip Paeps  # Normally, prefer whole seconds.  However, prefer subseconds
2189f9fc6bbSPhilip Paeps  # if generating vanguard form and the otherwise-undocumented
2199f9fc6bbSPhilip Paeps  # VANGUARD_SUBSECONDS environment variable is set.
2209f9fc6bbSPhilip Paeps  # This relies on #STDOFF comment lines in the data.
2219f9fc6bbSPhilip Paeps  # It is for hypothetical clients that support UT offsets that are
2229f9fc6bbSPhilip Paeps  # not integer multiples of one second (e.g., Europe/Lisbon, 1884 to 1912).
2239f9fc6bbSPhilip Paeps  # No known clients need this currently, and this experimental
2249f9fc6bbSPhilip Paeps  # feature may be changed or withdrawn in future releases.
2259f9fc6bbSPhilip Paeps  if ($1 == "#STDOFF") {
2269f9fc6bbSPhilip Paeps    stdoff = $2
2279f9fc6bbSPhilip Paeps    rounded_stdoff = round_to_second(stdoff)
2289f9fc6bbSPhilip Paeps    if (DATAFORM == "vanguard" && ENVIRON["VANGUARD_SUBSECONDS"]) {
2299f9fc6bbSPhilip Paeps      stdoff_subst[0] = rounded_stdoff
2309f9fc6bbSPhilip Paeps      stdoff_subst[1] = stdoff
2319f9fc6bbSPhilip Paeps    } else {
2329f9fc6bbSPhilip Paeps      stdoff_subst[0] = stdoff
2339f9fc6bbSPhilip Paeps      stdoff_subst[1] = rounded_stdoff
2349f9fc6bbSPhilip Paeps    }
2359f9fc6bbSPhilip Paeps  } else if (stdoff_subst[0]) {
2365f33eb72SPhilip Paeps    stdoff_column = 2 * ($0 ~ /^Zone/) + 1
2379f9fc6bbSPhilip Paeps    stdoff_column_val = $stdoff_column
2389f9fc6bbSPhilip Paeps    if (stdoff_column_val == stdoff_subst[0]) {
2399f9fc6bbSPhilip Paeps      sub(stdoff_subst[0], stdoff_subst[1])
2409f9fc6bbSPhilip Paeps    } else if (stdoff_column_val != stdoff_subst[1]) {
2419f9fc6bbSPhilip Paeps      stdoff_subst[0] = 0
2429f9fc6bbSPhilip Paeps    }
2439f9fc6bbSPhilip Paeps  }
2449f9fc6bbSPhilip Paeps
2459f9fc6bbSPhilip Paeps  # In rearguard form, change the Japan rule line with "Sat>=8 25:00"
246b9994124SPhilip Paeps  # to "Sun>=9 1:00", to cater to zic before 2007 and to older Java.
2475f33eb72SPhilip Paeps  if ($0 ~ /^Rule/ && $2 == "Japan") {
2489f9fc6bbSPhilip Paeps    if (DATAFORM == "rearguard") {
2499f9fc6bbSPhilip Paeps      if ($7 == "Sat>=8" && $8 == "25:00") {
250b9994124SPhilip Paeps	sub(/Sat>=8/, "Sun>=9")
251b9994124SPhilip Paeps	sub(/25:00/, " 1:00")
252b9994124SPhilip Paeps      }
2539f9fc6bbSPhilip Paeps    } else {
2549f9fc6bbSPhilip Paeps      if ($7 == "Sun>=9" && $8 == "1:00") {
2559f9fc6bbSPhilip Paeps	sub(/Sun>=9/, "Sat>=8")
2569f9fc6bbSPhilip Paeps	sub(/ 1:00/, "25:00")
2572c5e84ccSPhilip Paeps      }
2589f9fc6bbSPhilip Paeps    }
2599f9fc6bbSPhilip Paeps  }
2609f9fc6bbSPhilip Paeps
2619f9fc6bbSPhilip Paeps  # In rearguard form, change the Morocco lines with negative SAVE values
2629f9fc6bbSPhilip Paeps  # to use positive SAVE values.
2639f9fc6bbSPhilip Paeps  if ($2 == "Morocco") {
2645f33eb72SPhilip Paeps    if ($0 ~ /^Rule/) {
2659f9fc6bbSPhilip Paeps      if ($4 ~ /^201[78]$/ && $6 == "Oct") {
2669f9fc6bbSPhilip Paeps	if (DATAFORM == "rearguard") {
2679f9fc6bbSPhilip Paeps	  sub(/\t2018\t/, "\t2017\t")
2689f9fc6bbSPhilip Paeps	} else {
2699f9fc6bbSPhilip Paeps	  sub(/\t2017\t/, "\t2018\t")
2709f9fc6bbSPhilip Paeps	}
2719f9fc6bbSPhilip Paeps      }
2729f9fc6bbSPhilip Paeps
2739f9fc6bbSPhilip Paeps      if (2019 <= $3) {
2749f9fc6bbSPhilip Paeps	if ($8 == "2:00") {
2759f9fc6bbSPhilip Paeps	  if (DATAFORM == "rearguard") {
2762c5e84ccSPhilip Paeps	    sub(/\t0\t/, "\t1:00\t")
2772c5e84ccSPhilip Paeps	  } else {
2789f9fc6bbSPhilip Paeps	    sub(/\t1:00\t/, "\t0\t")
2799f9fc6bbSPhilip Paeps	  }
2809f9fc6bbSPhilip Paeps	} else {
2819f9fc6bbSPhilip Paeps	  if (DATAFORM == "rearguard") {
2822c5e84ccSPhilip Paeps	    sub(/\t-1:00\t/, "\t0\t")
2839f9fc6bbSPhilip Paeps	  } else {
2849f9fc6bbSPhilip Paeps	    sub(/\t0\t/, "\t-1:00\t")
2852c5e84ccSPhilip Paeps	  }
2862c5e84ccSPhilip Paeps	}
2872c5e84ccSPhilip Paeps      }
28846bee4edSPhilip Paeps    }
2899f9fc6bbSPhilip Paeps    if ($1 ~ /^[+0-9-]/ && NF == 3) {
2909f9fc6bbSPhilip Paeps      if (DATAFORM == "rearguard") {
2919f9fc6bbSPhilip Paeps	sub(/1:00\tMorocco/, "0:00\tMorocco")
2929f9fc6bbSPhilip Paeps	sub(/\t\+01\/\+00$/, "\t+00/+01")
2939f9fc6bbSPhilip Paeps      } else {
2949f9fc6bbSPhilip Paeps	sub(/0:00\tMorocco/, "1:00\tMorocco")
2959f9fc6bbSPhilip Paeps	sub(/\t\+00\/+01$/, "\t+01/+00")
2969f9fc6bbSPhilip Paeps      }
2979f9fc6bbSPhilip Paeps    }
2989f9fc6bbSPhilip Paeps  }
2999f9fc6bbSPhilip Paeps}
3009f9fc6bbSPhilip Paeps
3019f9fc6bbSPhilip Paeps/^Zone/ {
3029f9fc6bbSPhilip Paeps  packrat_ignored = FILENAME == PACKRATDATA && PACKRATLIST && !packratlist[$2];
3039f9fc6bbSPhilip Paeps}
3045f33eb72SPhilip Paeps{
3055f33eb72SPhilip Paeps  if (packrat_ignored && $0 !~ /^Rule/) {
3069f9fc6bbSPhilip Paeps    sub(/^/, "#")
3079f9fc6bbSPhilip Paeps  }
3085f33eb72SPhilip Paeps}
30946bee4edSPhilip Paeps
3109142a2a3SPhilip Paeps# Return a link line resulting by changing OLDLINE to link to TARGET
3119142a2a3SPhilip Paeps# from LINKNAME, instead of linking to OLDTARGET from LINKNAME.
3129142a2a3SPhilip Paeps# Align data columns the same as they were in OLDLINE.
3139142a2a3SPhilip Paeps# Also, replace any existing white space followed by comment with COMMENT.
3149142a2a3SPhilip Paepsfunction make_linkline(oldline, target, linkname, oldtarget, comment, \
3159142a2a3SPhilip Paeps		       oldprefix, oldprefixlen, oldtargettabs, \
3169142a2a3SPhilip Paeps		       replsuffix, targettabs)
3179142a2a3SPhilip Paeps{
3189142a2a3SPhilip Paeps  oldprefix = "Link\t" oldtarget "\t"
3199142a2a3SPhilip Paeps  oldprefixlen = length(oldprefix)
3209142a2a3SPhilip Paeps  if (substr(oldline, 1, oldprefixlen) == oldprefix) {
3219142a2a3SPhilip Paeps    # Use tab stops to preserve LINKNAME's column.
3229142a2a3SPhilip Paeps    replsuffix = substr(oldline, oldprefixlen + 1)
3239142a2a3SPhilip Paeps    sub(/[\t ]*#.*/, "", replsuffix)
3249142a2a3SPhilip Paeps    oldtargettabs = int(length(oldtarget) / 8) + 1
3259142a2a3SPhilip Paeps    targettabs = int(length(target) / 8) + 1
3269142a2a3SPhilip Paeps    for (; targettabs < oldtargettabs; targettabs++) {
3279142a2a3SPhilip Paeps      replsuffix = "\t" replsuffix
3289142a2a3SPhilip Paeps    }
3299142a2a3SPhilip Paeps    for (; oldtargettabs < targettabs && replsuffix ~ /^\t/; targettabs--) {
3309142a2a3SPhilip Paeps      replsuffix = substr(replsuffix, 2)
3319142a2a3SPhilip Paeps    }
3329142a2a3SPhilip Paeps  } else {
3339142a2a3SPhilip Paeps    # Odd format line; don't bother lining up its replacement nicely.
3349142a2a3SPhilip Paeps    replsuffix = linkname
3359142a2a3SPhilip Paeps  }
3369142a2a3SPhilip Paeps  return "Link\t" target "\t" replsuffix comment
3379142a2a3SPhilip Paeps}
3389142a2a3SPhilip Paeps
3399142a2a3SPhilip Paeps/^Link/ && $4 == "#=" && DATAFORM == "vanguard" {
3409142a2a3SPhilip Paeps  $0 = make_linkline($0, $5, $3, $2)
3419142a2a3SPhilip Paeps}
3429142a2a3SPhilip Paeps
34394c2d487SPhilip Paeps# If a Link line is followed by a Link or Zone line for the same data, comment
34446bee4edSPhilip Paeps# out the Link line.  This can happen if backzone overrides a Link
34594c2d487SPhilip Paeps# with a Zone or a different Link.
34646bee4edSPhilip Paeps/^Zone/ {
34746bee4edSPhilip Paeps  sub(/^Link/, "#Link", line[linkline[$2]])
34846bee4edSPhilip Paeps}
34994c2d487SPhilip Paeps/^Link/ {
35094c2d487SPhilip Paeps  sub(/^Link/, "#Link", line[linkline[$3]])
35194c2d487SPhilip Paeps  linkline[$3] = NR
3529142a2a3SPhilip Paeps  linktarget[$3] = $2
35394c2d487SPhilip Paeps}
35446bee4edSPhilip Paeps
35546bee4edSPhilip Paeps{ line[NR] = $0 }
35646bee4edSPhilip Paeps
3579142a2a3SPhilip Paepsfunction cut_link_chains_short( \
3589142a2a3SPhilip Paeps			       l, linkname, t, target)
3599142a2a3SPhilip Paeps{
3609142a2a3SPhilip Paeps  for (linkname in linktarget) {
3619142a2a3SPhilip Paeps    target = linktarget[linkname]
3629142a2a3SPhilip Paeps    t = linktarget[target]
3639142a2a3SPhilip Paeps    if (t) {
3649142a2a3SPhilip Paeps      # TARGET is itself a link name.  Replace the line "Link TARGET LINKNAME"
3659142a2a3SPhilip Paeps      # with "Link T LINKNAME #= TARGET", where T is at the end of the chain
3669142a2a3SPhilip Paeps      # of links that LINKNAME points to.
3679142a2a3SPhilip Paeps      while ((u = linktarget[t])) {
3689142a2a3SPhilip Paeps	t = u
3699142a2a3SPhilip Paeps      }
3709142a2a3SPhilip Paeps      l = linkline[linkname]
3719142a2a3SPhilip Paeps      line[l] = make_linkline(line[l], t, linkname, target, "\t#= " target)
3729142a2a3SPhilip Paeps    }
3739142a2a3SPhilip Paeps  }
3749142a2a3SPhilip Paeps}
3759142a2a3SPhilip Paeps
37646bee4edSPhilip PaepsEND {
3779142a2a3SPhilip Paeps  if (DATAFORM != "vanguard") {
3789142a2a3SPhilip Paeps    cut_link_chains_short()
3799142a2a3SPhilip Paeps  }
38046bee4edSPhilip Paeps  for (i = 1; i <= NR; i++)
38146bee4edSPhilip Paeps    print line[i]
38246bee4edSPhilip Paeps}
383