Mercurial > forge
changeset 1098:96a954e137da octave-forge
Re-add mktexi/mkdoc with the right execute flagscvs add mktexi mkdoc
author | adb014 |
---|---|
date | Thu, 06 Nov 2003 14:42:59 +0000 |
parents | 0761d9d1f861 |
children | 2b676999f159 |
files | admin/mkdoc admin/mktexi |
diffstat | 2 files changed, 570 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/admin/mkdoc Thu Nov 06 14:42:59 2003 +0000 @@ -0,0 +1,137 @@ +#!/usr/bin/env perl +# +# David Bateman Feb 02 2003 +# +# Extracts the help in texinfo format from *.cc and *.m files for use +# in documentation. Based on make_index script from octave_forge. + +use strict; +use File::Find; +use File::Basename; +use FileHandle; + +my $docdir = "."; +if (@ARGV) { + $docdir = @ARGV[0]; +} + +# locate all C++ and m-files in current directory +my @m_files = (); +my @C_files = (); +find(\&cc_and_m_files, $docdir); + +sub cc_and_m_files { # {{{1 populates global array @files + return unless -f and /\.(m|cc)$/; # .m and .cc files + my $path = "$File::Find::dir/$_"; + $path =~ s|^[.]/||; + if (/\.m$/) { + push @m_files, $path; + } else { + push @C_files, $path; + } +} # 1}}} + +# grab help from C++ files +foreach my $f ( @C_files ) { + # XXX FIXME XXX. Should run the preprocessor over the file first, since + # the help might include defines that are compile dependent. + if ( open(IN,$f) ) { + while (<IN>) { + # skip to the next function + next unless /^DEFUN_DLD/; + + # extract function name to pattern space + /\((\w*)\s*,/; + # remember function name + my $function = $1; + # skip to next line if comment doesn't start on this line + # XXX FIXME XXX maybe we want a loop here? + $_ = <IN> unless /\"/; + # skip to the beginning of the comment string by + # chopping everything up to opening " + my $desc = $_; + $desc =~ s/^[^\"]*\"//; + # join lines until you get the end of the comment string + # plus a bit more. You need the "plus a bit more" because + # C compilers allow implicitly concatenated string constants + # "A" "B" ==> "AB". + while ($desc !~ /[^\\]\"\s*\S/ && $desc !~ /^\"/) { + # if line ends in '\', chop it and the following '\n' + $desc =~ s/\\\s*\n//; + # join with the next line + $desc .= <IN>; + # eliminate consecutive quotes, being careful to ignore + # preceding slashes. XXX FIXME XXX what about \\" ? + $desc =~ s/([^\\])\"\s*\"/$1/; + } + $desc = "" if $desc =~ /^\"/; # chop everything if it was "" + $desc =~ s/\\n/\n/g; # insert fake line ends + $desc =~ s/([^\"])\".*$/$1/; # chop everything after final '"' + $desc =~ s/\\\"/\"/; # convert \"; XXX FIXME XXX \\" + $desc =~ s/$//g; # chop trailing ... + + if (!($desc =~ /^\s*-[*]- texinfo -[*]-/)) { + my $err = sprintf("Function %s, does not contain texinfo help\n", + $function); + print STDERR "$err"; + } + my $entry = sprintf("\037%s\n%s", $function, $desc); + print "$entry", "\n"; + } + close (IN); + } else { + print STDERR "Could not open file ($f): $!\n"; + } +} + +# grab help from m-files +foreach my $f ( @m_files ) { + my $desc = extract_description($f); + my $function = basename($f, ('.m')); + die "Null function?? [$f]\n" unless $function; + if (!($desc =~ /^\s*-[*]- texinfo -[*]-/)) { + my $err = sprintf("Function %s, does not contain texinfo help\n", + $function); + print STDERR "$err"; + } + my $entry = sprintf("\037%s\n%s", $function, $desc); + print "$entry", "\n"; +} + +sub extract_description { # {{{1 +# grab the entire documentation comment from an m-file + my ($file) = @_; + my $retval = ''; + + if( open( IN, "$file")) { + # skip leading blank lines + while (<IN>) { + last if /\S/; + } + if( m/\s*[%\#][\s\#%]* Copyright/) { + # next block is copyright statement, skip it + while (<IN>) { + last unless /^\s*[%\#]/; + } + } + # Skip everything until the next comment block + while ( !/^\s*[\#%]/ ) { + $_ = <IN>; + last if not defined $_; + } + # Return the next comment block as the documentation + while (/^\s*[\#%]/) { + s/^[\s%\#]*//; # strip leading comment characters + s/[\cM\s]*$//; # strip trailing spaces. + s/[\.*]$//; + $retval .= "$_\n"; + $_ = <IN>; + last if not defined $_; + } + close(IN); + return $retval; + } + else { + print STDERR "Could not open file ($file): $!\n"; + } +} # 1}}}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/admin/mktexi Thu Nov 06 14:42:59 2003 +0000 @@ -0,0 +1,433 @@ +#!/usr/bin/env perl +# +# David Bateman Feb 02 2003 +# +# Extracts the help in texinfo format for particular function for use +# in documentation. Based on make_index script from octave_forge. + +use strict; +use File::Find; +use File::Basename; +use Text::Wrap; +use FileHandle; +use IPC::Open3; +use POSIX ":sys_wait_h"; + +my $file = shift @ARGV; +my $docfile = shift @ARGV; +my $indexfile = shift @ARGV; +my $line; + +if ( open(IN,$file) ) { + $line = <IN>; + my $tex = 0; + while ($line) { + if ($line =~ /^\@DOCSTRING/) { + my $found = 0; + my $func = $line; + $func =~ s/\@DOCSTRING\(//; + $func =~ s/\)[\n\r]+//; + my $func0 = $func; + my $func1 = $func; + $func0 =~ s/,.*$//; + $func1 =~ s/^.*,//; + if ( open(DOC,$docfile) ) { + while (<DOC>) { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func0$/) { + my $desc = ""; + my $docline; + my $doctex = 0; + while (($docline = <DOC>) && ($docline !~ /^\037/)) { + $docline =~ s/^\s*-[*]- texinfo -[*]-\s*//; + if ($docline =~ /\@tex/) { + $doctex = 1; + } + if ($doctex) { + $docline =~ s/\\\\/\\/g; + } + if ($docline =~ /\@end tex/) { + $doctex = 0; + } + $desc .= $docline; + } + $desc =~ s/$func0/$func1/g; + $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g; + print "$desc", "\n"; + $found = 1; + last; + } + } + close (DOC); + if (! $found) { + print "\@emph{Not implemented}\n"; + } + } else { + print STDERR "Could not open file $docfile\n"; + exit 1; + } + } elsif ($line =~ /^\@REFERENCE_SECTION/) { + my $secfound = 0; + my $sec = $line; + $sec =~ s/\@REFERENCE_SECTION\(//; + $sec =~ s/\)[\n\r]+//; + my @listfunc = (); + my $nfunc = 0; + my $seccat = 0; + + if ( open(IND,$indexfile) ) { + while (<IND>) { + next unless /^[^ ]/; + my $section = $_; + $section =~ s/[\n\r]+//; + if ($section =~ /^(.*?)\s*>>\s*(.*?)$/) { + $section =~ s/.*>>(.*)/\1/; + $seccat = 1; + } + $section =~ s/^ *//; + $section =~ s/ *$//; + if ($section =~ /^$sec$/) { + if ($seccat) { + print "\@iftex\n"; + print "\@section Functions by Category\n"; + # Get the list of categories to index + my $firstcat = 1; + my $category; + while (<IND>) { + last if />>/; + if (/^[^ ]/) { + if (! $firstcat) { + print "\@end table\n"; + } else { + $firstcat = 0; + } + $category = $_; + $category =~ s/[\n\r]+//; + print "\@subsection $category\n"; + print "\@table \@asis\n"; + } elsif (/^\s+(\S.*\S)\s*=\s*(\S.*\S)\s*$/) { + my $func = $1; + my $desc = $2; + print "\@item $func\n"; + print "$desc\n"; + print "\n"; + } else { + if ($firstcat) { + print STDERR "Error parsing index file\n"; + exit 1; + } + s/^\s+//; + my @funcs = split /\s+/; + while ($#funcs >= 0) { + my $func = shift @funcs; + $func =~ s/^ *//; + $func =~ s/[\n\r]+//; + push @listfunc, $func; + $nfunc = $nfunc + 1; + print "\@item $func\n"; + print func_summary($func, $docfile); + print "\n"; + } + } + } + if (! $firstcat) { + print "\@end table\n"; + } + print "\n\@section Functions Alphabetically\n"; + print "\@end iftex\n\n"; + } else { + # Get the list of functions to index + my $indline; + while (($indline = <IND>) && ($indline =~ /^ /)) { + if ($indline =~ /^\s+(\S.*\S)\s*=\s*(\S.*\S)\s*$/) { + next; + } + $indline =~ s/^\s+//; + my @funcs = split(/\s+/,$indline); + while ($#funcs >= 0) { + my $func = shift @funcs; + $func =~ s/^ *//; + $func =~ s/[\n\r]+//; + push @listfunc, $func; + $nfunc = $nfunc + 1; + } + } + } + $secfound = 1; + last; + } + } + close (IND); + if (! $secfound) { + print STDERR "Did not find section $sec\n"; + } + } else { + print STDERR "Could not open file $indexfile\n"; + exit 1; + } + + @listfunc = sort(@listfunc); + my @listfunc2 = (); + my $indent = 16 - 3; + print "\@menu\n"; + foreach my $func (@listfunc) { + if ( open(DOC,$docfile) ) { + my $found = 0; + while (<DOC>) { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func$/) { + $found = 1; + last; + } + } + close (DOC); + if ($found) { + push @listfunc2, $func; + my $func0 = "${func}::"; + my $entry = sprintf("* %-*s %s",$indent,$func0,func_summary($func,$docfile)); + print wrap("","\t\t","$entry"), "\n"; + } + } else { + print STDERR "Could not open file $indexfile\n"; + exit 1; + } + } + print "\@end menu\n"; + + my $up = "Function Reference"; + my $next; + my $prev; + my $mfunc = 1; + foreach my $func (@listfunc2) { + if ($mfunc == $nfunc) { + $next = ""; + } else { + $next = @listfunc2[$mfunc]; + $mfunc = $mfunc + 1; + } + print "\n\@node $func, $next, $prev, $up\n"; + if ($seccat) { + print "\@subsection $func\n\n"; + } else { + print "\@section $func\n\n"; + } + $prev = $func; + my $found = 0; + my $desc = ""; + if ( open(DOC,$docfile) ) { + while (<DOC>) { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func$/) { + my $docline; + my $doctex = 0; + while (($docline = <DOC>) && ($docline !~ /^\037/)) { + $docline =~ s/^\s*-[*]- texinfo -[*]-\s*//; + if ($docline =~ /\@tex/) { + $doctex = 1; + } + if ($doctex) { + $docline =~ s/\\\\/\\/g; + } + if ($docline =~ /\@end tex/) { + $doctex = 0; + } + $desc .= $docline; + } + $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g; + print "$desc", "\n"; + $found = 1; + last; + } + } + close (DOC); + if (! $found) { + print "\@emph{Not implemented}\n"; + } + } else { + print STDERR "Could not open file $docfile\n"; + exit 1; + } + } + } else { + if ($line =~ /\@tex/) { + $tex = 1; + } + if ($tex) { + $line =~ s/\\\\/\\/g; + } + print "$line"; + if ($line =~ /\@end tex/) { + $tex = 0; + } + } + $line = <IN>; + } +} else { + print STDERR "Could not open file $file\n"; + exit 1; +} + +sub func_summary { # {{{1 + my ($func, # in function name + $docfile # in DOCSTRINGS + ) = @_; + + my $desc = ""; + my $found = 0; + if ( open(DOC,$docfile) ) { + while (<DOC>) { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func$/) { + my $docline; + my $doctex = 0; + while (($docline = <DOC>) && ($docline !~ /^\037/)) { + if ($docline =~ /\@tex/) { + $doctex = 1; + } + if ($doctex) { + $docline =~ s/\\\\/\\/g; + } + if ($docline =~ /\@end tex/) { + $doctex = 0; + } + $desc .= $docline; + } + $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g; + $found = 1; + last; + } + } + close (DOC); + if (! $found) { + $desc = "\@emph{Not implemented}"; + } + } else { + print STDERR "Could not open file $docfile\n"; + exit 1; + } + return first_sentence($desc); +} # 1}}} + + +sub first_sentence { # {{{1 +# grab the first real sentence from the function documentation + my ($desc) = @_; + my $retval = ''; + my $line; + my $next; + my @lines; + + my $trace = 0; + # $trace = 1 if $desc =~ /Levenberg/; + return "" unless defined $desc; + if ($desc =~ /^\s*-[*]- texinfo -[*]-/) { + # help text contains texinfo. Strip the indicator and run it + # through makeinfo. (XXX FIXME XXX this needs to be a function) + $desc =~ s/^\s*-[*]- texinfo -[*]-\s*//; + my $cmd = "makeinfo --fill-column 1600 --no-warn --no-validate --no-headers --force --ifinfo"; + open3(*Writer, *Reader, *Errer, $cmd) or die "Could not run info"; + print Writer "\@macro seealso {args}\n\n\@noindent\nSee also: \\args\\.\n\@end macro\n"; + print Writer "$desc"; close(Writer); + @lines = <Reader>; close(Reader); + my @err = <Errer>; close(Errer); + waitpid(-1,&WNOHANG); + + # Display source and errors, if any + if (@err) { + my $n = 1; + foreach $line ( split(/\n/,$desc) ) { + printf "%2d: %s\n",$n++,$line; + } + print ">>> @err"; + } + + # Print trace showing formatted output +# print "<texinfo--------------------------------\n"; +# print @lines; +# print "--------------------------------texinfo>\n"; + + # Skip prototype and blank lines + while (1) { + return "" unless @lines; + $line = shift @lines; + next if $line =~ /^\s*-/; + next if $line =~ /^\s*$/; + last; + } + + } else { + +# print "<plain--------------------------------\n"; +# print $desc; +# print "--------------------------------plain>\n"; + + # Skip prototype and blank lines + @lines = split(/\n/,$desc); + while (1) { + return "" if ($#lines < 0); + $line = shift @lines; + next if $line =~ /^\s*[Uu][Ss][Aa][Gg][Ee]/; # skip " usage " + + $line =~ s/^\s*\w+\s*://; # chop " blah : " + print "strip blah: $line\n" if $trace; + $line =~ s/^\s*[Ff]unction\s+//; # chop " function " + print "strip function $line\n" if $trace; + $line =~ s/^\s*\[.*\]\s*=\s*//; # chop " [a,b] = " + print "strip []= $line\n" if $trace; + $line =~ s/^\s*\w+\s*=\s*//; # chop " a = " + print "strip a= $line\n" if $trace; + $line =~ s/^\s*\w+\s*\([^\)]*\)\s*//; # chop " f(x) " + print "strip f(x) $line\n" if $trace; + $line =~ s/^\s*[;:]\s*//; # chop " ; " + print "strip ; $line\n" if $trace; + + $line =~ s/^\s*[[:upper:]][[:upper:]0-9_]+//; # chop " BLAH" + print "strip BLAH $line\n" if $trace; + $line =~ s/^\s*\w*\s*[-]+\s+//; # chop " blah --- " + print "strip blah --- $line\n" if $trace; + $line =~ s/^\s*\w+ *\t\s*//; # chop " blah <TAB> " + print "strip blah <TAB> $line\n" if $trace; + $line =~ s/^\s*\w+\s\s+//; # chop " blah " + print "strip blah <NL> $line\n" if $trace; + +# next if $line =~ /^\s*\[/; # skip [a,b] = f(x) +# next if $line =~ /^\s*\w+\s*(=|\()/; # skip a = f(x) OR f(x) + next if $line =~ /^\s*or\s*$/; # skip blah \n or \n blah + next if $line =~ /^\s*$/; # skip blank line + next if $line =~ /^\s?!\//; # skip # !/usr/bin/octave + # XXX FIXME XXX should be testing for unmatched () in proto + # before going to the next line! + last; + } + } + + # Try to make a complete sentence, including the '.' + if ( "$line " !~ /[^.][.]\s/ && $#lines >= 0) { + my $next = $lines[0]; + $line =~ s/\s*$//; # trim trailing blanks on last + $next =~ s/^\s*//; # trim leading blanks on next + $line .= " $next" if "$next " =~ /[^.][.]\s/; # ends the sentence + } + + # Tidy up the sentence. + chomp $line; # trim trailing newline, if there is one + $line =~ s/^\s*//; # trim leading blanks on line + $line =~ s/([^.][.])\s.*$/$1/; # trim everything after the sentence + print "Skipping:\n$desc---\n" if $line eq ""; + + # And return it. + return $line; + +} # 1}}}