home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / lyx21041.zip / XFree86 / lib / X11 / lyx / reLyX / reLyXmain.pl < prev    next >
Perl Script  |  1999-10-29  |  13KB  |  359 lines

  1. #!/usr/bin/perl -w
  2. #
  3. # Main code for reLyX - the LaTeX to LyX translator
  4. #
  5. # reLyX is Copyright (c) 1998-9 Amir Karger karger@post.harvard.edu
  6. # You are free to use and modify this code under the terms of
  7. # the GNU General Public Licence version 2 or later.
  8. #
  9. # This code usually gets called by the reLyX wrapper executable
  10. #
  11. # $Id: reLyXmain.pl,v 2.9.2.1 1999/05/02 21:56:19 karger Exp karger $
  12. #
  13.  
  14. require 5.002; # Perl 5.001 doesn't work. Perl 4 REALLY doesn't work.
  15.  
  16. # Standard Perl Library modules
  17. use strict; # must define all variables, no barewords, no hard references
  18.  
  19. # Variables from other files, like Getopt::Std, OR vars that need to be global
  20. # $opt_f etc. - command line options set by Getop::Std::getopts
  21. # $dot_lyxdir - the user's personal .lyx directory
  22. # $Success    - keep track of whether reLyX finished successfully or died
  23. # @File_List  - the list of files to translate. Initially this is just
  24. #               the file input by the user, but \input or \include commands
  25. #               will add to it.
  26. use vars qw($opt_c $opt_d $opt_f $opt_h $opt_n $opt_o $opt_p $opt_r $opt_s
  27.             $dot_lyxdir
  28.             $Success
  29.             @File_List
  30.        );
  31. use Cwd; # getcwd etc.
  32. use Getopt::Std; # read in command-line options
  33. use File::Basename; # &basename and &dirname
  34.  
  35. # Modules containing subroutines for reLyX
  36. # Note that @INC must include the directory that these modules are in. The
  37. # reLyX wrapper takes care of that.
  38. use Text::TeX; # TeX parser package
  39. use ReadCommands; # package to read LaTeX commands' syntax from a file
  40. use MakePreamble; # package to split off LaTeX preamble & translate it to LyX
  41. use CleanTeX; # package to clean TeX file for Lyxifying
  42. use BasicLyX; # package to translate clean TeX to Basic LyX
  43. use LastLyX; # package to print out LyX file once all translation is done
  44.  
  45.  
  46. # Hack to allow running reLyX without the wrapper
  47. if (!defined($lyxdir)) {$lyxdir = "$ENV{X11ROOT}/XFree86/lib/X11/lyx"}
  48. if (!defined($lyxname)) {$lyxname = "lyx"}
  49. # there's a use vars in the wrapper, so we only need these if running w/out it
  50. use vars qw($lyxdir $lyxname);
  51.  
  52. # variables that a user might want to change
  53. my @Suffix_List = '\.(ltx|latex|tex)'; # allowed suffixes for LaTeX file
  54. my $LyXFormat = "2.15"; #What to print in \lyxformat command in .lyx file
  55. my $syntaxname = "syntax.default"; # name of the default syntax file
  56. $dot_lyxdir = $ENV{'HOME'} . "/.$lyxname"; # personal .lyx directory
  57.  
  58. # This variable tells us if the program died or exited happily
  59. BEGIN{$Success = 0}
  60.  
  61. ##############################################################################
  62. # MAIN
  63. #
  64.  
  65. # Print welcome message including version info
  66. my $version_info = '$Date: 1999/05/02 21:56:19 $'; # RCS puts checkin date here
  67. $version_info =~ s&.*?(\d+/\d+/\d+).*&$1&; # take out just the date info
  68. warn "reLyX, the LaTeX to LyX translator. Revision date $version_info\n\n";
  69.  
  70. # Usage information
  71. my $Usage_Short = <<"ENDSHORTUSAGE";
  72.  
  73.  
  74. USAGE:
  75. $0 [ -c textclass ] [ -fd ] [ -o outputdir ]
  76.          [ -r renv1[,renv2...]] [ -s sfile1[,sfile2...]] inputfile
  77.  
  78. $0 -p -c textclass [ -fd ] [ -o outputdir ]
  79.          [ -r renv1[,renv2...]] [ -s sfile1[,sfile2...]] inputfile(s)
  80.  
  81. $0 -h   (to get more usage information)
  82.  
  83. ENDSHORTUSAGE
  84.  
  85. my $Usage_Long = $Usage_Short . <<"ENDLONGUSAGE";
  86.     -c    which textclass this file is (required with -p)
  87.              Overrides \\documentclass command, if one exists
  88.     -d    print lots of debug information & save temporary files
  89.     -f    force destruction of existing lyx file or temporary files
  90.     -h    print this message and quit
  91.     -n    convert a noweb file to a literate document (requires -c)
  92.     -o    output all LyX files to directory "outputdir"
  93.              Otherwise, LyX file is created in directory the LaTeX file is in
  94.     -p    translate LaTeX fragments or include files (requires -c)
  95.              I.e., files without \documentclass commands
  96.     -r    give reLyX a (list of) regular environment(s)
  97.     -s    give reLyX a (list of) additional syntax file(s) to read
  98.  
  99. man reLyX for lots of usage information
  100.  
  101.  
  102.  
  103. ENDLONGUSAGE
  104.  
  105. # Read command line
  106. # Get Options: set $opt_f etc. based on command line options
  107. getopts('c:dfhno:pr:s:') or die "Illegal option!$Usage_Short";
  108. if ($opt_h) {print $Usage_Long; $Success=1; exit}
  109. die "No LaTeX file was input on the command line$Usage_Short" unless @ARGV;
  110.  
  111. # Make each file in the file list an absolute file name (e.g., staring with '/')
  112. @File_List = map {&abs_file_name($_)} @ARGV;
  113.  
  114. # If noweb files, then we need to pre-process each file
  115. if (defined $opt_n) {
  116.     die "-n option requires -c!$Usage_Short" unless defined $opt_c;
  117.     foreach (@File_List) {
  118.         system("noweb2lyx.cmd", "-pre", "$_", "$_.pre$$");
  119.         $_ .= ".pre$$";
  120.     }
  121. }
  122.  
  123. # -p option allows multiple input files
  124. if (defined $opt_p) {
  125.     die "-p option requires -c!$Usage_Short" unless defined $opt_c;
  126. } else {
  127.     die "Only one input file allowed unless using -p option$Usage_Short"
  128.                     unless @ARGV == 1;
  129. }
  130.  
  131. # Make sure outputdir given with -o option is valid
  132. # Make it an absolute path, too!
  133. if (defined($opt_o)) {
  134.     die "directory $opt_o doesn't exist!\n$Usage_Short"
  135.                                  unless defined(-d $opt_o);
  136.     die "$opt_o isn't a directory!\n$Usage_Short" unless -d $opt_o;
  137.     $opt_o = &my_fast_abs_path($opt_o);
  138.     # may not have trailing slash.
  139.     $opt_o .= '/' unless $opt_o =~ /\/$/;
  140. }
  141.  
  142. # Read file(s) containing LaTeX commands and their syntax
  143. # Read personal syntax.default, or system-wide if there isn't a personal one
  144. # Then read other syntax files, given by the -s option
  145. my $default_file = "$dot_lyxdir/reLyX/$syntaxname";
  146. if (! -e $default_file) {
  147.     $default_file = "$lyxdir/reLyX/$syntaxname";
  148.     die "cannot find default syntax file $default_file" unless -e $default_file;
  149. }
  150. my @syntaxfiles = ($default_file);
  151. push (@syntaxfiles, (split(/,/,$opt_s))) if defined $opt_s;
  152. &ReadCommands::read_syntax_files(@syntaxfiles);
  153.  
  154. ########### Main loop over files (include files will be added to @File_List)
  155. my $count=0; #number of files we've done
  156. my @deletelist = (); # files to delete when we're done (if no '-d' flag)
  157. my $Doc_Class; # LaTeX documentclass
  158. my $LyX_Preamble = "";   # LyX Preamble not including Latex preamble part
  159. my $Latex_Preamble = "";
  160. my $File;
  161. while ($File = shift(@File_List)) {
  162.     # TODO we should always die (or something) if temp files exist & !opt_f
  163.     my $OutFileName;
  164.     my $filenum = 0; #numbering for temporary files
  165.  
  166.     # May need to add ".tex" to input file name.
  167.     #    PathBase is the output file name without ".lyx". It's used for building
  168.     # temporary files' file names, too.
  169.     #    Finally, make sure the file is valid, directory is writable, etc.
  170.     # Sub returns (undef, undef, undef) if something goes wrong.
  171.     my ($InFileDir, $InFileName, $PathBase) = &test_file($File);
  172.  
  173.     # Change to the input file's directory, so that if the input file has an
  174.     # \include{../foo} in it, we'll find the included file.
  175.     # Did something go wrong?
  176.     unless (defined($InFileDir) && chdir($InFileDir)) {
  177.     # main file must be ok; for included files or file fragments, just warn
  178.     next if ($count || $opt_p);
  179.     die "\n"; # printed error already
  180.     }
  181.  
  182.     # OK. Start parsing the file!
  183.     print STDERR "In Directory $InFileDir\n" if $opt_d;
  184.     print STDERR "($InFileName: ";
  185.  
  186.     # Read preamble and calculate document class if necessary
  187.     # (It's necessary when we're doing the first file.)
  188.     unless ($count) {
  189.  
  190.     if ($opt_p) { # it's a partial file
  191.         $Doc_Class = $opt_c;
  192.     } else {
  193.         # Split the preamble off of the rest of the file
  194.         my $PreambleName = $PathBase . ".relyx" . ++$filenum;
  195.         $OutFileName = $PathBase . ".relyx" . ++$filenum;
  196.         push @deletelist, $OutFileName, $PreambleName;
  197.         &MakePreamble::split_preamble($InFileName,
  198.                                 $PreambleName, $OutFileName);
  199.         $InFileName = $OutFileName;
  200.  
  201.         # Now read and translate the LaTeX preamble into LyX
  202.         # Return document's class so we know which layout file(s) to read
  203.         # Also return LyX preamble in a string, for later
  204.         ($Doc_Class, $LyX_Preamble, $Latex_Preamble) =
  205.          &MakePreamble::translate_preamble($PreambleName, $LyXFormat);
  206.  
  207.     } # end partial file if
  208.  
  209.     # Read file(s) containing the valid LyX layouts for this documentclass
  210.     # and their LaTeX command/environment equivalents
  211.     &ReadCommands::read_layout_files($Doc_Class);
  212.     }
  213.  
  214.     # Clean the TeX file (not including its preamble)
  215.     $OutFileName = $PathBase . ".relyx" . ++$filenum;
  216.     push @deletelist, $OutFileName;
  217.     &CleanTeX::call_parser($InFileName, $OutFileName);
  218.  
  219.     # Now convert basic constructs in the cleaned TeX file to LyX constructs
  220.     $InFileName = $OutFileName;
  221.     $OutFileName = $PathBase . ".relyx" . ++$filenum;
  222.     push @deletelist, $OutFileName;
  223.     &BasicLyX::call_parser($InFileName, $OutFileName);
  224.  
  225.     # Final cleanup step for noweb files
  226.     if (defined $opt_n) {
  227.         $InFileName = $OutFileName;
  228.         $OutFileName = $PathBase . ".relyx" . ++$filenum;
  229.         push @deletelist, $OutFileName;
  230.         system("noweb2lyx.cmd", "-post", $InFileName, $OutFileName);
  231.     }
  232.  
  233.     # Finally, print out the actual LyX file including the preamble
  234.     # For the *first* file, print out the LaTeX preamble too
  235.     $InFileName = $OutFileName;
  236.     if (defined $opt_n) {
  237.         push @deletelist, $PathBase;
  238.         $PathBase =~ s/.pre$$//;
  239.     }
  240.     $OutFileName = $PathBase . ".lyx";
  241.     my $preamble = $count ? $LyX_Preamble : $LyX_Preamble . $Latex_Preamble;
  242.     &LastLyX::last_lyx($InFileName, $OutFileName, $preamble);
  243.  
  244.     warn ")\n";
  245.  
  246. } continue {
  247.     $count++;
  248.  
  249. } # END MAIN WHILE LOOP
  250.  
  251. # Cleanup
  252. unless ($opt_d) {
  253.     warn "Deleting temp files\n";
  254.     unlink @deletelist;
  255. }
  256.  
  257. $Success = 1;
  258. exit;
  259.  
  260. # If we "die", output a sad message
  261. END{
  262.     if ($Success) {
  263.     warn "Finished successfully!\n";
  264.     } else {
  265.     warn "Exited due to fatal Error!\n";
  266.     }
  267. }
  268.  
  269. ##################### SUBROUTINES  ###########################################
  270. # Input: File (including absolute path)
  271. # Output: input file directory (absolute path)
  272. #         input file name (".tex" added if necessary) without path
  273. #         PathBase, the output file name (including path) without ".lyx" ending
  274. # Returns (undef, undef, undef) if something breaks
  275. #
  276. # Only allow certain suffixes
  277. #    Test for things, like writability of output directory, existence of
  278. # .lyx file we would be creating...
  279. sub test_file {
  280.     my $File = shift;
  281.     my @return_error = (undef, undef, undef);
  282.  
  283.     # Get file names, set up for making different temporary files
  284.     # fileparse_set_fstype("MSDOS") for DOS support!
  285.     my ($in_basename, $in_path, $suffix) = fileparse($File, @Suffix_List);
  286.     #$path .= '/' unless $path =~ /\/$/; # fix BUG in perl5.002 fileparse!
  287.  
  288.     # Try adding .tex to filename if you can't find the file the user input
  289.     unless (-e $File) {
  290.         if (! $suffix) { # didn't have a valid suffix. Try adding one
  291.         if (-e "$File.tex") {
  292.         $suffix = ".tex";
  293.         } else {
  294.          warn "\nCan't find input file $File or $File.tex\n";
  295.         return @return_error;
  296.         }
  297.     } else { # it had a valid suffix, but the file doesn't exist
  298.         warn "\nCan't find input file $File\n";
  299.         return @return_error;
  300.     }
  301.     }
  302.     my $in_filename = $in_basename . $suffix;
  303.  
  304.     # Make sure directory is valid
  305.     #    Note that we chdir to an input file's directory before translating it.
  306.     # Therefore, unless the -o option is given, we want to output files in '.'
  307.     #
  308.     # TODO if file foo.tex includes a/bar.tex and b/bar.tex, then with the
  309.     # -o option things will get ugly. We could test for that and create a name
  310.     # (like relyx-1-12345-bar.tex) for the second (and later!) bar.tex file(s)
  311.     my $out_path = defined $opt_o ? $opt_o : "./";
  312.     unless (-w $out_path) { # Note: "" isn't writable!
  313.     warn "\nDirectory $out_path isn't writable!\n";
  314.     return @return_error;
  315.     }
  316.     $out_path =~ s(^./)(); # "foo" is more readable than "./foo"
  317.     # This will be used for creating LyX file as well as temp files
  318.     my $PathBase = $out_path . $in_basename;
  319.  
  320.     # Check for files that already exist
  321.     my $lname = $PathBase . ".lyx";
  322.     if (-e $lname) {
  323.     if ($opt_f) {
  324.         warn "Will overwrite file $lname\n" if $opt_d;
  325.     } else {
  326.         warn "\nLyX file $lname already exists. Use -f to overwrite\n";
  327.         return @return_error;
  328.     }
  329.     }
  330.  
  331.     return ($in_path, $in_filename, $PathBase);
  332. } # end sub test_file
  333.  
  334.  
  335. sub abs_file_name {
  336.     my $File = shift;
  337.     my ($basename, $path, $suffix) = fileparse($File, @Suffix_List);
  338.     my $realpath = &my_fast_abs_path($path);
  339.     # add / at end
  340.     $realpath .= '/' unless $realpath =~ /\/$/; 
  341.     my $name = "$realpath$basename$suffix";
  342.     return $name;
  343. }
  344.  
  345.  
  346. # Stole this from Cwd.pm. Can't use the Cwd:: function cuz it's not in 5.003
  347. # I could test $] >5.004 or something, but why bother?
  348. sub my_fast_abs_path {
  349.     my $cwd = fastcwd();
  350.     my $path = shift || '.';
  351.     chdir($path) || die "Cannot chdir to $path:$!";
  352.     my $realpath = fastcwd();
  353.     chdir($cwd)  || die "Cannot chdir back to $cwd:$!";
  354.     $realpath;
  355. }
  356.  
  357.  
  358. 1; # return "true" to the wrapper
  359.