summaryrefslogtreecommitdiffstats
path: root/scripts/process-changes.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/process-changes.pl')
-rwxr-xr-xscripts/process-changes.pl844
1 files changed, 844 insertions, 0 deletions
diff --git a/scripts/process-changes.pl b/scripts/process-changes.pl
new file mode 100755
index 0000000..3c4dbbc
--- /dev/null
+++ b/scripts/process-changes.pl
@@ -0,0 +1,844 @@
+#!/usr/bin/perl -w
+#
+# Format changes TSV file
+#
+# USAGE:
+# process-changes.pl [OPTIONS] CHANGES-TSV-FILE
+#
+# Copyright (C) 2010-2011, David Beckett http://www.dajobe.org/
+#
+# This package is Free Software and part of Redland http://librdf.org/
+#
+# It is licensed under the following three licenses as alternatives:
+# 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
+# 2. GNU General Public License (GPL) V2 or any newer version
+# 3. Apache License, V2.0 or any newer version
+#
+# You may not use this file except in compliance with at least one of
+# the above three licenses.
+#
+# See LICENSE.html or LICENSE.txt at the top of this package for the
+# complete terms and further detail along with the license texts for
+# the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
+#
+#
+# Example of Format (9 fields):
+# OLD VERSION<tab>type | enum | OLD RETURN<tab>OLD NAME<tab>OLD ARGS<tab>NEW VERSION<tab>type | enum | NEW RETURN<tab>NEW NAME<tab>NEW ARGS<tab>NOTES
+#
+# Functions
+# 0.9.21<tab>void<tab>oldfunctionor-<tab>(args)<tab>0.9.22<tab>void<tab>newfunctionor-<tab>(args)<tab>NOTES
+# Types
+# 0.9.21<tab>type<tab>oldtypenameor-<tab>-<tab>0.9.22<tab>type<tab>newtypeor-<tab>-<tab>NOTES
+# Enums
+# 0.9.21<tab>enum<tab>oldenumvalueor-<tab>-<tab>0.9.22<tab>enum<tab>newenumvalueor-<tab>-<tab>NOTES
+#
+
+use strict;
+use File::Basename;
+use IO::File;
+use Getopt::Long;
+use Pod::Usage;
+
+our $program = basename $0;
+
+our $nbsp = '&#160;';
+
+our $id_prefix = undef;
+
+our $raptor_v1_version = '1.4.21';
+
+sub print_start_chapter_as_docbook_xml($$$$) {
+ my($fh, $id, $title, $intro_para)=@_;
+
+ print $fh <<"EOT";
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+<chapter id="$id">
+<title>$title</title>
+
+<para>$intro_para</para>
+EOT
+
+}
+
+sub print_end_chapter_as_docbook_xml($)
+{
+ my($fh)=@_;
+ print $fh <<"EOT";
+
+</chapter>
+EOT
+}
+
+
+
+sub print_docbook_xml($$$@) {
+ my($fh, $id, $title, @list)=@_;
+
+ print $fh <<"EOT";
+<section id="$id">
+<title>$title</title>
+EOT
+
+ print $fh <<"EOT";
+</section>
+EOT
+}
+
+sub print_start_section_as_docbook_xml($$$) {
+ my($fh, $id, $title)=@_;
+
+ print $fh <<"EOT";
+<section id="$id">
+<title>$title</title>
+
+EOT
+}
+
+
+sub format_function_name_as_docbook_xml($) {
+ my($name)=@_;
+
+ my $escaped_name = $name; $escaped_name =~ s/_/-/g;
+ return qq{<link linkend="$escaped_name"><function>$name</function></link>};
+}
+
+sub format_type_name_as_docbook_xml($) {
+ my($name)=@_;
+
+ my $escaped_name = $name; $escaped_name =~ s/_/-/g;
+ if($escaped_name =~ /^[-A-Z0-9]+$/) {
+ $escaped_name .= ":CAPS";
+ }
+ return qq{<link linkend="$escaped_name"><type>$name</type></link>};
+}
+
+sub format_enum_name_as_docbook_xml($) {
+ my($name)=@_;
+
+ my $escaped_name = $name; $escaped_name =~ s/_/-/g;
+ if($escaped_name =~ /^[-A-Z0-9]+$/) {
+ $escaped_name .= ":CAPS";
+ }
+ return qq{<link linkend="$escaped_name"><literal>$name</literal></link>};
+}
+
+
+sub format_fn_sig($$$$$) {
+ my($format_name, $show_sig, $fn_return, $fn_name, $fn_args)=@_;
+ my $formatted_name = $format_name ? format_function_name_as_docbook_xml($fn_name) : $fn_name;
+
+ return $show_sig ? $fn_return . " " . $formatted_name . $fn_args
+ : $formatted_name;
+}
+
+sub format_notes($$) {
+ my($is_inline,$notes)=@_;
+
+ if ($notes eq '') {
+ return $is_inline ? '' : $nbsp;
+ }
+
+ $notes =~ s{#((?:raptor|librdf|rasqal)\w+)}{format_type_name_as_docbook_xml($1)}ge;
+ $notes =~ s{#?((?:RAPTOR|LIBRDF|RASQAL)_\w+)}{format_enum_name_as_docbook_xml($1)}ge;
+ $notes =~ s{((?:raptor|librdf|rasqal)_\w+?)\(}{format_function_name_as_docbook_xml($1)."("}ge;
+
+ return $is_inline ? "- " . $notes : $notes;
+}
+
+sub print_functions_list_as_docbook_xml($$$$@) {
+ my($fh, $title, $format_name, $show_sig, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+ <itemizedlist>
+ <title>Functions</title>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ # Sort by fn_name name
+ @list = sort { $a->[1] cmp $b->[1] } @list;
+
+ for my $item (@list) {
+ my($fn_return, $fn_name, $fn_args, $notes) = @$item;
+ my $formatted_fn = format_fn_sig($format_name, $show_sig,
+ $fn_return, $fn_name, $fn_args);
+ $notes = format_notes(1, $notes);
+ print $fh " <listitem><para>$formatted_fn $notes</para></listitem>\n";
+ }
+ print $fh <<"EOT";
+ </itemizedlist>
+EOT
+}
+
+
+sub format_type_sig($$) {
+ my($format_name, $type_name)=@_;
+ return $format_name ? format_type_name_as_docbook_xml($type_name) : $type_name;
+}
+
+sub format_enum_sig($$) {
+ my($format_name, $enum_name)=@_;
+ return $format_name ? format_enum_name_as_docbook_xml($enum_name) : $enum_name;
+}
+
+
+sub print_types_list_as_docbook_xml($$$$@) {
+ my($fh, $title, $format_name, $show_sig, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+ <itemizedlist>
+ <title>Types</title>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ # Sort by type name
+ @list = sort { $a->[0] cmp $b->[0] } @list;
+
+ for my $item (@list) {
+ my($type_name, $notes) = @$item;
+ my $formatted_fn = format_type_sig($format_name, $type_name);
+ $notes = format_notes(1, $notes);
+ print $fh " <listitem><para>$formatted_fn $notes</para></listitem>\n";
+ }
+ print $fh <<"EOT";
+ </itemizedlist>
+EOT
+}
+
+
+sub print_enums_list_as_docbook_xml($$$$@) {
+ my($fh, $title, $format_name, $show_sig, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+ <itemizedlist>
+ <title>Enums and Constants</title>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ # Sort by format name
+ @list = sort { $a->[0] cmp $b->[0] } @list;
+
+ for my $item (@list) {
+ my($enum_name, $notes) = @$item;
+ my $formatted_fn = format_enum_sig($format_name, $enum_name);
+ $notes = format_notes(1, $notes);
+ print $fh " <listitem><para>$formatted_fn $notes</para></listitem>\n";
+ }
+ print $fh <<"EOT";
+ </itemizedlist>
+EOT
+}
+
+
+sub print_renamed_functions_as_docbook_xml($$$$@) {
+ my($fh, $title, $old_function_header, $new_function_header, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+<table border='1'>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ # Sort by from name
+ @list = sort { $a->[0] cmp $b->[0] } @list;
+
+ print $fh <<"EOT";
+ <thead>
+ </thead>
+ <tbody>
+ <tr>
+ <th>$old_function_header</th>
+ <th>$new_function_header</th>
+ <th>Notes</th>
+ </tr>
+EOT
+ for my $item (@list) {
+ my($from, $to, $notes) = @$item;
+ my $formatted_name = format_function_name_as_docbook_xml($to);
+
+ $notes = format_notes(0, $notes);
+ print $fh " <tr valign='top'>\n <td>$from</td> <td>$formatted_name</td> <td>$notes</td>\n </tr>\n";
+ }
+ print $fh <<"EOT";
+ </tbody>
+</table>
+EOT
+
+}
+
+sub print_changed_functions_as_docbook_xml($$$$@) {
+ my($fh, $title, $old_function_header, $new_function_header, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+<table border='1'>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ print $fh <<"EOT";
+ <thead>
+ </thead>
+ <tbody>
+ <tr>
+ <th>$old_function_header</th>
+ <th>$new_function_header</th>
+ <th>Notes</th>
+ </tr>
+EOT
+ for my $item (@list) {
+ my($old_fn_return, $old_fn_name, $old_fn_args,
+ $new_fn_return, $new_fn_name, $new_fn_args, $notes) = @$item;
+
+ my $old_formatted_fn = format_fn_sig(0, 1,
+ $old_fn_return, $old_fn_name, $old_fn_args);
+
+ my $new_formatted_fn = format_fn_sig(1, 1,
+ $new_fn_return, $new_fn_name, $new_fn_args);
+
+ $notes = format_notes(0, $notes);
+ print $fh " <tr valign='top'>\n <td>$old_formatted_fn</td> <td>$new_formatted_fn</td> <td>$notes</td>\n </tr>\n";
+ }
+ print $fh <<"EOT";
+ </tbody>
+</table>
+EOT
+
+}
+
+sub print_end_section_as_docbook_xml($)
+{
+ my($fh)=@_;
+ print $fh <<"EOT";
+
+</section>
+EOT
+}
+
+
+sub print_changed_types_as_docbook_xml($$$$@) {
+ my($fh, $title, $old_type_header, $new_type_header, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+<table border='1'>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ # Sort by old type name
+ @list = sort { $a->[0] cmp $b->[0] } @list;
+
+ print $fh <<"EOT";
+ <thead>
+ </thead>
+ <tbody>
+ <tr>
+ <th>$old_type_header</th>
+ <th>$new_type_header</th>
+ <th>Notes</th>
+ </tr>
+EOT
+ for my $item (@list) {
+ my($old_type_name, $new_type_name, $notes) = @$item;
+
+ my $old_formatted_type = format_type_sig(0, $old_type_name);
+ my $new_formatted_type = format_type_sig(1, $new_type_name);
+
+ $notes = format_notes(0, $notes);
+ print $fh " <tr valign='top'>\n <td>$old_formatted_type</td> <td>$new_formatted_type</td> <td>$notes</td>\n </tr>\n";
+ }
+ print $fh <<"EOT";
+ </tbody>
+</table>
+EOT
+
+}
+
+
+sub print_renamed_enums_as_docbook_xml($$$$@) {
+ my($fh, $title, $old_enum_header, $new_enum_header, @list)=@_;
+
+ return if !@list;
+
+ print $fh <<"EOT";
+<table border='1'>
+EOT
+
+ print $fh " <caption>$title</caption>\n"
+ if defined $title;
+
+ # Sort by from name
+ @list = sort { $a->[0] cmp $b->[0] } @list;
+
+ print $fh <<"EOT";
+ <thead>
+ </thead>
+ <tbody>
+ <tr>
+ <th>$old_enum_header</th>
+ <th>$new_enum_header</th>
+ <th>Notes</th>
+ </tr>
+EOT
+ for my $item (@list) {
+ my($from, $to, $notes) = @$item;
+ my $formatted_name = format_enum_name_as_docbook_xml($to);
+
+ $notes = format_notes(0, $notes);
+ print $fh " <tr valign='top'>\n <td>$from</td> <td>$formatted_name</td> <td>$notes</td>\n </tr>\n";
+ }
+ print $fh <<"EOT";
+ </tbody>
+</table>
+EOT
+
+}
+
+
+sub print_deletes_as_perl_script($$@) {
+ my($out_fh, $title, @names) = @_;
+
+ print $out_fh "\n# $title\n";
+
+ for my $entry (@names) {
+ my($name,$note)=@$entry;
+ $note ||= '';
+ print $out_fh qq{s|^(.*$name.*)\$|/\\* WARNING: $name - deleted. $note \\*/ \$1|g;\n};
+ }
+}
+
+
+sub print_renames_as_perl_script($$$@) {
+ my($out_fh, $title, $is_function, @names) = @_;
+
+ print $out_fh "\n# $title\n";
+
+ for my $entry (@names) {
+ my($from, $to, $note)=@$entry;
+ $note ||= '';
+ my $suffix = ($is_function ? '\\(' : '');
+ print $out_fh qq{s|$from$suffix|$to$suffix|g;\n};
+ }
+}
+
+
+sub print_changes_as_perl_script($$@) {
+ my($out_fh, $title, @names) = @_;
+
+ print $out_fh "\n# $title\n";
+
+ for my $entry (@names) {
+ my($from, $to, $note)=@$entry;
+ $note ||= '';
+ print $out_fh qq{s|^(.*)($from)(.*)\$|/\\* WARNING: $from. $note \\*/ \$\{1\}$to\$\{3\}|g;\n};
+ }
+}
+
+
+sub print_statement_field_renames_as_perl_script($) {
+ my($out_fh)=@_;
+ # These are tricky / tedious to deal with entirely by hand but
+ # the replacement for subject and object can only be determined by a person
+ my(%statement_field_maps) = (
+ 'subject' => 'subject.value.uri or subject.value.blank.string /* WARNING: must choose one */',
+ 'subject_type' => 'subject.type',
+ 'predicate' => 'predicate.value.uri',
+ 'predicate_type' => 'predicate.type',
+ 'object' => 'object.value.uri or object.value.literal.string or object.value.blank.string /* WARNING: must choose one */',
+ 'object_type' => 'object.type',
+ 'object_literal_datatype' => 'object.value.literal.datatype',
+ 'object_literal_language' => 'object.value.literal.language'
+ );
+ print $out_fh "\n# Replace statement fields with term fields.\n";
+ while(my($old,$new) = each %statement_field_maps) {
+ print $out_fh qq{s|->$old|->$new|g;\n};
+ }
+ print $out_fh "\n";
+}
+
+
+sub to_id($) {
+ my $id=shift;
+
+ $id =~ s/\W/-/g;
+ $id =~ s/\-+/-/g;
+ $id =~ s/^\-//;
+ $id =~ s/\-$//;
+
+ return $id;
+}
+
+
+# main
+
+my $docbook_xml_file = undef;
+my $upgrade_script_file = undef;
+my $usage = undef;
+
+GetOptions(
+ 'docbook-xml=s' => \$docbook_xml_file,
+ 'upgrade-script=s' => \$upgrade_script_file,
+ 'package=s' => \$id_prefix,
+ 'help|h|?' => \$usage
+) || pod2usage(2);
+
+pod2usage(-verbose => 2)
+ if $usage;
+
+# Arguments
+our($package, $file) = @ARGV;
+
+$id_prefix ||= $package;
+
+# Read in data
+
+our $expected_n_fields = 9;
+
+# "$old-$new" versions in order
+our(@version_pairs);
+# and seen
+our(%version_pairs_seen);
+
+# Hashes keyed by $version_pair. Value is array of descriptive
+# arrays specific to each type
+my(%new_functions);
+my(%deleted_functions);
+my(%renamed_functions);
+my(%changed_functions);
+
+my(%new_types);
+my(%deleted_types);
+my(%changed_types);
+
+my(%new_enums);
+my(%deleted_enums);
+my(%renamed_enums);
+
+open(IN, "<$file") or die "$program: Cannot read $file - $!\n";
+while(<IN>) {
+ chomp;
+
+ next if /^#/;
+
+ my(@fields)=split(/\t/);
+ my $actual_n_fields=scalar(@fields);
+ die "$program: Bad line has $actual_n_fields fields expected $expected_n_fields $.: $_\n"
+ unless $actual_n_fields == $expected_n_fields;
+
+ if($fields[1] eq 'type') {
+ my($old_ver, $dummy1, $old_name, $old_args, $new_ver, $dummy2, $new_name, $new_args,$notes)=@fields;
+
+ my $version_pair = $old_ver."-".$new_ver;
+ if(!$version_pairs_seen{$version_pair}) {
+ push(@version_pairs, [$old_ver, $new_ver]);
+ $version_pairs_seen{$version_pair} = 1;
+ }
+
+ $notes = '' if $notes eq '-';
+
+ if($old_name eq '-') {
+ push(@{$new_types{$version_pair}}, [$new_name, $notes]);
+ } elsif($new_name eq '-') {
+ push(@{$deleted_types{$version_pair}}, [$old_name, $notes]);
+ } elsif(($old_name eq $new_name) && $notes eq '') {
+ # same
+ } else {
+ # renamed and maybe something else changed - in the notes
+ push(@{$changed_types{$version_pair}}, [$old_name, $new_name, $notes]);
+ }
+
+ } elsif($fields[1] eq 'enum') {
+ my($old_ver, $dummy1, $old_name, $old_args, $new_ver, $dummy2, $new_name, $new_args,$notes)=@fields;
+
+ my $version_pair = $old_ver."-".$new_ver;
+ if(!$version_pairs_seen{$version_pair}) {
+ push(@version_pairs, [$old_ver, $new_ver]);
+ $version_pairs_seen{$version_pair} = 1;
+ }
+
+ $notes = '' if $notes eq '-';
+
+ if($old_name eq '-') {
+ push(@{$new_enums{$version_pair}}, [$new_name, $notes]);
+ } elsif($new_name eq '-') {
+ push(@{$deleted_enums{$version_pair}}, [$old_name, $notes]);
+ } elsif(($old_name eq $new_name) && $notes eq '') {
+ # same
+ } else {
+ push(@{$renamed_enums{$version_pair}}, [$old_name, $new_name, $notes]);
+ }
+
+ } else {
+ my($old_ver, $old_return, $old_name, $old_args, $new_ver, $new_return, $new_name, $new_args,$notes)=@fields;
+
+ my $version_pair = $old_ver."-".$new_ver;
+ if(!$version_pairs_seen{$version_pair}) {
+ push(@version_pairs, [$old_ver, $new_ver]);
+ $version_pairs_seen{$version_pair} = 1;
+ }
+
+ $notes = '' if $notes eq '-';
+
+ if($old_name eq '-') {
+ push(@{$new_functions{$version_pair}}, [$new_return, $new_name, $new_args, $notes]);
+ } elsif($new_name eq '-') {
+ push(@{$deleted_functions{$version_pair}}, [$old_return, $old_name, $old_args, $notes]);
+ } elsif($old_return eq $new_return && $old_name eq $new_name &&
+ $old_args eq $new_args) {
+ # same
+ warn "$program: Line records no function change old: $old_return $old_name $old_args to new: $new_return $new_name $new_args\n$.: $_\n"
+ if $old_ver ne $raptor_v1_version;
+ } elsif($old_return eq $new_return && $old_name ne $new_name &&
+ $old_args eq $new_args) {
+ # renamed but nothing else changed
+ push(@{$renamed_functions{$version_pair}}, [$old_name, $new_name, $notes]);
+ } else {
+ # something changed - args and/or return
+ push(@{$changed_functions{$version_pair}}, [$old_return, $old_name, $old_args, $new_return, $new_name, $new_args, $notes]);
+ }
+ }
+}
+close(IN);
+
+
+
+sub version_for_sort($) {
+ map { sprintf("%02d", $_) } split(/\./, $_[0]);
+}
+
+# Write Docbook XML output
+
+if(defined $docbook_xml_file) {
+ my $out_fh = new IO::File;
+ $out_fh->open(">$docbook_xml_file");
+
+ our $intro_title = "API Changes";
+ our $intro_para = <<"EOT";
+This chapter describes the API changes for $package.
+EOT
+
+ print_start_chapter_as_docbook_xml($out_fh,
+ $id_prefix.'-changes',
+ $intro_title,
+ $intro_para);
+
+
+ print_start_section_as_docbook_xml($out_fh,
+ $id_prefix.'-changes-intro',
+ "Introduction");
+ print $out_fh <<"EOT";
+<para>
+The following sections describe the changes in the API between
+versions including additions, deletions, renames (retaining the same
+number of parameters, types and return value type) and more complex
+changes to functions, types, enums and constants.
+</para>
+EOT
+
+ print_end_section_as_docbook_xml($out_fh);
+
+ # Sort by new version, newest first
+ for my $vp (sort { version_for_sort($b->[1]) cmp version_for_sort($a->[1]) } @version_pairs) {
+ my($old_version, $new_version)= @$vp;
+ my $id = to_id($old_version) . "-to-" . to_id($new_version);
+
+ my $version_pair = $old_version."-".$new_version;
+
+ print_start_section_as_docbook_xml($out_fh,
+ $id_prefix.'-changes-'.$id,
+ "Changes between $package $old_version and $new_version");
+
+ my(@f, @t, @e);
+ @f = @{$new_functions{$version_pair} || []};
+ @t = @{$new_types{$version_pair} || []};
+ @e = @{$new_enums{$version_pair} || []};
+
+ if(@f || @t || @e) {
+ print_start_section_as_docbook_xml($out_fh,
+ $id_prefix.'-changes-new-'.$id,
+ "New functions, types, enums and constants");
+ print_functions_list_as_docbook_xml($out_fh,
+ undef, 1, 1, @f);
+ print_types_list_as_docbook_xml($out_fh,
+ undef, 1, 1, @t);
+ print_enums_list_as_docbook_xml($out_fh,
+ undef, 1, 1, @e);
+ print_end_section_as_docbook_xml($out_fh);
+ }
+
+ @f = @{$deleted_functions{$version_pair} || []};
+ @t = @{$deleted_types{$version_pair} || []};
+ @e = @{$deleted_enums{$version_pair} || []};
+ if(@f || @t || @e) {
+ print_start_section_as_docbook_xml($out_fh,
+ $id_prefix.'-changes-deleted-'.$id,
+ "Deleted functions, types, enums and constants");
+ print_functions_list_as_docbook_xml($out_fh,
+ undef, 0, 0, @f);
+ print_types_list_as_docbook_xml($out_fh,
+ undef, 0, 1, @t);
+ print_enums_list_as_docbook_xml($out_fh,
+ undef, 0, 1, @e);
+ print_end_section_as_docbook_xml($out_fh);
+ }
+
+
+ @f = @{$renamed_functions{$version_pair} || []};
+ @e = @{$renamed_enums{$version_pair} || []};
+ if(@f || @e) {
+ print_start_section_as_docbook_xml($out_fh,
+ $id_prefix.'-changes-renamed-'.$id,
+ "Renamed functions, enums and constants");
+ print_renamed_functions_as_docbook_xml($out_fh,
+ undef,
+ "$old_version function",
+ "$new_version function",
+ @f);
+ print_renamed_enums_as_docbook_xml($out_fh,
+ undef,
+ "$old_version enum / constant",
+ "$new_version enum / constant",
+ @e);
+ print_end_section_as_docbook_xml($out_fh);
+ }
+
+ @f = @{$changed_functions{$version_pair} || []};
+ @t = @{$changed_types{$version_pair} || []};
+ if(@f || @t) {
+ print_start_section_as_docbook_xml($out_fh,
+ $id_prefix.'-changes-changed-'.$id,
+ "Changed functions and types");
+ print_changed_functions_as_docbook_xml($out_fh,
+ undef,
+ "$old_version function",
+ "$new_version function",
+ @f);
+ print_changed_types_as_docbook_xml($out_fh,
+ undef,
+ "$old_version type",
+ "$new_version type",
+ @t);
+ print_end_section_as_docbook_xml($out_fh);
+ }
+
+ print_end_section_as_docbook_xml($out_fh);
+
+ } # end pair of old/new versions
+
+ print_end_chapter_as_docbook_xml($out_fh);
+
+ $out_fh->close;
+}
+
+
+# Write Upgrade script output
+
+if(defined $upgrade_script_file) {
+ my $out_fh = new IO::File;
+ $out_fh->open(">$upgrade_script_file");
+
+ print $out_fh "#!/usr/bin/perl -pi~\n";
+
+ for my $vp (@version_pairs) {
+ my($old_version, $new_version)= @$vp;
+
+ my $version_pair = $old_version."-".$new_version;
+
+ print $out_fh "# Perl script to upgrade $package $old_version to $new_version\n\n";
+
+ print_statement_field_renames_as_perl_script($out_fh);
+
+ my(@f, @t, @e);
+
+ @f = @{$deleted_functions{$version_pair} || []};
+ @t = @{$deleted_types{$version_pair} || []};
+ @e = @{$deleted_enums{$version_pair} || []};
+
+ print_deletes_as_perl_script($out_fh, 'Deleted functions',
+ (map { [ $_->[1], $_->[3] ] } @f));
+
+ print_deletes_as_perl_script($out_fh, 'Deleted types',
+ @t);
+
+ print_deletes_as_perl_script($out_fh, 'Deleted enums and constants',
+ @e);
+
+ @f = @{$renamed_functions{$version_pair} || []};
+ @e = @{$renamed_enums{$version_pair} || []};
+ print_renames_as_perl_script($out_fh, 'Renamed functions', 1,
+ @f);
+
+ print_renames_as_perl_script($out_fh, 'Renamed enums and constants', 0,
+ @e);
+
+ @f = @{$changed_functions{$version_pair} || []};
+ @t = @{$changed_types{$version_pair} || []};
+ print_changes_as_perl_script($out_fh, 'Changed functions',
+ (map { [ $_->[1], $_->[4], $_->[6] ] } @f));
+
+ print_changes_as_perl_script($out_fh, 'Changed types',
+ @t);
+
+ } # end of version pair loop
+
+ $out_fh->close;
+}
+
+
+exit 0;
+
+
+__END__
+
+=head1 NAME
+
+process-changes - turn changes TSV into files
+
+=head1 SYNOPSIS
+
+process-changes [options] PACKAGE-NAME TSV-FILE
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>
+
+Give command help summary.
+
+=item B<--docbook-xml> DOCBOOK-XML
+
+Set the output docbook XML file
+
+=item B<--upgrade-script> UPGRADE-SCRIPT-PL
+
+Set the output perl script to upgrade the function and type names
+where possible.
+
+=back
+
+=head1 DESCRIPTION
+
+Turn a package's changes TSV file into docbook XML.
+
+=cut