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 \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 () { #@ # 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 () { print; } close(TOP); open(BODY, "$bodyfile") || die "$bodyfile: $!"; while() { 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 Tel (UK) 0483 300 200