Article 11813 of comp.lang.perl:
Path: feenix.metronet.com!news.utdallas.edu!wupost!howland.reston.ans.net!vixen.cso.uiuc.edu!news.uoregon.edu!gaia.ucs.orst.edu!ruby.oce.orst.edu!tardis.co.uk!bill
From: bill@tardis.co.uk (William Hails)
Newsgroups: comp.lang.perl
Subject: Re: Typesetting perl programs in TeX
Date: Tue, 22 Mar 94 10:50:42 GMT
Organization: University Computing Services - Oregon State University
Lines: 372
Message-ID: <11561.9403221050@devone.tardis.co.uk>
NNTP-Posting-Host: ruby.oce.orst.edu
Originator: root@ruby.oce.orst.edu


In article <2milcn$5e2@gap.cco.caltech.edu>,
napalm@gluttony.ugcs.caltech.edu (K. Bruner) writes:
|> 
|> Does anyone know of a program that will ``convert'' perl scripts to
|> something printable by TeX?

I don't know if this is exactly what was wanted, but someone may find
it useful:
8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
#!/usr/local/bin/perl
#
# $Id: sh2latex,v 1.3 1994/03/08 18:13:55 bill Exp $
#
#@top
#\documentstyle{article}
#
#\hyphenation{next-state next-states}
#\title{{\tt sh2latex}\\a Script to \LaTeX\ Converter}
#\author{Bill Hails ({\tt bill@tardis.co.uk})}
#\date{3rd March 1994}
#
#\begin{document}
#
#\maketitle
#
#\section*{Introduction}
#
#This script generates \LaTeX\ documents from script files whose comment
#delimeters run from \verb|#| to \verb|\n|, such as {\tt perl}, {\tt make},
#{\tt rdist} or {\tt sh}.
#
# If you are reading this as a well-formatted hardcopy document then it was
#created by  issuing the following command:
#\begin{center}
#\begin{verbatim}
#sh2latex sh2latex > sh2latex.tex
#\end{verbatim}
#\end{center}
#\noindent
#then running \LaTeX\ on the {\tt .tex} file and printing the
#resulting {\tt .dvi} file in the normal way.
#
#The main feature of {\tt sh2latex} is that introductory material
#(such as this) is
#allowed to ``float'' to the top of the resulting \LaTeX\ document, and
#therefore can appear to preceed the obligatory \verb|#!/|{\it interpreter}
#line which must be the first text in an executable
#script.
#
#The idea is to read the file, writing to two temp files ({\small TOP}
#and {\small BODY}), then cat the
#results together afterwards.  We look for lines that match
#\verb|/^\s*#@/|{\it word}, then act on the word as a command.
#
#Comment sections beginning \verb|#@top| are written to the {\small TOP}
#file as \LaTeX, while \verb|#@| sections without the {\tt top}
#switch introduce \LaTeX\ text which is simply output in-place.
#In both cases the leading \verb|#| is stripped out; and the
#section is terminated by a blank line, a non-comment line
#or a line beginning \verb|#@end|.
#Comment sections without an introductory \verb|#@| are untouched.
#
#A line beginning \verb|#@ignore| causes {\em all} subsequent lines to be
#discarded, up to and including a line beginning \verb|#@end| (I found I
#needed this feature when using {\tt sh2latex} to document a fairly
#large system, where inevitably the rules for building the documentation
#ended up in the {\tt Makefile}, which I wanted to document, but I
#didn't want the instructions for building the documentation to end up
#in the documentation).
#
#We implement this as a state table with pairs of actions (in italics)
#and nextstates (in roman) as follows (read ``perform actions then change to
#nextstate''):
#
#%LaTeX tables are a bit messy, but the results look good
#
#\begin{center}
#\begin{tabular}{|r||c|c|c|c|c|c|c|}
#\hline
#             &\multicolumn{7}{|c|}{STATES}\\ \hline\hline
#INPUTS       & S    & top  & tex  & verb & topverb & ig  & igverb \\ \hline
#\hline
#\verb|#@top| & -    & -    & -    & -    & -       & -   & -      \\ 
#             & top  & top  & top  & topverb& topverb& ig & igverb \\ \hline
#\verb|#@ignore| & -  & -    & -    & -    & -       & -   & -     \\
#	      & ig   & ig   & ig   & igverb & igverb& ig  & igverb \\ \hline
#\verb|#@end| & -    & -    & -    & -    & -       & -   & -      \\
#             & S    & top  & verb & verb & verb    & tex & verb   \\ \hline
#\verb|#@|    & -    & -    & -    & \it ev
#                                         & -       & -   & -      \\ 
#             & tex  & tex  & tex  & tex  & tex     & ig  & igverb \\ \hline
#\verb|#|     & \it bv, pB
#                    & \it sh, pT
#                           & \it sh, pB
#                                  & \it pB
#                                         & \it sh, pT
#					            & -   & -      \\ 
#             & verb & top  & tex  & verb & topverb &ig   & igverb \\ \hline
#\verb|blank| & -    & \it pT, bv
#                           & \it pB, bv
#                                  & \it pB
#				          & \it pT  & -   & -      \\ 
#             & S    & verb & verb & verb & verb    & ig  & igverb \\ \hline
#\verb|other| & \it bv, pB
#                    & \it bv, pB
#                           & \it bv, pB
#                                  & \it pB
#				          & \it pB  & -   & -      \\ 
#             & verb & verb & verb & verb & verb    & ig  & igverb \\ \hline
#\verb|EOF|   & -    & -    & -    & \it ev
#                                         & \it ev  & -   & \it ev \\ 
#             & end  & end  & end  & end  & end     & end & end    \\ \hline
#\end{tabular}
#\end{center}
#\noindent
# Where the actions (order is significant) are:
#\begin{center}
#\begin{tabular}{|c|l|}
#\hline
#-      & no action \\ \hline
#\it bv & output a \verb|\begin{verbatim}| to the {\small BODY} \\ \hline
#\it ev & output an \verb|\end{verbatim}| to the {\small BODY} \\ \hline
#\it sh & strip leading hashes from the line \\ \hline
#\it pB & print the line to the {\small BODY} \\ \hline
#\it pT & print the line to the {\small TOP} \\ \hline
#\end{tabular}
#\end{center}
#\noindent
#and the states are:
#\begin{center}
#\begin{tabular}{|c|l|}
#\hline
# S & start state \\ \hline
# top & writing to {\small TOP} without a verbatim in effect in
#       {\small BODY} \\ \hline
# tex & writing \LaTeX\ to {\small BODY} \\ \hline
# verb & writing verbatim text to {\small BODY} \\ \hline
# topverb & writing to top while a verbatim is in effect in
#           {\small BODY} \\ \hline
# ig & ignoring text without a verbatim in effect \\ \hline
# igverb & ignoring text while a verbatim is in effect in
#          {\small BODY} \\ \hline
#\end{tabular}
#\end{center}
#
#\section{Listing}

$0 =~ s#.*/##;

$usage = "use: $0 <file>\n";

$file = shift || die $usage;
$topfile = "/tmp/top$$";
$bodyfile = "/tmp/bod$$";

#@
# open the input and two temp files
open(IN, $file) || die "$file: $!";
open(TOP, ">$topfile") || die "$topfile: $!";
open(BODY, ">$bodyfile") || die "$bodyfile: $!";

#@
# read from the input file:

$state = 'S';	# start state

while (<IN>) {
#@
# replace leading tabs with 8 spaces
#@
# here we deal with lines beginning \verb|#@top|:

    if (/^\s*#@\s*top\b/) {
	if ($state eq 'S') {
	    &change('top');
	} elsif ($state eq 'tex') {
	    &change('top');
	} elsif ($state eq 'verb') {
	    &change('topverb');
	}
#@
# then lines beginning \verb|#@ignore|:

    } elsif (/^\s*#@\s*ignore\b/) {
	if ($state eq 'S') {
	    &change('ig');
	} elsif ($state eq 'top') {
	    &change('ig');
	} elsif ($state eq 'tex') {
	    &change('ig');
	} elsif ($state eq 'verb') {
	    &change('igverb');
	} elsif ($state eq 'topverb') {
	    &change('igverb');
	}
#@
# then lines beginning \verb|#@end|:

    } elsif (/^\s*#@\s*end\b/) {
	if ($state eq 'tex') {
	    &change('verb');
	} elsif ($state eq 'topverb') {
	    &change('verb');
	} elsif ($state eq 'ig') {
	    &change('tex');
	} elsif ($state eq 'igverb') {
	    &change('verb');
	}
#@
# then lines beginning \verb|#@|:

    } elsif (/^\s*#@/) {
	if ($state eq 'S') {
	    &change('tex');
	} elsif ($state eq 'top') {
	    &change('tex');
	} elsif ($state eq 'verb') {
	    &endverb;
	    &change('tex');
	} elsif ($state eq 'topverb') {
	    &change('tex');
	}
#@
# then comment lines:

    } elsif (/^\s*#/) {
	if ($state eq 'S') {
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    &beginverb;
	    print BODY $_;
	    &change('verb');
	} elsif ($state eq 'top') {
	    s/^\s*#//;
	    print TOP $_;
	} elsif ($state eq 'tex') {
	    s/^\s*#//;
	    print BODY $_;
	} elsif ($state eq 'verb') {
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    print BODY $_;
	} elsif ($state eq 'topverb') {
	    s/^\s*#//;
	    print TOP $_;
	}
#@
#blank lines:

    } elsif (/^\s*$/) {
	if ($state eq 'top') {
	    print TOP $_;
	    &beginverb;
	    &change('verb');
	} elsif ($state eq 'tex') {
	    print BODY $_;
	    &beginverb;
	    &change('verb');
	} elsif ($state eq 'verb') {
	    print BODY $_;
	} elsif ($state eq 'topverb') {
	    print TOP $_;
	    &change('verb');
	}

#@
# significant non-comment lines:

    } else {
	if ($state eq 'S') {
	    &beginverb;
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    print BODY $_;
	    &change('verb');
	} elsif ($state eq 'top') {
	    &beginverb;
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    print BODY $_;
	    &change('verb');
	} elsif ($state eq 'tex') {
	    &beginverb;
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    print BODY $_;
	    &change('verb');
	} elsif ($state eq 'verb') {
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    print BODY $_;
	} elsif ($state eq 'topverb') {
	    s/^(\t*)/' ' x 8 x length($1)/e;
	    print BODY $_;
	    &change('verb');
	}
    }
}

#@
#Now at {\tt EOF}. If the last thing we output to the body was
#verbatim, then we need to end it.

if ($state eq 'verb' || $state eq 'topverb' || $state eq 'igverb') {
    &endverb;
}

#@
# Now all we do is to close the two output files, open them for
# reading, and cat them together ({\small TOP} first) to {\tt STDOUT}.
#Then we delete them.

close(TOP);
close(BODY);

open(TOP, $topfile) || die "$topfile: $!";
while (<TOP>) {
    print;
}
close(TOP);


open(BODY, "$bodyfile") || die "$bodyfile: $!";
while(<BODY>) {
    print;
}
close(BODY);

unlink($topfile, $bodyfile);

#@
# Some subroutines. {\tt beginverb} and {\tt endverb} output the
# \LaTeX\ commands to change to and from {\tt verbatim} mode, while
# {\tt change} is used, rather than just doing assignment,
# purely to allow debugging.

sub beginverb {
    print BODY "\\bigskip\n";
    print BODY "\\hrule\n";
    print BODY "\\small\n";
    print BODY "\\begin{verbatim}\n";
}

sub endverb {
    printf BODY "\\%s\n", "end{verbatim}";
    print BODY "\\normalsize\n";
    print BODY "\\hrule\n";
    print BODY "\\bigskip\n";
}

sub change {
    local($newstate) = @_;
    warn "changing from $state to $newstate:\n$_\n" if $debug;
    $state = $newstate;
}

#@
#\section{wishlist}
#\begin{enumerate}
#\item
# It would be nice if the comment delimiters could be given
# as argument to the script rather than hardwired.
#\item
# A state table compiler would be good too, preferably one
# whose input could be formatted well for \LaTeX.
#\end{enumerate}
#\end{document}
8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
-- 

Cheers
        Bill

Bill Hails <bill@tardis.co.uk>
Tel (UK) 0483 300 200