source: git/doc/doc2tex.pl @ 224da5b

fieker-DuValspielwiese
Last change on this file since 224da5b was 224da5b, checked in by Olaf Bachmann <obachman@…>, 25 years ago
* improved doc2tex stuff git-svn-id: file:///usr/local/Singular/svn/trunk@3303 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 24.6 KB
Line 
1#!/usr/local/bin/perl
2# $Id: doc2tex.pl,v 1.10 1999-07-20 14:36:36 obachman Exp $
3###################################################################
4#  Computer Algebra System SINGULAR
5#
6#  doc2tex: utility to generate the Singular manual
7#
8####
9# @c example [error]
10#    -> the text till the next @c example is feed into Singular,
11#       the text is then substituted by
12#       @c computed example $example $doc_file:$line
13#       <text from the input>
14#       @expansion{} <corresponding output>
15#       ....
16#       @c end computed example $example $doc_file:$line
17#       reuse computed examples if ($reuse && -r $example.inc)
18#       cut absolute directory names from the loaded messages
19#       substituted @,{ and } by @@, @{ resp. @}
20#       wrap around output lines  longer than $ex_length = 73;
21#       Processing is aborted if error occures in Singular run,
22#       unless 'error' is specified
23#
24####
25# @c include file
26#    -> copy content of file into output file protecting texi special chars
27#
28####
29# @c ref
30# ....
31# @c ref
32#    -> scans intermediate lines for @ref{..} strings
33#    Creates menu of (sorted) refs for ifinfo
34#    Creates comma-separated (sorted) refs for iftex, prepended with
35#    the text before first @ref.
36#
37####
38# @c lib libname.lib[:proc] [no_ex, lib_fun, lib_ex]
39#   Without :proc
40#   --> includes info of libname.lib in output file
41#   --> includes function names of info into function index
42#   --> if lib_fun is given, includes listing of functions and
43#                      their help into output file
44#   --> if lib_ex is given, includes computed examples of functions, as well
45#   With :proc
46#   --> includes content of procedure 'proc' from library libname:lib
47#
48#   Optional no_ex, lib_fun, lib_ex arguments overwrite respective
49#    command-line arguments
50#
51#
52###################################################################
53
54#
55# default settings of command-line arguments
56#
57$Singular = "../Singular/Singular"; # should be overwritten
58$libparse = "../Singular/libparse"; # change in final version
59$Singular_opts = " -teqr12345678";
60$clean = 0;
61$verbose = 1;
62$reuse = 1;
63$no_ex = 0;
64$lib_fun = 0;
65$lib_ex = 0;
66$doc_subdir = "./d2t_singular";
67@include_dirs = (".", "../Singular/LIB");
68$doc_examples_db = "$doc_subdir/examples";
69
70#
71# misc. defaults
72#
73$ex_length = 73;
74$ERROR = "\n**** Error:";
75$WARNING = "\n** Warning:";
76
77#
78# flush stdout and stderr after every write
79#
80select(STDERR);
81$| = 1;
82select(STDOUT);
83$| = 1;
84
85#
86# get file to convert
87#
88$doc_file = pop(@ARGV);
89if ($doc_file =~  /(.+)\..*$/)
90{
91  die "*** Error: Need .doc file as input\n" . &Usage 
92    unless ($doc_file =~ /(.+)\.doc$/);
93}
94else
95{
96  if ($doc_file =~ /^-h(elp)?$/) { print &Usage; exit;}
97  $doc_file .= ".doc";
98}
99
100#
101# parse command line options
102#
103$args = join(" ", @ARGV);
104while (@ARGV && $ARGV[0] =~ /^-/) 
105{
106  $_ = shift(@ARGV);
107  if (/^-S(ingular)?$/)  { $Singular = shift(@ARGV); next;}
108  if (/^-l(ibparse)?$/)  { $libparse = shift(@ARGV); next;}
109  if (/^-o(output)?$/)   { $tex_file = shift(@ARGV); next;}
110  if (/^-no_r(euse)?$/)  { $reuse = 0; next;}
111  if (/^-c(lean)?$/)     { $clean = 1; next;}
112  if (/^-no_e(x)?$/)     { $no_ex = 1; next;}
113  if (/^-lib_fu(n)?$/)   { $lib_fun = 1;next;}
114  if (/^-lib_e(x)?$/)    { $lib_ex = 1; next;}
115  if (/^-s(ubdir)?$/)    { $doc_subdir = shift(@ARGV); next;}
116  if (/^-I$/)            { unshift(@include_dirs, shift(@ARGV)); next;}
117  if (/^-v(erbose)?$/)   { $verbose = shift(@ARGV); next;}
118  if (/^-h(elp)?$/)      { print &Usage; exit;}
119  die &Usage;
120}
121$verbose = ($verbose < 0 ? 0 : $verbose);
122
123#
124# construct filenames
125#
126($doc_dir = $doc_file) =~ s/(.+)\.doc$/$1/;
127if ($doc_dir =~ /(.*)\//)
128{
129  $doc = $';
130  $doc_dir = $1;
131}
132else
133{
134  $doc = $doc_dir;
135  $doc_dir = ".";
136}
137$tex_file = "$doc_dir/$doc.tex" unless ($tex_file);
138               
139#
140# open files
141#
142open(DOC, "<$doc_file") 
143  || Error("can't open $doc_file for reading: $!\n" . &Usage);
144open(TEX, ">$tex_file") || Error("can't open $tex_file for writing: $!\n");
145print "d2t: Generating $tex_file from $doc_file ...\n" if ($verbose > 1);
146print "d2t: $doc_file ==> $tex_file\n" if ($verbose == 1);
147if (-d $doc_subdir)
148{
149  print "d2t: Using $doc_subdir for intermediate files\n" 
150    if ($verbose > 1);
151}
152else
153{
154  mkdir($doc_subdir, oct(755)) 
155    || Error("can't create directory $doc_subdir: $!\n");
156  print "d2t: Created $doc_subdir for intermediate files\n" 
157    if ($verbose > 1);
158}
159
160dbmopen(%EXAMPLES, $doc_examples_db, oct(755)) || die "$ERROR: can't open examples data base: $!\n";
161
162#######################################################################
163#
164# go !
165#
166while (<DOC>)
167{
168  $line++;
169 
170  if (/^\@c\s*example/)     {&HandleExample; next;}
171  if (/^\@c\s*include\s+/)  {&HandleInclude; next;}
172  if (/^\@c\s*ref\s*$/)     {&HandleRef; next;}
173  if (/^\@c\s*lib\s+/)      {&HandleLib; next;}
174  if (/^\@setfilename/)     {print TEX "\@setfilename $doc.hlp\n"; next;}
175                             
176  print TEX $_;
177
178  if (/^\@bye$/)            {last;}
179}
180
181#
182# wrap up
183#
184close(TEX);
185dbmclose(%EXAMPLES);
186print "\nd2t: Finished generation of $tex_file \n" if ($verbose > 1);
187print "\n" if ($verbose == 1);
188
189
190######################################################################
191# @c example [error]
192#    -> the text till the next @c example is feed into Singular,
193#       the text is then substituted by
194#       @c computed example $example $doc_file:$line
195#       <text from the input>
196#       @expansion{} <corresponding output>
197#       ....
198#       @c end computed example $example $doc_file:$line
199#       reuse computed examples if ($reuse && -r $example.inc)
200#       cut absolute directory names from the loaded messages
201#       substituted @,{ and } by @@, @{ resp. @}
202#       wrap around output lines  longer than $ex_length = 73;
203#       Processing is aborted if error occures in Singular run,
204#       unless 'error' is specified
205sub HandleExample
206{
207  my($lline, $thisexample, $include, $error_ok);
208 
209  $lline = $line;
210  $example++;
211
212  if ($no_ex)
213  {
214    print "{$example}" if ($verbose);
215    print TEX "\@c skipped computation of example $example $doc_file:$lline \n";
216   
217  }
218
219  $thisexample = '';
220  $error_ok = 1 if /error/;
221  # print content in example file till next @c example
222  while (<DOC>)
223  {
224    $line++;
225    last if (/^\@c\s*example\s*$/);
226    s/^\s*//; # remove preceeding white spaces
227    if ($no_ex)
228    {
229      &protect_texi;
230      print TEX $_;
231    }
232    else
233    {
234      $thisexample .= $_ unless (/^\s*$/);
235    }
236  }
237  Error("no matching '\@c example' found for $doc_file:$lline\n")
238    unless (/^\@c\s*example\s*$/);
239
240  # done, if no examples
241  return if ($no_ex);
242
243  # check whether it can be reused
244  $include = $EXAMPLES{$thisexample};
245  if ($reuse && ($include = $EXAMPLES{$thisexample}))
246  {
247    print "<$example>" if ($verbose);
248    print TEX "\@c reused example $example $doc_file:$lline \n";
249  }
250  else
251  {
252    print "($example" if ($verbose == 1);
253    my ($ex_file, $res_file, $inc_file);
254    $inc_file = "$doc_subdir/$doc"."_$example.inc";
255    $ex_file = "$doc_subdir/$doc"."_$example.tst";
256    $res_file = "$doc_subdir/$doc"."_$example.res";
257
258    print TEX "\@c computed example $example $doc_file:$lline \n";
259
260    # run singular
261    open(EX, ">$ex_file") || Error("can't open $ex_file for writing: $!\n");
262    print EX "$thisexample\$\n";
263    close(EX);
264
265    &System("$Singular $Singular_opts $ex_file > $res_file");
266    print ")" if ($verbose == 1);
267
268    open(RES, "<$res_file") || Error("can't open $res_file for reading: $!\n");
269    open(INC, ">$inc_file") || Error("can't open $inc_file for writing: $!\n");
270
271    $include = '';
272    # get result, manipulate it and put it into inc file
273    while (<RES>)
274    {
275      last if (/^$ex_file\s*([0-9]+)..\$/);
276      # check for error
277      Error("while running example $example from $doc_file:$lline.\nCall: '$Singular $Singular_opts $ex_file > $res_file'\n")
278        if (/error occurred/ && ! $error_ok);
279      # remove stuff from echo
280      if (/^$ex_file\s*([0-9]+)../)
281      {
282        $_ = $';
283        &protect_texi;
284      }
285      else
286      {
287        local($to_do, $done);
288        # remove absolute path names from laoded messages
289        s/^(\/\/ \*\* loaded )(.*)\/(.+).lib(.*)/$1$3.lib$4/;
290        # shorten error occurred in messages
291        s/\? error occurred in [^ ]* line/\? error occurred in line/;
292        # break after $ex_length characters
293        $to_do = $_;
294        while (length($to_do) > $ex_length && $to_do =~ /\w/)
295        {
296          $done .= substr($to_do, 0, $ex_length)."\\\n   ";
297          $to_do = substr($to_do, $ex_length + 1);
298        }
299        $_ = $done.$to_do if($done);
300        &protect_texi;
301        $_ = "\@expansion{} ".$_;
302      }
303      $include .= $_;
304      print INC $_;
305    }
306    close(RES);
307    close(INC);
308    unlink $ex_file, $res_file, $inc_file if ($clean);
309    $EXAMPLES{$thisexample} = $include;
310  }
311  print TEX $include;
312  print TEX "\@c end example $example $doc_file:$lline\n";
313}
314 
315######################################################################
316# @c include file
317#    -> copy content of file into output file protecting texi special chars
318sub HandleInclude
319{
320  s/^\@c\s*include\s+([^\s]+)\s/$1/;
321  s/\s*$//;
322  unless (&Open(*INC, "<$_"))
323  {
324    warn "$WARNING HandleInclude: can't open $_ for reading\n";
325    print TEX "\@c include file $_ not found\n";
326    return;
327  }
328  print "<$_>" if ($verbose);
329  print TEX "\@c begin included file $_ from $doc_file:$line\n";
330  while (<INC>)
331  {
332    &protect_texi;
333    print TEX $_;
334  }
335  print TEX "\@c end included file from $doc_file:$line\n";
336  close (INC);
337}
338
339######################################################################
340# @c ref
341# ....
342# @c ref
343#    -> scans intermediate lines for @ref{..} strings
344#    Creates menu of (sorted) refs for ifinfo
345#    Creates comma-separated (sorted) refs for iftex, prepended with
346#    the text before first @ref.
347
348sub HandleRef
349{
350  local(%refs, @refs, $header, $lline, $lref);
351 
352  print TEX "\@c inserted refs from $doc_file:$line\n";
353 
354  # scan lines use %ref to remove duplicates
355  $lline = $line;
356  while (<DOC>)
357  {
358    $line++;
359    last if (/^\@c\s*ref\s*$/);
360   
361    while (/\@ref{(.*?)}/)
362    {
363      $refs{$1} = 1;
364      $_ = $';
365      unless ($header)
366      {
367        $header = $`;
368        $header = " " unless ($header);
369      }
370    }
371  }
372  die "$ERRROR no matching \@c ref found for $doc_file:$lline\n" 
373    unless (/^\@c\s*ref\s*$/);
374  # sort refs
375  @refs = sort(keys(%refs));
376  # put them out
377  print TEX "\@ifinfo\n\@menu\n";
378  print TEX $header ? "$header\n" : "See also:\n";
379  foreach $ref (@refs) {print TEX "* ".$ref."::\n";}
380  print TEX "\@end menu\n\@end ifinfo\n\@iftex\n";
381
382  if ($header ne " ")
383  {
384    print TEX "$header\n" unless ($header eq " ");
385  }
386  else
387  {
388    print TEX "\@strong{See also:}\n";
389  }
390  $lref = pop(@refs);
391  foreach $ref (@refs) {print TEX "\@ref{".$ref."};\n";}
392  print TEX "\@ref{".$lref."}.\n" if ($lref); 
393  print TEX "\@end iftex\n\@c end inserted refs from $doc_file:$lline\n";
394}
395
396###################################################################
397#
398# @c lib libname.lib [no_ex, lib_fun, lib_ex]
399#   --> includes info of libname.lib in output file
400#   --> includes function names of info into function index
401#   --> if lib_fun is given, includes listing of functions and
402#                      their help into output file
403#   --> if lib_ex is given, includes computed examples of functions, as well
404#
405# Optional no_ex, lib_fun, lib_ex arguments overwrite respective
406# command-line arguments
407#
408
409sub HandleLib
410{
411  local($lib, $lib_name, $ltex_file, $l_ex, $l_fun, $no_node, $section);
412  my ($func);
413
414  if (/^\@c\s*lib\s+([^\.]+)\.lib(.*)/)
415  {
416    $lib = $1;
417    $lib_name = $lib.".lib";
418    $_ = $2;
419  }
420  else
421  {
422    warn "$WARNING need .lib file to process '$_'\n";
423    print TEX $_;
424    return;
425  }
426
427  $func = $1 if (/^:(.*?) /);
428  $l_fun = 1 if (($lib_fun || (/lib_fun/)) && !/no_fun/);
429  $l_ex = 1 if (($lib_ex || /lib_ex/) && !/no_ex/ && $l_fun);
430  if (/(\w+)section/)
431  {
432    $section = $1. 'section';
433  }
434  else
435  {
436    $section = "subsection";
437  }
438  $ltex_file = "$doc_subdir/$lib"."_lib";
439  unless ($l_ex)
440  {
441    if ($l_fun)
442    {
443      $ltex_file .= "_noEx";
444    }
445    else
446    {
447      $ltex_file .= "_noFun";
448    }
449  }
450  $ltex_file .= ".tex";
451 
452  Error("can't open $lib.lib for reading: $!\n") 
453    unless  ($lib_dir = &Open(*LIB, "<$lib.lib"));
454  close (LIB);
455  if ($reuse && open(LTEX, "<$ltex_file") && 
456      IsNewer($ltex_file, "$lib_dir/$lib.lib"))
457  {
458    unless ($func)
459    {
460      print "<lib $lib>" if ($verbose);
461      print TEX "\@c reused lib docu for $lib_name $doc_file:$line \n";
462    }
463  }
464  elsif (&GenerateLibDoc($lib, $ltex_file, $l_fun, $l_ex))
465  {
466    print TEX "\@c generated lib docu for $lib_name $doc_file:$line \n"
467      unless $func;
468    open(LTEX, "<$ltex_file") 
469      || Error("can't open $ltex_file for reading: $!\n");
470  }
471  if ($func)
472  {
473    print "<$lib:$func" if $verbose;
474    print TEX "\@c generated lib proc docu for $lib_name:$func $doc_file:$line \n";
475    my $found = 0;
476    while (<LTEX>)
477    {
478      $found = 1 if /c ---content $func---/;
479      print TEX $_ if $found;
480      last if $found && /c ---end content $func---/;
481    }
482    if ($found)
483    {
484      Error("no end content found for lib proc docu for $lib_name:$func $doc_file:$line \n")
485        unless (/c ---end content $func---/);
486      print TEX "\@c generated lib proc docu for $lib_name:$func $doc_file:$line \n";
487    }
488    else
489    {
490      Error("did not find lib proc docu for $lib_name:$func $doc_file:$line \n");
491    }
492    print ">" if $verbose;
493  }
494  else
495  {
496    while (<LTEX>) {print TEX $_;}
497    print TEX "\@c end generated lib docu for $lib_name $doc_file:$line \n";
498  }
499  close(LTEX);
500  unlink $ltex_file if ($clean);
501}
502 
503sub GenerateLibDoc
504{
505  my($lib, $tex_file, $l_fun, $l_ex) = @_;
506  my($lib_dir, $scall, $pl_file, $doc_file, $i, $example,$largs, $ref);
507  # vars from executing the library perl scrip
508  local($info, $libary, $version, @procs, %example, %help, $table_is_open);
509 
510  print "(lib $lib: " if ($verbose == 1);
511  # construct doc/tex file name
512  $doc_file = "$doc_subdir/$lib"."_lib";
513  $doc_file .= "_noFun" unless ($l_fun);
514  $doc_file .= ".doc";
515
516  Error("can't open $lib.lib for reading: $!\n")
517    unless  ($lib_dir = &Open(*LIB, "<$lib.lib"));
518  close (LIB);
519  if (-r $doc_file && $reuse && IsNewer($doc_file, "$lib_dir/$lib.lib"))
520  {
521    print "<doc>" if ($verbose == 1);
522  }
523  else
524  {
525    # generate perl file, if necessary
526    $pl_file = "$doc_subdir/$lib"."_lib.pl";
527    if (-r $pl_file && $reuse && IsNewer($pl_file, "$lib_dir/$lib.lib"))
528    {
529      print "<pl>" if ($verbose == 1);
530    }
531    else
532    {
533      print "(pl" if ($verbose == 1);
534      &System("$libparse -i $lib_dir/$lib.lib > $pl_file");
535      print ")" if ($verbose == 1);
536    }
537
538    print "(doc" if ($verbose == 1);
539   
540    do $pl_file;
541    Error("error while executing $pl_file: $@\n") if ($@);
542    unlink ($pl_file) if ($clean);
543   
544    # generate doc file
545    open(LDOC, ">$doc_file") || die"$ERROR can't open $doc_file for writing: $!\n";
546   
547    # print header
548    print LDOC "\@c library version: $version\n";
549    print LDOC "\@c library file: $library\n";
550    undef @procs;
551    $ref = OutLibInfo(\*LDOC, $info, $l_fun);
552    OutRef(\*LDOC, $ref) if $ref;
553    # print menu of available functions
554    if ($l_fun)
555    {
556      # print help and example of each function
557      for ($i = 0; $i <= $#procs; $i++)
558      {
559        # print node and section heading
560        print LDOC "\n\@c ------------------- " . $procs[$i]." -------------\n";
561        print LDOC "\@node " . $procs[$i].",";
562        print LDOC " ".$procs[$i+1] if ($i < $#procs);
563        print LDOC ",";
564        print LDOC " ".$procs[$i-1] if ($i > 0);
565        print LDOC ", " . $lib ."_lib\n";
566        print LDOC "\@$section " . $procs[$i] . "\n";
567        print LDOC "\@cindex ". $procs[$i] . "\n";
568
569        print LDOC "\@c ---content $procs[$i]---\n";
570        print LDOC "Procedure from library \@code{$lib.lib} (\@pxref{${lib}_lib}).\n\n";
571        if ($help{$procs[$i]} =~ /^\@/)
572        {
573          print LDOC $help{$procs[$i]};
574          $ref = '';
575        }
576        else
577        {
578          print LDOC "\@table \@asis\n";
579          $table_is_open = 1;
580          # print help
581          $ref = OutInfo(\*LDOC, $help{$procs[$i]});
582          print LDOC "\@end table\n";
583        }
584        # print example
585        if ($example = &CleanUpExample($lib, $example{$procs[$i]}))
586        {
587          print LDOC "\@strong{Example:}\n";
588          print LDOC "\@smallexample\n\@c example\n";
589          print LDOC $example;
590          print LDOC "\n\@c example\n\@end smallexample\n";
591        }
592        OutRef(\*LDOC, $ref) if $ref;
593        print LDOC "\@c ---end content $procs[$i]---\n";
594      }
595    }
596    close(LDOC);
597    print ")" if ($verbose == 1);
598  }
599
600  $largs = "-no_ex" unless ($l_ex);
601  # call doc2tex on generated doc file
602  print "\n" if ($verbose == 1);
603  dbmclose(%EXAMPLES);
604  &System("$0 $args $largs -o $tex_file $doc_file");
605  dbmopen(%EXAMPLES, $doc_examples_db, oct(755)) 
606    || die "$ERROR: can't open examples data base: $!\n";
607 
608  unlink($doc_file) if ($clean);
609  return 1;
610}
611
612###########################################################################
613# parse and print-out libinfo
614sub OutLibInfo
615{
616  my ($FH, $info, $l_fun) = @_;
617  print $FH "\@c ---content LibInfo---\n";
618    if ($info =~ /^\@/)
619  {
620    print $FH $info;
621    return;
622  }
623  print $FH "\@table \@asis\n";
624  $table_is_open = 1;
625 
626  my ($ref) = OutInfo($FH, $info, $l_fun);
627
628  print $FH "\@end table\n" if $table_is_open;
629  print $FH "\@c ---end content LibInfo---\n";
630  $table_is_open = 0;
631  return $ref;
632}
633
634sub OutInfo
635{
636  my ($FH, $info, $l_fun) = @_;
637  if ($info =~ /^\s*\@/)
638  {
639    print $FH $info;
640    return;
641  }
642  $info =~ s/^\s*//;
643  $info =~ s/\s*$//;
644  $info .= "\n";
645
646  my ($item, $text, $line, $ref);
647  while ($info =~ m/(.*\n)/g)
648  {
649    $line = $1;
650    if ($1 =~ /^(\w.+?):(.*\n)/)
651    {
652      $ref .= OutInfoItem($FH, $item, $text, $l_fun) if $item && $text;
653      $item = $1;
654      $text = $2;
655    }
656    else
657    {
658      $text .= $line;
659    }
660  }
661  $ref .= OutInfoItem($FH, $item, $text, $l_fun) if $item && $text;
662  return $ref;
663}
664
665sub FormatInfoText
666{
667  my $length = shift;
668  $length = 0 unless $length;
669  # insert @* infront of all lines whose previous line is shorter than
670  # 60 characters
671  $_ = ' ' x $length . $_;
672  if (/^(.*)\n/)
673  {
674    $_ .= "\n";
675    my $pline;
676    my $line;
677    my $ptext = $_;
678    my $text = '';
679    while ($ptext =~ /(.*)\n/g)
680    {
681      $line = $1;
682      # break line if
683      $text .= '@*' 
684        if ($line =~ /\w/ && $pline =~ /\w/ # line and prev line are not empty
685            && $line !~ /^\s*\@\*/  # line does not start with @*
686            && $pline !~ /\@\*\s*/  # prev line does not end with @*
687            &&
688            ((length($pline) < 60  && # prev line is shorter than 60 chars
689              $pline !~ /\@code{.*?}/ # and does not contain @code, @math
690              && $pline !~ /\@math{.*?}/) 
691             ||
692             $line =~ /^\s*\w*\(.*?\)/ # $line starts with \w*(..)
693             ||
694             $pline =~ /^\s*\w*\(.*?\)[\s;:]*$/)); # prev line is only \w(..)
695      $line =~ s/\s*$//;
696      $text .= "$line\n";
697      $pline = $line;
698    }
699    $_ = $text;
700  }
701  s/\t/ /g;
702  s/\n +/\n/g;
703  s/\s*$//g;
704  s/ +/ /g;  # replace double whitespaces by one
705  s/(\w+\(.*?\))/\@code{$1}/g;
706  s/\@\*\s*/\@\*/g;
707  s/(\@[^\*])/\@$1/g; # escape @ signs, except @*
708  s/{/\@{/g; # escape {}
709  s/}/\@}/g;
710  # unprotect @@math@{@}, @code@{@}
711  while (s/\@\@math\@{(.*?)\@}/\@math{$1}/g) {} 
712  while (s/\@\@code\@{(.*?)\@}/\@code{$1}/g) {}
713  # remove @code{} inside @code{} and inside @math{}
714  while (s/\@math{([^}]*)\@code{(.*?)}(.*)?}/\@math{$1$2$3}/g) {}
715  while (s/\@code{([^}]*)\@code{(.*?)}(.*)?}/\@code{$1$2$3}/g) {}
716}
717
718sub OutInfoItem
719{
720  my ($FH, $item, $text, $l_fun) = @_;
721
722  $item = lc $item;
723  $item = ucfirst $item;
724
725  if ($item =~ /see also/i)
726  {
727    # return references
728    return $text;
729  }
730  elsif ($item =~ m/example/i)
731  {
732    # forget about example, since it comes explicitely
733    return '';
734  }
735  elsif ($item =~ m/procedure/i)
736  {
737    if ($l_fun && $table_is_open)
738    {
739      print $FH "\@end table\n\n";
740      $table_is_open = 0;
741    }
742    $text =~ s/^\s*//;
743    $text =~ s/\s*$//;
744    $text =~ s/.*$// if ($text=~/parameters.*brackets.*are.*optional.*$/);
745    $text .= "\n";
746   
747    my ($proc, $pargs, $pinfo, $line);
748    if ($l_fun)
749    {
750      print $FH "\@strong{$item:}\n\@menu\n";
751    }
752    else
753    {
754      print $FH "\@item \@strong{$item:}\n\@table \@asis\n";
755    }
756    while ($text =~ /(.*\n)/g)
757    {
758      $line = $1;
759      if ($1 =~ /^\s*(\w+)\((.*?)\)/)
760      {
761        OutProcInfo($FH, $proc, $procargs, $pinfo, $l_fun) if $proc && $pinfo;
762        $proc = $1;
763        $procargs = $2;
764        $pinfo = $';
765      }
766      else
767      {
768        $pinfo .= $line; 
769      }
770    }
771    OutProcInfo($FH, $proc, $procargs, $pinfo, $l_fun) if $proc && $pinfo;
772    print $FH ($l_fun ? "\@end menu\n" : "\@end table\n");
773    return '';
774  }
775
776  if (! $table_is_open)
777  {
778    print $FH "\@table \@asis\n";
779    $table_is_open = 1;
780  }
781  print $FH '@item @strong{'. "$item:}\n";
782  # prepare text:
783  local $_ = $text;
784  if (($item =~ m/^library/i)  && m/\s*(\w*)\.lib/)
785  {
786    print $FH "$1.lib\n";
787    $text = $';
788    if ($text =~ /\w/)
789    {
790      print $FH '@item @strong{Purpose:'."}\n";
791      print $FH lc $text;
792    }
793  }
794  else
795  {
796    # just print the text
797    FormatInfoText(length($item) + 1);
798    print $FH "$_\n";
799  }
800  return '';
801}
802
803sub OutProcInfo
804{
805  my($FH, $proc, $procargs, $pinfo, $l_fun) = @_;
806  local $_ = $pinfo;
807  s/^[;\s]*//;
808  s/\n/ /g;
809  FormatInfoText();
810 
811  if ($l_fun)
812  {
813    print $FH "* ${proc}:: $_\n";
814    push @procs, $proc;
815  }
816  else
817  {
818    print $FH "\@item \@code{$proc($procargs)}  ";
819    print $FH "\n\@cindex $proc\n$_\n";
820  }
821}
822
823sub OutRef
824{
825  my ($FH, $refs) = @_;
826  $refs =~ s/^\s*//;
827  $refs =~ s/\s*$//;
828  $refs =~ s/\n/,/g;
829  my @refs = split (/[,;\.]+/, $refs);
830  my $ref;
831
832  print $FH "\@c ref\nSee also:\n";
833  $ref = shift @refs;
834  print $FH "\@ref{$ref}";
835  for $ref (@refs)
836  {
837    $ref =~ s/^\s*//;
838    $ref =~ s/\s*$//;
839    print $FH ", \@ref{$ref}"  if ($ref =~ /\w/);
840  }
841  print $FH "\n\@c ref\n";
842}
843
844sub CleanUpExample
845{
846  local($lib, $example) = @_;
847 
848  # find portion in {}
849  $example =~ s/^[^{]*{(.*)}[^}]*$/$1/s;
850
851  if ($example =~ /EXAMPLE: \(not executed\)/)
852  {
853    # erase first three lines
854    $example =~ s/^.*\n.*\n.*\n/\n/;
855    # erase enclosing " " in every line
856    $example =~ s/\n\s*"/\n/g;
857    $example =~  s/";\n/\n/g;
858  }
859  # erase EXAMPLE, echo and pause statements
860  $example =~ s/"EXAMPLE.*"[^;]*;//g;
861  $example .= "\n";
862  my ($mexample, $line);
863  while ($example =~ m/(.*)\n/g)
864  {
865    $line = $1;
866    $line =~ s|echo[^;]*;||g if $line !~ m|(.*)//(.*)echo[^;]*;|;
867    $line =~ s|pause\(.*?\)[^;]*;||g if $line !~ m|(.*)//(.*)pause\(.*?\)[^;]*;|;
868    $mexample .= "$line\n";
869  }
870  $example = $mexample;
871 
872  # prepend LIB command
873  $example = "LIB \"$lib.lib\";\n".$example 
874    if ($example && $lib ne "standard");
875  # erase empty lines
876  $example =~ s/^\s*\n//g;
877  # erase spaces from beginning of lines
878  $example =~ s/\n\s*/\n/g;
879  $example =~ s/\s*$//g;
880  return $example;
881}
882
883###################################################################
884#
885# Auxiallary functions
886#
887sub IsNewer
888{
889  my $f1 = shift;
890  my $f2 = shift;
891  my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime)
892    = stat($f1);
893  my $m1 = $mtime;
894  ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime) = stat($f2);
895
896  return ($m1 > $mtime);
897}
898
899####################################################################
900# Auxillary routines
901#
902
903# protect texi special characters
904sub protect_texi
905{
906  s/\@/\@\@/g;
907  s/{/\@{/g;
908  s/}/\@}/g;
909}       
910
911# open w.r.t. include_dirs
912sub Open
913{
914  local(*FH, $file) = @_;
915  local($mode);
916  $file =~ s/^(.{1})(.*)/$2/;
917  $mode = $1;
918
919  foreach $dir (@include_dirs)
920  {
921    return $dir if(open(FH, $mode.$dir."/".$file));
922  }
923}
924   
925# system call with echo on verbose > 1 and die on fail
926sub System
927{
928  local($call) = @_;
929  print "\nd2t system: $call\n" if ($verbose > 1);
930  Error("non-zero exit status of system call: '$call': $!\n")
931    if (system($call));
932}
933
934sub Error
935{
936  print "$ERROR $_[0]";
937  close(TEX);
938  unlink $tex_file if $tex_file && -e $tex_file;
939  exit(1);
940}
941
942#
943# leave this here --otherwise fontification in my emacs gets screwd up
944#
945sub Usage
946{
947  return <<EOT;
948This is doc2tex: a utility to generate Singular texinfo from doc file
949To convert a doc file to texinfo: $0 [options] input_file.doc
950where options can be (abbreviated to shortest possible prefix):
951  -Singular prog: use 'prog' as Singular program to generate ex output
952                          (default: '../Singular/Singular')
953  -libparse prog: use 'prog' as libparse program to generate lib docu
954                          (default: '../Singular/libparse')
955  -output file  : use 'file' as output file
956                          (default: input_file.tex)
957  -clean        : delete intermediate files
958  -no_reuse     : don't reuse intermediate files
959  -no_ex        : skip computation of examples
960  -lib_fun      : include help for library functions
961  -lib_ex       : include example for library functions
962  -subdir  dir  : put intermediate files into 'dir'
963                          (default: './d2t_singular')
964  -I dir        : look also into 'dir' for include  and lib files
965                          (default: ".", "../Singular/LIB")
966  -verbose  val : Set verbosity to 'val' (0=quiet, 1=prot, >1=all)
967  -help         : print help and exit
968EOT
969}
970
Note: See TracBrowser for help on using the repository browser.