Refactor the pipeline/hsc interaction
[ghc.git] / utils / ltx / ltx.prl
1 #
2 # The perl script requires bindings for the following
3 # variables to be prepended:
4 #     DEFAULT_TMPDIR
5 #     CONTEXTDIFF
6 #
7
8 $Pgm = $0; $Pgm =~ s/.*\/([^\/]+)$/\1/;
9 #
10 # set up signal handler
11 sub quit_upon_signal { &rm_temp_files_and_exit(); }
12 $SIG{'INT'}  = 'quit_upon_signal';
13 $SIG{'QUIT'} = 'quit_upon_signal';
14 #
15 $Verbose = 0;
16 if ($ARGV[0] eq '-v') {
17     $Verbose = 1;
18     shift(@ARGV);
19 }
20 #
21 die "$Pgm: must have exactly one argument\n" if $#ARGV != 0;
22 # figure out input file and its filename root
23 if (-f $ARGV[0]) {
24     $TeX_input = $ARGV[0];
25     if ($TeX_input =~ /(.+)\.[^\.\/\n]+$/) {
26         $TeX_root  = $1;
27     } else {
28         $TeX_root  = $TeX_input;
29     }
30 } elsif (-f $ARGV[0].'.tex') {
31     $TeX_input = $ARGV[0].'.tex';
32     $TeX_root  = $ARGV[0];
33 } else {
34     die "$Pgm: input file $ARGV[0] doesn't exist\n";
35 }
36
37 if ( $ENV{'TMPDIR'} ) { # where to make tmp file names
38     $Tmp_prefix = $ENV{'TMPDIR'} ;
39 } else {
40     $Tmp_prefix ="$DEFAULT_TMPDIR";
41     $ENV{'TMPDIR'} = "$DEFAULT_TMPDIR"; # set the env var as well
42 }
43
44 sub rm_temp_files {
45     system("rm -f $Tmp_prefix/ltx-*.$$");
46 }
47 sub rm_temp_files_and_exit {
48     system("rm -f $Tmp_prefix/ltx-*.$$");
49     exit(1);
50 }
51 $SIG{'INT'}  = 'rm_temp_files_and_exit';
52 $SIG{'QUIT'} = 'rm_temp_files_and_exit';
53
54 sub die_gracefully {
55     local($msg) = @_;
56     
57     print STDERR $msg;
58     &rm_temp_files_and_exit();
59 }
60
61 # must read through root file to see if a \bibliography
62 # is there...
63 $Bibliography_requested = 0;
64 open(TEXIF, "<$TeX_input") 
65     || &die_gracefully("$Pgm: Can't read $TeX_input\n");
66 while (<TEXIF>) {
67     $Bibliography_requested = 1 if /^\\bibliography/;
68 }
69 close(TEXIF);
70 &die_gracefully("$Pgm: reading $TeX_input had errors\n") if $? >> 8;
71
72 # run latex first time (?)
73 &run_latex(); # sets $Says_labels_changed
74 $Times_run = 1;
75
76 while (&something_more_needed()) {
77
78     print STDERR "labels_changed=$Says_label_changed;bibtex_needed=$BibTeX_run_needed;makeindex_needed=$MakeIndex_run_needed\n" if $Verbose;
79
80     if ($BibTeX_run_needed) {
81         &run_bibtex();
82     }
83     if ($MakeIndex_run_needed) {
84         unlink "$TeX_root.ind";
85         (system("makeindex $TeX_root.idx") >> 8) 
86             && &die_gracefully("$Pgm: makeindex $TeX_root.idx had errors\n");
87     }
88
89     # save (copy) .aux file as .aux-prev file for future ref
90     # ditto for .idx file
91     unlink "$TeX_root.aux-prev";
92     (system("cp $TeX_root.aux $TeX_root.aux-prev") >> 8)
93         && &die_gracefully("$Pgm: cp $TeX_root.aux $TeX_root.aux-prev failed\n");
94     if (-f "$TeX_root.idx") {
95         unlink "$TeX_root.idx-prev";
96         (system("cp $TeX_root.idx $TeX_root.idx-prev") >> 8)
97             && &die_gracefully("$Pgm: cp $TeX_root.idx $TeX_root.idx-prev failed\n");
98     }
99
100     # run latex again
101     &run_latex(); # sets $Says_labels_changed
102     $Times_run++;
103
104     if ($Times_run >= 4) {
105         print STDERR "*** I don't run LaTeX more than four times;\n";
106         print STDERR "*** Something is probably wrong...\n";
107         &rm_temp_files_and_exit();
108     }
109 }
110 &rm_temp_files();
111 exit(0);
112
113 sub run_latex {
114     $Says_labels_changed = 0;
115     $Multiply_defined_labels = 0;
116
117     select(STDERR); $| = 1; select(STDOUT); # no buffering on STDERR
118     print STDERR "$Pgm: *** running LaTeX...\n" if $Verbose;
119     unlink "$TeX_root.dvi";
120
121     open(LTXPIPE, "latex $TeX_input 2>&1 |") 
122         || &die_gracefully("$Pgm: Can't run latex pipe\n");
123     while (<LTXPIPE>) {
124         $Multiply_defined_labels = 1 if /^LaTeX Warning: Label .* multiply defined/;
125         $Says_labels_changed = 1 if /^LaTeX Warning: Label\(s\) may have changed/
126                                         && ! $Multiply_defined_labels;
127         print STDERR $_;
128     }
129     close(LTXPIPE);
130     &die_gracefully("$Pgm: LaTeX run had errors\n") if $? >> 8;
131
132     # sort .idx file, because this helps makeindex
133     # (can you say `bug'?)
134     if (-f "$TeX_root.idx") {
135         print STDERR "$Pgm: *** sorting $TeX_root.idx...\n" if $Verbose;
136         (system("sort $TeX_root.idx -o $TeX_root.idx") >> 8)
137         && &die_gracefully("$Pgm: sorting $TeX_root.idx failed\n");
138     }
139
140 }
141
142 sub run_bibtex { # ugly because bibtex doesn't return a correct error status
143     local($bibtex_had_errors) = 0;
144
145     print STDERR "$Pgm: *** running BibTeX...\n" if $Verbose;
146     unlink "$TeX_root.bbl";
147
148     $| = 1; # no buffering
149     open(BIBTXPIPE, "bibtex $TeX_root 2>&1 |") 
150         || &die_gracefully("$Pgm: Can't run bibtex pipe\n");
151     while (<BIBTXPIPE>) {
152         $bibtex_had_errors = 1 if /^\(There.*error message(s)?\)$/;
153         print STDERR $_;
154     }
155     close(BIBTXPIPE);
156     &die_gracefully("$Pgm: BibTeX run had errors\n")
157         if $? >> 8 || $bibtex_had_errors;
158 }
159
160 sub something_more_needed {
161     # returns 1 or 0 if we need to run LaTeX
162     # possibly preceded by bibtex and/or makeindex run
163
164     # $Says_labels_changed was set by previous &run_latex...
165     $BibTeX_run_needed    = 0;
166     $MakeIndex_run_needed = 0;
167
168     if ( ! -f ($TeX_root . '.aux-prev')) { # this was the first run
169
170         print STDERR "$Pgm: *** 'twas first run of LaTeX on $TeX_input\n" if $Verbose;
171
172         # we need makeindex to run if a non-zero-sized .idx file exists
173         #
174         $MakeIndex_run_needed = 1
175             if -f "$TeX_root.idx" && -s "$TeX_root.idx";
176
177         # we need bibtex to run if there are \citations in the .aux file
178         #
179         &slurp_aux_file('aux');
180         $BibTeX_run_needed = 1
181             if $Bibliography_requested &&
182               -f "$Tmp_prefix/ltx-aux-cite.$$" &&
183               -s "$Tmp_prefix/ltx-aux-cite.$$";
184
185
186     } else { # ltx had been run before (.aux-prev/.idx-prev files exist)
187
188         # slurp both .aux and .aux-prev files
189         &slurp_aux_file('aux');
190         &slurp_aux_file('aux-prev');
191
192         local($tmp_pre) = "$Tmp_prefix/ltx";
193
194         if ((-s "$tmp_pre-.aux-cite.$$") # there are still \cite's in there
195          && (system("cmp -s $tmp_pre-.aux-cite.$$ $tmp_pre-.aux-prev-cite.$$") >> 8)) {
196             $BibTeX_run_needed = 1 if $Bibliography_requested;
197             if ($Verbose) {
198                 system("$CONTEXT_DIFF $tmp_pre-.aux-prev-cite.$$ $tmp_pre-.aux-cite.$$");
199             }
200         }
201
202         if (-f "$TeX_root.idx") {
203             $MakeIndex_run_needed =
204                 (system("cmp -s $TeX_root.idx $TeX_root.idx-prev") >> 8) ? 1 : 0;
205             if ($MakeIndex_run_needed && $Verbose) {
206                 system("$CONTEXT_DIFF $TeX_root.idx-prev $TeX_root.idx");
207             }
208         }
209     }
210
211     $Says_labels_changed || $BibTeX_run_needed || $MakeIndex_run_needed;
212 }
213
214 sub slurp_aux_file {
215     local($ext) = @_;
216
217     # copy all citations from slurpfile into $Tmp_prefix/ltx-$ext-cite.$$
218
219     open(SLURPF,"< $TeX_root.$ext")
220         || &die_gracefully("$Pgm: Can't open $TeX_root.$ext for reading\n");
221     open(CITEF,"> $Tmp_prefix/ltx-$ext-cite.$$")
222         || &die_gracefully("$Pgm: Can't open $Tmp_prefix/ltx-$ext-cite.$$ for writing\n");
223
224     while (<SLURPF>) {
225         print CITEF $_  if /\\citation/;
226     }
227     close(CITEF);
228     close(SLURPF);
229 }