299 lines
		
	
	
		
			9 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			299 lines
		
	
	
		
			9 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| 
								 | 
							
								#!/usr/bin/perl --
							 | 
						||
| 
								 | 
							
								# Copyright (C) 1993-1995 Ian Jackson.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# This file is free software; you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								# it under the terms of the GNU General Public License as published by
							 | 
						||
| 
								 | 
							
								# the Free Software Foundation; either version 2, or (at your option)
							 | 
						||
| 
								 | 
							
								# any later version.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# It is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								# but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						||
| 
								 | 
							
								# GNU General Public License for more details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# You should have received a copy of the GNU General Public License
							 | 
						||
| 
								 | 
							
								# along with GNU Emacs; see the file COPYING.  If not, write to
							 | 
						||
| 
								 | 
							
								# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
							 | 
						||
| 
								 | 
							
								# Boston, MA 02111-1307, USA.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# (Note: I do not consider works produced using these BFNN processing
							 | 
						||
| 
								 | 
							
								# tools to be derivative works of the tools, so they are NOT covered
							 | 
						||
| 
								 | 
							
								# by the GPL.  However, I would appreciate it if you credited me if
							 | 
						||
| 
								 | 
							
								# appropriate in any documents you format using BFNN.)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@outputs=('ascii','info','html');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								while ($ARGV[0] =~ m/^\-/) {
							 | 
						||
| 
								 | 
							
								    $_= shift(@ARGV);
							 | 
						||
| 
								 | 
							
								    if (m/^-only/) {
							 | 
						||
| 
								 | 
							
								        @outputs= (shift(@ARGV));
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        warn "unknown option `$_' ignored";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								$prefix= $ARGV[0];
							 | 
						||
| 
								 | 
							
								$prefix= 'stdin' unless length($prefix);
							 | 
						||
| 
								 | 
							
								$prefix =~ s/\.bfnn$//;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (open(O,"$prefix.xrefdb")) {
							 | 
						||
| 
								 | 
							
								    @xrefdb= <O>;
							 | 
						||
| 
								 | 
							
								    close(O);
							 | 
						||
| 
								 | 
							
								} else {
							 | 
						||
| 
								 | 
							
								    warn "no $prefix.xrefdb ($!)";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								$section= -1;
							 | 
						||
| 
								 | 
							
								for $thisxr (@xrefdb) {
							 | 
						||
| 
								 | 
							
								    $_= $thisxr;
							 | 
						||
| 
								 | 
							
								    chop;
							 | 
						||
| 
								 | 
							
								    if (m/^Q (\w+) ((\d+)\.(\d+)) (.*)$/) {
							 | 
						||
| 
								 | 
							
								        $qrefn{$1}= $2;
							 | 
						||
| 
								 | 
							
								        $qreft{$1}= $5;
							 | 
						||
| 
								 | 
							
								        $qn2ref{$3,$4}= $1;
							 | 
						||
| 
								 | 
							
								        $maxsection= $3;
							 | 
						||
| 
								 | 
							
								        $maxquestion[$3]= $4;
							 | 
						||
| 
								 | 
							
								    } elsif (m/^S (\d+) /) {
							 | 
						||
| 
								 | 
							
								        $maxsection= $1;
							 | 
						||
| 
								 | 
							
								        $sn2title{$1}=$';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								open(U,">$prefix.xrefdb-new");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for $x (@outputs) { require("m-$x.pl"); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								&call('init');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								while (<>) {
							 | 
						||
| 
								 | 
							
								    chop;
							 | 
						||
| 
								 | 
							
								    next if m/^\\comment\b/;
							 | 
						||
| 
								 | 
							
								    if (!m/\S/) {
							 | 
						||
| 
								 | 
							
								        &call('endpara');
							 | 
						||
| 
								 | 
							
								        next;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (s/^\\section +//) {
							 | 
						||
| 
								 | 
							
								        $line= $_;
							 | 
						||
| 
								 | 
							
								        $section++; $question=0;
							 | 
						||
| 
								 | 
							
								        print U "S $section $line\n";
							 | 
						||
| 
								 | 
							
								        $|=1; print "S$section",' 'x10,"\r"; $|=0;
							 | 
						||
| 
								 | 
							
								        &call('endpara');
							 | 
						||
| 
								 | 
							
								        &call('startmajorheading',"$section",
							 | 
						||
| 
								 | 
							
								              "Section $section",
							 | 
						||
| 
								 | 
							
								              $section<$maxsection ? "Section ".($section+1) : '',
							 | 
						||
| 
								 | 
							
								              $section>1 ? 'Section '.($section-1) : 'Top');
							 | 
						||
| 
								 | 
							
								        &text($line);
							 | 
						||
| 
								 | 
							
								        &call('endmajorheading');
							 | 
						||
| 
								 | 
							
								        if ($section) {
							 | 
						||
| 
								 | 
							
								            &call('endpara');
							 | 
						||
| 
								 | 
							
								            &call('startindex');
							 | 
						||
| 
								 | 
							
								            for $thisxr (@xrefdb) {
							 | 
						||
| 
								 | 
							
								                $_= $thisxr;
							 | 
						||
| 
								 | 
							
								                chop;
							 | 
						||
| 
								 | 
							
								                if (m/^Q (\w+) (\d+)\.(\d+) (.*)$/) {
							 | 
						||
| 
								 | 
							
								                    $ref= $1; $num1= $2; $num2= $3; $text= $4;
							 | 
						||
| 
								 | 
							
								                    next unless $num1 == $section;
							 | 
						||
| 
								 | 
							
								                    &call('startindexitem',$ref,"Q$num1.$num2","Question $num1.$num2");
							 | 
						||
| 
								 | 
							
								                    &text($text);
							 | 
						||
| 
								 | 
							
								                    &call('endindexitem');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            &call('endindex');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } elsif (s/^\\question \d{2}[a-z]{3}((:\w+)?) +//) {
							 | 
						||
| 
								 | 
							
								        $line= $_;
							 | 
						||
| 
								 | 
							
								        $question++;
							 | 
						||
| 
								 | 
							
								        $qrefstring= $1;
							 | 
						||
| 
								 | 
							
								        $qrefstring= "q_${section}_$question" unless $qrefstring =~ s/^://;
							 | 
						||
| 
								 | 
							
								        print U "Q $qrefstring $section.$question $line\n";
							 | 
						||
| 
								 | 
							
								        $|=1; print "Q$section.$question",' 'x10,"\r"; $|=0;
							 | 
						||
| 
								 | 
							
								        &call('endpara');
							 | 
						||
| 
								 | 
							
								        &call('startminorheading',$qrefstring,
							 | 
						||
| 
								 | 
							
								              "Question $section.$question",
							 | 
						||
| 
								 | 
							
								              $question < $maxquestion[$section] ? "Question $section.".($question+1) :
							 | 
						||
| 
								 | 
							
								              $section < $maxsection ? "Question ".($section+1).".1" : '',
							 | 
						||
| 
								 | 
							
								              $question > 1 ? "Question $section.".($question-1) :
							 | 
						||
| 
								 | 
							
								              $section > 1 ? "Question ".($section-1).'.'.($maxquestion[$section-1]) :
							 | 
						||
| 
								 | 
							
								              'Top',
							 | 
						||
| 
								 | 
							
								              "Section $section");
							 | 
						||
| 
								 | 
							
								        &text("Question $section.$question.  $line");
							 | 
						||
| 
								 | 
							
								        &call('endminorheading');
							 | 
						||
| 
								 | 
							
								    } elsif (s/^\\only +//) {
							 | 
						||
| 
								 | 
							
								        @saveoutputs= @outputs;
							 | 
						||
| 
								 | 
							
								        @outputs=();
							 | 
						||
| 
								 | 
							
								        for $x (split(/\s+/,$_)) {
							 | 
						||
| 
								 | 
							
								            push(@outputs,$x) if grep($x eq $_, @saveoutputs);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } elsif (s/^\\endonly$//) {
							 | 
						||
| 
								 | 
							
								        @outputs= @saveoutputs;
							 | 
						||
| 
								 | 
							
								    } elsif (s/^\\copyto +//) {
							 | 
						||
| 
								 | 
							
								        $fh= $';
							 | 
						||
| 
								 | 
							
								        while(<>) {
							 | 
						||
| 
								 | 
							
								            last if m/^\\endcopy$/;
							 | 
						||
| 
								 | 
							
								            while (s/^([^\`]*)\`//) {
							 | 
						||
| 
								 | 
							
								                print $fh $1;
							 | 
						||
| 
								 | 
							
								                m/([^\\])\`/ || warn "`$_'";
							 | 
						||
| 
								 | 
							
								                $_= $';
							 | 
						||
| 
								 | 
							
								                $cmd= $`.$1;
							 | 
						||
| 
								 | 
							
								                $it= `$cmd`; chop $it;
							 | 
						||
| 
								 | 
							
								                print $fh $it;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            print $fh $_;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } elsif (m/\\index$/) {
							 | 
						||
| 
								 | 
							
								        &call('startindex');
							 | 
						||
| 
								 | 
							
								        for $thisxr (@xrefdb) {
							 | 
						||
| 
								 | 
							
								            $_= $thisxr;
							 | 
						||
| 
								 | 
							
								            chop;
							 | 
						||
| 
								 | 
							
								            if (m/^Q (\w+) (\d+\.\d+) (.*)$/) {
							 | 
						||
| 
								 | 
							
								                $ref= $1; $num= $2; $text= $3;
							 | 
						||
| 
								 | 
							
								                &call('startindexitem',$ref,"Q$num","Question $num");
							 | 
						||
| 
								 | 
							
								                &text($text);
							 | 
						||
| 
								 | 
							
								                &call('endindexitem');
							 | 
						||
| 
								 | 
							
								            } elsif (m/^S (\d+) (.*)$/) {
							 | 
						||
| 
								 | 
							
								                $num= $1; $text= $2;
							 | 
						||
| 
								 | 
							
								                next unless $num;
							 | 
						||
| 
								 | 
							
								                &call('startindexmainitem',"s_$num",
							 | 
						||
| 
								 | 
							
								                      "Section $num.","Section $num");
							 | 
						||
| 
								 | 
							
								                &text($text);
							 | 
						||
| 
								 | 
							
								                &call('endindexitem');
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                warn $_;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        &call('endindex');
							 | 
						||
| 
								 | 
							
								    } elsif (m/^\\call-(\w+) +(\w+)\s*(.*)$/) {
							 | 
						||
| 
								 | 
							
								        $fn= $1.'_'.$2;
							 | 
						||
| 
								 | 
							
								        eval { &$fn($3); };
							 | 
						||
| 
								 | 
							
								        warn $@ if length($@);
							 | 
						||
| 
								 | 
							
								    } elsif (m/^\\call +(\w+)\s*(.*)$/) {
							 | 
						||
| 
								 | 
							
								        eval { &call($1,$2); };
							 | 
						||
| 
								 | 
							
								        warn $@ if length($@);
							 | 
						||
| 
								 | 
							
								    } elsif (s/^\\set +(\w+)\s*//) {
							 | 
						||
| 
								 | 
							
								        $svalue= $'; $svari= $1;
							 | 
						||
| 
								 | 
							
								        eval("\$user_$svari=\$svalue"); $@ && warn "setting $svalue failed: $@\n";
							 | 
						||
| 
								 | 
							
								    } elsif (m/^\\verbatim$/) {
							 | 
						||
| 
								 | 
							
								        &call('startverbatim');
							 | 
						||
| 
								 | 
							
								        while (<>) {
							 | 
						||
| 
								 | 
							
								            chop;
							 | 
						||
| 
								 | 
							
								            last if m/^\\endverbatim$/;
							 | 
						||
| 
								 | 
							
								            &call('verbatim',$_);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        &call('endverbatim');
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        s/\.$/\. /;
							 | 
						||
| 
								 | 
							
								        &text($_." ");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								print ' 'x25,"\r";
							 | 
						||
| 
								 | 
							
								&call('finish');
							 | 
						||
| 
								 | 
							
								rename("$prefix.xrefdb-new","$prefix.xrefdb") || warn "rename xrefdb: $!";
							 | 
						||
| 
								 | 
							
								exit 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub text {
							 | 
						||
| 
								 | 
							
								    local($in,$rhs,$word,$refn,$reft,$fn,$style);
							 | 
						||
| 
								 | 
							
								    $in= "$holdover$_[0]";
							 | 
						||
| 
								 | 
							
								    $holdover= '';
							 | 
						||
| 
								 | 
							
								    while ($in =~ m/\\/) {
							 | 
						||
| 
								 | 
							
								#print STDERR ">$`##$'\n";
							 | 
						||
| 
								 | 
							
								        $rhs=$';
							 | 
						||
| 
								 | 
							
								        &call('text',$`);
							 | 
						||
| 
								 | 
							
								        $_= $rhs;
							 | 
						||
| 
								 | 
							
								        if (m/^\w+ $/) {
							 | 
						||
| 
								 | 
							
								            $holdover= "\\$&";
							 | 
						||
| 
								 | 
							
								            $in= '';
							 | 
						||
| 
								 | 
							
								        } elsif (s/^fn\s+([^\s\\]*\w)//) {
							 | 
						||
| 
								 | 
							
								            $in= $_;
							 | 
						||
| 
								 | 
							
								            $word= $1;
							 | 
						||
| 
								 | 
							
								            &call('courier');
							 | 
						||
| 
								 | 
							
								            &call('text',$word);
							 | 
						||
| 
								 | 
							
								            &call('endcourier');
							 | 
						||
| 
								 | 
							
								        } elsif (s/^tab\s+(\d+)\s+//) {
							 | 
						||
| 
								 | 
							
								            $in= $_; &call('tab',$1);
							 | 
						||
| 
								 | 
							
								        } elsif (s/^nl\s+//) {
							 | 
						||
| 
								 | 
							
								            $in= $_; &call('newline');
							 | 
						||
| 
								 | 
							
								        } elsif (s/^qref\s+(\w+)//) {
							 | 
						||
| 
								 | 
							
								            $refn= $qrefn{$1};
							 | 
						||
| 
								 | 
							
								            $reft= $qreft{$1};
							 | 
						||
| 
								 | 
							
								            if (!length($refn)) {
							 | 
						||
| 
								 | 
							
								                warn "unknown question `$1'";
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $in= "$`\\pageref:$1:$refn:$reft\\endpageref.$_";
							 | 
						||
| 
								 | 
							
								        } elsif (s/^pageref:(\w+):([^:\n]+)://) {
							 | 
						||
| 
								 | 
							
								            $in= $_;
							 | 
						||
| 
								 | 
							
								            &call('pageref',$1,$2);
							 | 
						||
| 
								 | 
							
								        } elsif (s/^endpageref\.//) {
							 | 
						||
| 
								 | 
							
								            $in= $_; &call('endpageref');
							 | 
						||
| 
								 | 
							
								        } elsif (s/^(\w+)\{//) {
							 | 
						||
| 
								 | 
							
								            $in= $_; $fn= $1;
							 | 
						||
| 
								 | 
							
								            eval { &call("$fn"); };
							 | 
						||
| 
								 | 
							
								            if (length($@)) { warn $@; $fn= 'x'; }
							 | 
						||
| 
								 | 
							
								            push(@styles,$fn);
							 | 
						||
| 
								 | 
							
								        } elsif (s/^\}//) {
							 | 
						||
| 
								 | 
							
								            $in= $_;
							 | 
						||
| 
								 | 
							
								            $fn= pop(@styles);
							 | 
						||
| 
								 | 
							
								            if ($fn ne 'x') { &call("end$fn"); }
							 | 
						||
| 
								 | 
							
								        } elsif (s/^\\//) {
							 | 
						||
| 
								 | 
							
								            $in= $_;
							 | 
						||
| 
								 | 
							
								            &call('text',"\\");
							 | 
						||
| 
								 | 
							
								        } elsif (s,^(\w+)\s+([-A-Za-z0-9.\@:/]*\w),,) {
							 | 
						||
| 
								 | 
							
								#print STDERR "**$&**$_\n";
							 | 
						||
| 
								 | 
							
								            $in= $_;
							 | 
						||
| 
								 | 
							
								            $style=$1; $word= $2;
							 | 
						||
| 
								 | 
							
								            &call($style);
							 | 
						||
| 
								 | 
							
								            &call('text',$word);
							 | 
						||
| 
								 | 
							
								            &call("end$style");
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            warn "unknown control `\\$_'";
							 | 
						||
| 
								 | 
							
								            $in= $_;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    &call('text',$in);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub call {
							 | 
						||
| 
								 | 
							
								    local ($fnbase, @callargs) = @_;
							 | 
						||
| 
								 | 
							
								    local ($coutput);
							 | 
						||
| 
								 | 
							
								    for $coutput (@outputs) {
							 | 
						||
| 
								 | 
							
								        if ($fnbase eq 'text' && eval("\@${coutput}_cmds")) {
							 | 
						||
| 
								 | 
							
								#print STDERR "special handling text (@callargs) for $coutput\n";
							 | 
						||
| 
								 | 
							
								            $evstrg= "\$${coutput}_args[\$#${coutput}_args].=\"\@callargs\"";
							 | 
						||
| 
								 | 
							
								            eval($evstrg);
							 | 
						||
| 
								 | 
							
								            length($@) && warn "call adding for $coutput (($evstrg)): $@";
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $fntc= $coutput.'_'.$fnbase; 
							 | 
						||
| 
								 | 
							
								            &$fntc(@callargs);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub recurse {
							 | 
						||
| 
								 | 
							
								    local (@outputs) = $coutput;
							 | 
						||
| 
								 | 
							
								    local ($holdover);
							 | 
						||
| 
								 | 
							
								    &text($_[0]);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub arg {
							 | 
						||
| 
								 | 
							
								#print STDERR "arg($_[0]) from $coutput\n";
							 | 
						||
| 
								 | 
							
								    $cmd= $_[0];
							 | 
						||
| 
								 | 
							
								    eval("push(\@${coutput}_cmds,\$cmd); push(\@${coutput}_args,'')");
							 | 
						||
| 
								 | 
							
								    length($@) && warn "arg setting up for $coutput: $@";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub endarg {
							 | 
						||
| 
								 | 
							
								#print STDERR "endarg($_[0]) from $coutput\n";
							 | 
						||
| 
								 | 
							
								    $evstrg= "\$${coutput}_cmd= \$cmd= pop(\@${coutput}_cmds); ".
							 | 
						||
| 
								 | 
							
								             "\$${coutput}_arg= \$arg= pop(\@${coutput}_args); ";
							 | 
						||
| 
								 | 
							
								    eval($evstrg);
							 | 
						||
| 
								 | 
							
								    length($@) && warn "endarg extracting for $coutput (($evstrg)): $@";
							 | 
						||
| 
								 | 
							
								#print STDERR ">call $coutput $cmd $arg< (($evstrg))\n";
							 | 
						||
| 
								 | 
							
								    $evstrg= "&${coutput}_do_${cmd}(\$arg)";
							 | 
						||
| 
								 | 
							
								    eval($evstrg);
							 | 
						||
| 
								 | 
							
								    length($@) && warn "endarg running ${coutput}_do_${cmd} (($evstrg)): $@";
							 | 
						||
| 
								 | 
							
								}
							 |