diff --git a/.gitignore b/.gitignore index 2646fb98..6bc33572 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,6 @@ /src/lib/global/path.c /autom4te.cache /src/client/autom4te.cache -/subjects.mk # $(src_distgen) /aclocal.m4 /config.h.in diff --git a/Make.mk b/Make.mk index d34ad884..4a1b2328 100644 --- a/Make.mk +++ b/Make.mk @@ -56,8 +56,8 @@ tsrc := $(filter %.t, $(src)) man6 := $(filter man/%.6, $(src)) builtins := $(filter src/lib/global/%.config, $(src)) -# Info subjects (automatically generated) --include subjects.mk +# Info subjects +include $(srcdir)/info/subjects.mk # Abbreviations topics := $(patsubst %.t,%,$(notdir $(tsrc))) @@ -102,7 +102,7 @@ subst.in = sed \ # Generated files # See `Cleanliness' below -mk := subjects.mk +mk := ifeq ($(revctrl),git) mk += $(srcdir)/sources.mk endif @@ -322,19 +322,18 @@ $(libs) $(empth_lib): # Info formatting -# mksubj.pl reads $(tsrc) and writes subjects.mk $(tsubj). The naive -# rule -# subjects.mk $(ttop) $(tsubj): $(tsrc) +# mksubj.pl reads $(tsrc) and writes $(tsubj). The naive rule +# $(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. Use a stamp file. -subjects.mk $(tsubj): info/stamp-subj ; +$(tsubj): info/stamp-subj ; info/stamp-subj: info/mksubj.pl $(tsrc) - $(call quiet-command,perl $(srcdir)/info/mksubj.pl $(filter %.t, $^),GEN '$$(subjects)') + $(call quiet-command,perl $(srcdir)/info/mksubj.pl $(subjects) $(filter %.t, $^),GEN '$$(subjects)') >$@ -$(ttop): info/mktop.pl $(tsrc) +$(ttop): info/mktop.pl info/subjects.mk $(call quiet-command,perl $(srcdir)/info/mktop.pl $@ $(subjects),GEN $@) info.nr/all: $(filter-out info.nr/all, $(info.nr)) diff --git a/info/README b/info/README index e35d069f..b2a06f33 100644 --- a/info/README +++ b/info/README @@ -43,9 +43,9 @@ The first line must be a title header: The second line must be a name header: .NA arg1 arg2 - arg1 must be the name - - arg2 is a one-line description of the info page which will be - put on the Subject page that your info page belongs to. It should - be in double quotes + - arg2 is a one-line description of the info page which will be put + on the subject pages that your info page belongs to. It should be + in double quotes The third line must be a level header: .LV arg @@ -54,10 +54,11 @@ The third line must be a level header: The last line should be a see also: .SA "item1, item2, ..., subject1, subject2" - the stuff in quotes is a list of other info pages which are - related to this page and info Subjects to which this page belongs. + related to this page, and subjects to which this page belongs. - the stuff in quotes must all be on the same line - - You must include at least one subject (see the Subjects - subdirectory) in the list (at the end of the list by convention). + - You must include at least one subject in the list (at the end of + the list by convention). Valid subjects are listed in + info/subjects.mk. The lines in between can contain troff requests. The following additional requests are available: @@ -92,17 +93,9 @@ Fancy troff magic is prone to break HTML output. The scripts read all of the info pages and create a two-level table of contents for them, organized by subject. An info page belongs to a subject if that subject appears as an entry in the .SA ("SEE ALSO") -field of the info page _and_ that entry is not the name of another -info page. +field of the info page. -For example, the .SA field of headlines.t contains the entries -"newspaper" and "Communication". Since there's already an info page -called "newspaper.t", but there is no "Communication" info page, then -the headlines info page is considered to be a member of the -Communication -subject. - -The output of these script is a bunch of .t files. The file TOP.t is +The output of these scripts is a bunch of .t files. The file TOP.t is the top-level table of contents and lists all of the subjects. Then for each SUBJECT, a SUBJECT.t file is created, listing all of the info pages that belong to it. diff --git a/info/mksubj.pl b/info/mksubj.pl index 48e589e0..4e966b12 100644 --- a/info/mksubj.pl +++ b/info/mksubj.pl @@ -31,23 +31,21 @@ # Ken Stevens (when it was still info.pl) # Markus Armbruster, 2006-2013 # -# Usage: mksubj.pl INFO-FILE... +# Usage: mksubj.pl SUBJECT... INFO-FILE... # -# Read the INFO-FILE..., read and update subjects.mk, create -# info/SUBJECT.t for each SUBJECT. +# Read the INFO-FILE..., create info/SUBJECT.t for each SUBJECT. use strict; use warnings; use File::stat; -use Errno qw(ENOENT); use Fcntl qw(O_WRONLY O_EXCL O_CREAT); # The chapters, in order my @Chapters = qw/Introduction Concept Command Server/; my @Levels = qw/Basic Expert Obsolete/; -my @Subjects; +my %Subjects; # $filename{TOPIC} is TOPIC's file name my %filename; @@ -74,7 +72,9 @@ my %subject; # column formatting) my %largest; -@Subjects = split(' ', read_make_var("subjects", "subjects.mk", "")); +while ($#ARGV >= 0 && $ARGV[0] !~ /\.t$/) { + $Subjects{shift @ARGV} = undef; +} for (@ARGV) { parse_file($_); @@ -84,34 +84,7 @@ for my $t (sort keys %desc) { parse_see_also($t); } -@Subjects = create_subjects(); - -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 () { - if (/^[ \t]*\Q$var\E[ \t]*:?=[ \t]*(.*)/) { - $val = $1; - last; - } - } - close(F); - defined($val) or die "Can't find $var in $fname"; - return $val; -} +create_subjects(); # Parse an info file # Set $filename, $filename{TOPIC}, $long{TOPIC}, $chapter{TOPIC}, @@ -194,9 +167,12 @@ sub parse_see_also { my $found; # found a subject? $wanted = undef if $wanted eq 'Concept' or $wanted eq 'Command'; + $filename = $filename{$topic}; + $. = $sanr{$topic}; for (@see_also) { if (!exists $desc{$_}) { # is this entry a subject? + error("Unknown topic $_ in .SA") unless exists $Subjects{$_}; set_subject($_, $topic); $found = 1; } @@ -205,8 +181,6 @@ sub parse_see_also { } } - $filename = $filename{$topic}; - $. = $sanr{$topic}; error("No subject listed in .SA") unless $found; error("Chapter $wanted not listed in .SA") if $wanted; } @@ -224,10 +198,8 @@ sub set_subject { sub create_subj { my ($subj) = @_; my $fname = "info/$subj.t"; - my ($any_basic, $any_obsolete, $any_long); + my ($any_topic, $any_basic, $any_obsolete, $any_long); - 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"; @@ -239,6 +211,7 @@ sub create_subj { next unless exists $subject{$subj}{$chap}; print SUBJ ".s1\n"; for my $topic (split(/\n/, $subject{$subj}{$chap})) { + $any_topic = 1; my $flags = ""; if ($level{$topic} eq 'Basic') { $flags .= "*"; @@ -257,6 +230,10 @@ sub create_subj { print SUBJ "$desc{$topic}\n"; } } + unless ($any_topic) { + print STDERR "$0: Subject $subj has no topics\n"; + exit 1; + } print SUBJ ".s1\n" . ".in 0\n" . "For info on a particular subject, type \"info \" where is\n" @@ -274,21 +251,15 @@ sub create_subj { sub create_subjects { my (@subj); - for (@Subjects) { + for (keys %Subjects) { unlink "info/$_.t"; } @subj = sort keys %subject; - for my $subj (@Subjects) { - print "WARNING: The subject $subj has been removed.\n" - unless grep (/^$subj$/, @subj); - } - for my $subj (@subj) { create_subj($subj); } - return @subj; } # Print an integrity error message and exit with code 1 diff --git a/info/subjects.mk b/info/subjects.mk new file mode 100644 index 00000000..bb7c0b02 --- /dev/null +++ b/info/subjects.mk @@ -0,0 +1,4 @@ +subjects := Combat Commerce Commodities Communication Deity Detection \ +Diplomacy Distribution Introduction LandUnits Loans Maps Nations \ +Nukes Occupation Planes Playing Populace Producing Sectors Server \ +Ships Transportation Updates