]>
git.ipfire.org Git - thirdparty/bird.git/blob - doc/LinuxDocTools.pm
7 # LinuxDoc-Tools driver core. This contains all the basic functionality
8 # we need to control all other components.
10 # © Copyright 1996, Cees de Groot.
11 # © Copyright 2000, Taketoshi Sano
13 # THIS VERSION HAS BEEN HACKED FOR BIRD BY MARTIN MARES
15 package LinuxDocTools
;
22 LinuxDocTools - SGML conversion utilities for LinuxDoc DTD.
28 @files = LinuxDocTools::process_options ($0, @ARGV);
29 for $curfile (@files) {
30 LinuxDocTools::process_file ($curfile);
35 The LinuxDocTools package encapsulates all the functionality offered by
36 LinuxDoc-Tools. It is used, of course, by LinuxDoc-Tools;
37 but the encapsulation should provide for a simple interface for other users as well.
52 use LinuxDocTools
::Lang
;
53 use LinuxDocTools
::Utils
qw(process_options usage cleanup trap_signals remove_tmpfiles create_temp);
54 use LinuxDocTools
::Vars
;
59 # Make sure we're always looking here. Note that "use lib" adds
60 # on the front of the search path, so we first push dist, then
61 # site, so that site is searched first.
63 use lib
"$main::DataDir/dist";
64 use lib
"$main::DataDir/site";
67 =item LinuxDocTools::init
69 Takes care of initialization of package-global variables (which are actually
70 defined in L<LinuxDocTools::Vars>). The package-global variables are I<$global>,
71 a reference to a hash containing numerous settings, I<%Formats>, a hash
72 containing all the formats, and I<%FmtList>, a hash containing the currently
73 active formats for help texts.
75 Apart from this, C<LinuxDocTools::init> also finds all distributed and site-local
76 formatting backends and C<require>s them.
85 # Register the ``global'' pseudoformat. Apart from the global settings,
86 # we also use $global to keep the global variable name space clean;
87 # everything that we need to provide to other modules is stuffed
91 $global->{NAME
} = "global";
93 $global->{OPTIONS
} = [
94 { option
=> "backend", type
=> "l",
95 'values' => [ "html", "info", "latex",
96 "lyx", "rtf", "txt", "check" ],
98 { option
=> "papersize", type
=> "l",
99 'values' => [ "a4", "letter" ], short
=> "p" },
100 { option
=> "language", type
=> "l",
101 'values' => [ @LinuxDocTools::Lang
::Languages
], short
=> "l" },
102 { option
=> "charset", type
=> "l",
103 'values' => [ "latin", "ascii", "nippon", "euc-kr" ], short
=> "c" },
104 { option
=> "style", type
=> "s", short
=> "S" },
105 { option
=> "tabsize", type
=> "i", short
=> "t" },
106 # { option => "verbose", type => "f", short => "v" },
107 { option
=> "debug", type
=> "f", short
=> "d" },
108 { option
=> "define", type
=> "s", short
=> "D" },
109 { option
=> "include", type
=> "s", short
=> "i" },
110 { option
=> "pass", type
=> "s", short
=> "P" }
112 $global->{backend
} = "linuxdoc";
113 $global->{papersize
} = "a4";
114 $global->{language
} = "en";
115 $global->{charset
} = "ascii";
116 $global->{style
} = "";
117 $global->{tabsize
} = 8;
118 $global->{verbose
} = 0;
119 $global->{define
} = "";
120 $global->{debug
} = 0;
121 $global->{include
} = "";
122 $global->{pass
} = "";
123 $global->{InFiles
} = [];
124 $Formats{$global->{NAME
}} = $global; # All formats we know.
125 $FmtList{$global->{NAME
}} = $global; # List of formats for help msgs.
127 # automatic language detection: disabled by default
130 # foreach $lang (@LinuxDocTools::Lang::Languages)
132 # if (($ENV{"LC_ALL"} =~ /^$lang/i) ||
133 # ($ENV{"LC_CTYPE"} =~ /^$lang/i) ||
134 # ($ENV{"LANG"} =~ /^$lang/i)) {
135 # $global->{language} = Any2ISO($lang);
141 # Used when the format is "global" (from sgmlcheck).
143 $global->{preNSGMLS
} = sub {
144 $global->{NsgmlsOpts
} .= " -s ";
145 $global->{NsgmlsPrePipe
} = "cat $global->{file}";
149 # Build up the list of formatters.
153 chdir "$main::DataDir/dist";
154 my $dir = new DirHandle
(".");
155 die "Unable to read directory $main::DataDir/dist: $!" unless defined($dir);
156 foreach my $fmt (grep(/^fmt_.*\.pl$/, $dir->read()))
158 $Locs{$fmt} = "dist";
161 chdir "$main::DataDir/site";
162 $dir = new DirHandle
(".");
163 die "Unable to read directory $main::DataDir/site: $!" unless defined($dir);
164 foreach my $fmt (grep(/^fmt_.*\.pl$/, $dir->read()))
166 $Locs{$fmt} = "site";
169 foreach my $fmt (keys %Locs)
176 =item LinuxDocTools::process_options ($0, @ARGV)
178 This function contains all initialization that is bound to the current
179 invocation of LinuxDocTools. It looks in C<$0> to deduce the backend that
180 should be used (ld2txt activates the I<txt> backend) and parses the
181 options array. It returns an array of filenames it encountered during
184 As a side effect, the environment variables I<SGMLDECL> and
185 I<SGML_CATALOG_FILES> are modified.
191 my $progname = shift;
195 # Deduce the format from the caller's file name
197 my ($format, $dummy1, $dummy2) = fileparse
($progname, "");
198 $global->{myname
} = $format;
199 $format =~ s/sgml2*(.*)/$1/;
202 # check the option "--backend / -B"
204 if ($format eq "linuxdoc") {
205 my @backends = @args;
208 $arg = shift @backends;
210 $arg = shift @backends;
214 if ( $arg =~ s/--backend=(.*)/$1/ ) {
221 $format = "global" if $format eq "check";
222 usage
("") if $format eq "linuxdoc";
223 $format = "latex2e" if $format eq "latex";
224 $FmtList{$format} = $Formats{$format} or
225 usage
("$global->{myname}: unknown format");
226 $global->{format
} = $format;
229 # Parse all the options.
231 my @files = LinuxDocTools
::Utils
::process_options
(@args);
232 $global->{language
} = Any2ISO
($global->{language
});
234 # check the number of given files
235 $#files > -1 || usage
("no filenames given");
238 # Setup the SGML environment.
239 # (Note that Debian package rewrite path to catalog of
240 # iso-entities using debian/rules so that it can use
241 # entities from sgml-data pacakge. debian/rules also
242 # removes iso-entites sub directory after doing make install.)
244 $ENV{SGML_CATALOG_FILES
} .= (defined $ENV{SGML_CATALOG_FILES
} ?
":" : "") .
245 "$main::prefix/share/sgml/entities/sgml-iso-entities-8879.1986/catalog";
246 $ENV{SGML_CATALOG_FILES
} .= ":$main::DataDir/linuxdoc-tools.catalog";
247 $ENV{SGML_CATALOG_FILES
} .= ":$main::/etc/sgml.catalog";
248 if (-f
"$main::DataDir/dtd/$format.dcl")
250 $ENV{SGMLDECL
} = "$main::DataDir/dtd/$format.dcl";
252 elsif (-f
"$main::DataDir/dtd/$global->{style}.dcl")
254 $ENV{SGMLDECL
} = "$main::DataDir/dtd/$global->{style}.dcl";
256 elsif (-f
"$main::DataDir/dtd/sgml.dcl")
258 $ENV{SGMLDECL
} = "$main::DataDir/dtd/sgml.dcl";
262 # OK. Give the list of files we distilled from the options
263 # back to the caller.
268 =item LinuxDocTools::process_file
270 With all the configuration done, this routine will take a single filename
271 and convert it to the currently active backend format. The conversion is
272 done in a number of steps in tight interaction with the currently active
273 backend (see also L<LinuxDocTools::BackEnd>):
277 =item 1. Backend: set NSGMLS options and optionally create a pre-NSGMLS pipe.
279 =item 2. Here: Run the preprocessor to handle conditionals.
281 =item 3. Here: Run NSGMLS.
283 =item 4. Backend: run pre-ASP conversion.
285 =item 5. Here: Run SGMLSASP.
287 =item 6. Backend: run post-ASP conversion, generating the output.
291 All stages are influenced by command-line settings, currently active format,
292 etcetera. See the code for details.
298 my $file = shift (@_);
299 my $saved_umask = umask;
301 print "Processing file $file\n";
304 my ($filename, $filepath, $filesuffix) = fileparse
($file, "\.sgml");
305 my $tmpnam = $filepath . '/' . $filename;
306 $file = $tmpnam . $filesuffix;
307 -f
$file || $file =~ /.*.sgml$/ || ($file .= '.sgml');
308 -f
$file || ($file = $tmpnam . '.SGML');
309 -f
$file || die "Cannot find $file\n";
310 $global->{filename
} = $filename;
311 $global->{file
} = $file;
312 $global->{filepath
} = $filepath;
314 my $tmp = new FileHandle
"<$file";
319 # check for [<!doctype ... system] type definition
320 if ( /<!doctype\s*(\w*)\s*system/ )
325 # check for <!doctype ... PUBLIC ... DTD ...
326 if ( /<!doctype\s*\w*\s*public\s*.*\/\
/dtd\s*(\w*)/mi )
331 # check for <!doctype ...
333 # (multi-line version)
334 if ( /<!doctype\s*(\w*)/ )
339 if ( /\s*public\s*.*\/\
/dtd\s*(\w*)/ && $dtd eq "precheck" )
346 if ( $global->{debug
} )
348 print "DTD: " . $dtd . "\n";
350 $global->{dtd
} = $dtd;
352 # prepare temporary directory
353 my $tmpdir = $ENV{'TMPDIR'} || '/tmp';
354 $tmpdir = $tmpdir . '/' . 'linuxdoc-dir-' . $$;
355 mkdir ($tmpdir, 0700) ||
356 die " - temporary files can not be created, aborted - \n";
358 my $tmpbase = $global->{tmpbase
} = $tmpdir . '/sgmltmp.' . $filename;
359 $ENV{"SGML_SEARCH_PATH"} .= ":$filepath";
362 # Set up the preprocessing command. Conditionals have to be
363 # handled here until they can be moved into the DTD, otherwise
364 # a validating SGML parser will choke on them.
366 # check if output option for latex is pdf or not
367 if ($global->{format
} eq "latex2e")
369 if ($Formats{$global->{format
}}{output
} eq "pdf")
371 $global->{define
} .= " pdflatex=yes";
375 my($precmd) = "|sgmlpre output=$global->{format} $global->{define}";
378 # You can hack $NsgmlsOpts here, etcetera.
380 $global->{NsgmlsOpts
} .= "-D $main::prefix/share/sgml -D $main::DataDir";
381 $global->{NsgmlsOpts
} .= "-i$global->{include}" if ($global->{include
});
382 $global->{NsgmlsPrePipe
} = "NOTHING";
383 if ( defined $Formats{$global->{format
}}{preNSGMLS
} )
385 $global->{NsgmlsPrePipe
} = &{$Formats{$global->{format
}}{preNSGMLS
}};
389 # Run the prepocessor and nsgmls.
391 my ($ifile, $writensgmls);
393 if ($global->{NsgmlsPrePipe
} eq "NOTHING")
395 $ifile = new FileHandle
$file;
399 $ifile = new FileHandle
"$global->{NsgmlsPrePipe}|";
402 create_temp
("$tmpbase.1");
403 $writensgmls = new FileHandle
404 "$precmd|$main::progs->{NSGMLS} $global->{NsgmlsOpts} $ENV{SGMLDECL} >\"$tmpbase.1\"";
405 if ($global->{charset
} eq "latin")
409 # Outline these commands later on - CdG
410 #change latin1 characters to SGML
411 #by Farzad Farid, adapted by Greg Hankins
474 print $writensgmls $_;
481 print $writensgmls $_;
488 # Special case: if format is global, we're just checking.
490 $global->{format
} eq "global" && cleanup
;
493 # If the output file is empty, something went wrong.
495 ! -e
"$tmpbase.1" and die "can't create file - exiting";
496 -z
"$tmpbase.1" and die "SGML parsing error - exiting";
497 if ( $global->{debug
} )
499 print "Nsgmls stage finished.\n";
503 # If a preASP stage is defined, let the format handle it.
505 # preASP ($inhandle, $outhandle);
507 my $inpreasp = new FileHandle
"<$tmpbase.1";
508 my $outpreasp = new FileHandle
"$tmpbase.2",O_WRONLY
|O_CREAT
|O_EXCL
,0600;
509 if (defined $Formats{$global->{format
}}{preASP
})
511 &{$Formats{$global->{format
}}{preASP
}}($inpreasp, $outpreasp) == 0 or
512 die "error pre-processing $global->{format}.\n";
516 copy
($inpreasp, $outpreasp);
520 ! -e
"$tmpbase.2" and die "can't create file - exiting";
522 if ( $global->{debug
} )
524 print "PreASP stage finished.\n";
528 # Run sgmlsasp, with an optional style if specified.
531 # - datadir/site/<dtd>/<format>
532 # - datadir/dist/<dtd>/<format>
533 # So we need to fetch the doctype from the intermediate.
535 # Note: this is a very simplistic check - but as far as I know,
536 # it is correct. Am I right?
538 my $tmp = new FileHandle
"<$tmpbase.2";
540 while ( ($dtd = <$tmp>) && ! ( $dtd =~ /^\(/) ) { };
545 $global->{dtd
} = $dtd;
548 if ($global->{style
})
550 $style = "$main::DataDir/site/$dtd/$global->{format}/$global->{style}mapping";
552 $style = "$main::DataDir/dist/$dtd/$global->{format}/$global->{style}mapping";
554 my $mapping = "$main::DataDir/site/$dtd/$global->{format}/mapping";
555 -r
$mapping or $mapping = "$main::DataDir/dist/$dtd/$global->{format}/mapping";
557 $global->{charset
} = "nippon" if ($global->{language
} eq "ja");
559 # we don't have Korean groff so charset should be latin1.
561 if ($global->{language
} eq "ko")
563 if ($global->{format
} eq "groff")
565 $global->{charset
} = "latin1";
569 $global->{charset
} = "euc-kr";
573 if ($global->{format
} eq "groff" or $global->{format
} eq "latex2e")
575 if ($dtd eq "linuxdoctr")
577 $mapping = "$main::DataDir/dist/$dtd/$global->{format}/tr-mapping";
581 create_temp
("$tmpbase.3");
582 system ("$main::progs->{SGMLSASP} $style $mapping <\"$tmpbase.2\" |
583 expand -$global->{tabsize} >\"$tmpbase.3\"");
584 ! -e
"$tmpbase.3" and die "can't create file - exiting";
587 if ( $global->{debug
} )
589 print "ASP stage finished.\n";
593 # If a postASP stage is defined, let the format handle it.
594 # It should leave whatever it thinks is right based on $file.
596 # postASP ($inhandle)
599 my $inpostasp = new FileHandle
"<$tmpbase.3";
600 if (defined $Formats{$global->{format
}}{postASP
})
602 &{$Formats{$global->{format
}}{postASP
}}($inpostasp) == 0 or
603 die "error post-processing $global->{format}.\n";
607 if ( $global->{debug
} )
609 print "postASP stage finished.\n";
613 # All done, remove the temporaries.
615 if( !$global->{debug
} ) {
616 remove_tmpfiles
($tmpbase);
626 Documentation for various sub-packages of LinuxDocTools.
629 SGMLTools are written by Cees de Groot, C<E<lt>cg@cdegroot.comE<gt>>,
630 and various SGML-Tools contributors as listed in C<CONTRIBUTORS>.
631 Taketoshi Sano C<E<lt>sano@debian.org<gt>> rename to LinuxDocTools.