pennmush/game/data/
pennmush/game/log/
pennmush/game/save/
pennmush/game/txt/evt/
pennmush/game/txt/nws/
pennmush/os2/
pennmush/po/
pennmush/win32/msvc.net/
pennmush/win32/msvc6/
#!/usr/local/bin/perl
#
# You make have to change the path to perl above, unless you call this
# script with 'make update'
#
# update-cnf.pl - integrate previous mush.cnf settings with new 
#                  mush.cnf.dist. Results appear in mush.cnf
#
# Usage: update-cnf.pl old-file new-file
#  e.g.: update-cnf.pl game/mush.cnf game/mush.cnf.dist
#
# 'make update' calls this program as in the example above.
#
# Here's how it works.
# First, we make a backup of your old-file to old-file.bak
# Then we read all the directives in the old-file, and their
#  associated comments. Associated comments are those which
#  appear on lines preceding the directive.
#  We store the names of all the directives, 
#  their comments, and how they're defined.
# Then we do the same for the new-file. If we find a directive
#  that wasn't in the old-file, we show the user the comment
#  and ask them how they want it set. Every time we write out
#  a directive, we delete it from the list of directives from old-file
# Finally, if there's anything left from old-file that's not in
#  new-file, we ask if the user would like to retain each one.
#  Presumably users want to retain their custom directives, but don't
#  want to retain obsoleted directives. Retained directives appear at
#  the end of the file.

die "Usage: update-cnf.pl old-file new-file\n" unless $#ARGV == 1;

$old = $ARGV[0];
$bak = $old . ".bak";
$new = $ARGV[1];


# Part 1 - back up the old file (inefficient but reliable method)
if (-r $old) {
    print "*** Backing up $old to $bak...\n";
    die "update-cnf.pl: Unable to open $old\n" unless open(OLD,"$old"); 
    die "update-cnf.pl: Unable to open $bak\n" unless open(BAK,">$bak");
    print BAK <OLD>;
    close(BAK);
    close(OLD);
} else {
    # Heck, let's just copy the new file to the old one and quit!
    print "*** Creating $old from $new...\n";
    die "update-cnf.pl: Unable to open $old\n" unless open(OLD,">$old"); 
    die "update-cnf.pl: Unable to open $new\n" unless open(NEW,"$new"); 
    print OLD <NEW>;
    close(OLD);
    close(NEW);
    exit 0;
}
  

# Part 2 - read the settings from the old file and store them
if (-r $old) {
    print "*** Reading your settings from $old...\n";
    die "update-cnf.pl: Unable to open $old\n" unless open(OLD,"$old"); 
    while (<OLD>) {
	# We can have comments, which start with #,
        # or directives, which start with anything else.
	if (/^#/) {
	  # A comment
 	  push(@comment,$_);
	} elsif (/^(\S+)\s+(.+)$/) {
	  # A directive
	  $key = $1; $val = $2;
	  chop;
	  if (defined($directive{$key})) {
	      # This is a repeatable directive! 
	      $num{$key}++;
	      $directive{"$key/$num{$key}"} = $val;
	      $comment{"$key/$num{$key}"} = join("",@comment);
	  } else {
	      $directive{$key} = $val; 
	      $comment{$key} = join("",@comment);
	  }
	  undef @comment;
        } elsif (/^(\S+)/) {
          # A directive that's defined as blank
          $key = $1; $val = "";
          $directive{$key} = $val;
	  $comment{$key} = join("",@comment);
          undef @comment;
    	} elsif (/^$/) {
	  # A blank line. Ignore comments so far
	  undef @comment;
	}
    }
    close(OLD);
}

# Part 3 - read in the new file, modifying its definition lines to
#          match the old file. If we come across a definition that
#          isn't in the old file, ask the user about it. 
print "*** Updating $old from $new...\n";
die "update-cnf.pl: Unable to open $old\n" unless open(OLD,">$old"); 
die "update-cnf.pl: Unable to open $new\n" unless open(NEW,"$new"); 
while (<NEW>) {
    # We can have comments, which start with #,
    # or directives, which start with anything else.
    if (/^#/) {
	# A comment
	push(@comment,$_);
    } elsif (/^(\S+)/) {
	# Not a comment
	$key = $1;
	chop;
	if ($num{$key}) {
	    if ($num{$key} > 0) {
		# A repeatable directive!
		# Spew them all here. It's probably the best we can do.
		print OLD @comment;
		print OLD "$key\t$directive{$key}\n\n";
		delete $comment{$key};
		for ($i = 1; $i <= $num{$key}; $i++) {
		    print OLD $comment{"$key/$i"};
		    print OLD "$key\t", $directive{"$key/$i"},"\n\n";
		    delete $comment{"$key/$i"};
		    delete $directive{"$key/$i"};
		} 
		$num{$key} = -1; # Don't spew again
	    }
	} else {
	    print OLD @comment;
	    if (!defined($directive{$key}) || $key eq "include") {
		# It's new, just add it
		print OLD $_,"\n";
		push(@newoptions,$key);
              delete $comment{$key} if $key eq "include";
	    } else {
		# It's old. Put it in, with a value if one's set.
		print OLD $key;
		print OLD "\t$directive{$key}" if (defined($directive{$key}));
		print OLD "\n";
		# Remove its comment.
		delete $comment{$key};
	    }
	}
	undef @comment;
    } elsif (/^$/) {
	print OLD @comment;
	undef @comment;
	print OLD;
    } else {
	print OLD;
    }
}
close(NEW);

# Part 4 - if there are any definitions left from the old file,
#          offer to delete them (or not)
print "\n*** Checking for leftover defines from $old...\n";
foreach $d (sort { $directive{$a} cmp $directive{$b} } keys %comment) {
    $newd = $d;
    $newd =~ s!/.*!!;
    print "\nI found:\n";
    print $comment{$d};
    print "$newd\t$directive{$d}\n";
    print "\n";
    print "If this is a directive that you hacked in, you probably should retain it.\n";
    print "If not, it's probably an obsolete directive from an earlier release,\n";
    print "and you need not retain it.\n";
    print "Do you want to retain this in your $old file? [y] ";
    $yn = <STDIN>;
    if ($yn !~ /^[Nn]/) {
	print "Retaining directive. It will appear at the end of $old.\n";
        @retained = (@retained, $newd);
	print OLD $comment{$d};
	print OLD "$newd\t$directive{$d}\n";
	print OLD "\n";
    } else {
	print "Deleting definition.\n";
	@deleted = (@deleted, $d);
    }
}
close(OLD);

print "\nSummary of changes:\n";
print "New options from $new: ",join(" ",@newoptions),"\n";
print "Old options retained: ",join(" ",@retained),"\n";
print "Old options deleted: ",join(" ",@deleted),"\n";
print "If this is wrong, you can recover $old from $bak.\n";
print "Done!\n";
exit 0;