%\iffalse % makedtx.dtx generated using makedtx version 0.93b (c) Nicola Talbot % Command line args: % -macrocode ".*\.p.*l" % -src "creatdtx.(.*)=>creatdtx.\1" % -src "makedtx=>makedtx.pl" % -author "Nicola Talbot" % -v "1" % -dir "source" % -setambles ".*\.p.*l=>\nopreamble\nopostamble" % -comment "ARRAY(0x91ff234)" % -doc "manual.tex" % -codetitle "creatdtx.sty code" % makedtx % Created on 2007/8/2 15:16 %\fi %\iffalse %<*package> %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} % %\fi % \iffalse % Doc-Source file to use with LaTeX2e % Copyright (C) 2007 Nicola Talbot, all rights reserved. % \fi % \iffalse %<*driver> \documentclass[a4paper]{ltxdoc} \usepackage[colorlinks, bookmarks, hyperindex=false, bookmarksopen, pdfauthor={Nicola Talbot}, pdftitle={makedtx : a Perl script to help create a DTX file from source code}]{hyperref} \renewcommand{\usage}[1]{\textit{\hyperpage{#1}}} \renewcommand{\main}[1]{\hyperpage{#1}} \newcommand{\see}[2]{\emph{see} #1} \makeatletter \def\index@prologue{\section*{Index}} \makeatother \RecordChanges \PageIndex \CodelineNumbered \newcommand{\latextohtml}{\LaTeX2HTML} \newcommand{\switch}[1]{\texttt{-#1}\index{makedtx switches=\texttt{makedtx} switches>#1=\texttt{-#1}}} \newcommand{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}} \CheckSum{8} \begin{document} \DocInput{makedtx.dtx} \end{document} % %\fi %\title{makedtx v0.93b : a Perl script to help create a DTX %file from source code} %\author{Nicola Talbot\\ %\url{http://theoval.cmp.uea.ac.uk/~nlct/}} %\date{2nd August 2007} %\maketitle % %\tableofcontents % %\begin{abstract} %The \texttt{makedtx} bundle is provided to help developers to write %the code and documentation in separate files, and then combine them %into a single DTX file for distribution. It automatically generates %the character table, and also writes the associated installation %(.ins) script. %\end{abstract} % %\section{Introduction} % %\changes{0.9}{2005/02/11}{Initial beta release}% %Authors of \LaTeXe\ class files or packages are encouraged to bundle %their source and documentation together into a single DTX file. This %makes distribution much easier, as users need only download the DTX %file and possibly a corresponding installation script (INS file) %instead of a multitude of \texttt{.sty}, \texttt{.cls}, \texttt{.def} %etc files. However, having the documentation and code bundled %together can cause problems if a developer wants to, say, use %\texttt{ispell} to spell check the documentation, or convert the %documentation to a format other than DVI, PostScript or PDF (such as %HTML). % %Why should I want to convert my documentation to HTML when I can just %use PDF\LaTeX? The more general purpose packages that I write (such %as \texttt{datetime} and \texttt{glossary}) I upload to CTAN, however %most of the packages I write are specific to the School of Computing %Sciences at the University of East Anglia, so these I keep on my web %site, and as some of the faculty either don't have a PDF plug in or %prefer to view HTML rather than PDF documents, I have taken to writing %both PDF and HTML versions of my package documentation. However, %\latextohtml\ doesn't work on a \texttt{.dtx} file so I used to %convert them manually which is fine for one or two small documents, %but becomes rather cumbersome as soon as I have large documents or a %lot of packages. Therefore I decided to write the documentation %separately, and use a Perl script to bundle everything together. It %also has the added convenience in that I don't have to keep copying %and pasting the character table every time I write a new package, and %it saves the laborious task of writing the installation %script\footnote{or at least, it's laborious if there are rather a lot %of files associated with a package}. % %This document is structured as follows: Section~\ref{sec:install} %describes how to install the \texttt{makedtx} bundle, %Section~\ref{sec:makedtx} gives an overview of the \texttt{makedtx.pl} %Perl script, Section~\ref{sec:creatdtx} describes the %\texttt{creatdtx} package, Section~\ref{sec:examples} illustrates the %use of the \texttt{makedtx} bundle with examples and %Section~\ref{sec:problems} gives a list of possible errors and their %solutions. % %\section{Installation}\label{sec:install} % %You need to download both \texttt{makedtx.dtx} and %\texttt{makedtx.ins}, and run the installation script through %\LaTeX:\par \texttt{latex makedtx.ins} % %The following files will be created: %\begin{description} %\item[\texttt{makedtx.pl}] Perl script %\item[\texttt{creatdtx.sty}] \LaTeX\ package for use with \texttt{makedtx.pl} %\item[\texttt{creatdtx.perl}] Corresponding Perl script for use with LaTeX2HTML %\end{description} % %If you are using UNIX/Linux etc you will need to make %\texttt{makedtx.pl} executable using %\texttt{chmod}:\par\vspace{6pt}\noindent\texttt{chmod a+x %makedtx.pl}\par\vspace{6pt}\noindent and place it somewhere on your %path. If \texttt{perl} is located somewhere other than %\texttt{/usr/bin/} you will need to edit the first line of %\texttt{makedtx.pl}. (If you don't know where \texttt{perl} is %located, you can use the command: \texttt{which perl}.) The package %\texttt{creatdtx.sty} needs to be placed somewhere on the \LaTeX\ path %and \texttt{creatdtx.perl} should be placed in a directory searched by %\latextohtml. (See the \latextohtml\ documentation for details.) % %\section{makedtx.pl}\label{sec:makedtx} % %The Perl script \texttt{makedtx.pl} has the following syntax:\par %\texttt{makedtx.pl} \oarg{options} \switch{src} %\texttt{"}\meta{expr1}\verb|=>|\meta{expr2}\texttt{"} %\switch{doc} \meta{filename} \meta{basename} % %\subsection{Compulsory Arguments} % %The very last argument \meta{basename} is the basename of the %\texttt{.dtx} and \texttt{.ins} files you want to create. The %\switch{doc} \meta{filename} switch indicates the file containing the %documentation and \switch{src} %\verb!"!\meta{expr1}\verb+=>+\meta{expr2}\verb'"' indicates the %original source file(s), given by \meta{expr1}, and the corresponding %file name when it has been extracted from the \texttt{.dtx} file, %given by \meta{expr2}. This switch is a little complicated, so it's %best described using examples. % %Suppose you have your documentation in the file \texttt{foodoc.tex}, %and the original source code is in the file \texttt{foosrc.sty}. You %want to create the files \texttt{foo.dtx} and \texttt{foo.ins}. When %you \LaTeX\ \texttt{foo.dtx} you want the documentation as specified %in \texttt{foodoc.tex} and when you \LaTeX\ \texttt{foo.ins} you want %the file \texttt{foo.sty} to be created, using the code specified in %\texttt{foosrc.sty}. You will need to do: %\begin{verbatim} %makedtx.pl -src "foosrc\.sty=>foo.sty" -doc foodoc.tex foo %\end{verbatim} % %You may have multiple invocations of the \switch{src} switch. For %example, suppose you also have the file \texttt{barsrc.sty} which you %want to be extracted from the \texttt{.dtx} file as \texttt{bar.sty}, %you can do: %\begin{verbatim} %makedtx.pl -src "foosrc\.sty=>foo.sty" -src "barsrc\.sty=>bar.sty" -doc foodoc.tex foo %\end{verbatim} %Alternatively, you can use Perl-type regular expressions: %\begin{verbatim} %makedtx.pl -src "(.*)src\.sty=>\1.sty" -doc foodoc.tex foo %\end{verbatim} %(Note the use of double quotes to prevent shell expansion.) %Appendix~\ref{sec:prex} gives a brief overview of Perl regular %expressions for the uninitiated. % %\subsection{Options} % %\begin{description} %\item[\switch{h} or \switch{help}] Prints on-line help, and exits. % %\item[\switch{version}] Prints version number, and exits. %\changes{0.93}{2007/08/02}{version switch added}% % %\item[\switch{v}] Uses verbose mode. % %\item[\switch{dir} \meta{name}] Specifies directory containing source %files, as specified by the \switch{src} switch. For example, suppose %you have source files \texttt{foo.sty}, \texttt{bar.sty} in the %subdirectory \texttt{sourcefiles} you can do: %\begin{verbatim} %makedtx.pl -dir sourcefiles -src "(.*)\.sty=>\1.sty" -doc foodoc.tex foo %\end{verbatim} % %\item[\switch{op} \meta{character}] sets the Perl pattern matching %operator (the default is set to \texttt{=} symbol since the \texttt{/} %character is used as the directory divider). % %\item[\switch{askforoverwrite}] uses \ics{askforoverwritetrue} in %the installation script. % %\item[\switch{noaskforoverwrite}] uses \ics{askforoverwritefalse} %in the installation script (default). % %\item[\switch{noins}] Don't create the installation script %(\texttt{.ins} file). This is useful if you want to tweak the file %manually and you don't want your modifications overwritten. % %\item[\switch{preamble} \meta{text}] Set the preamble to %\texttt{text}. The default preamble is:\par %\begin{ttfamily} %Copyright (C) \meta{date} \meta{author}, all rights reserved. %If you modify this file, you must change its name first. %You are NOT ALLOWED to distribute this file alone. You are NOT %ALLOWED to take money for the distribution or use of either this %file or a changed version, except for a nominal charge for copying %etc. %\end{ttfamily} % %where \meta{date} is the copyright date, and \meta{author} is the %author's name (see below). % %\item[\switch{postamble} \meta{text}] Set the postamble to %\texttt{text}. If this is omitted the \ics{postamble} command is %omitted from the installation script. % %\item[\switch{author} \meta{name}] The author's name (as used in the %default preamble). If omitted the user's name is used. % %\item[\switch{date} \meta{text}] The copyright date (as used in the %default preamble). If omitted the current year is used. % %\item[\switch{stopeventually} \meta{text}] Insert \meta{text} into the %argument of \ics{StopEventually}. For example: %\verb+-stopeventually "\\PrintIndex"+ will result in the line: %\cs{StopEventually}\verb"{\PrintIndex}". If \texttt{makedtx.pl} %encounters a \cs{StopEventually} command within the document, %this will be used instead. If there is no \cs{StopEventually} %command in the document and the \switch{stopeventually} switch is %absent \cs{StopEventually}\marg{} will be inserted in the DTX %file. % %\item[\switch{prefinale} \meta{text}] %\changes{0.91}{2006/07/21}{prefinale switch added}% %Inset \meta{text} immediately prior to \cs{Finale} %in the dtx file. % %\item[\switch{setambles} \texttt{"}\meta{expr}\texttt{=\symbol{62}}\meta{text}\texttt{"}] %Sets the pre- and postambles for files matching \meta{expr} within the %\cs{file} command in the installation script. To illustrate this, %let's suppose you have source files \texttt{foo.sty}, \texttt{bar.sty} %and \texttt{foobar.pl} in the subdirectory \texttt{sourcefiles}. %Since \texttt{foo.sty} and \texttt{bar.sty} are \LaTeX\ files, they %should have pre- and postambles, but \texttt{foobar.pl} is a Perl %file, and since the percent symbol (\%) is not a comment character in %Perl, there should be no pre- and postambles for this file. Therefore %you would need to do something like: %\begin{verbatim} %makedtx.pl -dir sourcefiles -src "(.*)\.sty=>\1.sty" -src "foobar.pl=>foobar.pl" %-setambles "foobar\.pl=>\\nopreamble\\nopostamble" -doc foodoc.tex foo %\end{verbatim} %(Note that the line is only broken to fit it onto the page, and there %should be no line break when entering at the command prompt.) % %If the argument to \switch{setambles} contains the string %\verb"\\nopreamble", the character table will be excluded from the %corresponding files. So, in the above example, when you do: %\verb"latex foo.ins" the resulting files \texttt{foo.sty} and %\texttt{bar.sty} will contain the character table, but %\texttt{foobar.pl} won't. (If for some reason you don't want a %preamble but you do want the character table included use %\verb"\\usepreamble\\empty" instead of \verb'\\nopreamble'. %Conversely, if you want a preamble but don't want the character table %do something like \verb"\\nopreamble\\usepreamble\\defaultpreamble", %although I can't think of a good reason for wanting either of these %situations.) % %Note that the \verb"=>"\meta{text} part is optional. If it is %omitted, \meta{text} is assumed to be empty. % %\item[\switch{macrocode} \texttt{"}\meta{expr}\texttt{"}] If source %file matches the Perl regular expression given by \meta{expr}, the %source code is inserted into a \texttt{macrocode} environment in the %DTX file. % %\item[\switch{comment} \texttt{"}\meta{expr}\texttt{"}] %\changes{0.93}{2007/08/02}{comment switch added}% %If the source file matches the Perl regular expression given by %\meta{expr}, the source code will be inserted between \cs{iffalse} %\cs{fi} commands. The contents of this file will be included in the %DTX file, but will be excluded from the documentation. Since this %is provided mainly for non-TeX files (such as Perl scripts) the %\switch{comment} switch will typically need to be used in conjunction %with \switch{macrocode}. % %\item[\switch{codetitle} \texttt{"}\meta{title}\texttt{"}] %\changes{0.93}{2007/08/02}{Added codetitle switch}% %This sets the title for the code section. The default is %\texttt{The Code}. %\end{description} % %\section{The creatdtx Package} %\label{sec:creatdtx} % %The documentation source code, as specified using the \switch{doc} %switch will typically be a standard \LaTeX\ document using the %\texttt{ltxdoc} class file. Unlike the DTX file, there is no %\ics{DocInput} command, and the lines do not begin with a percent %symbol, which means that the document can be, say, passed to the %\latextohtml\ converter, or some other application that would %otherwise be confused by a DTX file. The \texttt{creatdtx} package %can be used in this document using %\begin{verbatim} %\usepackage{creatdtx} %\end{verbatim} %although this package will be not be included in the DTX file by %\texttt{makedtx.pl}. There is only one command defined in this %package:\ics{ifmakedtx}\marg{dtx text}\marg{non dtx text}. The first %argument \meta{dtx text} will be copied to the DTX file by %\texttt{makedtx.pl}, but the second argument \meta{non dtx text} %won't. However, if you \LaTeX\ the document, the first argument will %be ignored, and the second argument will be used. % %For example, if your code (in \texttt{foodoc.tex}) contains the %line:\par\vspace{6pt}\noindent\texttt{\cs{ifmakedtx}\{\}\{\cs{usepackage}\{html\}\}} %\par\vspace{6pt}\noindent the \texttt{html} package will only be %loaded if you \LaTeX\ \texttt{foodoc.tex}, but not when you \LaTeX\ %\texttt{foo.dtx}. % %The Perl script \texttt{creatdtx.perl} ignores the following commands %(and any associated arguments): \ics{OnlyDescription}, %\ics{RecordChanges}, \ics{MakeShortVerb}, \ics{DeleteShortVerb}, %\ics{DoNotIndex}, \ics{EnableCrossrefs}, \ics{CodelineIndex}, %\ics{GetFileInfo}, \ics{PrintChanges}, \ics{changes}, \ics{CheckSum}, %\ics{DescribeMacro} and \ics{DescribeEnvironment}. So even if you don't %use the \cs{ifmakedtx} command, using the \texttt{creatdtx} package %will help ensure that extraneous text does not appear in the HTML %document when using \latextohtml. % %As from version 0.93b, \texttt{creatdtx.perl} also defines the %commands \ics{cs}, \ics{marg}, \ics{oarg} and \ics{parg}, since there %is no \latextohtml\ implementation of the \texttt{ltxdoc} class file. % %\section{Examples} %\label{sec:examples} % %Let's first consider a very simple example. Suppose you want to %create a package that redefines \cs{today} so that the date is %displayed in the form: yyyy-m-d. Let's call this package %\texttt{dashdate}. The file \texttt{dashdate.sty} should look %something like: %\begin{verbatim} % % First define package: % % \begin{macrocode} % \NeedsTeXFormat{LaTeX2e} % \ProvidesPackage{dashdate} % % \end{macrocode} % % Redefine |\today| command: % % \begin{macrocode} % \renewcommand{\today}{\the\year-\the\month-\the\day} % % \end{macrocode} %\end{verbatim} %Now let's make some (very brief) documentation. Let's call the file, %say \texttt{manual.tex}\footnote{Note: if you want to use %\latextohtml\ on this document, you will need to use, e.g., %\cs{verb}\texttt{!\cs{today}!} instead of %\texttt{\symbol{124}\cs{today}\symbol{124}} since it doesn't recognise %\ics{MakeShortVerb}.}: %\begin{verbatim} %\documentclass{ltxdoc} %\usepackage{creatdtx} % %\begin{document} %\title{A Sample Package} %\author{AN Other} %\maketitle % %The \texttt{dashdate} package redefines |\today| %to produce the current date in the form: yyyy-m-d. %\end{document} %\end{verbatim} %Suppose you have saved \texttt{dashdate.sty} and \texttt{manual.tex} %in the subdirectory \texttt{source}. You can now create the %\texttt{.dtx} and \texttt{.ins} file using the command: %\begin{verbatim} %makedtx.pl -author "AN Other" -dir source -src "dashdate\.sty=>dashdate.sty" %-doc source/manual.tex dashdate %\end{verbatim} %The file \texttt{dashdate.dtx} is created, and contains the following %code: %\begin{verbatim} % %\iffalse % % dashdate.dtx generated using makedtx.pl version 0.9b (c) Nicola Talbot % % Command line args: % % -dir "source" % % -src "dashdate\.sty=>dashdate.sty" % % -author "AN Other" % % -doc "source/manual.tex" % % dashdate % % Created on 2005/2/10 22:22 % %\fi % %\iffalse % %<*package> % %% \CharacterTable % %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % %% Digits \0\1\2\3\4\5\6\7\8\9 % %% Exclamation \! Double quote \" Hash (number) \# % %% Dollar \$ Percent \% Ampersand \& % %% Acute accent \' Left paren \( Right paren \) % %% Asterisk \* Plus \+ Comma \, % %% Minus \- Point \. Solidus \/ % %% Colon \: Semicolon \; Less than \< % %% Equals \= Greater than \> Question mark \? % %% Commercial at \@ Left bracket \[ Backslash \\ % %% Right bracket \] Circumflex \^ Underscore \_ % %% Grave accent \` Left brace \{ Vertical bar \| % %% Right brace \} Tilde \~} % % % %\fi % % \iffalse % % Doc-Source file to use with LaTeX2e % % Copyright (C) 2005 AN Other, all rights reserved. % % \fi % % \iffalse % %<*driver> % \documentclass{ltxdoc} % % \begin{document} % \DocInput{dashdate.dtx} % \end{document} % % % %\fi % %\title{A Sample Package} % %\author{AN Other} % %\maketitle % % % %The \texttt{dashdate} package redefines "\today" % %to produce the current date in the form: yyyy-m-d. % %\end{document} % % % %\StopEventually{} % %\section{The Code} % %\iffalse % % \begin{macrocode} % %<*dashdate.sty> % % \end{macrocode} % %\fi % % First define package: % % \begin{macrocode} % \NeedsTeXFormat{LaTeX2e} % \ProvidesPackage{dashdate} % % \end{macrocode} % % Redefine |\today| command: % % \begin{macrocode} % \renewcommand{\today}{\the\year-\the\month-\the\day} % % \end{macrocode} % %\iffalse % % \begin{macrocode} % % % % \end{macrocode} % %\fi % %\Finale % \endinput %\end{verbatim} %The installation file \texttt{dashdate.ins} looks like: %\begin{verbatim} % % dashdate.ins generated using makedtx.pl version 0.9b 2005/2/10 22:22 % \input docstrip % % \preamble % Copyright (C) 2005 AN Other, all rights reserved. % If you modify this file, you must change its name first. % You are NOT ALLOWED to distribute this file alone. You are NOT % ALLOWED to take money for the distribution or use of either this % file or a changed version, except for a nominal charge for copying % etc. % \endpreamble % % \askforoverwritefalse % % \generate{\file{dashdate.sty}{\usepreamble\defaultpreamble % \usepostamble\defaultpostamble\from{dashdate.dtx}{dashdate.sty,package}} % } % % \endbatchfile %\end{verbatim} %Note that the command \verb"\usepackage{creatdtx}" has not been %transcribed to \texttt{dashdate.dtx} (although in this simple example %it's not really needed). % %Now let's extend the example: suppose you want to create an analogous %Perl script for use with \latextohtml. This will need to be called %\texttt{dashdate.perl} and will look something like: %\begin{verbatim} %package main; % %sub do_cmd_today{ % local($_) = @_; % local($today) = &get_date(); % $today =~ s|(\d+)/(\d+)/(\d+)|$3-$1-$2|; % "$today$_"; %} % %1; %\end{verbatim} %You will now need to call \texttt{makedtx.pl} as follows: %\begin{verbatim} %makedtx.pl -author "AN Other" -dir source -src "dashdate\.sty=>dashdate.sty" %-src "dashdate\.perl=>dashdate.perl" %-setambles "dashdate\.perl=>\\nopreamble\\nopostamble" %-macrocode "dashdate\.perl" -doc source/manual.tex dashdate %\end{verbatim} %(Note that the line is only broken to allow it to fit onto the page, %there should be no line break when you enter it on the command line.) %Alternatively, you could save typing and do: %\begin{verbatim} %makedtx.pl -author "AN Other" -dir source -src "dashdate\.(.*)=>dashdate.\1" %-setambles "dashdate\.perl=>\\nopreamble\\nopostamble" -macrocode "dashdate\.perl" %-doc source/manual.tex dashdate %\end{verbatim} %Note the use of the \switch{setambles} switch which suppresses the %insertion of text at the start and end of the Perl script which would %only confuse Perl. Note also the use of the \switch{macrocode} %switch. This is not needed for \texttt{dashdate.sty} since it has %already been included in the source code, but since \% is not a %comment character in Perl, the \texttt{macrocode} environment is not %included in the source code, and needs to be added. (If you are %unfamiliar with DocStrip and the use of the \texttt{macrocode} %environment, I suggest you read either \emph{A guide to %\LaTeX}~\cite[Appendix~D]{Kopka98} or \emph{The \LaTeX\ %companion}~\cite[Chapter~14]{Goossens93}.) % %It's likely that you may not want the Perl code to appear in the %document, but you still want it included in the DTX file. In addition %to the \switch{macrocode} switch, you would then also need to use %the \switch{comment} switch: %\begin{verbatim} %makedtx.pl -author "AN Other" -dir source -src "dashdate\.(.*)=>dashdate.\1" %-setambles "dashdate\.perl=>\\nopreamble\\nopostamble" -macrocode "dashdate\.perl" %-comment "dashdate\.perl" -doc source/manual.tex dashdate %\end{verbatim} % %As another example, consider the \texttt{datetime} package. Version %2.42 of this package has 2 \texttt{.sty} files and 42 \texttt{.def} %files. The documentation is written in the file \texttt{manual.tex}, %and the \texttt{.sty} and \texttt{.def} files are saved in a %subdirectory called \texttt{source}. Since these are the only files %in this directory, they can easily be merged into one \texttt{.dtx} %file using: %\begin{verbatim} %makedtx.pl -author "Nicola Talbot" -dir source -src "(.+)\.(.+)=>\1.\2" %-doc manual.tex datetime %\end{verbatim} %This creates the files \texttt{datetime.dtx} and \texttt{datetime.ins} which can then be distributed. The PDF version %of the documentation is obtained by doing: %\begin{verbatim} %pdflatex datetime.dtx %\end{verbatim} %and the HTML version (\texttt{manual.html}) is obtained by doing: %\begin{verbatim} %latex2html -split 0 -nonavigation -nofootnode -numbered_footnotes -noinfo manual %\end{verbatim} %Any minor differences between the HTML and PDF versions are dealt by %using \cs{ifmakedtx} in the original file \texttt{manual.tex}. % %\section{Troubleshooting} %\label{sec:problems} % %The \texttt{makedtx} bundle has only been tested under Linux using %Perl v5.6.0. There are no guarantees whether or not it will work on %other operating systems or on different versions (in fact, there are %no guarantees or warranties at all). % %\subsection{Known Bugs} % %It's possible to confuse \texttt{makedtx.pl} by placing either the %command \cs{end}\marg{document} or the command \ics{ifmakedtx} in a %\cs{verb} command, or by having the \ics{ifmakedtx} command on the same %line as \cs{begin}\marg{document}. You will also need to take care %about lines beginning with a percent symbol (\%) in the documentation, %as this will get converted into a line beginning with \verb"%%" in the %\texttt{.dtx} file, which has a special meaning. Either place a space %immediately prior the percent symbol, or do \verb"\relax%" if you %really don't want the extra space (or place your comment in an %\cs{iffalse} \ldots\ \cs{fi} conditional). % %\subsection{Possible errors encountered using \texttt{makedtx.pl}} % %Note: be careful to use double quotes around arguments that contain %characters that the shell might try interpreting, e.g.\ \verb"*" or %\verb'>'. % %Syntax error messages: %\begin{enumerate} %\item \texttt{No document source specified (missing -doc)} % %You must use the \switch{doc} switch. % %\item \texttt{No source code specified (missing -src)} % %You must specify at least one \switch{src} switch. % %\item \texttt{No basename specified} % %You must specify the basename of the \texttt{.dtx} and \texttt{.ins} files. This should %be the last argument passed to \texttt{makedtx.pl}. % %\item \texttt{-src \ldots\ argument invalid (no output file specified)} % %You have omitted the \verb"=>" separator in the argument of the %\switch{src} switch. % %\item \texttt{-src argument \ldots\ invalid (too many => specified)} % %You have used too many \verb"=>" separators in the argument of the %\switch{src} switch. (Similarly for the \switch{setambles} switch.) %\end{enumerate} % %\appendix % %\section{Perl Regular Expressions} %\label{sec:prex} % %This section gives a very brief overview of Perl regular expressions. For more detail, look at the Perl %documentation (use \verb"man perlre" for the man page.) % %\begin{tabular}{ll} %\verb'\' & Quote the next character\\ %\verb"." & Match any character\\ %\verb"|" & Alternation\\ %\verb"()" & Grouping\\ %\verb"[]" & Character class\\ %\verb"*" & Match 0 or more times\\ %\verb"+" & Match 1 or more times\\ %\verb"?" & Match 1 or 0 times\\ %\verb"{n}" & Match exactly \texttt{n} times\\ %\verb"{n,}" & Match at least \texttt{n} times\\ %\verb"{n,m}" & Match at least \texttt{n} but no more than \texttt{m} times. %\end{tabular} % %In the replacement text, a backslash followed by a number \meta{n} indicates the text from the \meta{n}th group. % %For example, suppose you have the following files: %\begin{verbatim} %abcsrc.sty %abcsrc.bst %abcsrc.perl %foosrc.sty %foobarsrc.sty %\end{verbatim} %then if you pass the following switch to \texttt{makedtx.pl}: %\begin{itemize} %\item \verb'-src "abcsrc\.([styb]+)=>abc.\1"' %will be equivalent to: %\begin{verbatim} %-src "abcsrc.sty=>abc.sty" -src "abcsrc.bst=>abc.bst" %\end{verbatim} %since \verb'[styb]+' will match one or more of the letters \texttt{styb} (so it will match \texttt{sty} and \texttt{bst}). %\verb'\1' indicates the text found in the first group, which in this example will either be \texttt{sty} or \texttt{bst}. % %\item \verb'-src "abcsrc\.(.+)=>abc.\1"' %will be equivalent to: %\begin{verbatim} %-src "abcsrc.sty=>abc.sty" -src "abcsrc.bst=>abc.bst" -src "abcsrc.perl=>abc.perl" %\end{verbatim} %Note that a full stop represents any character so \texttt{.+} means any string of length 1 or more, whereas %\verb"\." means an actual full stop character. % %\item \verb'-src "foo(.*)src\.sty=>foo\1.sty"' %will be equivalent to: %\begin{verbatim} %-src "foosrc.sty=>foo.sty" -src "foobarsrc.sty=>foobar.sty" %\end{verbatim} % %\item \verb'-src "(.+)src\.(.+)=>\1.\2"' %will be equivalent to %\begin{verbatim} %-src "abcsrc.sty=>abc.sty" %-src "abcsrc.bst=>abc.bst" %-src "abcsrc.perl=>abc.perl" %-src "foosrc.sty=>foo.sty" %-src "foobarsrc.sty=>foobar.sty" %\end{verbatim} % %\end{itemize} % %\StopEventually{\phantomsection\addcontentsline{toc}{section}{\refname} %\csname begin\endcsname{thebibliography}{1} %\bibitem{Goossens93} The \LaTeX\ companion. Michel~Goossens, Frank~Mittelbach and Alexander~Samarin. %Addison-Wesley 1993. % %\bibitem{Kopka98} A guide to \LaTeX. Helmut~Kopka and Patrick~W.~Daly. Addison-Wesley 1998. %\csname end\endcsname{thebibliography} %\PrintChanges %\phantomsection\addcontentsline{toc}{section}{Index} %\PrintIndex} % % % % %\section{creatdtx.sty code} %\iffalse % \begin{macrocode} %<*creatdtx.perl> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} # creatdtx.perl LaTeX2HTML file corresponding to creatdtx.sty package # author : Nicola Talbot # date : 2nd August 2007 package main; print " [creatdtx v0.93b (N.L.C. Talbot)]"; sub do_cmd_meta { &do_cmd_emph(@_); } sub do_cmd_cs{ local($_) = @_; local($name); $name = &missing_braces unless (s/$next_pair_pr_rx/$name=$2;''/eo); "\$name$_"; } sub do_cmd_marg{ local($_) = @_; local($arg); $arg = &missing_braces unless (s/$next_pair_pr_rx/$arg=$2;''/eo); "{$arg}$_"; } sub do_cmd_oarg{ local($_) = @_; local($arg); $arg = &missing_braces unless (s/$next_pair_pr_rx/$arg=$2;''/eo); "[$arg]$_"; } sub do_cmd_parg{ local($_) = @_; local($arg); $arg = &missing_braces unless (s/$next_pair_pr_rx/$arg=$2;''/eo); "($arg)$_"; } &ignore_commands( <<_IGNORED_CMDS_); ifmakedtx # {} StopEventually # {} OnlyDescription RecordChanges PrintChanges EnableCrossRefs CodelineIndex GetFileInfo # {} CheckSum # {} DescribeMacro # {} DescribeEnvironment # {} DoNotIndex # {} changes # {} # {} # {} DeleteShortVerb # {} MakeShortVerb # {} _IGNORED_CMDS_ 1; % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*creatdtx.sty> % \end{macrocode} %\fi % This is the code for the \texttt{creatdtx} package. This % package should not be used in a .dtx file. % First define the package: % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{creatdtx}[2005/02/11 v0.9b (N.L.C. Talbot)] % \end{macrocode} % Define \cmd{ifmakedtx}. The first argument will always be ignored by \LaTeX: % \begin{macrocode} \newcommand{\ifmakedtx}[2]{#2} % \end{macrocode} % Redefine |\StopEventually| so that it simply prints its argument % \begin{macrocode} \providecommand{\StopEventually}{} \renewcommand{\StopEventually}[1]{#1} % \end{macrocode} %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*makedtx.pl> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} #!/usr/bin/perl # File : makedtx # Author : Dr Nicola Talbot # Date : 29 Oct 2004 # Last Modified : 2 Aug 2007 # Version : 0.93b # usage : makedtx [options] -src => -doc # # -h : help message # -src => : e.g. -src "(foo)src\.(bar)=>$1.$2" will add foosrc.bar to .dtx to be extracted to foo.bar # -doc : file containing documentation. # -prefinale : text to add to dtx file just before \Finale (added to version 0.91b) # : create .dtx and .ins use Getopt::Long; $version = "0.93b"; # process command line options %optctl = (); &GetOptions(\%optctl, "h", "help", "v", "src=s@", "doc=s", "dir=s", "op=s", "askforoverwrite!", "ins!", "preamble=s", "postamble=s", "setambles=s@", "macrocode=s@", "author=s", "date=s", "stopeventually=s", "prefinale=s", "codetitle=s", "comment=s@", "version") or &syntaxerror(); $srcdir = "."; $patternop = "="; $verbose = 0; $noins = 0; $askforoverwrite = 0; $preamble = ""; $postamble = ""; $author = (getpwuid($<))[6] || 'Unknown'; $stopeventually = ""; $prefinale = ""; $codetitle = "The Code"; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); $year = $year + 1900; foreach $setting (keys %optctl) { if (($setting eq "h") || ($setting eq "help")) { &help(); } elsif ($setting eq "version") { die "makedtx version $version\n"; } elsif ($setting eq "doc") { $docsrc = $optctl{$setting}; } elsif ($setting eq "src") { @source = @{ $optctl{$setting} }; } elsif ($setting eq "dir") { $srcdir = $optctl{$setting}; } elsif ($setting eq "op") { $patternop = $optctl{$setting}; } elsif ($setting eq "v") { $verbose = 1; } elsif ($setting eq "ins") { $noins = 1-$optctl{$setting}; } elsif ($setting eq "askforoverwrite") { $askforoverwrite = $optctl{$setting}; } elsif ($setting eq "preamble") { $preamble = $optctl{$setting}; } elsif ($setting eq "postamble") { $postamble = $optctl{$setting}; } elsif ($setting eq "setambles") { @setambles = @{ $optctl{$setting} }; } elsif ($setting eq "macrocode") { @macrocode = @{ $optctl{$setting} }; } elsif ($setting eq "author") { $author = $optctl{$setting}; } elsif ($setting eq "date") { $year = $optctl{$setting}; } elsif ($setting eq "stopeventually") { $stopeventually = $optctl{$setting}; } elsif ($setting eq "prefinale") { $prefinale = $optctl{$setting}; } elsif ($setting eq "codetitle") { $codetitle = $optctl{$setting}; } elsif ($setting eq "comment") { @comment = @{ $optctl{$setting} }; } } if ($preamble eq "") { $preamble = "Copyright (C) $year $author, all rights reserved.\n"; $preamble = $preamble . "If you modify this file, you must change its name first.\n"; $preamble = $preamble . "You are NOT ALLOWED to distribute this file alone. You are NOT\n"; $preamble = $preamble . "ALLOWED to take money for the distribution or use of either this\n"; $preamble = $preamble . "file or a changed version, except for a nominal charge for copying\n"; $preamble = $preamble . "etc."; } if ($docsrc eq "") { print "No document source specified (missing -doc)\n"; &syntaxerror(); } if ($#ARGV != 0) { print "No basename specified\n"; &syntaxerror(); } if ($#source == -1) { print "No source code specified (missing -src)\n"; &syntaxerror(); } $basename = $ARGV[0]; open DTX, ">$basename.dtx" or die "Can't open '$basename.dtx'\n"; if ($verbose) { print "Documentation source : " . $docsrc . "\n"; } open DOC, $docsrc or die "Can't open '$docsrc'\n"; print DTX "\%\\iffalse\n"; print DTX "\% $basename.dtx generated using makedtx version $version (c) Nicola Talbot\n"; print DTX "\% Command line args:\n"; foreach $setting (keys %optctl) { if ($setting eq "src") { foreach $source (@source) { print DTX "\% -src \"$source\"\n"; } } elsif ($setting eq "setambles") { foreach $setamble (@setambles) { print DTX "\% -setambles \"$setamble\"\n"; } } elsif ($setting eq "macrocode") { foreach $macrocode (@macrocode) { print DTX "\% -macrocode \"$macrocode\"\n"; } } else { $val = $optctl{$setting}; $val=~s/\\/\\\\/g; print DTX "\% -", $setting, " \"", $val, "\"\n"; } } print DTX "\% $basename\n"; print DTX "\% Created on $year/", $mon+1, "/$mday $hour:", $min<10?"0$min" : $min,"\n"; print DTX "\%\\fi\n"; print DTX "\%\\iffalse\n"; print DTX "\%<*package>\n"; print DTX "\%\% \\CharacterTable\n"; print DTX "\%\% {Upper-case \\A\\B\\C\\D\\E\\F\\G\\H\\I\\J\\K\\L\\M\\N\\O\\P\\Q\\R\\S\\T\\U\\V\\W\\X\\Y\\Z\n"; print DTX "\%\% Lower-case \\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\l\\m\\n\\o\\p\\q\\r\\s\\t\\u\\v\\w\\x\\y\\z\n"; print DTX "\%\% Digits \\0\\1\\2\\3\\4\\5\\6\\7\\8\\9\n"; print DTX "\%\% Exclamation \\! Double quote \\\" Hash (number) \\#\n"; print DTX "\%\% Dollar \\\$ Percent \\\% Ampersand \\&\n"; print DTX "\%\% Acute accent \\\' Left paren \\( Right paren \\)\n"; print DTX "\%\% Asterisk \\* Plus \\+ Comma \\,\n"; print DTX "\%\% Minus \\- Point \\. Solidus \\/\n"; print DTX "\%\% Colon \\: Semicolon \\; Less than \\<\n"; print DTX "\%\% Equals \\= Greater than \\> Question mark \\?\n"; print DTX "\%\% Commercial at \\\@ Left bracket \\[ Backslash \\\\\n"; print DTX "\%\% Right bracket \\] Circumflex \\^ Underscore \\_\n"; print DTX "\%\% Grave accent \\\` Left brace \\{ Vertical bar \\|\n"; print DTX "\%\% Right brace \\} Tilde \\~}\n"; print DTX "\%\n"; print DTX "\%\\fi\n"; print DTX "\% \\iffalse\n"; print DTX "\% Doc-Source file to use with LaTeX2e\n"; print DTX "\% Copyright (C) $year $author, all rights reserved.\n"; print DTX "\% \\fi\n"; # driver print DTX "\% \\iffalse\n"; print DTX "\%<*driver>\n"; $indoc=0; while () { s/\\usepackage{creatdtx}//; $restofline = $_; $beginline = ""; $line = $restofline; while ($restofline =~ /(.*)\\ifmakedtx(.*)/) { $beginline = $1; ($group,$restofline,$done) = &getnextgroup($2); $startline = $.; while (!$done) { if ($nextline = ) { $line = $line . $nextline; $restofline = $restofline . $nextline; ($group,$restofline,$done) = &getnextgroup($restofline); } else { die "EOF found whilst scanning first argument to \\ifmakedtx on line $startline\n"; } } # print first arg, ignore second $beginline = $beginline . $group; ($group,$restofline,$done) = &getnextgroup($restofline); while (!$done) { if ($nextline = ) { $line = $line . $nextline; $restofline = $restofline . $nextline; ($group,$restofline,$done) = &getnextgroup($restofline); } else { die "EOF found whilst scanning second argument to \\ifmakedtx on line $startline\n"; } } $line = $restofline; } $line = $beginline . $restofline; print DTX $line; if ($line=~/\\begin{document}/) { $indoc = 1; last; } } print DTX "\\DocInput{$basename.dtx}\n"; print DTX "\\end{document}\n"; print DTX "\%\n"; print DTX "\%\\fi\n"; $inverb=0; $stopfound=0; print DTX "\%"; while () { if (/\\begin{verbatim}/) { $inverb=1; } if (/\\end{verbatim}/) { $inverb=0; } if (/\\StopEventually/ && ($inverb==0)) { $stopfound=1; } $restofline = $_; $beginline = ""; $line = $restofline; while ($restofline =~ /(.*)\\ifmakedtx(.*)/) { $beginline = $1; ($group,$restofline,$done) = &getnextgroup($2); $startline = $.; while (!$done) { if ($nextline = ) { $line = $line . $nextline; $restofline = $restofline . $nextline; ($group,$restofline,$done) = &getnextgroup($restofline); } else { die "EOF found whilst scanning first argument to \\ifmakedtx on line $startline\n"; } } # print first arg, ignore second $beginline = $beginline . $group; ($group,$restofline,$done) = &getnextgroup($restofline); while (!$done) { if ($nextline = ) { $line = $line . $nextline; $restofline = $restofline . $nextline; ($group,$restofline,$done) = &getnextgroup($restofline); } else { die "EOF found whilst scanning second argument to \\ifmakedtx on line $startline\n"; } } $line = $restofline; } $line = $beginline . $restofline; if (($line=~/\\end{document}/) and not $inverb) { $indoc=0; $line=~s/\\end{document}//; } $line=~s/\n/\n\%/mg; print DTX "$line"; } close DOC; print DTX "\n"; if ($stopfound==0) { print DTX "\%\\StopEventually{$stopeventually}\n"; } print DTX "\%\\section{$codetitle}\n"; @srcdirfile = glob("$srcdir/*"); %file = (); foreach $source (@source) { ($infile, $outfile, $remainder) = split /=>/, $source; if ($outfile eq "") { print "-src $source argument invalid (no output file specified)\n"; &syntaxerror(); } if (not ($remainder eq "")) { print "-src $source argument invalid (too many => specified)\n"; &syntaxerror(); } foreach $srcdirfile (@srcdirfile) { $fileexp = $srcdir . "/" . $infile; $_ = $srcdirfile; $expr = "s$patternop$fileexp$patternop$outfile$patternop"; if (eval($expr)) { if ($verbose) { print "$srcdirfile -> $_ \n"; } $thisoutfile = $_; $thisinfile = $srcdirfile; open SRC, $thisinfile or die "Can't open $thisinfile\n"; print DTX "\%\\iffalse\n"; print DTX "\% \\begin{macrocode}\n"; print DTX "\%<*$thisoutfile>\n"; print DTX "\% \\end{macrocode}\n"; print DTX "\%\\fi\n"; $macrocode = 0; $comment = 0; foreach $expr (@comment) { if ($thisoutfile =~ m/$expr/) { print DTX "\%\\iffalse\n"; $comment = 1; } } foreach $expr (@macrocode) { if ($thisoutfile =~ m/$expr/) { print DTX "\% \\begin{macrocode}\n"; $macrocode = 1; } } while () { print DTX "$_"; } if ($macrocode == 1) { print DTX "\% \\end{macrocode}\n"; } if ($comment == 1) { print DTX "\%\\fi\n"; } print DTX "\%\\iffalse\n"; print DTX "\% \\begin{macrocode}\n"; print DTX "\%\n"; print DTX "\% \\end{macrocode}\n"; print DTX "\%\\fi\n"; close SRC; $file{$thisinfile} = $thisoutfile; } } } print DTX "\%$prefinale\n" if ($prefinale); print DTX "\%\\Finale\n"; print DTX "\\endinput\n"; close DTX; if (!$noins) { open INS, ">$basename.ins" or die "Can't open '$basename.ins'\n"; print INS "\% $basename.ins generated using makedtx version $version $year/",$mon+1,"/$mday $hour:", $min<10?"0$min":$min,"\n"; print INS "\\input docstrip\n\n"; print INS "\\preamble\n"; print INS "$preamble\n"; print INS "\\endpreamble\n\n"; if ($postamble ne "") { print INS "\\postamble\n"; print INS "$postamble\n"; print INS "\\endpostamble\n\n"; } if ($askforoverwrite) { print INS "\\askforoverwritetrue\n\n"; } else { print INS "\\askforoverwritefalse\n\n"; } print INS "\\generate{"; foreach $file (keys %file) { $outfile = $file{$file}; print INS "\\file{$outfile}{"; $ambleset = 0; $noamble = 0; foreach $setamble (@setambles) { ($fileexp, $amble, $remainder) = split /=>/, $setamble; if (not ($remainder eq "")) { die "-setambles $setamble argument invalid (too many => specified)\n"; } if ($outfile =~ m/$fileexp/) { if ($verbose) { print "$fileexp matches $outfile -> setting \"$amble\"\n"; } print INS $amble; $ambleset = 1; if ($amble =~ m/\\nopreamble/) { $noamble = 1; } } } if (!$ambleset) { print INS "\\usepreamble\\defaultpreamble\n\\usepostamble\\defaultpostamble"; } print INS "\\from{$basename.dtx}{$outfile"; if ($noamble == 0) { # this will add the character table to all files except those that use \nopreamble print INS ",package"; } print INS "}}\n"; } print INS "}\n\n"; print INS "\\endbatchfile\n"; close INS; } sub syntaxerror { die "Syntax : makedtx [options] \nUse -h for help\n"; } sub help { print "makedtx Help\n\n"; print "Current Version : $version\n\n"; print "usage : makedtx [options] -src \"=>\" -doc \n\n"; print "makedtx can be used to construct a LaTeX2e dtx and ins file from\n"; print "the specified source code. The final command line argument\n"; print " should be used to specify the basename of the dtx\n"; print "and ins files.\n\n"; print "-src \"=>\"\n"; print "The command line switch -src identifies the original source code and the name\n"; print "of the file to which it will utimately be extracted on latexing the ins file\n"; print " can be a Perl expression, such as (foo)src.(sty), and can\n"; print "a Perl substitution style expression, such as $1.$2\n"; print "Note that double quotes must be used to prevent shell expansion\n"; print "Multiple invocations of -src are permitted\n"; print "See examples below.\n\n"; print "-doc \n"; print "The name of the documentation source code. This should be a LaTeX2e document\n\n"; print "Optional Arguments:\n\n"; print "-dir : search for source files in \n"; print "-op : set the pattern matching operator (default '$patternop')\n"; print "-askforoverwrite : set askforoverwrite switch in INS file to true\n"; print "-noaskforoverwrite : set askforoverwrite switch in INS file to false (default)\n"; print "-preamble : set the preamble. Standard one inserted if omitted\n"; print "-postamble : set the postamble.\n"; print "-setambles \"=>\" : set pre- and postambles to if file matches pattern\n"; print "-author : name of author (inserted into standard preamble. User name inserted if omitted)\n"; print "-date : copyright date\n"; print "-ins : create the ins file (default)\n"; print "-noins : don't create the ins file\n"; print "-prefinale : add immediately prior to \\Finale\n"; print "-macrocode : surround any file which matches in a macrocode environment\n"; print "-comment : surround any file which matches with \\iffalse \\fi pair\n"; print "-codetitle : The title for the documented code section (default: The Code)\n"; print "-h : help message\n"; print "-v : verbose\n\n"; print "Examples:\n\n"; print "Example 1:\n"; print "Documenation is in foodoc.tex\n"; print "Source code is in foosrc.sty. The final extracted version should be \n"; print "called foo.sty. The dtx file should be called foo.dtx and the ins file\n"; print " should be called foo.ins\n\n"; print "makedtx -src \"foosrc\\.sty=>foo.sty\" -doc foodoc.tex foo\n\n"; print "Example 2:\n"; print "Documenation is in bardoc.tex\n"; print "Source code is in barsrc.sty. The final extracted version should be\n"; print "called bar.sty. Source code is also in barsrc.bst. The final extracted\n"; print "version should be called bar.bst. The dtx file should be called bar.dtx and\n"; print "the ins file should be called bar.ins\n\n"; print "makedtx -src \"barsrc\\.sty=>bar.sty\" -src \"barsrc\\.bst=>bar.bst\" -doc bardoc.tex bar\n\n"; print "Or\n\n"; print "makedtx -src \"barsrc\\.(bst|sty)=>bar.\$1\" -doc bardoc.tex bar\n\n"; die; } sub eatinitialspaces { my ($STR) = @_; while (substr($STR,0,1) eq "\s") { $STR = substr($STR,1); } return $STR; } sub getnextgroup { my($curline) = @_; $curline = &eatinitialspaces($curline); # check to see if current string is blank if ($curline!~/[^\s]+/m) { return ("","",0); } if (($group = substr($curline,0,1)) ne "{") { # next group hasn't been delimited with braces # return first non-whitespace character $curline = substr($curline,1); # unless it's a backslash, in which case get command name if ($group eq "\\") { if ($curline=~/([a-zA-Z]+)(^[a-zA-Z].*)/m) { $group = $1; $curline = $2; } else { # command is made up of backslash followed by symbol $curline=~/([\W_0-9\s\\])(.*)/m; $group = $1; $curline = $2; } } return ($group,$curline,1); } my $pos=index($curline, "{"); my $startpos=$pos; my $posopen=0; my $posclose=0; my $bracelevel = 1; my $done=0; while (!$done) { $pos++; $posopen = index($curline, "{", $pos); # check to make sure it's not a \{ while ((substr($curline, $posopen-1,1) eq "\\") and ($posopen > 0)) { # count how many backlashes come before it. $i = $posopen-1; $numbs = 1; while ((substr($curline, $i-1,1) eq "\\") and ($i > 0)) { $numbs++; $i--; } # is $numbs is odd, we have a \{, otherwise we have \\{ if ($numbs%2 == 0) { last; } else { $posopen = index($curline, "{", $posopen+1); } } $posclose= index($curline, "}", $pos); # check to make sure it's not a \} while ((substr($curline, $posclose-1,1) eq "\\") and ($posclose > 0)) { # count how many backlashes come before it. $i = $posclose-1; $numbs = 1; while ((substr($curline, $i-1,1) eq "\\") and ($i > 0)) { $numbs++; $i--; } # is $numbs is odd, we have a \}, otherwise we have \\} if ($numbs%2 == 0) { last; } else { $posclose = index($curline, "}", $posclose+1); } } if (($posopen==-1) and ($posclose==-1)) { $done=1; } elsif ($posopen==-1) { $pos=$posclose; $bracelevel--; if ($bracelevel==0) { $group = substr($curline, $startpos+1, $pos-$startpos-1); $curline = substr($curline, $pos+1); return ($group,$curline,1); } } elsif ($posclose==-1) { $pos=$posopen; $bracelevel++; } elsif ($posopen<$posclose) { $pos=$posopen; $bracelevel++; } elsif ($posclose<$posopen) { $pos=$posclose; $bracelevel--; if ($bracelevel==0) { $group = substr($curline, $startpos+1, $pos-$startpos-1); $curline = substr($curline, $pos+1); return ($group,$curline,1); } } } # closing brace must be on another line return ("", $curline, 0); } 1; % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\Finale \endinput