1#!/bin/perl
2#
3#Used to prepare the book "tommath.src" for LaTeX by pre-processing it into a .tex file
4#
5#Essentially you write the "tommath.src" as normal LaTex except where you want code snippets you put
6#
7#EXAM,file
8#
9#This preprocessor will then open "file" and insert it as a verbatim copy.
10#
11#Tom St Denis
12
13#get graphics type
14if (shift =~ /PDF/) {
15   $graph = "";
16} else {
17   $graph = ".ps";
18}
19
20open(IN,"<tommath.src") or die "Can't open source file";
21open(OUT,">tommath.tex") or die "Can't open destination file";
22
23print "Scanning for sections\n";
24$chapter = $section = $subsection = 0;
25$x = 0;
26while (<IN>) {
27   print ".";
28   if (!(++$x % 80)) { print "\n"; }
29   #update the headings
30   if (~($_ =~ /\*/)) {
31      if ($_ =~ /\\chapter{.+}/) {
32          ++$chapter;
33          $section = $subsection = 0;
34      } elsif ($_ =~ /\\section{.+}/) {
35          ++$section;
36          $subsection = 0;
37      } elsif ($_ =~ /\\subsection{.+}/) {
38          ++$subsection;
39      }
40   }
41
42   if ($_ =~ m/MARK/) {
43      @m = split(",",$_);
44      chomp(@m[1]);
45      $index1{@m[1]} = $chapter;
46      $index2{@m[1]} = $section;
47      $index3{@m[1]} = $subsection;
48   }
49}
50close(IN);
51
52open(IN,"<tommath.src") or die "Can't open source file";
53$readline = $wroteline = 0;
54$srcline = 0;
55
56while (<IN>) {
57   ++$readline;
58   ++$srcline;
59
60   if ($_ =~ m/MARK/) {
61   } elsif ($_ =~ m/EXAM/ || $_ =~ m/LIST/) {
62      if ($_ =~ m/EXAM/) {
63         $skipheader = 1;
64      } else {
65         $skipheader = 0;
66      }
67
68      # EXAM,file
69      chomp($_);
70      @m = split(",",$_);
71      open(SRC,"<$m[1]") or die "Error:$srcline:Can't open source file $m[1]";
72
73      print "$srcline:Inserting $m[1]:";
74
75      $line = 0;
76      $tmp = $m[1];
77      $tmp =~ s/_/"\\_"/ge;
78      print OUT "\\vspace{+3mm}\\begin{small}\n\\hspace{-5.1mm}{\\bf File}: $tmp\n\\vspace{-3mm}\n\\begin{alltt}\n";
79      $wroteline += 5;
80
81      if ($skipheader == 1) {
82         # scan till next end of comment, e.g. skip license
83         while (<SRC>) {
84            $text[$line++] = $_;
85            last if ($_ =~ /math\.libtomcrypt\.com/);
86         }
87         <SRC>;
88      }
89
90      $inline = 0;
91      while (<SRC>) {
92      next if ($_ =~ /\$Source/);
93      next if ($_ =~ /\$Revision/);
94      next if ($_ =~ /\$Date/);
95         $text[$line++] = $_;
96         ++$inline;
97         chomp($_);
98         $_ =~ s/\t/"    "/ge;
99         $_ =~ s/{/"^{"/ge;
100         $_ =~ s/}/"^}"/ge;
101         $_ =~ s/\\/'\symbol{92}'/ge;
102         $_ =~ s/\^/"\\"/ge;
103
104         printf OUT ("%03d   ", $line);
105         for ($x = 0; $x < length($_); $x++) {
106             print OUT chr(vec($_, $x, 8));
107             if ($x == 75) {
108                 print OUT "\n      ";
109                 ++$wroteline;
110             }
111         }
112         print OUT "\n";
113         ++$wroteline;
114      }
115      $totlines = $line;
116      print OUT "\\end{alltt}\n\\end{small}\n";
117      close(SRC);
118      print "$inline lines\n";
119      $wroteline += 2;
120   } elsif ($_ =~ m/@\d+,.+@/) {
121     # line contains [number,text]
122     # e.g. @14,for (ix = 0)@
123     $txt = $_;
124     while ($txt =~ m/@\d+,.+@/) {
125        @m = split("@",$txt);      # splits into text, one, two
126        @parms = split(",",$m[1]);  # splits one,two into two elements
127
128        # now search from $parms[0] down for $parms[1]
129        $found1 = 0;
130        $found2 = 0;
131        for ($i = $parms[0]; $i < $totlines && $found1 == 0; $i++) {
132           if ($text[$i] =~ m/\Q$parms[1]\E/) {
133              $foundline1 = $i + 1;
134              $found1 = 1;
135           }
136        }
137
138        # now search backwards
139        for ($i = $parms[0] - 1; $i >= 0 && $found2 == 0; $i--) {
140           if ($text[$i] =~ m/\Q$parms[1]\E/) {
141              $foundline2 = $i + 1;
142              $found2 = 1;
143           }
144        }
145
146        # now use the closest match or the first if tied
147        if ($found1 == 1 && $found2 == 0) {
148           $found = 1;
149           $foundline = $foundline1;
150        } elsif ($found1 == 0 && $found2 == 1) {
151           $found = 1;
152           $foundline = $foundline2;
153        } elsif ($found1 == 1 && $found2 == 1) {
154           $found = 1;
155           if (($foundline1 - $parms[0]) <= ($parms[0] - $foundline2)) {
156              $foundline = $foundline1;
157           } else {
158              $foundline = $foundline2;
159           }
160        } else {
161           $found = 0;
162        }
163
164        # if found replace
165        if ($found == 1) {
166           $delta = $parms[0] - $foundline;
167           print "Found replacement tag for \"$parms[1]\" on line $srcline which refers to line $foundline (delta $delta)\n";
168           $_ =~ s/@\Q$m[1]\E@/$foundline/;
169        } else {
170           print "ERROR:  The tag \"$parms[1]\" on line $srcline was not found in the most recently parsed source!\n";
171        }
172
173        # remake the rest of the line
174        $cnt = @m;
175        $txt = "";
176        for ($i = 2; $i < $cnt; $i++) {
177            $txt = $txt . $m[$i] . "@";
178        }
179     }
180     print OUT $_;
181     ++$wroteline;
182   } elsif ($_ =~ /~.+~/) {
183      # line contains a ~text~ pair used to refer to indexing :-)
184      $txt = $_;
185      while ($txt =~ /~.+~/) {
186         @m = split("~", $txt);
187
188         # word is the second position
189         $word = @m[1];
190         $a = $index1{$word};
191         $b = $index2{$word};
192         $c = $index3{$word};
193
194         # if chapter (a) is zero it wasn't found
195         if ($a == 0) {
196            print "ERROR: the tag \"$word\" on line $srcline was not found previously marked.\n";
197         } else {
198            # format the tag as x, x.y or x.y.z depending on the values
199            $str = $a;
200            $str = $str . ".$b" if ($b != 0);
201            $str = $str . ".$c" if ($c != 0);
202
203            if ($b == 0 && $c == 0) {
204               # its a chapter
205               if ($a <= 10) {
206                  if ($a == 1) {
207                     $str = "chapter one";
208                  } elsif ($a == 2) {
209                     $str = "chapter two";
210                  } elsif ($a == 3) {
211                     $str = "chapter three";
212                  } elsif ($a == 4) {
213                     $str = "chapter four";
214                  } elsif ($a == 5) {
215                     $str = "chapter five";
216                  } elsif ($a == 6) {
217                     $str = "chapter six";
218                  } elsif ($a == 7) {
219                     $str = "chapter seven";
220                  } elsif ($a == 8) {
221                     $str = "chapter eight";
222                  } elsif ($a == 9) {
223                     $str = "chapter nine";
224                  } elsif ($a == 10) {
225                     $str = "chapter ten";
226                  }
227               } else {
228                  $str = "chapter " . $str;
229               }
230            } else {
231               $str = "section " . $str     if ($b != 0 && $c == 0);
232               $str = "sub-section " . $str if ($b != 0 && $c != 0);
233            }
234
235            #substitute
236            $_ =~ s/~\Q$word\E~/$str/;
237
238            print "Found replacement tag for marker \"$word\" on line $srcline which refers to $str\n";
239         }
240
241         # remake rest of the line
242         $cnt = @m;
243         $txt = "";
244         for ($i = 2; $i < $cnt; $i++) {
245             $txt = $txt . $m[$i] . "~";
246         }
247      }
248      print OUT $_;
249      ++$wroteline;
250   } elsif ($_ =~ m/FIGU/) {
251      # FIGU,file,caption
252      chomp($_);
253      @m = split(",", $_);
254      print OUT "\\begin{center}\n\\begin{figure}[here]\n\\includegraphics{pics/$m[1]$graph}\n";
255      print OUT "\\caption{$m[2]}\n\\label{pic:$m[1]}\n\\end{figure}\n\\end{center}\n";
256      $wroteline += 4;
257   } else {
258      print OUT $_;
259      ++$wroteline;
260   }
261}
262print "Read $readline lines, wrote $wroteline lines\n";
263
264close (OUT);
265close (IN);
266