5 # Create Subjects/Subject.t files from the Info Pages.
7 # written by Ken Stevens
11 # info.pl reads all of the info pages and creates a table of contents
12 # for them organized by subject. An info page belongs to a subject if
13 # that subject appears as an entry in the .SA ("SEE ALSO") field of the
14 # info page _and_ that entry is not the name of another info page.
16 # For example, the .SA field of headlines.t contains the entries
17 # "newspaper" and "Communication". Since there's already an info page
18 # called "newspaper.t", but there is no "Communication" info page, then
19 # the headlines info page is considered to be a member of the
20 # Communication subject.
22 # An info page may belong to more than one subject, and if it belongs
23 # to no subject, then its subject will be set to the name of the subdirectory
24 # it is in (e.g. the Server and Information info pages work this way).
26 # The output of this script is a bunch of files in the "Subjects"
27 # subdirectory. The file Subjects/TOP.t is the toplevel table of
28 # contents and lists all of the subjects. This is what the player
29 # sees when they type "info". Then for each subject, a
30 # Subjects/Subject.t file is created, listing all of the info pages that
31 # belong to that subject.
34 # info.pl requires perl5 to run. If you don't have version 5 of perl, then
35 # you'll either have to install it, or you'll have to get someone to create
36 # your Subjects.t files for you.
39 # Type "info.pl" at the unix prompt.
42 # mail your bug-reports and comments to:
43 # Ken Stevens <children@empire.net>
46 # item.t An info page file
48 # Subject An entry in a SEE ALSO entry which is not an item
49 # subdirectory Where the info files are kept
51 # --- Global variables ---
52 # @dirs Subdirectories of info directory containing item.t files
53 # @Subjects Subjects which already exist (as Subjects/Subject.t)
54 # $dir The current subdirectory we're working in
55 # $filename The name of an item.t file
57 # The subdirectory item.t is in
58 # F Filehandle for item.t
60 # A one line description of the item (second arg to .NA)
62 # The difficulty level of the page. At present either
64 # $see_also{$filename}
65 # A list of SEE ALSO items for the file (.SA argument)
67 # SUBJ Filehandle for Subject.t
68 # $subject{$subj}{$dir} = "item1\nitem2\n..."
69 # Items in that subject organized by directory.
70 # $largest{$sub} The largest item in that subject (used for column formatting)
71 # TOP Filehandle for Subjects/TOP.t
72 # @rowsubj List of subjects
73 # @colsubj List of subjects organized into 3 columns
77 # read_subjects Get list of current subjects
78 # parse_files Parse all the item.t files in one $dir
79 # parse_file Check the .TH, .NA, and .SA fields & parse them
80 # parse_see_also Create %subject from %see_also
81 # set_subject Add a new entry to %subject and possibly to %largest
82 # create_subj Create a Subject.t file
83 # create_subjects Remove the old Subject.t files and create new ones
84 # flush_subj Print a row of Subjects to TOP
85 # error Print an integrity error to STDERR and exit with code 1.
87 eval("require 5"); # Test for perl version 5
88 die "info.pl requires version 5 of perl.\n" if $@;
90 # These are the directories which contain item.t files:
91 @dirs = ('Commands', 'Concepts', 'Server', 'Introduction');
93 # Get list of current subjects
96 # Parse the item.t files in each info directory
101 # Create %subject from %see_also
102 for $filename (sort keys %filedir) {
106 # Create the Subject.t files
111 # Get list of current subjects
113 open (LS, "ls Subjects|");
117 next unless /^(\S+).t/;
123 # Parse all the item.t files in one $dir with lots of integrity checks
125 local ($type) = $dir;
126 chop($type) unless $type eq "Server" || $type eq "Introduction";
128 if (defined $filedir{$dir}) {
130 &error("Illegal filename (it is a directory name).");
131 } elsif (defined $filedir{$type}) {
133 &error("Illegal filename (it is a type name).");
136 open (LS, "ls $dir|");
140 next if /^GNUmakefile$/;
141 next if /^Makefile$/;
142 next if /^MakeSrcs$/;
149 # Check the .TH, .NA, and .SA fields.
150 # Parse .NA into %desc and .SA into %see_also
152 $filename =~ s/\.t$//;
154 if (grep (/^$filename$/, @dirs)) {
155 &error("Illegal filename. $filename is a name of a subdirectory of the info directory.");
157 if ($filedir{$filename}) {
158 &error("$filename.t is in both $filedir{$filename} and $dir");
159 } elsif (grep (/^$filename$/, @Subjects)) {
160 &error("Illegal filename. $filename is already a Subject name.");
162 $filedir{$filename} = $dir;
165 die "Can't open $dir/$filename.t\n" unless open(F, "<$dir/$filename.t");
168 if (/^\.TH (\S+) (\S.+\S)$/) {
170 &error("First argument to .TH was '$1' but it should be '$type'");
172 if ($type eq "Command" && $2 ne "\U$filename") {
173 &error("Second argument to .TH was '$2' but it should be '\U$filename'");
176 &error("The first line in the file must be a .TH entry");
179 if (/^\.NA (\S+) "(\S.+\S)"$/) {
180 if ($filename ne $1) {
181 &error("First argument to .NA was '$1' but it should be '$filename'");
183 $desc{$filename} = $2;
185 &error("The second line in the file must be an .NA entry");
188 if (/^\.LV (\S+)$/) {
189 if ($1 ne 'Basic' && $1 ne 'Expert') {
190 &error("The argument to .LV was '$1' but it must be either 'Basic' or 'Expert'");
192 $level{$filename} = $1;
194 &error("The third line in the file must be a .LV entry");
200 if (/^\.SA "([^\"]*)"/) {
201 $see_also{$filename} = $1;
203 &error("Incorrect .SA Syntax. Syntax should be '.SA \"item1, item2\"'");
206 &error("Multiple .SA entries. Each file may contain at most one .SA entry") if /^\.SA/;
212 # Create %subject from %see_also
214 local (@see_also) = split(/, /, $see_also{$filename});
215 local ($dir) = $filedir{$filename};
216 local ($found); # Does this item belong to any Subject?
219 if (!(defined $filedir{$_})) { # is this entry a subject?
225 &error("No Subject listed in .SA field") unless $found;
228 # Add a new entry to %subject and possibly to %largest
230 $subject{$_}{$dir} .= "$filename\n";
231 $largest{$_} = $filename if length $filename > length $largest{$_};
232 $largest{$_} = $dir if length $dir > length $largest{$_};
235 # Create a Subject.t file
237 print " Creating Subjects/$subj.t\n";
238 print "WARNING: $subj is a NEW subject\n" unless
239 grep(/^$subj$/, @Subjects);
240 die "Unable to write to Subjects/$subj.t\n" unless
241 open(SUBJ, ">Subjects/$subj.t");
243 print SUBJ '.\" DO NOT EDIT THIS FILE. It was automatically generated by info.pl'."\n";
244 print SUBJ ".TH Subject \U$subj\n";
245 $largest{$subj} =~ s/-/M/g;
246 print SUBJ ".in \\w'$largest{$subj}XX\\0\\0\\0\\0'u\n";
247 for $dir (keys %{$subject{$subj}}) {
249 for (split(/\n/, $subject{$subj}{$dir})) {
250 print SUBJ ".L \"$_ ";
251 if ($level{$_} eq 'Basic') {
256 print SUBJ "$desc{$_}\n";
262 For info on a particular subject, type "info <subject>" where <subject> is
263 one of the subjects listed above. Subjects marked by * are the most
264 important and should be read by new players.
269 # Remove the old Subject.t files and create the Subject.t files and TOP.t
270 sub create_subjects {
271 print " Removing Subjects/*.t\n";
272 `rm -f Subjects/*.t`;
273 print " Creating Subjects/TOP.t\n";
274 die "Can't open Subjects/TOP.t" unless open(TOP, ">Subjects/TOP.t");
276 .TH Info "List of Subjects"
278 Empire info is available on the following subjects:
282 @rowsubj = sort keys %subject;
284 for $subj (@Subjects) {
285 print "WARNING: The subject $subj has been removed.\n" unless
286 $subj eq 'TOP' || grep (/^$subj$/, @rowsubj);
290 for ($j = $i; $j <= $#rowsubj; $j += 3) {
291 $colsubj[$j] = $rowsubj[$k++];
295 for $subj (@colsubj) {
298 &flush_subj if $#subj > 1;
303 Type "info <Subject>" where <Subject> is one of the subjects listed above.
304 For a complete list of all info topics, type "info all".
309 # Print a row of subjects to TOP
311 return unless $#subj >= 0;
314 printf TOP "%-25s", $_;
320 # Print an integrity error message and exit with code 1
324 print STDERR "Error on line $. of $filedir{$filename}/$filename.t:\n";
326 print STDERR "\n" unless /\n$/;
327 print STDERR "$error\n";