# slow and tricky. Do not use them gratuitously. If you don't
# understand this, always use `:=' rather than `='.
+# Default goal
+all:
+
# Delete target on error. Every Makefile should have this.
.DELETE_ON_ERROR:
$(AR) rc $@ $?
$(RANLIB) $@
-# info.pl reads $(tsrc) and writes subjects.mk $(ttop) $(tsubj). The
-# naive rule
-# subjects.mk $(ttop) $(tsubj): $(tsrc)
-# COMMAND
-# runs COMMAND once for each target. That's because multiple targets
-# in an explicit rule is just a shorthand for one rule per target,
-# each with the same prerequisites and commands. A pattern rule with
-# multiple targets does what we want. So we artificially turn the
-# explicit rule into a pattern rule: we replace info with %, and
-# insert a touch target info/stamp.
-# FIXME if sources.mk is out-of-date, $(tsubj) is, and the bogus deps can prevent remaking of subjects.mk and thus sources.mk
-$(patsubst info/%, \%/%, $(ttop) $(tsubj)): %/stamp
- perl $(srcdir)/info/info.pl
-info/stamp: $(tsrc) info/info.pl sources.mk
- >$@
-subjects.mk: $(ttop)
- :
+subjects.mk: $(tsrc) info/findsubj.pl sources.mk
+ perl $(srcdir)/info/findsubj.pl
+
+$(tsubj): info/mksubj.pl
+ perl $(srcdir)/info/mksubj.pl $@ $(filter %.t, $^)
+
+$(ttop): $(tsubj)
+ perl $(srcdir)/info/mktop.pl $@ $(filter %.t, $^)
info.nr/all: $(filter-out info.nr/all, $(info.nr))
(cd info.nr && ls -CF) >$@
--- /dev/null
+#!/usr/bin/perl
+#
+# Empire - A multi-player, client/server Internet based war game.
+# Copyright (C) 1986-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Ken Stevens, Steve McClure
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# ---
+#
+# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
+# related information and legal notices. It is expected that any future
+# projects/authors will amend these files as needed.
+#
+# ---
+#
+# findsubj.pl: Find info subjects, update subjects.mk
+#
+# Known contributors to this file:
+# Ken Stevens (when it was still info.pl)
+# Markus Armbruster, 2006
+#
+
+# Run it at the root of the build tree. This updates the make include
+# file subjects.mk, which guides the remaking of info index files.
+#
+# --- Global variables ---
+# @Subjects Existing subjects
+# $filename The name of the current info file
+# $chapter{TOPIC} TOPIC's chapter (first arg to .TH)
+# $see_also{TOPIC}
+# TOPIC's SEE ALSO items (.SA argument)
+# $sanr{TOPIC} Line number of TOPIC's .SA request
+# $subjfil{SUBJECT}
+# info files for SUBJECT separated by space
+#
+# --- File handles ---
+# F Filehandle for info page sources and makefiles
+#
+# --- Functions ---
+#
+# read_make_var Read a variable value from a makefile
+# parse_file Read an info file
+# parse_see_also Create %subjfil from %see_also
+# error Print an integrity error to STDERR and exit with code 1.
+
+use strict;
+use warnings;
+
+use Errno qw(ENOENT);
+
+our (%chapter, %see_also, %sanr);
+our ($filename, %subjfil);
+
+# Get known subjects
+our @Subjects = split(' ', read_make_var("subjects", "subjects.mk", ""));
+# Get source directory
+my $srcdir = read_make_var("srcdir", "GNUmakefile");
+# Get info sources
+my @tsrc = grep(/\.t$/, split(' ' , read_make_var("src", "sources.mk")));
+
+# Parse the .t files
+for my $t (@tsrc) {
+ parse_file("$srcdir/$t");
+}
+
+# Create %subjfil from %see_also
+for my $t (sort keys %see_also) {
+ parse_see_also($t);
+}
+
+# Update @Subjects from %subjfil
+for my $t (@Subjects) {
+ print STDERR "WARNING: The subject $t has been removed.\n"
+ unless exists $subjfil{$t};
+}
+for my $t (keys %subjfil) {
+ unless (grep(/^$t$/, @Subjects)) {
+ print STDERR "WARNING: $t is a NEW subject\n";
+ my $fname = "info/$t.t";
+ print STDERR "File $fname exists\n" if -e $fname;
+ exit 1;
+ }
+}
+@Subjects = sort keys %subjfil;
+
+# Update subjects.mk
+open(F, ">subjects.mk")
+ or die "Can't open subjects.mk for writing: $!";
+print F "subjects := " . join(' ', @Subjects) . "\n";
+for my $t (@Subjects) {
+ print F "info/$t.t:$subjfil{$t}\n";
+}
+close(F);
+
+exit 0;
+
+# Read a variable value from a makefile
+sub read_make_var {
+ my ($var, $fname, $dflt) = @_;
+ my $val;
+
+ unless (open(F, "<$fname")) {
+ return $dflt if $! == ENOENT and defined $dflt;
+ die "Can't open $fname: $!";
+ }
+ while (<F>) {
+ if (/^[ \t]*\Q$var\E[ \t]:?=*(.*)/) {
+ $val = $1;
+ last;
+ }
+ }
+ close(F);
+ $val or die "Can't find $var in $fname";
+ return $val;
+}
+
+# Read an info file
+# Parse .TH into %chapter and .SA into %see_also, %sanr
+sub parse_file {
+ ($filename) = @_;
+ my $topic;
+
+ $topic = $filename;
+ $topic =~ s,.*/([^/]*)\.t$,$1,;
+
+ open(F, "<$filename")
+ or die "Can't open $filename: $!";
+
+ $_ = <F>;
+ if (/^\.TH (\S+) (\S.+\S)$/) {
+ $chapter{$topic} = $1;
+ } else {
+ error("The first line in the file must be a .TH request");
+ }
+
+ while (<F>) {
+ last if /^\.SA/;
+ }
+
+ if ($_) {
+ if (/^\.SA "([^\"]*)"/) {
+ $see_also{$topic} = $1;
+ $sanr{$topic} = $.;
+ } else {
+ error("Incorrect .SA Syntax. Syntax should be '.SA \"item1, item2\"'");
+ }
+
+ while (<F>) {
+ error("Multiple .SA requests. Each file may contain at most one.") if /^\.SA/;
+ }
+ } else {
+ error(".SA request is missing");
+ }
+
+ close F;
+}
+
+# Create %subjfil from %see_also
+sub parse_see_also {
+ my ($topic) = @_;
+ my @see_also = split(/, /, $see_also{$topic});
+ my $wanted = $chapter{$topic};
+ my $found; # found a subject?
+
+ $wanted = undef if $wanted eq 'Concept' or $wanted eq 'Command';
+ $filename = "$srcdir/$topic";
+
+ for (@see_also) {
+ if (!exists $see_also{$_}) { # is this entry a subject?
+ $subjfil{$_} .= " info/$topic.t";
+ $found = 1;
+ }
+ if ($wanted && $_ eq $wanted) {
+ $wanted = undef;
+ }
+ }
+
+ $. = $sanr{$topic};
+ error("No subject listed in .SA") unless $found;
+ error("Chapter $wanted not listed in .SA") if $wanted;
+}
+
+# Print an integrity error message and exit with code 1
+sub error {
+ my ($error) = @_;
+
+ print STDERR "info.pl:$filename:$.: $error\n";
+ exit 1;
+}
+++ /dev/null
-#!/usr/local/bin/perl
-#
-# info.pl
-#
-# Create SUBJECT.t files from the Info Pages.
-#
-# written by Ken Stevens
-#
-#
-# DESCRIPTION:
-# info.pl reads all of the info pages and creates a table of contents
-# for them organized by subject.
-#
-# Info consists of pages organized into chapters and subjects. Each
-# page is about a topic. The page for topic ITEM is in info file
-# info/ITEM.t. An info page's chapter is the first argument of its
-# .TH request. It belongs to a subject if that subject appears in its
-# .SA request ("SEE ALSO") _and_ that entry is not the name of another
-# info page. An info page may belong to more than one subject.
-#
-# For example, the .SA request of headlines.t contains "newspaper" and
-# "Communication". Since there's already an info page called
-# "newspaper.t", but there is no "Communication" info page, the
-# headlines info page is considered to be a member of the
-# Communication subject.
-#
-# This script reads GNUmakefile and sources.mk to find info sources.
-# It reads existing subjects from subjects.mk, and updates that file.
-# It creates a file info/SUBJECT.t for each SUBJECT, and a table of
-# subjects info/TOP.t.
-#
-# REQUIREMENTS:
-# info.pl requires perl5 to run. If you don't have version 5 of perl, then
-# you'll either have to install it, or you'll have to get someone to create
-# your Subjects.t files for you.
-#
-# HOW TO RUN IT:
-# Run "info.pl" at the root of the build tree.
-
-# --- Global variables ---
-# @Subjects Existing subjects
-# @Chapters Existing chapters
-# $filename The name of the current info file
-# $chapter{TOPIC} TOPIC's chapter (first arg to .TH)
-# $desc{TOPIC} A one line description of TOPIC (second arg to .NA)
-# $level{TOPIC} TOPIC's difficulty level (arg to .LV)
-# $see_also{TOPIC}
-# TOPIC's SEE ALSO items (.SA argument)
-# $sanr{TOPIC} Line number of TOPIC's .SA request
-# $subject{$subj}{$chap} = "item1\nitem2\n..."
-# Topics in that subject organized by chapter.
-# $largest{$sub} The largest topic name in that subject (used for
-# column formatting)
-#
-# --- File handles ---
-# F Filehandle for info page sources and makefiles
-# SUBJ Filehandle for Subject.t
-# TOP Filehandle for TOP.t
-#
-# --- Functions ---
-#
-# read_make_var Read a variable value from a makefile
-# parse_file Check the .TH, .NA, and .SA fields & parse them
-# parse_see_also Create %subject from %see_also
-# set_subject Add a new entry to %subject and possibly to %largest
-# create_subj Create a Subject.t file
-# create_subjects Remove the old Subject.t files and create new ones
-# flush_subj Print a row of Subjects to TOP
-# error Print an integrity error to STDERR and exit with code 1.
-
-use strict;
-use warnings;
-
-use Errno qw(ENOENT);
-use Fcntl qw(O_WRONLY O_EXCL O_CREAT);
-
-our (%chapter, %desc, %level, %see_also, %sanr);
-our ($filename, %subject, %largest);
-
-eval("require 5"); # Test for perl version 5
-die "$0 requires version 5 of perl.\n" if $@;
-
-# The chapters, in order
-our @Chapters = qw/Introduction Concept Command Server/;
-
-# Get known subjects
-our @Subjects = split(' ', read_make_var("subjects", "subjects.mk", ""));
-# Get source directory
-my $srcdir = read_make_var("srcdir", "GNUmakefile");
-# Get info sources
-my @tsrc = grep(/\.t$/, split(' ' , read_make_var("src", "sources.mk")));
-
-# Parse the .t files
-for my $t (@tsrc) {
- parse_file("$srcdir/$t");
-}
-
-# Create %subject from %see_also
-for my $t (sort keys %desc) {
- parse_see_also($t);
-}
-
-# Create the Subject.t files
-@Subjects = create_subjects();
-
-# Update subjects.mk
-open(F, ">subjects.mk")
- or die "Can't open subjects.mk for writing: $!";
-print F "subjects := " . join(' ', @Subjects) . "\n";
-close(F);
-
-exit 0;
-
-# Read a variable value from a makefile
-sub read_make_var {
- my ($var, $fname, $dflt) = @_;
- my $val;
-
- unless (open(F, "<$fname")) {
- return $dflt if $! == ENOENT and defined $dflt;
- die "Can't open $fname: $!";
- }
- while (<F>) {
- if (/^[ \t]*\Q$var\E[ \t]:?=*(.*)/) {
- $val = $1;
- last;
- }
- }
- close(F);
- $val or die "Can't find $var in $fname";
- return $val;
-}
-
-# Check .TH, .NA, .LV and .SA.
-# Parse .NA into %desc and .SA into %see_also
-sub parse_file {
- ($filename) = @_;
- my $topic;
-
- $topic = $filename;
- $topic =~ s,.*/([^/]*)\.t$,$1,;
-
- open(F, "<$filename")
- or die "Can't open $filename: $!";
-
- $_ = <F>;
- if (/^\.TH (\S+) (\S.+\S)$/) {
- if (!grep(/^$1$/, @Chapters)) {
- error("First argument to .TH was '$1', which is not a known chapter");
- }
- $chapter{$topic} = $1;
- if ($1 eq "Command" && $2 ne "\U$topic") {
- error("Second argument to .TH was '$2' but it should be '\U$topic'");
- }
- } else {
- error("The first line in the file must be a .TH request");
- }
-
- $_ = <F>;
- if (/^\.NA (\S+) "(\S.+\S)"$/) {
- if ($topic ne $1) {
- error("First argument to .NA was '$1' but it should be '$topic'");
- }
- $desc{$topic} = $2;
- } else {
- error("The second line in the file must be a .NA request");
- }
-
- $_ = <F>;
- if (/^\.LV (\S+)$/) {
- if ($1 ne 'Basic' && $1 ne 'Expert') {
- error("The argument to .LV was '$1' but it must be either 'Basic' or 'Expert'");
- }
- $level{$topic} = $1;
- } else {
- error("The third line in the file must be a .LV request");
- }
-
- while (<F>) {
- last if /^\.SA/;
- }
-
- if ($_) {
- if (/^\.SA "([^\"]*)"/) {
- $see_also{$topic} = $1;
- $sanr{$topic} = $.;
- } else {
- error("Incorrect .SA Syntax. Syntax should be '.SA \"item1, item2\"'");
- }
-
- while (<F>) {
- error("Multiple .SA requests. Each file may contain at most one.") if /^\.SA/;
- }
- } else {
- error(".SA request is missing");
- }
-
- close F;
-}
-
-# Create %subject from %see_also
-sub parse_see_also {
- my ($topic) = @_;
- my @see_also = split(/, /, $see_also{$topic});
- my $wanted = $chapter{$topic};
- my $found; # found a subject?
-
- $wanted = undef if $wanted eq 'Concept' or $wanted eq 'Command';
- $filename = "$srcdir/$topic";
-
- for (@see_also) {
- if (!exists $desc{$_}) { # is this entry a subject?
- set_subject($_, $topic);
- $found = 1;
- }
- if ($wanted && $_ eq $wanted) {
- $wanted = undef;
- }
- }
-
- $. = $sanr{$topic};
- error("No subject listed in .SA") unless $found;
- error("Chapter $wanted not listed in .SA") if $wanted;
-}
-
-# Add a new entry to %subject and possibly to %largest
-sub set_subject {
- my ($sub, $topic) = @_;
- my $chap = $chapter{$topic};
- $subject{$sub}{$chap} .= "$topic\n";
- $largest{$sub} = "" unless defined $largest{$_};
- $largest{$sub} = $topic if length $topic > length $largest{$sub};
- $largest{$sub} = $chap if length $chap > length $largest{$_};
-}
-
-# Create a Subject.t file
-sub create_subj {
- my ($subj) = @_;
- my $fname = "info/$subj.t";
-
- print "WARNING: $subj is a NEW subject\n"
- unless grep(/^$subj$/, @Subjects);
- sysopen(SUBJ, $fname, O_WRONLY | O_EXCL | O_CREAT)
- or die "Unable to create $fname: $!\n";
-
- print SUBJ '.\" DO NOT EDIT THIS FILE. It was automatically generated by info.pl'."\n";
- print SUBJ ".TH Subject \U$subj\n";
- $largest{$subj} =~ s/-/M/g;
- print SUBJ ".in \\w'$largest{$subj}XX\\0\\0\\0\\0'u\n";
- for my $chap (@Chapters) {
- next unless exists $subject{$subj}{$chap};
- print SUBJ ".s1\n";
- for (split(/\n/, $subject{$subj}{$chap})) {
- print SUBJ ".L \"$_ ";
- if ($level{$_} eq 'Basic') {
- print SUBJ "* \"\n";
- } else {
- print SUBJ " \"\n";
- }
- print SUBJ "$desc{$_}\n";
- }
- }
- print SUBJ <<EOF;
-.s1
-.in 0
-For info on a particular subject, type "info <subject>" where <subject> is
-one of the subjects listed above. Subjects marked by * are the most
-important and should be read by new players.
-EOF
- close SUBJ;
-}
-
-# Remove the old Subject.t files and create the Subject.t files and TOP.t
-sub create_subjects {
- my (@colsubj, @rowsubj, @subj);
-
- for (@Subjects) {
- unlink "info/$_.t";
- }
- open(TOP, ">info/TOP.t")
- or die "Can't open info/TOP.t: $!";
- print TOP <<EOF;
-.TH Info "List of Subjects"
-.s1
-Empire info is available on the following subjects:
-.NF
-EOF
-
- @rowsubj = sort keys %subject;
-
- for my $subj (@Subjects) {
- print "WARNING: The subject $subj has been removed.\n"
- unless grep (/^$subj$/, @rowsubj);
- }
-
- # reorder subjects for display in three columns
- my $k = 0;
- for my $i (0..2) {
- for (my $j = $i; $j <= $#rowsubj; $j += 3) {
- $colsubj[$j] = $rowsubj[$k++];
- }
- }
-
- for my $subj (@colsubj) {
- create_subj($subj);
- push(@subj, $subj);
- if ($#subj > 1) {
- flush_subj(@subj);
- @subj = ();
- }
- }
- flush_subj(@subj);
- print TOP <<EOF;
-.FI
-Type "info <Subject>" where <Subject> is one of the subjects listed above.
-For a complete list of all info topics, type "info all".
-EOF
- close TOP;
- return @rowsubj;
-}
-
-# Print a row of subjects to TOP
-sub flush_subj {
- return unless $#_ >= 0;
- print TOP " ";
- for (@_) {
- printf TOP "%-25s", $_;
- }
- print TOP "\n";
-}
-
-# Print an integrity error message and exit with code 1
-sub error {
- my ($error) = @_;
-
- print STDERR "info.pl:$filename:$.: $error\n";
- exit 1;
-}
--- /dev/null
+#!/usr/bin/perl
+#
+# Empire - A multi-player, client/server Internet based war game.
+# Copyright (C) 1986-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Ken Stevens, Steve McClure
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# ---
+#
+# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
+# related information and legal notices. It is expected that any future
+# projects/authors will amend these files as needed.
+#
+# ---
+#
+# mksubj.pl: Create the index for a subject
+#
+# Known contributors to this file:
+# Ken Stevens (when it was still info.pl)
+# Markus Armbruster, 2006
+#
+
+# Usage: mksubj.pl OUTFILE INFILE...
+# The INFILE... contain all the topics belonging to a subject. Read
+# and check the information required for the index from them, write
+# the index to OUTFILE.
+
+use strict;
+use warnings;
+
+# The chapters, in order
+our @Chapters = qw/Introduction Concept Command Server/;
+
+our $filename;
+my (%subject, %level, %desc);
+my $largest = "";
+
+my $out = shift @ARGV;
+$out =~ /([^\/]*)\.t$/
+ or die "Strange subject file name $out";
+my $subj = $1;
+
+for (@ARGV) {
+ my ($topic, $chap, $lvl, $desc) = parse_file($_);
+ $largest = $topic if length $topic > length $largest;
+ $subject{$chap} .= "$topic\n";
+ $level{$topic} = $lvl;
+ $desc{$topic} = $desc;
+}
+
+open(SUBJ, ">$out")
+ or die "Can't open $out for writing: $!";
+
+print SUBJ '.\" DO NOT EDIT THIS FILE. It was automatically generated by mksubj.pl'."\n";
+print SUBJ ".TH Subject \U$subj\n";
+$largest =~ s/-/M/g;
+print SUBJ ".in \\w'$largest", "XX\\0\\0\\0\\0'u\n";
+
+for my $chap (@Chapters) {
+ next unless exists $subject{$chap};
+ print SUBJ ".s1\n";
+ for (split(/\n/, $subject{$chap})) {
+ print SUBJ ".L \"$_ ";
+ if ($level{$_} eq 'Basic') {
+ print SUBJ "* \"\n";
+ } else {
+ print SUBJ " \"\n";
+ }
+ print SUBJ "$desc{$_}\n";
+ }
+}
+
+print SUBJ <<EOF;
+.s1
+.in 0
+For info on a particular subject, type "info <subject>" where <subject> is
+one of the subjects listed above. Subjects marked by * are the most
+important and should be read by new players.
+EOF
+close SUBJ;
+
+
+# Check .TH, .NA, .LV and .SA.
+# Parse .NA into %desc and .SA into %see_also
+sub parse_file {
+ ($filename) = @_;
+ my ($topic, $chap, $lvl, $desc);
+
+ $topic = $filename;
+ $topic =~ s,.*/([^/]*)\.t$,$1,;
+
+ open(F, "<$filename")
+ or die "Can't open $filename: $!";
+
+ $_ = <F>;
+ if (/^\.TH (\S+) (\S.+\S)$/) {
+ if (!grep(/^$1$/, @Chapters)) {
+ error("First argument to .TH was '$1', which is not a known chapter");
+ }
+ $chap = $1;
+ if ($1 eq "Command" && $2 ne "\U$topic") {
+ error("Second argument to .TH was '$2' but it should be '\U$topic'");
+ }
+ } else {
+ error("The first line in the file must be a .TH request");
+ }
+
+ $_ = <F>;
+ if (/^\.NA (\S+) "(\S.+\S)"$/) {
+ if ($topic ne $1) {
+ error("First argument to .NA was '$1' but it should be '$topic'");
+ }
+ $desc = $2;
+ } else {
+ error("The second line in the file must be a .NA request");
+ }
+
+ $_ = <F>;
+ if (/^\.LV (\S+)$/) {
+ if ($1 ne 'Basic' && $1 ne 'Expert') {
+ error("The argument to .LV was '$1' but it must be either 'Basic' or 'Expert'");
+ }
+ $lvl = $1;
+ } else {
+ error("The third line in the file must be a .LV request");
+ }
+
+ close F;
+
+ return ($topic, $chap, $lvl, $desc);
+}
+
+# Print an integrity error message and exit with code 1
+sub error {
+ my ($error) = @_;
+
+ print STDERR "info.pl:$filename:$.: $error\n";
+ exit 1;
+}
--- /dev/null
+#!/usr/bin/perl
+#
+# Empire - A multi-player, client/server Internet based war game.
+# Copyright (C) 1986-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Ken Stevens, Steve McClure
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# ---
+#
+# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
+# related information and legal notices. It is expected that any future
+# projects/authors will amend these files as needed.
+#
+# ---
+#
+# mktop.pl: Create the index of subjects
+#
+# Known contributors to this file:
+# Ken Stevens (when it was still info.pl)
+# Markus Armbruster, 2006
+#
+
+# Usage: mktop.pl OUTFILE SUBJECT-INDEX-FILE...
+# The SUBJECT-INDEX-FILE... contain all the subject indexes. Derive
+# the subjects from the file names, write the index to OUTFILE. Only
+# the file names are used, the files aren't accessed.
+
+my $out = shift @ARGV;
+my @subject = ();
+for (@ARGV) {
+ /([^\/]*)\.t$/
+ or die "Strange subject file name";
+ push @subject, $1;
+}
+@subject = sort @subject;
+
+open(TOP, ">$out")
+ or die "Can't open $out: $!";
+print TOP <<EOF;
+.TH Info "List of Subjects"
+.s1
+Empire info is available on the following subjects:
+.NF
+EOF
+
+# reorder subjects for display in three columns
+my $k = 0;
+for my $i (0..2) {
+ for (my $j = $i; $j <= $#subject; $j += 3) {
+ $colsubj[$j] = $subject[$k++];
+ }
+}
+
+for my $subj (@colsubj) {
+ push(@subj, $subj);
+ if ($#subj > 1) {
+ flush_subj(@subj);
+ @subj = ();
+ }
+}
+flush_subj(@subj);
+print TOP <<EOF;
+.FI
+Type "info <Subject>" where <Subject> is one of the subjects listed above.
+For a complete list of all info topics, type "info all".
+EOF
+close TOP;
+
+# Print a row of subjects to TOP
+sub flush_subj {
+ return unless $#_ >= 0;
+ print TOP " ";
+ for (@_) {
+ printf TOP "%-25s", $_;
+ }
+ print TOP "\n";
+}