#
# Program: make_timezonelist.pl
#
# Copyright 2003 Double Precision, Inc.  See COPYING for
# distribution information.
#
# Author: Sam Varshavchik <mrsam@courier-mta.com>
#
#
#       Original Author: Paul L. Allen <pla@softflare.com>
#
#       Version: pla-0.1, 11-Aug-2003
#
# Purpose: uses Olsen zoneinfo data to generate TIMEZONELIST
#
# OS: most recent release of *nix that include the Olsen TZ system.
#
# Warning: if you have updated the TZ source files without recompiling
# then then some of the timezones generated by this program won't
# work.  But you wouldn't forget to recompile, would you?
#
# Copyright conditions: do whatever you want with it provided that if
# you make changes and distribute the changed version you:
#
#   1) Replace the author with your contact details so I don't get people
#   asking me what's wrong with your changed version.
#
#   2) Add an "Original Author:" line with my contact details.
#
#   3) Change the version to be prefixed with your initials rather than
#   mine.


# List of possible paths to the zoneinfo directory with the most common
# cases first.  Let me know if there are any others that should be included.
@zoneinfo_dirs = qw
(
   /usr/share/zoneinfo
   /usr/local/etc/zoneinfo
   /usr/compat/linux/usr/share/zoneinfo
   /usr/share/lib/zoneinfo
);

foreach $dir (@zoneinfo_dirs)
{
  if (-d($dir))
  {
    $zoneinfo_dir = $dir;
    last;
  }
}
die "Could not find a zoneinfo directory\n" unless ($zoneinfo_dir);
if ( $^O eq "freebsd" )
{
  $iso3166tab = "/usr/share/misc/iso3166";
}
elsif ( $^O eq "netbsd" )
{
  $iso3166tab = "/usr/share/misc/domains"
}
else
{
  $iso3166tab = "$zoneinfo_dir/iso3166.tab";
}
$zonetab = "$zoneinfo_dir/zone.tab";
$etc_dir = "$zoneinfo_dir/Etc";

$output = 'TIMEZONELIST';

open(ISO3166, $iso3166tab) ||
  die "Could not open '$iso3166tab' for reading ($!)\n";
@lines = <ISO3166>;
close(ISO3166);

foreach $line (@lines)
{
  next if ($line =~ /^\s*#/);
  next unless ($line =~ /\S/);
    
  chomp($line);
if ( $^O eq "freebsd" )
{
  ($code, undef, undef, $country) = split(/\t/, $line, 4);
}
else
{
  ($code, $country) = split(/\t/, $line, 2);
}    

  $countries{$code} = $country;
}

# Correct the entry for GB.
$countries{GB} = 'United Kingdom';

if ( open(ZONES, $zonetab) == 0 )
{
  if ( $^O eq "netbsd" )
  {    
    die "Could not open '$zonetab' for reading ($!). Currently, NetBSD does not install zone.tab by default. You must manually fetch sharesrc.tgz from the source of your version and extract zone.tab into /usr/share/zoneinfo\n";
  }  
  else 
  {    
    die "Could not open '$zonetab' for reading ($!)\n";
  }
}
@lines = <ZONES>;
close(ZONES);

foreach $line (@lines)
{
  next if ($line =~ /^\s*#/);
  next unless ($line =~ /\S/);
    
  chomp($line);
  ($country_code, undef, $tz, $comment) = split(/\t/, $line, 4);
    
  $country = $countries{$country_code};
  push(@zones, [lc($country), $tz, $country, $comment]);
  $longest_tz = length($tz) if (length($tz) > $longest_tz);
}

$num_tabs = int($longest_tz / 8) + 1;

@sorted_zones = sort
  {
    $a->[0] cmp $b->[0] ||
    $a->[3] cmp $b->[3] ||
    $a cmp $b
  } @zones;

open(OUT, ">$output") ||
  die "Could not open '$output' for writing ($!)\n";

print OUT '*', "\t" x $num_tabs, "*\n";

foreach $zone (@sorted_zones)
{
  if ($zone->[3])
  {
    print OUT $zone->[1],
      "\t" x ($num_tabs - int(length($zone->[1]) / 8)),
      "$zone->[2]: $zone->[3]\n";
  }
  else
  {
    print OUT $zone->[1],
	"\t" x  ($num_tabs - int(length($zone->[1]) / 8)),
	"$zone->[2]\n";
  }
}

# might not have zoneinfo/Etc on this machine so don't complain if it's
# not there
if (opendir(ETC, $etc_dir))
{
  @objects = readdir(ETC);
  closedir(ETC);

  foreach $object (@objects)
  {
    next unless ($object =~ /^GMT(.*)$/);
    next if ($1 =~ /^[+-]?0$/);
   
    if ($1)
    {
      push(@gmts, [$object, $1]);
    }
    else
    {
      $gmt_no_offset++;
    }
  }

  @sorted_gmts = sort {$b->[1] <=> $a->[1]} (@gmts);

  print OUT 'Etc/GMT', "\t" x $num_tabs, "GMT\n" if ($gmt_no_offset);
    
  foreach $gmt (@sorted_gmts)
  {
    $offset = $gmt->[1];
    $abs_offset = abs($offset);
    $designator = "Etc/GMT$offset";
    
    print OUT $designator,
      "\t" x ($num_tabs - int(length($designator) / 8)),
      "$abs_offset hour",
      ($abs_offset == 1 ? '' : 's'),
      ($offset < 0 ? ' ahead of' : ' behind'),
      " GMT\n";; 
  }

  close(OUT);
}
