{@default_thread

} {@ext_default <>} {@@i}{@output_name } {@@p}{@output_name } {@@h}{@output_name } {@@i1}{@output_name } {@@t1}{@output_name } {@@@}{@include } {@@@1}{@use_map0} {@@ip} {@map1} {@@+} % {@end@} {@map2} {@@+} %% {@end@} {@map4}<$<$ {@map4}>$>$ {@map4}§

{@@h} {@map4}<< {@map4}>> {@map4}§

{@@hi1} {@map3} _ {@map3}\{@end@} {@unmap} \ @#1 v arg {@#.arg} @# \tex {@@h}TeX {@@^h}\TeX{} @# \latex {@@h}LaTeX {@@^h}\LaTeX{} @# \tc {@@h}tiny_c2l {@@^h}|tiny_c2l| @# \cvt {@@h}cvt2ltx {@@^h}|cvt2ltx| @# \mb \txt {@@h}\txt {@@^h}\mbox{\txt} @# \em \txt {@@h}\txt {@@^h}\emph{\txt} @#1 section txt {@@h}

{@#.txt}

{@@ip}\section{{@#.txt}} {@@@1} @#1 subsection txt {@@h}

{@#.txt}

{@@ip}\subsection{{@#.txt}} {@@@1} @#1 subsubsection txt {@@h}

{@#.txt}

{@@ip}\subsubsection{{@#.txt}} {@@@1} @#1 dm macro {@@ip}\DescribeMacro{{@#.macro}} {@@h} {@@t1} {@@i1}\index{{@#.macro+3}}{@@+} @#1 bm macro {@@ip} \begin{macrocode}{@@+} {@#.macro}{@@+} % \end{macrocode} {@@h}
{@@+}
{@#.macro}{@@+}
{@@@1} @#1 bm1 macro {@@ip} \begin{macrocode}{@@+} {@#.macro} {@@h}
{@@+}
{@#.macro}
{@@@1}

@#1 bm2 macro
{@@ip}{@#.macro}{@@+}
%    \end{macrocode}
{@@h}{@#.macro}{@@+}
{@@@1}
@#1+4 c x {@@i@1} {@@p}/$\ast$\bs{}{@#.x} {@@h}/*\{@#.x} @#1+4 o x {@@i@1} {@@p}/$\ast$\bs{}o{@#.x}$\ast$/ {@@h}/*\o{@#.x}*/ {@@-} {@calc [\beta] "%s" \minor_version%2==1 ? " (beta release)" : "";} {@calc [\version] "%s" "\major_version.\minor_version.\patch_level\beta"} {@calc [\ltx_date] "%d/%02d/%02d" get_year("\datum");get_month("\datum");get_day("\datum");} {@@}--- END OF PROLOG --- {@@p@1}{@use_char} % \iffalse %% %% File `position.dtx'. {@#copyright} %% Please send error reports and suggestions for improvements to: %% %% Michael Plugge %% Neustadter Str. 132 %% D-67360 Lingenfeld %% Germany %% Internet: %% % \fi % \CheckSum{0}{@use_map2} \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 \~}{@use_char} % % \iffalse %<*driver> \documentclass{ltxdoc} \usepackage{a4wide,fancyhdr} \pagestyle{fancy} \newenvironment{dsc}{\begin{list}{}{\leftmargin7em\labelwidth5em \itemindent0em\itemsep0pt}}{\end{list}} \newenvironment{dsca}{\begin{list}{}{\leftmargin7em\labelwidth5em \itemindent0em\itemsep0pt\parsep0pt}}{\end{list}} \newenvironment{dscb}{\begin{list}{}{\leftmargin4em\labelwidth3em \itemindent0em\itemsep0pt\parsep0pt}}{\end{list}} \gdef\itx#1{\item[\bs\tt #1\hfill]} \gdef\itm#1{\item[\tt #1\hfill]} \gdef\<#1>{$<$#1$>$} \gdef\bs{$\backslash$} \begin{document} \DocInput{position.dtx} \end{document} %{@use_map1} \fi \pagenumbering{roman} \tableofcontents \pagenumbering{arabic} \title{The position package and tiny\_c2l: \\[-.5ex]First Attempt in vertical Alignment and ``smart'' Line Breaking} \author{Michael Plugge} \date{{@#ltx_date}} \maketitle {@@hp} \begin{abstract} This package provides a set of macros that can be used for vertical alignment of code and ``smart'' (context-sensitive) linebreaking. It is an first attempt to solve the problems concerning whitespace and linebreaking in prettyprinting. A small \{C/C++/Java\}$\rightarrow$\latex converter (\tc) is included as sample application to show how the macros can be used. \end{abstract} {@#section}{Introduction} Position.sty and \tc --- Makros for vertical alignment and ``smart'' line breaking. This is a set of experimental macros, which I hacked for use in the cvt2tx package. The macros allow a vertical alignment using the roman(!) font. The basic idea is to have a grid of ``should be'' positions on the paper, for example .5em per (input) character. If two or more blanks or a tab character are found in the input text, the corresponding position is used for output; if there is only one blank, it is stretched (or shrinked) to get near this ``ideal'' position. The actual value for one blank is \mb{{@#min_blank} \dots{} {@#max_blank}}. Another macro (|\mpout|) can be used to generate ``leaders'' between specific positions in the input text. You specify the (ASCII/grid) start position, the end position and the fill character; then the corresponding range in the .dvi fileis filled using this pattern. This macro is quite useful for block comments or long horizontal structures. A small \mb{\{C/C++/Java\} $\rightarrow$ \latex} converter (\tc) is also included as example how to use the macros. Only a few very basic things are implemented: recognition of keywords, comments, strings etc. No reformatting of text is done, lex/yacc files are not recognized (this may lead to erors if a pattern contains a single \texttt{"} without prepended backslash!)\dots{} The first version of \tc was just a quick \& dirty hack to get some testfiles for the macros. Later I added some features in order to build a tiny but usable converter. The macros are intended to be used later in another package (\cvt). The converters of this family are much more powerful and and have less restrictions. Unfortunately I didn't get the time to do some work on these, too. The main reason for making public this test software is to get opinions and critics as well as additions of personal needs. The more feedback I will get, the faster \cvt and \tc will come to a more useful state. The documentation is quite poor; if I get the time, it will be improved. Comments, bug reports/fixes or extensions are welcome. Copyright \copyright{} 1997,1998 Michael Plugge \ {@#subsection}{The Problem} When one starts writing a prettyprinter that uses \latex for formatting, some tough nuts are to crack. Two of these are handling of white space and linebreaking. AFAIK, these problems are currently not solved in a satisfactory way. One common way to handle blanks and tabs is to convert tab characters to an appropriate number of spaces and then convert each space to a fixed amount of space (for example 0.5em). If a proportional font is used to document the program source (this gives IMHO the fanciest result), vertical structures as assignment blocks, block comments, vertical alignment of Lex actions etc. are lost because the characters have different width. Some converters try to handle this problem by using a non-proportional font (typewriter); but this seems to be not a satisfactory way (it is not often used, too). The other problem is that of overlong source lines. For this problem currently three different approaches are used: \begin{itemize} \item The first way is to do no linebreaking at all; the user has to be aware that lines are not too long; if not, one simply gets overful \tex boxes. This way is ok if one uses the prettyprinter mainly for own programs; but it is bad if you have to print foreign programs with many overlong lines. \item The second way uses \latex for linebreaking, without additional environments etc. This is a simple solution, but the result does not satisfy: the start of the continuation lines goes back to the line begin. So all indentation is messes up. \item The third way is a little more elaborated: in this case linebreaking does not go back to the begin of the line, but rather to the current indentation level (with a little additional offset to denote the continuation line). This method was used in \cvt; it gives generally better results, but doesn't satisfy in all situations too. If this method is used for strings, the (inserted) blanks at line begin are not part of the real string; but they would be included by a compiler. Even far worse is the case of C++ comments (//): these end naturally at the end of a line. The text from the continuation lines would be interpreted by a compiler (from syntax point of view) as code, not as comment. \end{itemize} {@#subsection}{Line breaking in the tiny\_c2l/position package} The \tc/position package has a very flexible system for line breaking: it can output some text before the actual line break, change the value of indentation and output some text at the begin of the new (continuation) line. In \tc, these features are used to generate a context-sensitive way of linebreaking: \begin{itemize} \item For normal code the current indentation is used with a little additional offset (.5 em) to mark continuation lines. \item For preprocessor lines, `{\tt \symbol{'040}}\bs' is appended to the end of the line; the continuation lines are indented slightly more than normal code lines (1.5 em). \item For strings, a backslash is appended at the end of the line; the continuation lines get \emph{no} indentation (they go back to the start of the new line). \item C comments (starting with /$\ast$) get a `$\ast$' at the start of each continuation line. Indentation is done such that the `$\ast$' characters are vertically aligned (even if the comment start is shifted right due to wide characters as shown in testfile.l). \item C++ comments (starting with //) get `//' at line begin. The `//' characters of the continuation lines are vertically aligned with the first `//' (as in the case of C comments) \end{itemize} Even though some problems remain, this way of line breaking gives much more satisfactory results than the other three ways. {@#subsection}{Handling of white space in the tiny\_c2l/position package} In the \tc/position package, white space is handled quite different than in other converters. The goal is to get an output that is (concerning vertical structures) mostly similar to the ASCII input. To approach this goal the output sheed is divided into several (equidistant) positions which are directly mapped to the ``ASCII positions'' of the source file In the current version, the ``grid width'' is 0.5em; it is determined by the macro |\ind|). All text must be output using one of three macros: |\jmpo{position}{txt}|, |\njo{position}{text}|, |\xnjo{cnt}{position}{txt}| or |mpout\{pos1\}\{pos2\}\{pattern\}|. \begin{dsc} \itx{jmpo\{pos\}\{txt\}:} jump to the position which is specified in the first parameter, and then output the text from the second parameter. This macro does the main work for vertical alignment; it is used if in the source text multiple blanks or (at least one) tab character is found. (Depending on the current output position, it may jump a long way concerned to the ASCII file.) \itx{njo\{pos\}\{txt\}:} nojump, output: This macro is used if a single blank is found in the source text. In this case, the output does not jump to the ``grid'' position, but rather tries to reach this position using some glue ({@#min_blank} to {@#max_blank}). If the grid position is too far right, {@#max_blank} is used; if the current position is already more right than the grid position, {@#min_blank} is used. \itx{xnjo\{cnt\}\{pos\}\{txt\}:} This macro is similar to |\njo|, with a little difference: the glue is {@#min_xblank} to {@#max_xblank}, and it can be used for multiple blanks (the actual count is given in the first parameter). This macro is used for ``fill comments'' in \tc to avoid |\jmpo| in this context; it gives a relative constant blank width in this case. \itx{mpout\{p1\}\{p2\}\{c\}\{k\}:} This macro is used to fill the space between the positions |p1| and |p2| with the character(s) given in |c|. The parameter |\{k\}| specifies an additional kern (positive or negative) that is inserted after each pattern (this is used for example for $<$ or $>$). \end{dsc} These macros keep track of the current position in the .dvi file. If the current position is already larger than the requested grid position, only a small space ({@#min_blank}) is inserted in all cases. If direct output would be used (without these macros), the position macros cannot work properly because the internal variables contain wrong position values. {@#section}{tiny\_c2l Mini Manual} |tiny_c2l| is a little converter that converts C, C++ or Java source code to \latex. The first version of |tiny_c2l| was just a quick hack to generate some testfiles for the position macros. Now it is slightly extended to work as a ``real'' converter, although it has many limitations. It can be used either as a simple converter, as starting point for an own converter project or just as example how to use the macros of the position package. {@#subsection}{Invocation} |tiny_c2l| accepts two arguments and a number of options. The first argument is the input file name, the second argument is the output file name. Both may be omitted: if no output name is given, stdout is used instead; if no input name is given, stdin is used for input. If you want to use stdin for input, you can also use the -o$<$name$>$ option to specify an output file name. {@#subsection}{Options} |tiny_c2l| has a number of options; these can be placed anywhere in the command line (before, between or after the filenames). If multiple values are given for a specific option, the only last value is used. All options accept only a short form. If an option accepts parameters, no blank must be inserted between the option character and the option parameter. If an option contains blanks (for example a header or footer text) it must be quoted. Valid options are: \begin{dsca} \itm{-h} \itm{-f} These two options control the header (-h) and footer (-f) text. || is a single character that specifies the requested position: l~(left), c~(center) or r~(right). || is the text that will be output at this position. For the || parameter, some escape sequences are defined for inclusion of file name and date/time: \begin{dscb} \itm{\%f} input file name \itm{\%p} page number \itm{\%t} time (HH:MM) \itm{\%D} date (DD-MMM-YYYY) \itm{\%h} hour \itm{\%M} minute \itm{\%d} day of month \itm{\%m} month (numeric value) \itm{\%n} (english) name of month (full form) \itm{\%s} (english) name of month (short form) \itm{\%N} (local) name of month (full form) \itm{\%S} (local) name of month (short form) \itm{\%y} year \itm{\%\%} the `\%' character itself \end{dscb} Usually these texts will contain some blanks; in this case they must be quoted. For example the standard center header would be written as \par\hspace*{2em}\mb{\tt "-hcProduced from \%f on \%D \%t"} \itm{-+} use C++ mode (with additional keywords and // comments) \itm{-j} use Java mode (with additional keywords and // comments) \itm{-t} number of blanks per tab \itm{-d} debug mode; the FLEX debug output is written to the file tiny\_c2l.dbg \itm{-o} specify output name (useful if stdin is used for input) \itm{-?} show a short help screen \end{dsca} {@#subsection}{Special Features} {@#subsubsection}{Embedded \latex comments} |tiny_c2l| provides two backdoors to include embedded \latex comments: ``append mode'' and ``verbatim mode''. \begin{itemize} \item The ``append mode'' embedded \latex is defined for C or C++ style comments. It starts with {@#c}(a) (resp. //\bs{}a) and ends with the comment end ($\ast$/ for C comments, line end for C++ comments). The comment delimiters (in the standard form /$\ast$ or //) are written to the output file. Everything within these comments is copied directly to the output file, without any modifications. So you can include formulas (or even pictures ;-))) in the comment. \item ``Verbatim mode'' embedded \latex is defined only for C style comments. It is used to include global (\latex) options or section commands as |\section|, |\subsection|, \dots{}, |\index| in the file; it could be used also to generate a two-column listing of a part of the file. This mode is started with {@#c}(v) and ends with the comment end (at the first $\ast$/). The comment delimiters /$\ast$ and $\ast$/ are not written to the output file. \end{itemize} {@#subsubsection}{``Fill'' Comments} Fill comments are a special mode for of normal (multiline) comments in which linebreaks are rearranged to fill the lines in the generated .dvi file. Fill comments are started with {@#c}(f) (resp. //\bs{}f). For C style comments each new line must have a leading `$\ast$'. The linebreak, leading blanks, and (in C mode) the `$\ast$' and following blanks are replacedby a single blank. So the whole comment appears in the \latex file as a single long line; this is broken by the |\njo| and |\xnjo| macros. Blanks in fill comments are not handled by the |\jmpo| macro, but rather by |\xnjo|. This macro uses reduced glue (the current range is from {@#min_xblank} to {@#max_xblank}); for multiple blanks no jump to the grid position is done, it inserts just more space. This is done because in fill comments positioning makes no sense. You can force a linebreak if you use a single @ character at the end of a line. This character is not printed in the output file. {@#subsubsection}{Block comments} Block comments start with {@#c}(b) and end with $\ast$/. They are used mainly for procedure headers; they use some special formatting options: \begin{itemize} \item The used font is |\blockfont| (default: roman). \item The `:' character is moved to the grid position even after a single blank. \item If a single character is found at the end of the line, this is also moved to the grid position. \end{itemize} {@#subsubsection}{Omitting source lines in the Output} To omit a number of lines in the output, the command {@#o}() can be used. It must appear on an own line (leading or trailing blanks are allowed). \ is the number of lines to omit: for example, {@#o}(20) would omit the next 20 lines. To omit a larger piece of code, the command {@#o}(+) and {@#o}(-) can be used. Everything between the lines containing these commands is omitted; instead a line is inserted which tells how many lines were skipped. If you want to omit lines without the skip message, use the command {@#o}(q) (instead of {@#o}(+)) or {@#o}(q) (instead of {@#o}()). These commands suppress the skip message; they just skip the lines. {@#subsubsection}{Support for multiple File Projects} The generated file contains some code to detect if it is used as standalone file or if it is included from another file. All you have to do for this feature is to include a line containing |\usepackage{position,fancyhdr}| in the preamble of the wrapper file; then you may include (or input) one or more files generated by \tc. {@#subsubsection}{\LaTeX~2.09/\LaTeXe\ Support} The generated file automagically detects if \latex~2.09 or \LaTeXe\ is used by checking the |\documentclass| macro. Two preambles are provided; so you can use the file with any \latex version without trouble and without changing to the slow compatibility mode of \LaTeXe. {@#section}{Future Enhancements} {@#subsection}{tiny\_c2l Converter:} Many enhancements are possible for \tc. Some of these are: \begin{itemize} \item Special support for Lex/Yacc files \item Support for other programming languages \item Integrated invocation of \latex, xdvi, dvips and print (using a command-line option) \item Special (direct) support for multiple-file projects \item Native VMS-CLI interface \item Autogeneration of |\section|, |\subsection| and |\index| entries for all functions (and classes); autogenerate also a fileheader and (on request) a table of contents and index \item Refinement of the linebreaking and alignment code (will be discussed in the next two sections) \end{itemize} Many of these features are implemented already in the \cvt package. If I get the time, I'll include them into |tiny_c2l| (or rewrite \cvt to include the |tiny_c2l| code). {@#subsection}{Line Breaking:} Currently line breaking is done in a brute force way: the only check that is done by the macros is if the line is too long if the current box is added. If yes, the line is broken, if not, the box is just shipped out. This approach leads sometimes to bad linebreaks: for example, it is possible that a linebreak occurs directly after a ", or in the mid of a |for(;;)| command (between the two `;'). A much better solution would be to have not only \em{one} output box, but rather 3 or~5, which are filled sequentially and are used as a \emph{fifo} register. Each box should have an associated |\penalty| dependend on the syntactical structure of the box and its position in the output. Each box gets some additional |\penalty| if a new box is added to the list (and the other boxes are shifted left by this). This reflects the decision that the linebreak should appear at the rightmost position, if it is syntactically ok. Linebreaking would be done at the position with the lowest |\penalty| (which could be even the first box). The actual values of |\penalty| would need some thorough studies. This approach would yield a much more fancy way of linebreaking: linebreaks would be done at ``good'' positions, not simply at the first position that leads to an overful line (which is also usually the last possible position for the linebreak). {@#subsection}{Vertical Alignment:} Also in this area some refinements could be done; but they seem to be not very simple: In |tiny_c2l|, vertical alignment is done on a local point of view: only the current environment is considered. It would be nice to extend the scope for alignments to be consistent for a page (or even complete functions or the whole file). One could look for the position of some special structures (for example start position of comments, position of the `=' in assignments etc.) and to keep a list of these positions in the last 100 lines (in the case of scope of a page). The corresponding positions in the .dvi file should be calculated too (either by \tex or by using approximate values in C). If in the selected range (100 lines back, in the current function or in the file) two patterns have the same ASCII position, they should get also the same .dvi position (which means, these structures get a position that must not be a grid position, but could be shifted right also. Implementing this feature would give a fine output without user intervention, but it seems to be not trivial. It would require at least two scanner passes; if the .dvi positions are calculated by \tex, it would be still more expensive in terms of processing time. {@#section}{Implementation} {@#subsection}{Annnouncement Message} {@#dm}{announcement message} First, we announce the macro package. {@#bm1}§%<*package> \ifx\documentclass\undefined %this package may be used also with LaTeX 2.09 ;-))) \message{position.sty §{@use_char}{@#version}\space <{@#ltx_date}>} \else \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{position}[{@#ltx_date}\space {@#version}] \typeout{Package: position {@#version}\space {@@##} <{@#ltx_date}{@use_map1}{@#bm2}§>} \fi§ {@#subsection}{\latex Format and standalone/include file check} {@#dm}{file prolog} Now comes a tricky part: we want to check (without need of user input) if this file is used with \LaTeXe or \LaTeX~2.09, and also if it is used as standalone file or as an include file. This task is done by the macro |\getformat| and the conditional |\ifmfiles| in the following way: The prolog of a generated file looks like this (explanation follows): \begin{verbatim} \ifx\getformat\undefined \newcount\getformat\getformat0 \else \mfilestrue\getformat3 \fi \ifx\documentclass\undefined\advance\getformat1\fi \ifcase\getformat \documentclass[10pt]{article} \usepackage{a4wide,position,fancyhdr} \usepackage[latin1]{inputenc} \or \documentstyle[a4wide,position,fancyhdr]{article} \else\fi % multiple file input: don't load format \end{verbatim} The first line checks, if |\getformat| is already defined; if yes, we can be sure that the file was included (in this case, |\getformat| was defined in position.sty). The conditional |\ifmfiles| is set to true (|\mfilestrue|) and |\getformat| is set to 3. If |\getformat| was not yet defined, we are in single file mode: |\getformat| is declared and initialized with~0. The next line checks the used format file: if |\documentclass| is undefined, we are in \LaTeX~2.09, otherwise we use \LaTeXe. Now we have all informations available in the counter register |\getformat|: \begin{itemize} \item If |\getformat| is 0, we are in single file mode, using \LaTeX~2.09 \item If |\getformat| is 1, we are in single file mode, using\LaTeXe \item If |\getformat| is 3, we are in multiple file mode, using\LaTeX~2.09 \item If |\getformat| is 4, we are in multiple file mode, using\LaTeXe \end{itemize} In multiple file mode, the conditional |\ifmfiles| is also set to true (this conditional is used at the end of the file). Now comes a multiway-switch (|\ifcase\getformat|) with the |\documentclass| (|\getformat|==0 for \LaTeXe) or |documentstyle| (|\getformat|==1 for \LaTeX~2.09) command. If |\getformat| is larger than~1, nothing is done at this point. In this case the file is included into another file, which already loaded the position style file. {@#dm}{file epilog} The epilog of a generated file has the following structure: \begin{verbatim} \ifmfiles\def\END{\relax}\else\def\END{\end{document}}\fi \END \end{verbatim} If the conditional |\ifmfiles| is true (it is set at beginning of the file), the macro |\END| is defined as |\relax|, otherwise it is defined as |\end{document}|. If the file was used as standalone file, the final macro |\END| is expanded to |\end{document}|; otherwise it is expanded to |\relax|, and control goes back to the wrapper file. {@#dm}{\getformat} Now we are again in the file |position.sty|. First we have to check if |\getformat| was already defined (in case of a stand-alone file). If not, it it declared at this point. {@#bm}§\ifx\getformat\undefined\newcount\getformat\getformat0\fi \newif\ifmfiles\mfilesfalse§ {@#subsection}{Definitions} {@#subsubsection}{Font definitions} The following part contains some definitions for used fonts. The switch |ifoldlatex| is used for compatibility with \LaTeX~2.09. If this conditional is set to true, the low-level font declarations |\rm|, |\bf|\dots{} are used instead of the \LaTeXe{} font declarations |\normalfont|, |\bfseries|\dots{} The font |\blockfont| is used for block comments (that is for comments starting with |/*\b| or |/*********...*****\b| in C. All other definitions should be obviously. {@#dm}{special characters} The hyphen character (`-') is too short for standard program code; so it is replaced by a macro |\mm|. For text fonts, we use a dash with a little kern around it for the ASCII character `-' (|{@#hyphen_kern}{--}{@#hyphen_kern}|); for the tt font we have to switch back to a single hyphen. Another problem are the braces |\{| and |\}|: in the tt fonts they are not defined. In the generated file, `\{' is replaced by the macro |\brl| and `\}' is replaced by the macro |\brr|. In a text font, the macros |\brl| and |\brr| are expanded to `\bs\{' resp.\ `\bs\}'; for the tt font family these macros are replaced by |\symbol{`\{}}| and |\symbol{`\}}}|. All these definitions are made by two macros: |\pstd| enables the definitions for a standard font, while |\ptt| enables the tt font definitions. Each font command contains the (\latex) font change command (e.g. |\bfseries|) and either |\ptt| or |\pstd| to select the translation of the special symbols. {@#bm1}§\newif\ifoldlatex\oldlatextrue \gdef\pstd{\gdef\mm{§{@#hyphen_kern}{--}{@#hyphen_kern}{@#bm2}§{}}\gdef\brl{\{}\gdef\brr{\}}} \gdef\ptt{\gdef\mm{-}\gdef\brl{\symbol{`\{}}\gdef\brr{\symbol{`\}}}} \ifoldlatex \gdef\basefont{\rm\pstd} \gdef\blockfont{\rm\pstd} \gdef\keywordfont{\bf\pstd} \gdef\stringfont{\tt\ptt} \gdef\commentfont{\it\pstd} \gdef\headfont{\sl\pstd} \gdef\footfont{\sl\pstd} \else \gdef\basefont{\normalfont\pstd} \gdef\blockfont{\normalfont\pstd} \gdef\keywordfont{\bfseries\pstd} \gdef\stringfont{\ttfamily\ptt} \gdef\commentfont{\itshape\pstd} \gdef\headfont{\slshape\pstd} \gdef\footfont{\slshape\pstd} \fi \basefont§ {@#subsubsection}{Definition of special Characters} Here are the definitions for some special characters and some macros for output of multiple characters: \begin{dsca} \itx{spy} symbol for blank in LEX/YACC pattern (printed as {\tt \symbol{'040}}) \itx{sq} symbol used for single quote in program code \itx{qql} opening double quote for strings (\latex or tt style; default is \latex style) \itx{qqr} closing double quote for strings (same as above) \itx{ul} alternate form for `\_' (with additional kern) \itx{bs} multiple backslashes (with additional kern) \itx{mlt} multiple $<$ characters (with additional kern) \itx{mgt} multiple $>$ characters (with additional kern) \itx{mast} multiple stars \itx{mblank} multiple blanks \itx{n} empty line/end of a line \end{dsca} The alternate forms for |\qql|, |\qqr| and |\ul| are commented out; you may use these if you like. {@#bm}§\gdef\spy{{\tt \symbol{'040}}} \gdef\sq{{\tt\symbol{13}}} \gdef\qql{``} \gdef\qqr{''} \gdef\ul{{\_\kern.1em}} %\gdef\qql{{\tt "}} %\gdef\qqr{{\tt "}} %\gdef\ul{\_} \gdef\bs#1{$\count255=1\loop\ifnum\count255<#1\advance\count255 by 1 \backslash\hspace*{-.2em}\repeat\backslash$} \gdef\mlt#1{$\count255=1 \loop\ifnum\count255<#1\advance\count255 by 1 <\hspace*{-.4em}\repeat<$} \gdef\mgt#1{$\count255=1 \loop\ifnum\count255<#1\advance\count255 by 1 >\hspace*{-.4em}\repeat>$} \gdef\mast#1{$\count255=0 \loop\ifnum\count255<#1\advance\count255 by 1 \ast\repeat$} \gdef\mblank#1{\count255=0 \loop\ifnum\count255<#1\advance\count255 by 1 ~\repeat} \gdef\n{\mbox{}\\}§ {@#subsection}{Internal Macros} {@#subsubsection}{Register Allocations} {@#dm}{Allocations} Now we go into medias res. First some register allocations: \begin{dsca} \itx{poutbox} box for output \itx{pstartbox} box for line begin (inserted \emph{after} a line break) \itx{pendbox} box for line end (inserted \emph{before} a line break) \itx{pcur} current position \itx{pcurbr} indentation value for line break in comments \itx{pcmtstart} start position of a multi-line comment \itx{plena} current line length, depending on indentation and continuation \itx{pdecr} decrement value for too long lines \itx{pstarta} value of indentation at line begin \itx{pstart} current value of indentation \itx{ind} indentation unit (width for 1 ASCII position difference; standard is .5em) \itx{pst} macro for inserting a `$\ast$' in continuation lines of C comments \itx{ifpend} test if |\pendbox| should be shipped out at end of line. \itx{ifpbrk} enable/disable automatic linebreak (not yet used) \end{dsca} {@#bm}§\newbox\poutbox \newbox\pstartbox \newbox\pendbox \newif\ifpend \newif\ifpbrk \newlength\pcur \newlength\pcurbr \newlength\pcmtstart \newlength\plena \newlength\plinenowidth \newlength\ind \newcount\pdecr \newcount\pstarta \newcount\pstart \gdef\pst{$\ast$} \pbrktrue \ind.5em \setbox\pstartbox=\hbox{} \setbox\pendbox=\hbox{}§ {@#dm}{\init} This macro (or |\initc|) must be used at the beginning of each line; it initializes the position environment. {@#bm}§\gdef\init#1#2{% \par\noindent\hbox to \plinenowidth{\hss {\rm\scriptsize #2}\hspace{1em}}% \plena\textwidth \advance\plena -\plinenowidth \pdecr0 \pcurbr0pt \setbox\pstartbox=\hbox{}% \pstart#1\advance\pstart 1 \pstarta\pstart \skip0\ind\multiply\skip0 by #1 \pcur\skip0 \ifnum #1>0 \hspace*{\skip0}\fi% \ifpend\advance\plena -\wd\pendbox\fi% }§ {@#dm}{\initc} This macro is used instead of |\init| for continuation lines of multi-line strings/comments to preserve the current indentation and |\pstartbox|. Supplied parameters are: \begin{dsca} \itm{Parameter \tt \#1:\hfill} amount of space to move left or right (relative to the last line) \itm{Parameter \tt \#2:\hfill} mode flag \itm{Parameter \tt \#3:\hfill} number of blanks before text start \end{dsca} the mode flag has the following values: \begin{dsca} \itm{mode=0:} used for strings \itm{mode=1:} not in use \itm{mode=2:} not in use \itm{mode=3:} not in use \itm{mode=4:} used for C++ comments \itm{mode=5:} used for C comments (with $\ast$ at line begin) \itm{mode=6:} used for C comments (without $\ast$ at line begin) \itm{mode=7:} not in use \end{dsca} NOTE: Not all modes are currently in use or fully implemented in the |tiny_c2l| converter. They may be used/modified in a later version (or change the values or actions). {@#bm}§\gdef\initc#1#2#3#4{% \par\noindent\pdecr0% \hbox to \plinenowidth{\hss {\rm\scriptsize #4}\hspace{1em}}% \ifcase#2 \pcurbr\ind\multiply\pcurbr #1 \pcur\pcurbr \gdef\pst{}% 0 \or% \pcurbr\ind\multiply\pcurbr #1 \gdef\pst{$\ast$}% 1 \or% \pcurbr\ind\multiply\pcurbr #1 \advance\pcurbr\pcmtstart \gdef\pst{}% 2 \or% \pcurbr\ind\multiply\pcurbr #1 \advance\pcurbr\pcmtstart \gdef\pst{$\ast$}% 3 \or% \pcurbr\pcmtstart \setbox\poutbox=\hbox{/}% \advance\pcurbr\wd\poutbox \gdef\pst{}% 4 \or% \pcurbr\pcmtstart \setbox\poutbox=\hbox{/}% \advance\pcurbr\wd\poutbox \gdef\pst{$\ast$}% 5 \or% \pcurbr\pcmtstart \setbox\poutbox=\hbox{/$\ast$}% \advance\pcurbr\wd\poutbox \gdef\pst{}% 6 \or% \pcurbr\pcmtstart \setbox\poutbox=\hbox{/$\ast$}% \advance\pcurbr\wd\poutbox \gdef\pst{$\ast$}% 7 \or% \pcurbr\ind\multiply\pcurbr #1 \gdef\pst{}% 8 \else% \pcurbr0pt \gdef\pst{}% \fi% \setbox\pstartbox=\hbox{\pst\mblank{#3}}% \hspace*{\pcurbr}\copy\pstartbox% \pcur\pcurbr \advance\pcur\wd\pstartbox \ifpend\advance\plena -\wd\pendbox \fi% \ifnum#2=8 \pcurbr0pt\fi% }§ {@#dm}{\plcntmargin} This macro is used to set the margin width for line numbers. It is invoked after a page is shipped out; so you should use a width that is enough for the next 100 lines or so. {@#bm}§\gdef\plcntmargin#1{% \setbox\poutbox=\hbox{#1\hspace{1em}}\global\plinenowidth\wd\poutbox }§ {@#dm}{line end macros} These two macros enable (|\pee|) and disable (|\ped|) the insertion of |\pendbox| at the end of a source line. The actual value is set using the macro |\pes|. All three macros modify the value of |\plena| (the current page width) to ensure correct line breaking. {@#bm}§\gdef\pee{\advance\plena -\wd\pendbox\pendtrue} \gdef\ped{\advance\plena \wd\pendbox\pendfalse} \gdef\pes#1#2{% \setbox\pendbox=\hbox{#1}% \advance\plena -\wd\pendbox \ifnum#2 > -1 \pstart#2\fi% \pendtrue% }§ {@#dm}{\psinit} This macro is used to initialize |\pstartbox| and |\pstart|. {@#bm}§\gdef\psinit#1#2{% \ifnum#1>-1 \pstart#1\fi% \ifnum#1=-2 \pstart\pstarta\fi% \setbox\pstartbox=\hbox{#2}% }§ {@#dm}{\cmtinit} This macro is used to save the current indentation at start of a comment. {@#bm}§\gdef\cmtinit{\pcurbr\pcur \pcmtstart\pcur}§ {@#dm}{\eol} This macro is used at end of a line (for breaking overlong lines). If the condition |\ifpend| is true, copy |\pendbox| to the end of the line, then a line break is inserted. {@#bm}§\gdef\eol{\ifpend\copy\pendbox\else\mbox{}\fi\\\hspace*{\plinenowidth}}§ {@#dm}{\calcindent} This macro is used to calculate the indentation after a linebreak {@#bm}§\gdef\calcindent{% \ifdim\pcurbr>0pt\skip0\pcurbr \else% \skip0\ind \multiply\skip0\pstart \fi }§ {@#dm}{\brkln} This macro is used to break the current line. {@#bm}§\gdef\brkln{% \ifpbrk% \eol %insert line break \calcindent% calculate the indentation for the new line \pdecr\count255 \advance\pdecr-\pstart \pcur\wd\poutbox \advance\pcur\skip0 \hspace*{\skip0}\copy\pstartbox% \advance\pcur\wd\pstartbox \else% \hspace*{\skip0}% \fi% }§ {@#dm}{\jmpo} This macro is used to jump to the position specified in |#1| and print the text from |#2|. If this position is smaller than the current position, insert a small space ({@#min_blank}) and then print the text. If the output would exceed the line length, break the line, preserving the current indentation (in this case the starting point is the current indentation+1|\ind|). {@#bm1}§\gdef\jmpo#1#2{% \ifnum#1>0 \count255 #1\advance\count255 -\pdecr \skip0\ind \multiply\skip0\count255 %calculate the output position \advance\skip0-\pcur %calculate the width of the needed space \count255 #1 %current start position (needed for line break) \fi%§{@use_char} \ifdim\skip0<{@#min_blank} %(current position > target position) \skip0 {@#min_blank}{@use_map1}{@#bm2}§% insert a small space \fi% \ifnum #1<1 \skip0 0pt \count255 -#1\fi% %copy #2 to \poutbox and add the width of the box to \pcur \setbox\poutbox=\hbox{#2}% %%%% probieren: \advance\pcur\wd\poutbox \advance\pcur\skip0 %%%% dann ohne \relax \advance\pcur\skip0 \advance\pcur\wd\poutbox %calculate the new position \relax% TeX seems to be tired at this point; give it some rest ;-))) \ifdim\pcur>\plena %requested position > right margin; break line \brkln% \else% \hspace*{\skip0}% \fi% \box\poutbox% }§ {@#dm}{\xnjo} This macro is used to output the text in |#3| at ``wish position'' in |#2|, using |#1| blanks. The used space per blank is from {@#min_xblank} to {@#max_xblank} (according to the current position). This macro does nearly the same as |\njo|, but is intended only for multiple blanks; the cases for |#2|$<$1 are left out. The used space interval is smallter than that used for |\njo|; this macro is intended to be used in comments etc. {@#bm1}§\gdef\xnjo#1#2#3{% \count255 #2 \advance\count255 -\pdecr \skip0\ind \multiply\skip0\count255 \advance\skip0-\pcur \divide\skip0 #1 \count255 #2 %current start position (for line break)§{@use_char} \ifdim\skip0<{@#min_xblank} \skip0 {@#min_xblank} \multiply\skip0 #1\fi% \ifdim\skip0>{@#max_xblank} \skip0 {@#max_xblank} \multiply\skip0 #1\fi% %copy #3 to \poutbox and add the width of the box to \pcur \setbox\poutbox=\hbox{#3}%{@use_map1}{@#bm2}§ \advance\pcur\wd\poutbox \advance\pcur\skip0 \ifdim\pcur>\plena %requested position > right margin \brkln% insert a line break \else% \hspace*{\skip0}% \fi% \box\poutbox% }§ {@#dm}{\njo} This macro is used to output the text specified in parameter~2 at the grid position specified in parameter~1, without jumping to the position (used for a single blank). The actual used space is from {@#min_blank} to {@#max_blank}, according to the current position. If |#1|$\leq 0$, output |#2| directly (without blank). If the output would exceed the line length, break the line as in |\jmpo|. {@#bm1}§\gdef\njo#1#2{% \ifnum#1<0 \count255 -#1 \skip0 0pt\fi% \ifnum#1=0 \count255 0 \skip0 0pt\fi% \ifnum#1>0% \count255 #1 \advance\count255 -\pdecr \skip0\ind \multiply\skip0\count255 \advance\skip0-\pcur \count255 #1 %current start position (for line break) \fi%§{@use_char} \ifdim\skip0<{@#min_blank} \skip0 {@#min_blank}\fi% \ifdim\skip0>{@#max_blank} \skip0 {@#max_blank}\fi% \ifnum#1<1 \skip0 0pt\fi%{@use_map1}{@#bm2}§ %copy #2 to \poutbox and add the width of the box to \pcur \setbox\poutbox=\hbox{#2}% \advance\pcur\wd\poutbox \advance\pcur\skip0 \ifdim\pcur>\plena %requested position > right margin \brkln% insert a line break \else% \hspace*{\skip0}% \fi% \box\poutbox% }§ {@#dm}{\mpout} This macro is related to the \tex |\leaders|. It outputs the character (or text) specified in |#3| from grid position |#1| to grid position |#2|. |#4| can is used to specify additional kern (this is used for example for $<$ and $>$). {@#bm}§\gdef\mpout#1#2#3#4{% \ifnum#1>0 \skip0\ind\multiply\skip0 by #1\advance\skip0-\pcur \fi% \ifdim\skip0<0pt \skip0 0pt\fi% don't move back! \ifnum#1>0 \hspace*{\skip0}\advance\pcur\skip0\fi% \setbox\poutbox=\hbox{#3}\skip0\wd\poutbox %width of one output character (#3) \skip1\ind\multiply\skip1 by #2 \skip2\skip1 \advance\skip1-\pcur \pcur\skip2 \advance\pcur\skip0 \skip2\skip1 %total width of line \advance\skip0 #4 %add kern \divide\skip1\skip0 \count255\skip1 \advance\count255 by 1% number of characters \skip1\wd\poutbox \multiply\skip1 by \count255 \advance\skip2 -\skip1 \ifdim\skip2<0pt \advance\count255 -1 \advance\skip2 \wd\poutbox \fi% \divide\skip2\count255 \copy\poutbox% \loop% \ifnum\count255>0\advance\count255 by -1 \hspace*{\skip2}\copy\poutbox% \repeat% } %§ % \Finale \endinput {@use_char} {@@i}{@use_char} {@#copyright} \def\batchfile{position.ins} \input docstrip.tex \keepsilent \preamble \endpreamble \generateFile{position.sty}{f}{\from{position.dtx}{package}}