diff options
Diffstat (limited to 'support/lgrind')
32 files changed, 6592 insertions, 0 deletions
diff --git a/support/lgrind/FAQ b/support/lgrind/FAQ new file mode 100644 index 0000000000..1c5dee867d --- /dev/null +++ b/support/lgrind/FAQ @@ -0,0 +1,37 @@ +How do I produce `@' in LGrinded texts? + + Please RTFM. But since it comes up so often: use @@ in program text. To + produce @ in LaTeX text in embedded listings mode you have to turn usage + of @ off using a '%@-' comment. You can turn it on again using '%@+'. + + + +How can I use filenames containing a `$'? This is rather important since +the `$' denotes the root directory under RISC OS. + + I really cannot figure out what exactly goes wrong. But at least I can + offer a workaround. When using T1 or LY1 encoding there are no problems. + Put \usepackage[x]{fontenc} (with x=T1 or x=LY1 and possibly others, but + not OT1) in the preamble. (For standalone listings use firstpreamble in + the lgrindef file.) + + + +My source code doesn't seem to align properly. What am I doing wrong? + + LGrind uses by default a proportional font for its output. That's part + of the beauty. However, aligning with spaces doesn't work, since they + are relative horizontal motions. When using tabs, everything is fine. If + the standard tab width of 8 is too big for you, fiddle around with your + editor to save the file with tabwidth 4, say, and then use '-t 4' as an + option to LGrind. + + + +How do I activate line wrap? + + There is no line-wrap. LGrind has no way of knowing where a line break + should be. It depends on the surrounding LaTeX, after all. Make your lines + short enough to be pretty; or make your margins and font small. + + diff --git a/support/lgrind/Makefile b/support/lgrind/Makefile new file mode 100644 index 0000000000..01f4c7e5f7 --- /dev/null +++ b/support/lgrind/Makefile @@ -0,0 +1,63 @@ +# Makefile for LGrind, a LaTeX prettyprinter + +# $Id: Makefile,v 1.10 2000/12/27 21:42:37 mike Exp $ + +BASEDIR=/usr +#DEFSFILE=${HOME}/Work/lgrind/lgrindef +DEFSFILE=$(BASEDIR)/share/texmf/tex/latex/lgrind/lgrindef +TEXFILEDIR=$(BASEDIR)/share/texmf/tex/latex/lgrind +DOCDIR=$(BASEDIR)/doc/lgrind + +INSTALL=install +SOURCES=lgrind.c lgutil.c regexp.c regexp.h lgrindef.c lgrindef.h retest.c v2lg.c +TEXFILES=lgrind.dtx lgrind.sty lgrind.ins + +VERSION=3.66 +DISTVERSION=lgrind-$(VERSION) + +.PHONY: all install clean distribution lgrind + +all: lgrind.sty lgrind.dvi lgrind + +lgrind.sty: lgrind.dtx + latex lgrind.ins + +lgrind.dvi: lgrind.dtx + latex lgrind.dtx + latex lgrind.dtx + +lgrind: + cd source; \ + make DEFSFILE=$(DEFSFILE) BASEDIR=$(BASEDIR) INSTALL=$(INSTALL) VERSION=$(VERSION) + +clean: + rm -f lgrind.log + rm -f lgrind.aux + rm -f lgrind.dvi + rm -f lgrind.sty + rm -f lgrind.idx + rm -f lgrind.glo + rm -f doc-lgrind.lg + cd source; \ + make clean + +distribution: clean + mkdir $(DISTVERSION) + cp -r example $(DISTVERSION) + rm -rf $(DISTVERSION)/example/CVS + cp -r source $(DISTVERSION) + rm -rf $(DISTVERSION)/source/CVS + cp README FAQ lgrind.* lgrindef $(DISTVERSION) + sed -e "s/^#DEFSFILE/=DEFSFILE/;s/^DEFSFILE/#DEFSFILE/;s/^=DEFSFILE/DEFSFILE/"\ + < Makefile >$(DISTVERSION)/Makefile + tar czf $(DISTVERSION).tar.gz $(DISTVERSION) + rm -r $(DISTVERSION) + +install: all + $(INSTALL) -m 755 -d $(TEXFILEDIR) + $(INSTALL) -m 644 lgrind.sty $(TEXFILEDIR) + $(INSTALL) -m 755 -d $(DOCDIR) + $(INSTALL) -m 644 lgrind.dvi $(DOCDIR) + $(INSTALL) -m 644 lgrindef $(DEFSFILE) + cd source; \ + make install BASEDIR=$(BASEDIR) INSTALL=$(INSTALL) diff --git a/support/lgrind/README b/support/lgrind/README new file mode 100644 index 0000000000..5db42af138 --- /dev/null +++ b/support/lgrind/README @@ -0,0 +1,87 @@ +=----- +LGrind - a source pretty printer for LaTeX +=----- +Version 3.67 + +Welcome to LGrind. LGrind is a descendant of the Unix utility vgrind. It is +used to produce a beautified version of your source code using LaTeX. Unlike +other packages this is not pure TeX but an external preprocessor. You run e.g. + lgrind example.c > example.tex + latex example.tex +to get a complete listing. Options for producing includable files and pro- +cessing embedded listings in LaTeX texts are provided. + + +What you need: (Installation part 2) +^^^^^^^^^^^^^^ +- lgrind (or lgrind.exe) just where you like it +- lgrind.sty somewhere in LaTeXs reach +- lgrindef anywhere; (position is semi-fixed in the executable) +- LaTeX2e the obsolete LaTeX 2.09 is not supported +- LGrind utilizes by default the fancyhdr package by Piet van Oostrum. You + can change this behaviour by modifying the lgrindef file. + + +How to get these files: (Installation part 1) +^^^^^^^^^^^^^^^^^^^^^^^ +- If your executable is not provided, all the source files are in the source + directory, a makefile provided. +- Run LaTeX or TeX on lgrind.ins. You will obtain lgrind.sty. +- Or simply run make in the top directory. This also gives lgrind.sty + + +Documentation +^^^^^^^^^^^^^ +Main documentation is in lgrind.dtx. Run LaTeX on lgrind.dtx and the result is +lgrind.dvi. There are also manpages lgrind.1 and lgrindef.5 for people who +prefer those, but notice that I am not always able to keep them up to date. +To right the wrong impression: parts of the documentation have been written +by my predecessors, my thanks to them. + + + +Files in the directories: +^^^^^^^^^^^^^^^^^^^^^^^^^ +lgrind.ins DocStrip driver +lgrind.dtx Documented package +lgrind.gls Glossary and index for the documentation (for the ones with- +lgrind.ind out MakeIndex, and because it had to be modified by hand) +lgrindef The language definition file + + +In the directory 'source': +lgrind.c The source code for the LGrind executable +lgutil.c +lgrindef.c +lgrindef.h +regexp.c +regexp.h +v2lg.c Source code for verbatim to embedded source converter +retest.c Test program for the regular expression routines +lgrind.1 Man-pages for the LGrind program +lgrindef.5 and the language definition file +Makefile Makefile for Unices +makefile.dos Makefile for MS-DOS (not tested anymore) +makefile.emx Makefile for use with DMAKE + + +In the directory 'example': +c2tex.bat Example batch files for facilitating calls to LGrind +asm2tex.bat +c2tex ditto as Bourne shell scripts +asm2tex +egmasm.asm Example sources +egcprog.c +subst Example substitution file +lgrindeg.tex Example making use of the above + + + +Comments, contributions, questions and cheques +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LGrind contains non-free code written by Van Jacobson, who does not answer +to any request for changing his licence. This software is therefore not +maintained. I also do not accept any cheques anymore. + +Have Fun! + diff --git a/support/lgrind/example/asm2tex b/support/lgrind/example/asm2tex new file mode 100755 index 0000000000..dcb2fc5a6f --- /dev/null +++ b/support/lgrind/example/asm2tex @@ -0,0 +1,17 @@ +#!/bin/sh +# convert .asm (Microsoft [or whatever] assembler) to .lg + +if [ -n "$1" ] && [ -f $1 -o -f $1.asm ] +then + if [ `basename $1` = `basename $1 .asm` ] + then + lgrind -i -lmasm $1.asm > $1.lg + echo Created $1.lg + else + lgrind -i -lmasm $1 > `basename $1 .asm`.lg + echo Created `basename $1 .asm`.lg + fi +else + echo Usage: $0 "<file>[.asm]" + echo $1.asm does not exist. +fi diff --git a/support/lgrind/example/asm2tex.bat b/support/lgrind/example/asm2tex.bat new file mode 100644 index 0000000000..b89f223bab --- /dev/null +++ b/support/lgrind/example/asm2tex.bat @@ -0,0 +1,14 @@ +@echo off
+rem convert .asm (Microsoft assembler) to .lg
+if not exist %1.asm goto Complain
+
+lgrind -i -lmasm %1.asm > %1.lg
+echo Created %1.lg
+goto Done
+
+:Complain
+echo '%1.asm' does not exist.
+
+:Done
+
+
diff --git a/support/lgrind/example/c2tex b/support/lgrind/example/c2tex new file mode 100755 index 0000000000..48a301a726 --- /dev/null +++ b/support/lgrind/example/c2tex @@ -0,0 +1,17 @@ +#!/bin/sh +# convert .c to .lg + +if [ -n "$1" ] && [ -f $1 -o -f $1.c ] +then + if [ `basename $1` = `basename $1 .c` ] + then + lgrind -i -v subst $1.c > $1.lg + echo Created $1.lg + else + lgrind -i -v subst $1 > `basename $1 .c`.lg + echo Created `basename $1 .c`.lg + fi +else + echo Usage: $0 "<file>[.c]" + echo $1.c does not exist. +fi diff --git a/support/lgrind/example/c2tex.bat b/support/lgrind/example/c2tex.bat new file mode 100644 index 0000000000..f4b4a2fbc2 --- /dev/null +++ b/support/lgrind/example/c2tex.bat @@ -0,0 +1,14 @@ +@echo off
+rem convert .c to .lg
+if not exist %1.c goto Complain
+
+lgrind -i -v subst %1.c > %1.lg
+echo Created %1.lg
+goto Done
+
+:Complain
+echo '%1.c' does not exist.
+
+:Done
+
+
diff --git a/support/lgrind/example/egcprog.c b/support/lgrind/example/egcprog.c new file mode 100644 index 0000000000..b79f448051 --- /dev/null +++ b/support/lgrind/example/egcprog.c @@ -0,0 +1,34 @@ +/* endian.c + * Demonstrates endian ordering + */ + +#include <stdio.h> + +void main( void ) +{ + short Data_16; + long Data_32; + char far *p; + + Data_16 = 0x1234; + Data_32 = 0x56789abc; + + p = (char far *)&Data_16; + printf("16-bit quantity, data=%04x\n", Data_16); + printf("address %Fp = %02x\n", p, (int)(*p) & 0xff); + p++ ; + printf("address %Fp = %02x\n", p, (int)(*p) & 0xff); + p++ ; + + + p = (char far *)&Data_32; + printf("32-bit quantity, data=%08lx\n", Data_32); + printf("address %Fp = %02x\n", p, (int)(*p) & 0xff); + p++ ; + printf("address %Fp = %02x\n", p, (int)(*p) & 0xff); + p++ ; + printf("address %Fp = %02x\n", p, (int)(*p) & 0xff); + p++ ; + printf("address %Fp = %02x\n", p, (int)(*p) & 0xff); + +} diff --git a/support/lgrind/example/egmasm.asm b/support/lgrind/example/egmasm.asm new file mode 100644 index 0000000000..b4baa5962c --- /dev/null +++ b/support/lgrind/example/egmasm.asm @@ -0,0 +1,145 @@ +;************************************************
+; vgac.asm
+; PC VGA graphics control in assembly language
+; uses BIOS for keyboard read and setting graphics
+; modes, and procedure for setting a VGA pixel
+; version for C calling convention :-
+; LARGE model
+; no MAIN entry point
+; assemble only (no link)
+; underscore for C-callable functions
+; don't pop arguments off stack (caller does this)
+;
+; J Leis
+; 24 May 1994
+;************************************************
+
+TITLE vgac.asm - vga assembler program, callable from C
+.MODEL LARGE
+.286
+.DOSSEG
+
+; stack segment directive
+.STACK
+
+; data segment directive
+.DATA
+
+; code segment directive
+.CODE
+
+
+_VgaMode PROC
+
+ pusha
+ mov ah, 0 ; function 0 = set video mode
+ mov al, 12h ; mode 12 = vga graphics
+ int 10h
+ popa
+ ret
+
+_VgaMode ENDP
+
+
+_TextMode PROC
+
+ pusha
+ mov ah, 0 ; function 0 = set video
+ mov al, 03h ; mode 3 = text
+ int 10h
+ popa
+ ret
+
+_TextMode ENDP
+
+
+_ShowMessage PROC
+
+ pusha ; save registers if necessary
+
+ ; call DOS interrupt to display a message
+ mov bx, 01h
+ lea dx, mesg ; equivalent to mov dx, OFFSET mesg
+ mov cx, l_mesg
+ mov ah, 040h
+ int 021h
+
+ popa
+ ret
+
+_ShowMessage ENDP
+
+
+_ReadKey PROC
+
+ pusha ; save registers if necessary
+
+ mov ah, 00h ; function 0 - wait for key & read it
+ int 16h ; int 16h = keyboard services
+ ; al now equals ascii code of key
+
+ popa
+ ret
+
+_ReadKey ENDP
+
+
+; setpixel( xc, yc, color )
+; stacking order:
+; memory near call far call
+; color highest [bp+8] [bp+10]
+; y-coord [bp+6] [bp+8]
+; x-coord lowest [bp+4] [bp+6]
+;
+_SetPixel PROC
+
+ push bp
+ mov bp, sp
+
+ pusha ; save registers if necessary
+
+ mov dx, 03CEh ; graphics controller register
+
+ mov ax, 0205h ; write mode 2
+ out dx, ax
+
+ mov ax, 0003h ; function
+ out dx, ax
+
+ mov ax, 0A000h ; graphics screen segment
+ mov es, ax
+
+ mov ax, [bp+8] ; get y co-ord
+ mov bx, 640/8 ; 80 bytes/line
+ mul bx
+ mov bx, [bp+6] ; get x-coord
+ mov cl, 3 ; divide by 8 bits/byte
+ shr bx, cl
+ add bx, ax
+
+ mov al, es:[bx] ; dummy write to latch data in screen RAM
+ mov cx, [bp+6] ; get x-coord
+ and cx, 0007h ; get bit mask
+ mov al, 07h
+ sub al, cl
+ mov ah, 80h
+ shr ah, cl ; shift to bit position
+ mov al, 08h ; set mask register
+
+ mov dx, 03CEh ; dx destroyed by mul
+ out dx, ax ; write bit mask
+
+ mov cx, [bp+10]; color ; write the color value
+ mov es:[bx], cl
+
+ popa
+
+ pop bp
+ ret ; don't pop args off stack - C does this
+
+_SetPixel ENDP
+
+;no main procedure (main in C)
+
+; end of file
+END
diff --git a/support/lgrind/example/lgrindeg.tex b/support/lgrind/example/lgrindeg.tex new file mode 100644 index 0000000000..5de9f4592f --- /dev/null +++ b/support/lgrind/example/lgrindeg.tex @@ -0,0 +1,51 @@ +% lgrindeg.tex
+% Simple example program for testing `lgrind' additions
+% MATLAB/QBASIC/C/MASM/LaTeX
+% Note: Matlab,qbasic, masm are registered trademarks.
+%
+% John Leis, 18 June 1996
+% University of Southern Queensland
+% leis@usq.edu.au
+
+\documentclass[a4paper]{article}
+
+\usepackage{lgrind}
+
+\begin{document}
+
+\title{ Example of the `LGrind' Package }
+\author{ John Leis }
+\date{ 15 June 1996 }
+\maketitle
+
+\clearpage
+
+\begin{figure}
+ \begin{center}
+ \begin{tabular}{ll}
+ \hline\hline
+ Language & Command in DOS batch file \\
+ \hline
+ C & \verb+ lgrind -i -v subst %1.c > %1.lg + \\
+ MASM & \verb+ lgrind -i -lmasm %1.asm > %1.lg + \\
+ \hline \\
+ \end{tabular}
+ \end{center}
+ \caption{Commands for lgrind'ing source file into \LaTeXe\ format}
+ \label{fig:commands}
+\end{figure}
+
+
+\lagrind{egcprog.lg}{Example `C' language program.}{fig:egcprog}
+
+\clearpage
+\begin{center}
+ \textbf{\large This is a multi-page listing} \\
+ It has no caption. \\
+ Used for Appendices etc. \\
+\end{center}
+
+\lgrindfile{egmasm.lg}
+
+\end{document}
+
diff --git a/support/lgrind/example/subst b/support/lgrind/example/subst new file mode 100644 index 0000000000..062741373c --- /dev/null +++ b/support/lgrind/example/subst @@ -0,0 +1,5 @@ +x_gamma=x$\sb\gamma$ +f_1=f$_1$ +delta=$\delta$ +Data_16=Data$\sb{16}$ +Data_32=Data$\sb{32}$ diff --git a/support/lgrind/lgrind.dtx b/support/lgrind/lgrind.dtx new file mode 100644 index 0000000000..999bd0e408 --- /dev/null +++ b/support/lgrind/lgrind.dtx @@ -0,0 +1,1174 @@ +% \iffalse +% +% This is LGrind.DTX. This was written by: +% +% - Van Jacobson, Lawrence Berkeley Laboratory (based on +% vgrind by Dave Presotto & William Joy of UC Berkeley), +% the original written for \TeX. +% - Jerry Leichter of Yale University, modifications for \LaTeX. +% - George V. Reilly of Brown University, renamed to lgrind +% - Michael Piefel, Humboldt-University Berlin, for \LaTeXe +% and a thousand little changes +% +% \fi +% \iffalse +%% Based on Van Jacobson's ``tgrindmac'', a macro package for TeX. +%% Modified, 1987 by Jerry Leichter. Put '@' in all internal names. +%% Modified, 1991 by George Reilly. Changed name from tgrind to lgrind. +%% Modified, 1995 by Michael Piefel. Made it work with \LaTeXe. +%% -1999 Hundreds of bells and whistles. No changelog here. +% +%<*dtx> +\ProvidesFile{lgrind.dtx} + [2002/01/28 v3.67 LGrind environment and supporting stuff] +%</dtx> +%<package>\NeedsTeXFormat{LaTeX2e}[1996/06/01] +%<package>\ProvidesPackage{lgrind} +%<package> [2002/01/28 v3.67 LGrind environment and supporting stuff] +%<*driver> +\NeedsTeXFormat{LaTeX2e}[1996/06/01] +\documentclass{ltxdoc} +\CodelineIndex +\RecordChanges +\DocInput{lgrind.dtx} +\end{document} +%</driver> +% \fi +% +% \newcommand{\LG}{\textsf{LGrind}} +% \newcommand{\NFSS}{\textsf{NFSS}} +% \frenchspacing +% +% \GetFileInfo{lgrind.dtx} +% \begin{document} +% \title{The \LG{} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}} +% \author{Various Artists} +% \date{\filedate} +% \maketitle +% +% \CheckSum{679} +% +% \begin{abstract} +% The \LG{} package is a pretty printer for source +% code. It evolved from vgrind, supported \TeX{} (tgrind) and +% \LaTeX{} and now finally \LaTeXe, in particular \NFSS. +% \end{abstract} +% +% \changes{v1.0}{1985/02/10}{Written} +% \changes{v2.0}{1991/09/06}{Upgrade to \LaTeX2.09} +% \changes{v3.0}{1995/09/24}{Upgrade to \LaTeXe} +% +% \section{Introduction} +% \subsection{What is it?} +% The \LG{} package consists of three files: +% \begin{itemize} +% \item \texttt{lgrind} or \texttt{lgrind.exe} is the executable. It will +% convert an \LaTeX-File with embedded listings or a source code file +% into a lot of macro-calls. +% \item \texttt{lgrind.sty} provides the environments and macros to make +% the produced mess readable. +% \item \texttt{lgrindef} contains the information +% needed to tell keywords from comments, comments from strings \dots +% \end{itemize} +% +% \subsection{Who is to blame?} +% \LG{} is not the work of a single one. The program is based on +% \textsf{vgrind} by Dave Presotto \& William Joy of UC Berkeley. +% +% Van Jacobson wrote \textsf{tgrind} for \TeX. Jerry Leichter +% of Yale University modified it for \LaTeX. George V. Reilly of +% Brown University changed the name to lgrind and added the +% program-text-within-comments and @-within-\LaTeX{} features, +% and finally +% Michael Piefel of the Humboldt-University Berlin converted it to +% work under \LaTeXe, i.\,e. with \NFSS, and improved the documentation. +% +% However, there have been many contributors who supported the development; in +% particular the range of supported languages is mainly due to them. +% Unfortunately I do not know all of them, but my thanks go to everybody. +% A special Thank You to +% Torsten Sch\"utze for his OS/2 support and many and various hints. +% +% \section{\LG{} -- grind nice program listings} +% +% \begin{tabbing} +% \texttt{lgrind} \= \texttt{[-s] [-e] [-i] [-o \meta{file}] [-n] [-c] [-t }\meta{width} +% \texttt{] [-h }\meta{header}\texttt{]} \\ +% \>\texttt{[-v }\meta{varfile}\texttt{] [-d[!] }\meta{description file}\texttt{]} +% \texttt{[-l}\meta{language}\texttt{] [}\meta{name}\texttt{\textbar-]} +% \end{tabbing} +% +% \LG{} processes its input file(s) and writes the result to standard +% output. This output can be saved for later editing, inclusion in a +% larger document, etc. +% +% The options are: +% +% \makebox[2em][l]{-e} process a \LaTeX-file for embedded text. +% +% \makebox[2em][l]{-i} process for inclusion in a \LaTeX-document. +% +% \makebox[2em][l]{-} take input from standard input. +% +% \changes{v3.5}{1998/05/23}{Output redirection (-o) implemented.} +% \makebox[2em][l]{-o} redirect output. +% +% \makebox[2em][l]{-n} don't boldface keywords. +% +% \makebox[2em][l]{-a} don't treat @, etc. specially in \LaTeX. +% +% \makebox[2em][l]{-c} don't treat @, etc. specially in comments. +% +% \makebox[2em][l]{-t} change tab width (default 8). +% +% \makebox[2em][l]{-h} specifies text to go on the left side of every output +% page (default is none). +% +% \makebox[2em][l]{-v} take variable substitution strings from file. +% +% \makebox[2em][l]{-d} specifies the language definitions file. +% +% \changes{v3.3}{1996/08/23}{"lgrindef" position can be changed permanently} +% \makebox[2em][l]{-d!} same as -d, except the change is permanent (modifies +% executable) +% +% \makebox[2em][l]{-l} specifies the language to use. +% +% \makebox[2em][l]{-s} shows a list of currently known languages. +% +% The standard for \LG{} is to take its input from the file given on the +% command line and write on standard output. You can change this behaviour with +% the options - and -o, respectively. Please note that as soon as a file is +% detected on the command line (either its name or a -) it is processed with the +% options then in effect, thus +% allowing to give multiple files on one line with possibly multiple targets. +% +% If neither -e nor -i are specified, a complete \LaTeX-file is produced. When +% no language is given on the command line, \LG{} tries to figure out the +% language via the extension of the file. A table of extensions and their +% languages is in the definition file. If the extension is unknown, C is chosen +% as a default. +% +% When \LG{} is started without any parameters, it will show a short help screen. +% The same happens when the appropriate option is given, but this is +% implementation dependent (usually what is common for the operation system, the +% default for DOS is |-?| and for Unix |--help|). +% +% The position of the \texttt{lgrindef}-file is determined by giving it on the +% command line (highest priority), by defining an environment variable +% \texttt{LGRINDEF}, and by the position fixed in \LG{}s executable. The latter +% can be changed by using -d! and then using the newly created file as the new +% \LG{}. +% \changes{v3.5}{1998/05/30}{Now testing for \texttt{LGRINDEF} environment variable.} +% +% The languages which are currently known are stored in the language definition +% file; their number increases more or less rapidly. At the time of writing the +% languages in the table below are part of the distribution. +% +% \begin{table}\begin{minipage}{0.8\linewidth} +% \let\thefootnote\thempfootnote +% \newcommand{\fnm}[1]{\textsuperscript{\itshape#1}} +% \begin{tabbing} +% \hspace*{2em} \= \hspace{9em} \= \hspace{9em} \= \\ +% \> Ada \> \LaTeX\footnote{John Leis, University of Southern Queensland, leis@usq.edu.au.} +% \> RATFOR \\ +% \> Asm \> LDL \> RLaB\footnote{Jim Green, National Physical Laboratory, jjg1@cise.npl.co.uk} \\ +% \> Asm68 \> Lex \> Russell \\ +% \> BASIC\fnm{a} \> Linda \> SAS\footnote{Michael Friendly, friendly@hotspur.psych.yorku.ca} \\ +% \> Batch\fnm{b} \> Lisp (Emacs) \> Scheme\footnote{Neale Pickett, npickett@watchguard.com} \\ +% \> C \> MASM\fnm{a} \> sh \\ +% \> C++ \> MATLAB\fnm{a} \> SICStus\fnm{b} \\ +% \> csh \> ML\fnm{d} \> src \\ +% \> FORTRAN \> Mercury \> SQL \\ +% \> Gnuplot\footnote{Denis Petrovic, Denis.Petrovic@public.srce.hr} +% \> model \> Tcl/Tk\footnote{Alexander Bednarz, Forsch.-zentrum J\"ulich, A.Bednarz@kfa-juelich.de} \\ +% \> Icon \> Modula2 \> VisualBasic\fnm{a} \\ +% \> IDL\footnote{Diego Berrueta, diego@berrueta.net} +% \> Pascal \> VMSasm \\ +% \> ISP \> PERL \> yacc \\ +% \> Java \> PostScript \> \\ +% \> Kimwitu++ \> PROLOG \> +% \end{tabbing}\par +% \let\footnoterule\relax +% \end{minipage}\end{table} +% \changes{v3.67}{2002/01/28}{Added Scheme and ML language definitions} +% \subsection{Operation modes} +% There are three modes of operation: stand-alone, include and embedded. +% +% Use |lgrind -ly bary.y > bary.tex| (or |lgrind -o bary.tex bary.y|) to +% produce a stand-alone \LaTeX-file from, say, a Yacc file. This results in a +% document which is formatted using Piet van Oostrum's \textsf{fancyhdr.sty} to +% make the headers and footers. BTW: You really should have this package. It's +% marvellous. But of course you can change the layout to your likings by +% editing the \texttt{lgrindef}-file. +% +% To include a C-file named \texttt{foo.c} into your \LaTeX-document, first +% give the command: |lgrind -i -lc foo.c > foo.tex| This will generate +% \texttt{foo.tex}, which will have the pretty-printed version of +% \texttt{foo.c}. Then include \texttt{lgrind.sty} as you include any other +% package, namely with |\usepackage{lgrind}| at the beginning of your +% \LaTeX-document. Having done this, within the document you can include +% \texttt{foo.tex} using |\lagrind| and |\lgrindfile| described in the next section. +% +% Finally, for the embedded (and probably most powerful) mode, when you have a +% \LaTeX-file with embedded program listings, you can preprocess it with a command like: +% |lgrind -e pretty-sources.lg > even-prettier-sources.tex| +% and get a new \LaTeX-file which you then feed into \LaTeX. Commands you can +% use within embedded texts are described below. +% +% \section{Preparing documents} +% +% \subsection{Using the \LG.sty-file} +% The \LG{} package is included via the |\usepackage| command. You have to include it +% in your document preamble when you want to include listings and when using embedded +% mode. It is done automatically for stand-alone listings. +% Currently the following options are supported: +% \begin{description} +% \changes{v3.5}{1998/05/23}{Procedure names added to index in addition to +% printing them in the margin.} +% \item[procnames] prints the names of starting and, if nested +% procedures are allowed, continued procedures in the margin. Don't make the +% margin too small, or don't make the names too long \dots +% \item[noprocindex] do not put found procedure beginnings in the index +% \item[noindent] cancels the indentation. Useful for long listings or listings +% within their own sections. +% \item[fussy] lets \LaTeX\ print all overfull hboxes. The default is to suppress +% this for about a tenth of an inch. +% \item[norules] lets \LG{} suppress the surrounding rules for included material +% (using |\lagrind| and |\lgrindfile|). +% \item[nolineno] doesn't print line numbers.\footnote{To be exact, prints line +% numbers every 50,000 lines. But source code should never get so long in a +% single file~-- that's over 3 MByte! If you really want no numbers, +% set $\backslash$\texttt{LGnuminterval} to zero; then you won't get procedure +% names, either.} +% \item[lineno5] prints line numbers every 5 lines. The default is 10. +% \item[leftno] print line numbers in the left margin. Default is the right. +% \end{description} +% +% \subsection{Stand-alone and included listings} +% After processing a source code file with \LG{} without the -e or -i +% options you get a \LaTeX-file which can be directly compiled. +% +% When using -i \LG{} will produce a file which can be included with the +% following macros: +% +% \DescribeMacro{\lgrindfile} +% The first is |\lgrindfile{|\meta{file}|}|, which will simply include +% the file \meta{file} at that point of text, and will draw horizontal +% lines before and after the listing. +% +% \DescribeMacro{\lagrind} +% The macro +% |\lagrind[|\meta{float}|]{|\meta{file}|}{|\meta{caption}|}{|\meta{label}|}| +% will put the listing also within a figure environment, using the \meta{float} +% options (h, t, b or p), \meta{caption} and \meta{label} you gave. The starred +% form of |\lagrind| will also use the starred |figure*|. +% +% Note that floats cannot be longer than one page, so you should only use +% |\lagrind| for short fragments, longer pieces should use |\lgrindfile| (which +% is non-floating). +% +% \DeleteShortVerb{\|}\MakeShortVerb{\"}\MakePercentIgnore +% \subsection{Embedded programs within a \LaTeX-file} +% You don't have to process every single source file with \LG{}, only to +% include it in your document. Within the text of your \LaTeX-file, you can +% mark groups of lines as program code, either text- or display-style to +% be specific. You can use several commands for controlling the inclusion +% of source code into your \LaTeX-file. +% +% Write your text, don't forget to include \LG.sty. Use the following +% commands. You can `debug' your text without including the lengthy +% listings. As a last step (but one), you process your file with \LG{} +% and its option -e, which will provide you with your final \LaTeX{} +% source file. +% +% The commands are similar to the math environments. \DescribeEnv{\%( \%)} +% With "%(" and "%)" you obtain code in text style, i.\,e. in the same line. +% \DescribeEnv{@ @}Surrounding the text with "@" is a shorthand. +% \begin{verbatim} +% The expression +% %( +% a + 3 +% %) +% produces 10.\end{verbatim} +% produces the same as "The expression @a + 3@ produces 10." The output +% will have `a + 3' set as a program. +% +% \DescribeEnv{\%[ \%]}As with math, the square bracket equivalent produces +% display style listings, i.\,e. indented text on an own line. +% +% \DescribeEnv{\%*} As long listings tend not to fit on one page, there will +% be page breaks inserted. Since page breaks can considerably affect readability +% there will be none at all unless you insert lines consisting of just "%*". +% Pages will end here and only here, but not necessarily here. (That is, you +% allow (or recommend) a page break. It will be taken if needed.) +% \changes{v3.3}{1996/09/02}{Allow page breaks in embedded listings} +% +% \DescribeEnv{\%=} You can insert your own code by using a line starting with +% "%=" in the program text. Whatever you enter after that is left in the output, +% exactly as you typed it. It will be executed in a strange environment, so +% doing anything fancy is very tricky. \DescribeMacro{\Line} A macro, "\Line", +% is provided to help you do simple things. For example, +% \begin{verbatim} +% %[ +% %=\Line{________\vdots} +% a = 1; +% %]\end{verbatim} +% produces: +% +% \hspace*{4em}\vdots +% +% \hspace*{4em}\textit{a}\textsf{ = 1;} +% +% (Within the program text, \_ is active and expands to a +% fixed-width space. A whole bunch of macros are also defined. If you +% understand how \LG{} sets lines up, you can replace the 8 \_'s +% with a call to "\Tab"---but I'll let you hang yourself on that one.) +% +% \DescribeEnv{\%<}The "%<"\meta{file} command includes \meta{file} as a +% program listing in your document. Before inclusion it will be pretty +% printed. This is the almost the same as \LG ing the \meta{file} +% separately and with -i and including it via "\lgrindfile", only that +% it's simpler for you. \DescribeEnv{\%!} With "%!"\meta{command} the +% input is taken from a shell command. +% +% While you can specify the language used on the command line, this does +% not suffice for mixed-language programs (or projects). The command +% \DescribeEnv{\%\#}"%#"\meta{language} provides you a means to change +% the language on the fly wherever you want. +% +% \DescribeEnv{\%@}The shorthand "@" is very useful, and since "@" is not usable +% in normal \LaTeX{} text there is no conflict. If, however, you use "@" in your +% text (after "\makeatletter") the result produced by \LG{} is not satisfactory. +% To disable the shorthand you can use a command line option, or locally "%@-". +% Using "%@+" will switch it on again. +% +% Important rules: +% \begin{itemize} +% \item "%" and the following character must be the first two characters on +% the line to be recognized. +% \item +% Put \emph{nothing} on the line after the "%" and the key character. +% If you do that, \LG{} will provide a default environment that will +% produce an "\hbox" for "%( )%", and a "\vbox" for "%[ %]". +% If you put stuff on the line, \LG{} assumes you want to control +% the format completely. Doing this requires understanding \emph{exactly} +% what the code \LG{} produces is doing. (Sometimes I'm not sure I do!) +% \item +% "%)" and "%]" are simply ignored outside +% of a code group, but any extra "%(" or "%[" produces a +% warning, so a missing "%)" or "%]" is usually caught. +% \item +% Remember that the code between "%("/"%[" and "%)"/"%]" is put into a +% single box. Expect the usual problems with long boxes! Use "%*" if needed. +% \end{itemize} +% +% \subsection{Formatting your source code} +% Well, \LG{} uses a different font for comments. This has as a consequence +% that functions you refer to are typeset differently in the program and +% in the comments, which is unsatisfactory. And, wouldn't it be great to +% use \LaTeX{} commands to produce e.\,g. `\copyright'? +% +% The \texttt{lgrindef}-file defines environments for exactly these +% purposes. They are usually defined as follows, but of course it is possible +% to use other strings if the standard collides with the syntax of the +% language in question. +% +% \DescribeEnv{\%\% \%\%}Text which is surrounded by "%%" is directly +% passed to \LaTeX, a pair of curled braces around it. So the copyright +% symbol would be produced with "%%\copyright%%". +% \DescribeEnv{\%\$ \$\%}The "%$"\meta{text}"$%" works much the same, +% except that \meta{text} is set in math mode. +% +% When \LG{} discovers a line that contains \emph{only} a comment beginning +% right at the start of the line and ending at the very end (no spaces), containing +% \emph{only} \LaTeX{} text as in the environment described above, the line +% will be copied verbatim into the resulting \LaTeX{} document, with a newline +% appended. This allows (e.\,g., in C): +% \begin{verbatim} +% /*%%\section{Main program}%%*/ +% int main() +% { +% //%%\subsection{Variables}%% +% int a;\end{verbatim} +% \changes{v3.6}{1999/05/28}{Complete \LaTeX{} lines allowed} +% +% The underscore which is normally the subscripting operator in math mode is +% used internally in \LG{}. You can still use the command "\sb" instead (and +% "\sp" for superscripts).\label{underscore} +% +% \DescribeEnv{\%| |\%}In "%|"\meta{text}"|%" a kind of verbatim +% environment is provided. \meta{Text} is typeset in typewriter. +% +% \DescribeEnv{@ @}Program text within a comment is surrounded by "@". The text +% is processed exactly as if it wasn't a comment. To produce an at-sign +% you have to use "@@". +% +% \subsection{Greater control\dots} +% Many things are controllable by re-defining various macros. You can +% change what fonts \LG{} will use for various kinds of things, how +% much it indents the output, whether it adds line numbers, and if so at +% what interval it prints them and whether it sticks them on the left or +% right, and so on. This stuff is all described below in the code section, +% though probably not very well. The default settings produce output +% that looks reasonable to me, though I can't say I'm ecstatic about it. +% Doing a \emph{really} good job would require defining some special fonts. +% +% Nonetheless as an example my own private font setup. After having defined a +% font family called ttp (for typewriter proportional), using Boton (a +% commercial font which has a nice `code look' to it), I define: +% +% \begin{verbatim} +% \def\CMfont{\ttpfamily\itshape} +% \def\KWfont{\ttpfamily\bfseries} +% \def\VRfont{\ttpfamily} +% \def\BGfont{\ttpfamily} +% \end{verbatim} +% +% You can put these redefinitions in the preamble of your \LaTeX-file when +% using embedded and included mode; for stand-alone listings you have to put +% them into the \texttt{lgrindef}-file. This will change fonts for all modes. +% +% \subsection{Error messages} +% The output of \LG{} always contains exactly one output line for each input +% line. Hence, you can look up line numbers in \TeX{} error messages in your +% original file, rather than in the \LG ed (LGround?) file. (Of course, if +% the problem is in the \LG{} output\dots) +% +% \subsection{Variable substitution} +% \LG{} usually prints variables exactly the way they appear in the source +% code. However, very often one uses names for variables which really denote +% symbols and have special formatting, only that the input alphabet of the +% target language does of course not allow anything fancier than plain ASCII. +% +% I find myself using greek variables very often, because they are used in the +% problem domain. So there is a `delta' which really should be `$\delta$', +% there is a `gamma\_1' for `$\gamma\sb1$' and so forth. LG{} allows you to +% change those names back to what you desire by use of a variable substution +% file (using option -v). +% +% This file is very simple, and so is its parser. There is one substitution per +% line, giving the original name, an equality sign, and the text replacing the +% original: +% \begin{verbatim} +% delta=$\delta$ +% gamma_1=$\gamma\sb1$ +% \end{verbatim} +% You can do everything you want to here. Remember that \emph{usually} variable +% names are set upright and not in math mode. Therefore don't forget the +% dollar-sign, and use "\sb" instead of "_" (see section \ref{underscore}). +% +% \section{The \texttt{lgrindef}-file} +% The \texttt{lgrindef}-file is \LG's language definition data base. +% It is here where \LG{} learns what are keywords, what comments, where +% are functions, how to distinguish plain comments from \LaTeX-commands etc. +% +% The first field is just the language name (and any variants +% of it). Thus the C language could be specified to \LG{} as `c' or `C'. +% +% \subsection{Capabilities} +% Capabilities are of two types: Boolean capabilities which indicate that +% the language has some particular feature and string capabilities which +% give a regular expression or keyword list. +% +% Entries may continue onto multiple lines by giving a "\" as the last +% character of a line. Lines starting with "#" are comments. +% +% The following table names and describes each capability. +% \bgroup\renewcommand{\descriptionlabel}[1]{\hspace{\labelsep}\makebox[1.5em][l]{\textsf{#1}}} +% \begin{description} +% \item[ab] Regular expression for the start of an alternate form comment +% \item[ae] Regular expression for the end of an alternate form comment +% \item[bb] Regular expression for the start of a block +% \item[be] Regular expression for the end of a lexical block +% \item[cb] Regular expression for the start of a comment +% \item[ce] Regular expression for the end of a comment +% \item[cf] (Boolean) Use specialized routine for detecting C functions +% \changes{v3.1}{1995/11/12}{C functions are now detected much more reliably} +% \item[id] String giving characters other than letters and digits +% that may legally occur in identifiers (default `\_') +% \item[kw] A list of keywords separated by spaces +% \item[lb] Regular expression for the start of a character constant +% \item[le] Regular expression for the end of a character constant +% \item[mb] Regular expression for the start of \TeX{} math within a comment +% \item[me] Regular expression for the end of \TeX{} math within a comment +% \item[np] Regular expression for a line that does \emph{not} contain +% the start of a procedure (e.\,g. prototypes) +% \item[oc] (Boolean) Present means upper and lower case are equivalent +% \item[pb] Regular expression for start of a procedure +% \item[pl] (Boolean) Procedure definitions are constrained to the lexical +% level matched by the `px' capability +% \item[px] A match for this regular expression indicates that procedure +% definitions may occur at the next lexical level. Useful for lisp-like +% languages in which procedure definitions occur as subexpressions of defuns. +% \item[rb] Regular expression for the start of block outside the actual +% code.\footnote{I included this especially for the \texttt{objects} and +% \texttt{records} in Pascal and Modula-2. They \emph{end} (with the "<"be">" +% expression), but shouldn't have any influence on the surrounding procedure. +% When defining \texttt{record} as normal block start, its \texttt{end} ends +% the procedure. Workaround: Make \texttt{record} itself a procedure start. +% But that prints a continuation mark when \textsf{procnames} is on.} +% \changes{v3.1}{1995/11/12}{Pascal objects now treated properly} +% \item[sb] Regular expression for the start of a string +% \item[se] Regular expression for the end of a string +% \item[tb] Regular expression for the start of \TeX{} text within a comment +% \item[tc] (String) Use the named language entry as a continuation of the +% current one +% \item[te] Regular expression for the end of \TeX{} text within a comment +% \item[tl] (Boolean) Present means procedures are only defined at the top +% lexical level +% \item[vb] Regular expression for the start of typewriter text within a +% comment +% \item[ve] Regular expression for the end of typewriter text within a comment +% \item[zb] Regular expression for the start of program text within a comment +% \item[ze] Regular expression for the end of program text within a comment +% \end{description} +% \egroup +% +% \subsection{Regular Expressions} +% \texttt{lgrindef} uses regular expressions similar to those of +% \textsf{ex} and \textsf{lex}. The characters `"^"', `"$"', `"|"', `:', +%%stopzone % VIM syncing +% and `"\"' are reserved characters and must be `quoted' with a preceding +% "\" if they are to be included as normal characters. +% +% The meta-symbols and their meanings are: +% \begin{description} +% \item[\$] The end of a line +% \item[\^] The beginning of a line +% \item[$\backslash$d] A delimiter (space, tab, newline, start of line) +% \item[$\backslash$a] Matches any string of symbols (like `.*' in lex) +% \item[$\backslash$p] Matches any identifier. In a procedure definition +% (the `pb' capability) the string that matches this symbol is used +% as the procedure name. +% \item[( )] Grouping +% \item[$|$] Alternation +% \item[?] Last item is optional +% \item[$\backslash$e] Preceding any string means that the string will not +% match an input string if the input string is preceded by an escape character +% ("\"). This is typically used for languages (like C) that can include the +% string delimiter in a string by escaping it. +% \end{description} +% +% Unlike other regular expressions in the system, these match words and +% not characters. Hence something like `(tramp"|"steamer)flies?' +% would match `tramp', `steamer', `trampflies', or `steamerflies'. +% Contrary to some forms of regular expressions, \texttt{lgrindef} +% alternation binds very tightly. Grouping parentheses are likely to +% be necessary in expressions involving alternation. +% +% \subsection{Keyword List} +% The keyword list is just a list of keywords in the language separated +% by spaces. If the `oc' boolean is specified, indicating that upper +% and lower case are equivalent, then all the keywords should be specified +% in lower case. +% +% \subsection{Configuration options} +% \changes{v3.1}{1995/11/07}{The \LaTeX-text put into the files +% can be configured} +% In addition to the language definitions the \texttt{lgrindef}-file +% contains various configuration data. When the entries do not exist, +% default values are used: +% \begin{description} +% \item[firstpreamble] is the (\LaTeX-)text that comes at the beginning of +% an stand-alone file created by \LG{} from source code (it must contain +% "\begin{document}" somewhere). +% \item[postamble] is the (\LaTeX-)text that comes at the end of +% an stand-alone file (and must contain "\end{document}"). This is the place to +% put a "\printindex" if you wish so (don't forget "\usepackage{makeidx}" and +% "\makeindex" in the preamble). +% \item[filepreamble] is inserted before every processed source file in a +% stand-alone \LaTeX-file. In these two preambles you can use "\f", which +% will be substituted by the current input file (e.\,g. to put it into the +% header). +% \item[configuration] follows the opening of the \texttt{lgrind}-environment. +% This is used for redefining the macros used within it, e.\,g. the fonts +% or the width of a space (the "\@ts" unit). +% \item[chartab] is a list of characters that will be substituted by a +% \LaTeX-string. This is useful when you do (or can) not use any of the fancy +% methods to persuade \LaTeX{} into using your extended ASCII-characters. +% The format is a two digit hex number (the ASCII- (or whatever) value of the +% character), an equal sign, and the according \LaTeX{}-string, ended with a +% colon. You have to escape certain characters (like the backslash). So if +% you, e.\,g., have IBM ASCII code page 437 input and use the +% \textsf{german}-package, you can have your \"a using \verb+84="a+. Note +% that the substituting string must contain more than one character; +% otherwise it will be ignored. To print a `b' instead of an `a' you can +% use \verb+61={b}+. +% \end{description} +% +% \StopEventually{\PrintChanges\PrintIndex} +% +% \section{The Implementation of \LG.sty} +% \begin{macrocode} +%<*package> +% \end{macrocode} +% \setlength{\parindent}{0pt} +% +% \begin{macro}{\LGnuminterval}\begin{macro}{\lc@unt}\begin{macro}{\ln@xt} +% The counter "\LGnuminterval" represents the line numbering interval. +% Its default is 10, it is set by two options and can be changed everywhere +% you want to. "\lc@unt" counts the current line, "\ln@xt" contains the next +% line to get numbered. +% \begin{macrocode} +\newcount\lc@unt +\newcount\ln@xt +\newcount\LGnuminterval +\LGnuminterval=10 +\DeclareOption{nolineno}{\LGnuminterval=50000} +\DeclareOption{lineno5}{\LGnuminterval=5} +% \end{macrocode} +% \end{macro}\end{macro}\end{macro} +% +% \begin{macro}{\LGleftnum} +% Line numbers are usually on the right. By setting "LGleftnum" to true +% or false this behaviour can be altered. +% \begin{macrocode} +\newif\ifLGleftnum +\DeclareOption{leftno}{\LGleftnumtrue} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\LGindent} +% "\LGindent" is the indentation for all display style listing lines. +% \begin{macrocode} +\newskip\LGindent +\LGindent=1.6667\parindent +\DeclareOption{noindent}{\LGindent=0pt} +% \end{macrocode} +% \end{macro} +% +% \changes{v3.4}{1997/02/05}{Rules around included material can be suppressed. +% New option norules.} +% \begin{macro}{\LGnorules} +% Normally \LG{} puts rules around everything that is included (via "\lagrind" +% and "\lgrindfile"), this can be changed with an option. +% \begin{macrocode} +\newif\ifLGnorules +\DeclareOption{norules}{\LGnorulestrue} +% \end{macrocode} +% \end{macro} +% +% \changes{v3.4}{1997/01/30}{Prevent slightly overfull hboxes. New option fussy.} +% \begin{macro}{\LGsloppy} +% "\LGsloppy" is the amount that a horizontal box may be overfull without getting +% a warning from \LaTeX. This is useful since there are often many boxes which are +% overfull by only a few points, and this does not really show since listings are +% very ragged. +% \begin{macrocode} +\newlength{\LGsloppy} +\setlength{\LGsloppy}{7.2pt} +\DeclareOption{fussy}{\LGsloppy=0pt} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\Proc}\begin{macro}{\ProcCont} +% There's a "\Proc{"\meta{ProcName}"}" at the start of each procedure. If +% the language allows nested procedures (e.\,g. Pascal), there +% will be a "\ProcCont{"\meta{ProcName}"}" at the end of each inner procedure. +% (In this case, \meta{ProcName} is the name of the outer procedure. I.\,e., +% "\ProcCont" marks the continuation of \meta{ProcName}). +% +% \begin{macro}{\DefaultProc} +% \changes{v3.0}{1995/09/24}{Reintroduced procedure names in the margins} +% \begin{macro}{\DefaultProcCont} +% Default is not to do anything with the name. Optionally the names are +% printed in the same margin as the line numbers. The name is put into a +% box which will be output whenever it is not empty. +% +% \begin{macrocode} +\newcommand{\DefaultProc}{\@gobble} +\newcommand{\DefaultProcCont}{\@gobble} +\DeclareOption{procnames}{ +\renewcommand{\DefaultProc}[1]{\renewcommand{\Procname}{#1}% +\global\setbox\procbox=\hbox{\PNsize #1}} +\renewcommand{\DefaultProcCont}[1]{\renewcommand\Procname{#1} +\global\setbox\procbox=\hbox{\PNsize\dots #1}}} +\newbox\procbox +\newcommand{\Procname}{} +% \end{macrocode} +% \end{macro}\end{macro}\end{macro}\end{macro} +% +% \begin{macro}{\ifLGnoprocindex} +% \changes{v3.6}{1999/05/27}{Added option to suppress indexing of functions} +% \begin{macrocode} +\newif\ifLGnoprocindex +\DeclareOption{noprocindex}{\LGnoprocindextrue} +% \end{macrocode} +% \end{macro} +% +% End of initialization, execute any options. +% \begin{macrocode} +\ProcessOptions +% \end{macrocode} +% \changes{v3.0}{1995/09/28}{Added package options} +% +% \begin{macro}{\BGfont}\begin{macro}{\CMfont}\begin{macro}{\NOfont} +% \changes{v3.1}{1995/11/12}{Numbers can now have an own style (i.\,e. font)} +% \begin{macro}{\KWfont}\begin{macro}{\STfont}\begin{macro}{\TTfont} +% \begin{macro}{\VRfont}\begin{macro}{\PNsize}\begin{macro}{\LGsize} +% \begin{macro}{\LGfsize} +% These are the fonts and sizes for background (everything that doesn't fit +% elsewhere), comments, numbers, keywords, strings, verbatim text, variables, +% the procedure names +% in the margins, displayed code ("%[ ]%"), and included code ("\lgrindfile" +% and "\lagrind"), respectively. Note that the suffixes `font' and `size' +% have been chosen solely for the author's intention; you can do anything +% you want, e.\,g. "\tiny" comments. You have to use, however, font changes +% which don't require an argument. +% \begin{macrocode} +\def\BGfont{\sffamily} +\def\CMfont{\rmfamily\itshape} +\def\NOfont{\sffamily} +\def\KWfont{\rmfamily\bfseries} +\def\STfont{\ttfamily} +\def\TTfont{\ttfamily\upshape} +\def\VRfont{\rmfamily} +\def\PNsize{\BGfont\small} +\def\LGsize{\small} +\def\LGfsize{\footnotesize} +% \end{macrocode} +% \end{macro}\end{macro}\end{macro} +% \end{macro}\end{macro}\end{macro} +% \end{macro}\end{macro}\end{macro} +% \end{macro} +% +% \begin{macro}{\ifLGinline}\begin{macro}{\ifLGd@fault} +% \begin{macro}{\LGbegin}\begin{macro}{\LGend} +% The flag "LGinline" is true for in-line code. "\LGbegin" and "\LGend" are +% default commands to open and close a code example and use it to perform +% certain ops depending whether we're in-line or display style."\LGend" is +% a no-op unless "\LGbegin" (where "LGd@fault" is set true) was executed, +% so you can provide explicit open +% code on the "%[" or "%(" line without providing any special code on the +% matching "%]" or "%)" line. +% \begin{macrocode} +\newif\ifLGinline +\newif\ifLGd@fault +\def\LGbegin{\ifLGinline$\hbox\else$$\vbox\fi\bgroup\LGd@faulttrue} +\def\LGend{\ifLGd@fault\egroup\ifLGinline$\else$$\fi\LGd@faultfalse\fi} +% \end{macrocode} +% \end{macro}\end{macro}\end{macro}\end{macro} +%%stopzone % VIM syncing +% +% \begin{macro}{\ifc@omment}\begin{macro}{\ifstr@ng} +% These two conditions indicate if we are setting a comment or maybe +% a string constant, respectively. +% \begin{macrocode} +\newif\ifc@mment +\newif\ifstr@ng +% \end{macrocode} +% \end{macro}\end{macro} +% +% \begin{macro}{\ifright@} +% To get decent quotes (opening and closing) within comments, we remember +% whether the next one is going to be `{}``'{} or, if true, `{}'''{}. +% \begin{macrocode} +\newif\ifright@ +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ls@far}\begin{macro}{\tb@x}\begin{macro}{\TBw@d} +% These three are all for the sake of tabbing. "\ls@far" stores the +% ``line so far''. The tabwidth goes in "\TBw@d", whilst "\tb@x" is +% merely a temporary variable for "\Tab" and setting "\@ts". +% \begin{macrocode} +\newbox\ls@far +\newbox\tb@x +\newdimen\TBw@d +% \end{macrocode} +% \end{macro}\end{macro}\end{macro} +% +% The underscore marks a point where the pre-processor wants a fixed-width +% space (of width "\@ts"). +% \begin{macrocode} +\newdimen\@ts +{\catcode`\_=\active \gdef\@setunder{\let_=\sp@ce}} +% \end{macrocode} +% +% \begin{macro}{\lgrindhead} +% \begin{macro}{\lgrindfilename}\begin{macro}{\lgrindfilesize} +% \begin{macro}{\lgrindmodyear}\begin{macro}{\lgrindmodmonth} +% \begin{macro}{\lgrindmodday}\begin{macro}{\lgrindmodtime} +% We pollute the global namspace once more with these macros, for when they +% are used in the headers or footers, their values must still be known. +% Therefore they cannot be local to the "lgrind" environment. +% \begin{macrocode} +\newcommand{\lgrindhead}{} +\newcommand{\lgrindfilename}{}\newcommand{\lgrindfilesize}{} +\newcommand{\lgrindmodyear}{}\newcommand{\lgrindmodmonth}{} +\newcommand{\lgrindmodday}{}\newcommand{\lgrindmodtime}{} +% \end{macrocode} +% \end{macro}\end{macro}\end{macro}\end{macro} +% \end{macro}\end{macro}\end{macro} +% +% \begin{environment}{lgrind} +% This is the environment that eventually defines all necessary macros for +% formatting. All \LG ed text goes into such an environment, no matter if +% directly so or from within another one. It takes one optional argument, +% the line number. +% \begin{macrocode} +\newenvironment{lgrind}[1][1]{% +% \end{macrocode} +% +% \begin{macro}{\Line} +% The "\Line" macro is provided for use with "%=" in embedded listings. +% It's just there to hide the actual structure of this, for nobody +% \emph{really} wants to know anyway. +% \begin{macrocode} +\def\Line##1{\L{\LB{##1}}}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\Head}\begin{macro}{\File} +% \changes{v3.3}{1996/09/11}{given a meaningful definition} +% The next are primarily meant for stand-alone listings. "\Head" and +% "\File" are inserted by \LG, they define macros that contain +% a user-specified string (the header option -h), the name, size +% and modification time of the processed file. These can then be +% used e.\,g. in the headers and footers. +% \begin{macrocode} +\newcommand{\Head}[1]{\gdef\lgrindhead{##1}}% +\newcommand{\File}[6]{\gdef\lgrindfilename{##1}\message{(LGround: ##1)}% + \gdef\lgrindmodyear{##2}\gdef\lgrindmodmonth{##3}% + \gdef\lgrindmodday{##4}\gdef\lgrindmodtime{##5}% + \gdef\lgrindfilesize{##6}}% +% \end{macrocode} +% \end{macro}\end{macro} +% The "\Proc"s now get what +% was specified for them in the options section. +% \begin{macrocode} +\let\Proc=\DefaultProc% +\let\ProcCont=\DefaultProcCont% +\ifLGnoprocindex% + \let\index\@gobble% +\fi% +% \end{macrocode} +% +% We set a "\hfuzz" to prevent some of the lesser overfull hbox warnings. +% \begin{macrocode} +\hfuzz=\LGsloppy% +% \end{macrocode} +% +% \begin{macro}{\NewPage} +% Each formfeed in the input is replaced by a "\NewPage" macro. If +% you really want a page break here, define this as "\vfill\eject". +% \begin{macrocode} +\def\NewPage{\filbreak\bigskip}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\L} +% Each line of displayed program text is enclosed by a "\L{"\dots"}". We +% turn each line into an hbox. Firstly we look whether we are in-line. +% Every "\LGnuminterval" lines we output a +% small line number in past the margin. +% \begin{macrocode} +\ifLGinline% + \def\L##1{\setbox\ls@far\null{\CF\strut##1}\ignorespaces}% +% \end{macrocode} +% \begin{macro}{\r@ghtlno}\begin{macro}{\l@ftlno} +% Things get more difficult for display style listings. Here we set +% "\r@ghtlno" and "\l@ftlno" to no-ops, only to redefine them shortly +% after. +% \begin{macrocode} +\else% + \let\r@ghtlno\relax\let\l@ftlno\relax% + \ifnum\LGnuminterval>\z@% + \ifLGleftnum% +% \end{macrocode} +% If there was a procedure name somewhere, "\procbox" is not empty and +% thus ready to be printed. Otherwise we test "\lc@unt" against "\ln@ext" +% to determine whether or not to print a line number. +% \begin{macrocode} + \def\l@ftlno{\ifnum\lc@unt>\ln@xt% + \global\advance\ln@xt by\LGnuminterval% + \llap{{\normalfont\scriptsize\the\lc@unt\quad}}\fi}% + \def\r@ghtlno{\rlap{\enspace\box\procbox}}% +% \end{macrocode} +% And once again when the line number is meant to be on the right. +% \begin{macrocode} + \else% + \def\r@ghtlno{\ifnum\lc@unt>\ln@xt% + \global\advance\ln@xt by\LGnuminterval% + \rlap{{\normalfont\scriptsize\enspace\the\lc@unt% + \enspace\box\procbox}}% + \else\rlap{\enspace\box\procbox}\fi}% + \fi% + \fi% +% \end{macrocode} +% \end{macro}\end{macro} +% "\lc@unt" is incremented and everything is squeezed into a "\hbox". +% \begin{macrocode} + \def\L##1{\@@par\setbox\ls@far=\null\strut% + \global\advance\lc@unt by1% + \hbox to \linewidth{\hskip\LGindent\l@ftlno ##1\egroup% + \hfil\r@ghtlno}% + \ignorespaces}% +\fi% +% \end{macrocode} +% \end{macro} +% +% The initialization of "\lc@unt" and "\ln@xt". Every "lgrind"-environment +% starts over unless given a line number as argument. +% \begin{macrocode} +\lc@unt=#1\advance\lc@unt by-1% +\ln@xt=\LGnuminterval\advance\ln@xt by-1% +\loop\ifnum\lc@unt>\ln@xt\advance\ln@xt by\LGnuminterval\repeat% +% \end{macrocode} +% +% \begin{macro}{\LB}\begin{macro}{\Tab} +% The following weirdness is to deal with tabs. ``Pieces'' of a line +% between tabs are output as "\LB{"\dots"}". E.\,g., a line with a tab at +% column 16 would be output as "\LB{xxx}\Tab{16}\LB{yyy}". (Actually, to +% reduce the number of characters in the ".tex" file the "\Tab" macro +% supplies the 2nd \& subsequent "\LB"s.) We accumulate the "\LB" stuff in +% an "\hbox". When we see a "\Tab", we grab this hbox (using "\lastbox") +% and turn it into a box that extends to the tab position. We stash this +% box in "\ls@far" \& stick it on in front of the next piece of the line. +% (There must be a better way of doing tabs but I'm not enough of a \TeX +% wizard to come up with it. Suggestions would be appreciated. Oh, well, +% this comment's been in here for a decade. I don't believe in Santa Claus.) +% \begin{macrocode} +\def\LB{\hbox\bgroup\bgroup\box\ls@far\CF\let\next=}% +\def\Tab##1{\egroup\setbox\tb@x=\lastbox\TBw@d=\wd\tb@x% + \advance\TBw@d by 1\@ts\ifdim\TBw@d>##1\@ts% + \setbox\ls@far=\hbox{\box\ls@far \box\tb@x \sp@ce}\else% + \setbox\ls@far=\hbox to ##1\@ts{\box\ls@far \box\tb@x \hfil}\fi\LB}% +% \end{macrocode} +% \end{macro}\end{macro} +% +% A normal space is too thin for code listings. We make spaces \& tabs +% be in "\@ts" units, which for displays are 80 \% the width of a ``0'' in the +% typewriter font. For inline stuff, on the other hand, we prefer a +% somewhat smaller space -- actually, the same size as normal inter-word +% spaces -- to help make the included stuff look like a unit. +% \begin{macrocode} +\ifLGinline\def\sp@ce{{\hskip .3333em}}% +\else \setbox\tb@x=\hbox{\texttt{0}}% + \@ts=0.8\wd\tb@x \def\sp@ce{{\hskip 1\@ts}}\fi% +\catcode`\_=\active \@setunder% +% \end{macrocode} +% +% \begin{macro}{\CF}\begin{macro}{\N}\begin{macro}{\K}\begin{macro}{\V} +% \begin{macro}{\ic@r} +% \begin{macro}{\C}\begin{macro}{\CE}\begin{macro}{\S}\begin{macro}{\SE} +% Font changing. Since we are usually changing the font inside of a "\LB" +% macro, we remember the current font in "\CF" \& stick a "\CF" at the +% start of each new box. Also, the characters ``\texttt{\char'042}'' and +% ``"'"'' behave differently in comments than in code, and others behave +% differently in strings than in code. +% +% "\N" is for numbers, "\K" marks keywords, "\V" variables, "\C" and "\CE" +% surround comments, "\S" and "\SE" strings. +% "\ic@r" inserts an optional "\/". +% \begin{macrocode} +\def\CF{\ifc@mment\CMfont\else\ifstr@ng\STfont\fi\fi}% +\def\N##1{{\NOfont ##1}\global\futurelet\next\ic@r}% +\def\K##1{{\KWfont ##1}\global\futurelet\next\ic@r}% +\def\V##1{{\VRfont ##1}\global\futurelet\next\ic@r}% +\def\ic@r{\let\@tempa\/\ifx.\next\let\@tempa\relax% + \else\ifx,\next\let\@tempa\relax\fi\fi\@tempa}% +\def\C{\egroup\bgroup\CMfont \global\c@mmenttrue \global\right@false}% +\def\CE{\egroup\bgroup \global\c@mmentfalse}% +\def\S{\egroup\bgroup\STfont \global\str@ngtrue}% +\def\SE{\egroup\bgroup \global\str@ngfalse}% +% \end{macrocode} +% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro} +% \end{macro}\end{macro}\end{macro}\end{macro} +% +% \begin{macro}{\,}\begin{macro}{\!} +% We need positive and negative thinspaces in both text and math modes, so +% we re-define "\," and "\!" here. The definition for "\," isn't really +% needed for \LaTeX, but we try to be more complete. Note that in \LaTeX{} +% terms, the new definition isn't robust, like the old~-- but nothing we +% produce here is likely to be robust --~or \emph{needs} to be!~-- anyway! +% \begin{macrocode} +\def\,{\relax \ifmmode\mskip\thinmuskip \else\thinspace \fi}% +\def\!{\relax \ifmmode\mskip-\thinmuskip \else\negthinspace \fi}% +% \end{macrocode} +% \end{macro}\end{macro} +% +% Special characters. "\CH" chooses its first option alone in math mode; +% its second option in a string; and its third option, enclosed in "$"s, +%%stopzone % VIM syncing +% otherwise. (At the moment, nothing is ever set in math mode, but you +% never know \dots) +% \begin{macrocode} +\def\CH##1##2##3{\relax\ifmmode ##1\relax% +\else\ifstr@ng ##2\relax\else$##3$\fi\fi }% +\def\|{\CH|||}% not necessary for T1 +\def\<{\CH<<<}% dto. +\def\>{\CH>>>}% dto. +\def\-{\CH---}% minus sign nicer than hyphen +\def\_{\ifstr@ng {\char'137}\else% + \leavevmode \kern.06em \vbox{\hrule width.35em}% + \ifdim\fontdimen\@ne\font=\z@ \kern.06em \fi\fi }% +\def\#{{\STfont\char'043}}% +\def\2{\CH\backslash {\char'134}\backslash }% % \ +\def\3{\ifc@mment\ifright@ ''\global\right@false% + \else``\global\right@true \fi% + \else{\texttt{\char'042}}\fi}% % " +\def\5{{\texttt{\char'136}}}% % ^ +% \end{macrocode} +% +% Finally we don't want any indentation other than our own. We allow \LaTeX{} +% to stretch our listings a bit. Then we open a group, select the background +% font and (fanfare!) are ready to begin. +% \begin{macrocode} +\parindent\z@\parskip\z@ plus 1pt% +\bgroup\BGfont% +} +% \end{macrocode} +% +% This is the end of the "lgrind" environment. Rather short (in comparison!) +% \begin{macrocode} +{\egroup\@@par} % end of environment lgrind +% \end{macrocode} +% \end{environment} +% +% The following are generated as part of opening and closing included +% code sequences. +% \begin{macrocode} +\def\lgrinde{\ifLGinline\else\LGsize\fi\begin{lgrind}} +\def\endlgrinde{\end{lgrind}} +% \end{macrocode} +% +% \begin{macro}{\lagrind} +% The "lagrind" environment is one of two for including files. It puts +% its argument inside a "figure" environment. It can be used without or +% with a star (first line), and with or without the usual floating +% arguments (second and third). +% \begin{macrocode} +\def\lagrind{\@ifstar{\@slagrind}{\@lagrind}} + +\def\@lagrind{\@ifnextchar[{\@@lagrind}{\@@lagrind[t]}} +\def\@slagrind{\@ifnextchar[{\@@slagrind}{\@@slagrind[t]}} +% \end{macrocode} +% +% \begin{macro}{\@@lagrind} +% The unstarred version. Everything is pretty obvious, we open a "figure", +% put in a "minipage", input the file in question, make caption and label +% and that's it. +% \begin{macrocode} +\def\@@lagrind[#1]#2#3#4{% + \begin{figure}[#1] +\ifLGnorules\else\hrule\fi +\vskip .5\baselineskip +\begin{minipage}\columnwidth\LGsize\LGindent\z@ + \begin{lgrind} +\input #2\relax + \end{lgrind} +\end{minipage} +\vskip .5\baselineskip plus .5\baselineskip +\ifLGnorules\else\hrule\fi\vskip .5\baselineskip +\begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ +\caption{#3}% +\label{#4}% + \else +\captcont{#3}% + \fi +\endgroup +\vskip 2pt + \end{figure} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@slagrind} +% D\'ej\`a vu? The starred version got an asterisk attached to "figure". +% \begin{macrocode} +\def\@@slagrind[#1]#2#3#4{% + \begin{figure*}[#1] +\ifLGnorules\else\hrule\fi +\vskip .5\baselineskip +\begin{minipage}\linewidth\LGsize\LGindent\z@ + \begin{lgrind} +\input #2\relax + \end{lgrind} +\end{minipage} +\vskip .5\baselineskip plus .5\baselineskip +\ifLGnorules\else\hrule\fi\vskip .5\baselineskip +\begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ +\caption{#3}% +\label{#4}% + \else +\captcont{#3}% + \fi +\endgroup +\vskip 2pt + \end{figure*} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\lgrindfile} +% This is similar. We draw lines above and below, no "figure". But it can +% get longer than one page. +% \begin{macrocode} +\def\lgrindfile#1{% + \par\addvspace{0.1in} + \ifLGnorules\else\hrule\fi + \vskip .5\baselineskip + \begingroup\LGfsize\LGindent\z@ +\begin{lgrind} + \input #1\relax +\end{lgrind} + \endgroup + \vskip .5\baselineskip + \ifLGnorules\else\hrule\vspace{0.1in}\fi +} +% \end{macrocode} +% \end{macro} +% +% And now \dots +% \begin{macrocode} +%</package> +% \end{macrocode} +% That's it. Thank you for reading up to here. +% +% Michael Piefel +% +% \vspace{2ex} +% \hrule +% +% \Finale +% +% \iffalse +%<*example> +\documentclass{report} +\usepackage{lgrind} + +\begin{document} + +\chapter{Introduction} +This is a \LaTeX file with embedded code. Process it with \textsf{LGrind} +and its option -e. + +\appendix +\chapter{lgrind.c} +%<example>%< lgrind.c + +\chapter{regexp.c} +\section{Header} +%<example>%< regexp.h +\section{Code} +%<example>%< regexp.c + +\chapter{lgrindef.c} +\section{Header} +%<example>%< lgrindef.h +\section{Code} +%<example>%< lgrindef.c + +\end{document} +%</example> +% \fi +\endinput diff --git a/support/lgrind/lgrind.gls b/support/lgrind/lgrind.gls new file mode 100644 index 0000000000..ab7dc39e93 --- /dev/null +++ b/support/lgrind/lgrind.gls @@ -0,0 +1,37 @@ + + \begin{theglossary} + + \makeatletter\scan@allowedfalse + + \item v1.0\efill + \subitem General:\ Written\pfill 1 + \item v2.0\efill + \subitem General:\ Upgrade to \LaTeX 2.09\pfill 1 + \item v3.0\efill + \subitem General:\ Added package options\pfill 11 + \subsubitem Upgrade to \LaTeXe \pfill 1 + \subitem \verb*+\DefaultProc+:\ Reintroduced procedure names in the margins\pfill 11 + \item v3.1\efill + \subitem General:\ C functions are now detected much more reliably\pfill 8 + \subsubitem Pascal objects now treated properly\pfill 8 + \subsubitem The \LaTeX -text put into the files can be configured\pfill + 10 + \subitem \verb*+\NOfont+:\ Numbers can now have an own style (i.\,e. font)\pfill 11 + \item v3.3\efill + \subitem General:\ "lgrindef" position can be changed permanently\pfill 2 + \subsubitem Allow page breaks in embedded listings\pfill 5 + \subitem \verb*+\File+:\ given a meaningful definition\pfill 13 + \item v3.4\efill + \subitem General:\ Prevent slightly overfull hboxes. New option fussy.\pfill 11 + \subsubitem Rules around included material can be suppressed. New option norules.\pfill + 11 + \item v3.5\efill + \subitem General:\ Now testing for \texttt {LGRINDEF} environment variable.\pfill 2 + \subsubitem Output redirection (-o) implemented.\pfill 2 + \subsubitem Procedure names added to index in addition to printing them in the margin.\pfill + 3 + \item v3.6\efill + \subitem General:\ Complete \LaTeX {} lines allowed\pfill 6 + \subitem \verb*+\ifLGnoprocindex+:\ Added option to suppress indexing of functions\pfill 11 + + \end{theglossary} diff --git a/support/lgrind/lgrind.ind b/support/lgrind/lgrind.ind new file mode 100644 index 0000000000..2b31491fd3 --- /dev/null +++ b/support/lgrind/lgrind.ind @@ -0,0 +1,156 @@ + + \begin{theindex} + \makeatletter\scan@allowedfalse +{\bfseries\hfil Symbols\hfil}\nopagebreak + + \item \verb*+\,+\pfill \main{116} + \item =\verb*+\!+\pfill \main{116} + \item {\ttfamily @ @} (environment)\pfill \usage{4}, \usage{6} + \item \verb*+\@@lagrind+\pfill \main{143} + \item \verb*+\@@slagrind+\pfill \main{166} + \item {\ttfamily \%!} (environment)\pfill \usage{5} + \item {\ttfamily \%( \%)} (environment)\pfill \usage{4} + \item {\ttfamily \%*} (environment)\pfill \usage{5} + \item {\ttfamily \%<} (environment)\pfill \usage{5} + \item {\ttfamily \%=} (environment)\pfill \usage{5} + \item {\ttfamily \%@} (environment)\pfill \usage{5} + \item {\ttfamily \%[ \%]} (environment)\pfill \usage{5} + \item {\ttfamily \%\#} (environment)\pfill \usage{5} + \item {\ttfamily \%\$ \$\%} (environment)\pfill \usage{6} + \item {\ttfamily \%\% \%\%} (environment)\pfill \usage{6} + \item {\ttfamily \%| |\%} (environment)\pfill \usage{6} + + \indexspace +{\bfseries\hfil B\hfil}\nopagebreak + + \item \verb*+\BGfont+\pfill \main{30} + + \indexspace +{\bfseries\hfil C\hfil}\nopagebreak + + \item \verb*+\C+\pfill \main{106} + \item \verb*+\CE+\pfill \main{106} + \item \verb*+\CF+\pfill \main{106} + \item \verb*+\CMfont+\pfill \main{30} + + \indexspace +{\bfseries\hfil D\hfil}\nopagebreak + + \item \verb*+\DefaultProc+\pfill \main{18} + \item \verb*+\DefaultProcCont+\pfill \main{18} + + \indexspace +{\bfseries\hfil E\hfil}\nopagebreak + + \item environments:\efill + \subitem {\ttfamily @ @}\pfill \usage{4}, \usage{6} + \subitem {\ttfamily \%!}\pfill \usage{5} + \subitem {\ttfamily \%( \%)}\pfill \usage{4} + \subitem {\ttfamily \%*}\pfill \usage{5} + \subitem {\ttfamily \%<}\pfill \usage{5} + \subitem {\ttfamily \%=}\pfill \usage{5} + \subitem {\ttfamily \%@}\pfill \usage{5} + \subitem {\ttfamily \%[ \%]}\pfill \usage{5} + \subitem {\ttfamily \%\#}\pfill \usage{5} + \subitem {\ttfamily \%\$ \$\%}\pfill \usage{6} + \subitem {\ttfamily \%\% \%\%}\pfill \usage{6} + \subitem {\ttfamily lgrind}\pfill \main{13} + + \indexspace +{\bfseries\hfil F\hfil}\nopagebreak + + \item \verb*+\File+\pfill \main{58} + + \indexspace +{\bfseries\hfil H\hfil}\nopagebreak + + \item \verb*+\Head+\pfill \main{58} + + \indexspace +{\bfseries\hfil I\hfil}\nopagebreak + + \item \verb*+\ic@r+\pfill \main{106} + \item \verb*+\ifc@omment+\pfill \main{44} + \item \verb*+\ifLGd@fault+\pfill \main{40} + \item \verb*+\ifLGinline+\pfill \main{40} + \item \verb*+\ifLGnoprocindex+\pfill \main{27} + \item \verb*+\ifright@+\pfill \main{46} + \item \verb*+\ifstr@ng+\pfill \main{44} + + \indexspace +{\bfseries\hfil K\hfil}\nopagebreak + + \item \verb*+\K+\pfill \main{106} + \item \verb*+\KWfont+\pfill \main{30} + + \indexspace +{\bfseries\hfil L\hfil}\nopagebreak + + \item \verb*+\L+\pfill \main{70} + \item \verb*+\l@ftlno+\pfill \main{72} + \item \verb*+\lagrind+\pfill \usage{4}, \main{139} + \item \verb*+\LB+\pfill \main{97} + \item \verb*+\lc@unt+\pfill \main{2} + \item \verb*+\LGbegin+\pfill \main{40} + \item \verb*+\LGend+\pfill \main{40} + \item \verb*+\LGfsize+\pfill \main{30} + \item \verb*+\LGindent+\pfill \main{10} + \item \verb*+\LGleftnum+\pfill \main{8} + \item \verb*+\LGnorules+\pfill \main{13} + \item \verb*+\LGnuminterval+\pfill \main{2} + \item {\ttfamily lgrind} (environment)\pfill \main{56} + \item \verb*+\lgrindfile+\pfill \usage{4}, \main{189} + \item \verb*+\lgrindfilename+\pfill \main{52} + \item \verb*+\lgrindfilesize+\pfill \main{52} + \item \verb*+\lgrindhead+\pfill \main{52} + \item \verb*+\lgrindmodday+\pfill \main{52} + \item \verb*+\lgrindmodmonth+\pfill \main{52} + \item \verb*+\lgrindmodtime+\pfill \main{52} + \item \verb*+\lgrindmodyear+\pfill \main{52} + \item \verb*+\LGsize+\pfill \main{30} + \item \verb*+\LGsloppy+\pfill \main{15} + \item \verb*+\Line+\pfill \usage{5}, \main{57} + \item \verb*+\ln@xt+\pfill \main{2} + \item \verb*+\ls@far+\pfill \main{47} + + \indexspace +{\bfseries\hfil N\hfil}\nopagebreak + + \item \verb*+\N+\pfill \main{106} + \item \verb*+\NewPage+\pfill \main{69} + \item \verb*+\NOfont+\pfill \main{30} + + \indexspace +{\bfseries\hfil P\hfil}\nopagebreak + + \item \verb*+\PNsize+\pfill \main{30} + \item \verb*+\Proc+\pfill \main{18} + \item \verb*+\ProcCont+\pfill \main{18} + + \indexspace +{\bfseries\hfil R\hfil}\nopagebreak + + \item \verb*+\r@ghtlno+\pfill \main{72} + + \indexspace +{\bfseries\hfil S\hfil}\nopagebreak + + \item \verb*+\S+\pfill \main{106} + \item \verb*+\SE+\pfill \main{106} + \item \verb*+\STfont+\pfill \main{30} + + \indexspace +{\bfseries\hfil T\hfil}\nopagebreak + + \item \verb*+\Tab+\pfill \main{97} + \item \verb*+\tb@x+\pfill \main{47} + \item \verb*+\TBw@d+\pfill \main{47} + \item \verb*+\TTfont+\pfill \main{30} + + \indexspace +{\bfseries\hfil V\hfil}\nopagebreak + + \item \verb*+\V+\pfill \main{106} + \item \verb*+\VRfont+\pfill \main{30} + + \end{theindex} diff --git a/support/lgrind/lgrind.ins b/support/lgrind/lgrind.ins new file mode 100644 index 0000000000..fb78e75beb --- /dev/null +++ b/support/lgrind/lgrind.ins @@ -0,0 +1,27 @@ +%% +%% This file will generate fast loadable files and documentation +%% driver files from the doc files in this package when run through +%% LaTeX or TeX. +%% +\def\batchfile{lgrind.ins} +\input docstrip.tex +\preamble + +LGrind is used to format source code of different programming +languages for LaTeX. + +LGrind is a major adaptation of Jerry Leichter's tgrind for LaTeX, +which was a notable improvement upon Van Jacobsen's tgrind for +plain TeX, which was adapted from vgrind, a troff prettyprinter. + +LGrind contains non-free code written by Van Jacobson, who does not answer +to any request for changing his licence. This software is therefore not +maintained. I also do not accept any cheques anymore. +\endpreamble +\keepsilent + +\generateFile{lgrind.sty}{t}{% + \from{lgrind.dtx}{package}} + +\generateFile{doc-lgrind.lg}{t}{% + \from{lgrind.dtx}{example}} diff --git a/support/lgrind/lgrind.pdf b/support/lgrind/lgrind.pdf Binary files differnew file mode 100644 index 0000000000..4ad643093e --- /dev/null +++ b/support/lgrind/lgrind.pdf diff --git a/support/lgrind/lgrindef b/support/lgrind/lgrindef new file mode 100644 index 0000000000..c2311f8688 --- /dev/null +++ b/support/lgrind/lgrindef @@ -0,0 +1,850 @@ +# Database of program templates for lgrind +# $Id: lgrindef,v 1.7 2000/12/27 21:42:37 mike Exp $ + +Ada:\ + :pb=(^\d?procedure|function\d\p\d|\():\ + :np=;\d?$:id=_.:\ + :bb=\d(begin|case|do|if|loop|select)\d:be=\dend\d|;:\ + :rb=(\=|\:|\d|^)(protected|record):\ + :oc:\ + :cb=--:ce=$:ab=--:ae=$:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=":se=":lb=':le=':\ + :kw=abort abs accept access aliased all and array at begin body case\ + constant declare delay delta digits do else elsif end entry exception exit\ + for function generic goto if in is limited loop mod new not null of or\ + others out package pragma private procedure protected raise range record\ + rem renames requeue return reverse select separate subtype tagged task\ + terminate then type until use when while with xor: + +Asm:\ + :oc:\ + :cb=#:ce=$:ab=/*:ae=*/:\ + :sb=':se=':lb=":le=":\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=ascii block byte end equ globl text data word even long\ + #else #endif #if #ifdef #ifndef #include #undef #define else endif\ + if ifdef ifndef include undef define: + +Asm68:\ + :pb=(^\d?.proc\d\p\d:\ + :oc:\ + :cb=;:ce=$:\ + :sb=':se=':lb=":le=":\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=ascii block byte end equ include long proc word: + +# JL - Added QBASIC Aug 95 +BASIC:\ + :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:\ + :cb=':ce=$:sb=":se=":\ + :le=\e':tl:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw= ABS APPEND ABSOLUTE AS ACCESS ASC AND ATN ANY \ + BASE BLOAD BEEP BSAVE BINARY \ + CALL COLOR CALL ABSOLUTE COM CASE COMMON CDBL CONST\ + CHAIN COS CHDIR CSNG CHR$ CSRLIN CINT CVD CIRCLE CVDMBF\ + CLEAR CVI CLNG CVL CLOSE CVS CLS CVSMBF \ + DATA DEFLNG DEFSNG DATE$ DEFSTR DATE$ DIM DECLARE DO LOOP\ + DEF FNDOUBLE DEF SEG DRAW DEFDBL $DYNAMIC DEFINT \ + ELSE ERDEV ELSEIF ERDEV$ END ERL ENVIRON ERR ENVIRON$ \ + ERROR EOF EXIT EQV EXP ERASE \ + FIELD FOR NEXT FILEATTR FRE FILES FREEFILE FIX FUNCTION\ + GET GOSUB GET GOTO \ + HEX$ IF THEN ELSE INSTR IMP INT INKEY$ INTEGER \ + INP IOCTL INPUT IOCTL$ INPUT$ IS \ + KEY KILL KEY \ + LBOUND LOCK UNLOCK LCASE$ LOF LEFT$ LOG LEN LONG LET LOOP\ + LINE LPOS LINE INPUT LPRINT LIST LPRINT USING LOC LSET LOCATE LTRIM$\ + MID$ MKI$ MID$ MKL$ MKD$ MKS$ MKDIR MKSMBF$ MKDMBF$ MOD \ + NAME NOT NEXT \ + OCT$ ON TIMER OFF ON GOSUB ON COM ON GOTO ON ERROR OPEN \ + ON OPEN COM ON KEY OPTION BASE ON PEN OR ON PLAY OUT ON STRIG OUTPUT \ + PAINT POINT PALETTE POKE PCOPY POS PEEK PRESET PEN PRINT \ + PEN PRINT USING PLAY PSET PLAY PUT PLAY PUT PMAP \ + RANDOM RETURN RANDOMIZE RIGHT$ READ RMDIR REDIM RND REM RSET RESET \ + RTRIM$ RESTORE RUN RESUME \ + SCREEN SQR STATIC SEEK $STATIC SEEK STEP SELECT CASE STICK SGN STOP \ + SHARED STR$ SHELL STRIG SIN STRIG SINGLE STRING SLEEP STRING$ \ + SOUND SUB SPACE$ SWAP SPC SYSTEM \ + TAB TIMER TAN TO THEN TROFF TIME$ TRON TIME$ TYPE TIMER \ + UBOUND UNTIL UCASE$ USING UNLOCK \ + VAL VARSEG VARPTR VIEW VARPTR$ VIEW \ + WAIT WIDTH WEND WINDOW WHILE WEND WRITE \ + XOR : + +# DOS Batch file language description for the LGrind pretty-printer +# Jim Green <j.j.green@shef.ac.uk> 11/15/96 Notice that the tex block +# is a triple-precent rather than a double, and that `program text +# within a comment' also has an added percent (to avoid conflicts with +# environmental variables and `@echo off' statements respectively). +# This assumes that it is possible to write a batch file sufficiently +# complex to need such explanation. +Batch|bat:\ + :pb=^\d?\:\p\d?$:\ + :cb=rem :ce=$:\ + :sb=echo:se=$:\ + :zb=%@:ze=%@:tb=%%%:te=%%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=call do echo @echo exist for goto if in not pause rem shift: + +C:\ + :pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\ + :cb=/*:ce=*/:sb=":se=\e":lb=':le=\e':\ + :tl:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=asm auto break case cdecl char continue default do double else\ + enum extern far float for fortran goto huge if int interrupt long\ + near pascal register return short signed sizeof static struct\ + switch typedef union unsigned void while\ + #define #else #endif #if #ifdef #ifndef #include #undef # define\ + else endif if ifdef ifndef include undef #pragma #elif pragma elif\ + #module #dictionary module dictionary\ + variant_struct variant_union\ + noshare readonly globaldef globalref globalvalue main_program: +#Last couple of lines are partial ANSI, plus VAX-C specific + +C++|CC:\ + :pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\ + :cb=/*:ce=*/:ab=//:ae=$:sb=":se=\e":lb=':le=\e':\ + :tl:id=_~\::\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=and and_eq asm auto bitand bitor bool break case catch char class\ + compl const const_cast continue default delete do double dynamic_cast\ + else enum explicit export extern false float for friend goto if inline\ + int long mutable namespace new not not_eq operator or or_eq private\ + private\: protected protected\: public public\: register\ + reinterpret_cast return short signed sizeof static static_cast struct\ + switch template this throw true try typedef typeid typename union\ + unsigned using virtual void volatile wchar_t while xor xor_eq\ + static_cast const_cast dynamic_cast reinterpret_cast\ + #define #else #endif #if #ifdef #ifndef #include #undef #pragma #\ + define else endif if ifdef ifndef include undef defined: + +csh:\ + :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :le=\e':tl:\ + :kw=alias alloc break breaksw case cd chdir continue default\ + echo else end endif endsw exec exit foreach \ + glob goto history if logout nice nohup onintr repeat set\ + setenv shift source switch then time \ + while umask unalias unset wait while @ env \ + argv child home ignoreeof noclobber noglob \ + nomatch path prompt shell status verbose : + +FORTRAN|f77|f:\ + :pb=(function|subroutine|program)\d\p\d?\(\a?\):\ + :bb=(function|subroutine|program)\d\p\d?\(\a?\):be=^\dend\d:\ + :cb=^(c|C|*):ce=$:\ + :sb=':se=':\ + :oc:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=call character close common complex continue data dimension do\ + double else elseif end enddo endif entry equivalence format function\ + goto if implicit include integer logical open pause parameter print\ + precision program read real return stop subroutine then write\ + gt ge lt le eq ne and or not false true: +# The last should contain a lot more periods. But LGrind's parser doesn't like +# them. So you can't use 'gt' as identifier. (Who would want to, anyway?) + +Gnuplot:\ + :pb=\d?\p\(\a\)=:\ + :cb=#:ce=$:\ + :sb=("|'):se=("|'):\ + :zb=@:ze=@:\ + :tb=%%:te=%%::mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=cd clear exit load pause plot pwd quit replot save set showsplot\ + title using with: + +Icon:\ + :pb=^\d?procedure\d\p\d?\(\a?\):\ + :bb=(^\d?procedure\d\p\d?\(\a?\))|{:be=}|(^\d?end\d?$):\ + :cb=#:ce=$:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=":se=\e":lb=':le=\e':tl:\ + :kw=break by case create default do dynamic else end every external\ + fail global if initial local next not of procedure record\ + repeat return static suspend then to until using while\ + &ascii &clock &cset &date &dateline &errout &fail &host &input\ + &lcase &level &main &null &output &pos &random &source &subject\ + &time &trace &ucase &version: + +# Written by Diego Berrueta <diego@berrueta.net> +IDL:\ + :pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\ + :cb=/*:ce=*/:ab=//:ae=$:sb=":se=\e":lb=':le=\e':\ + :tl:id=_~\::\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=abstract any attribute boolean case char const context \ + custom default double exception enum factory FALSE fixed float \ + in inout interface local long module native Object\ + octet oneway out private public raises readonly sequence short \ + string struct supports switch TRUE truncatable typedef unsigned \ + union ValueBase valuetype void wchar wstring\ + #define #else #endif #if #ifdef #ifndef #include #undef #pragma #\ + define else endif if ifdef ifndef include undef defined: + +ISP:\ + :cb=!:ce=!|$:oc:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=and begin decode define end eql eqv geq gtr if leave leq lss mod\ + neq next not or otherwise repeat restart resume sr0 sr1 srd\ + srr sl0 sl1 sld slr tst xor: + +Java:\ + :pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\ + :cb=/*:ce=*/:ab=//:ae=$:sb=":se=\e":lb=':\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :le=\e':tl:id=_~\:\ + :kw=abstract boolean break byte byvalue case catch char class const\ + continue default do double else extends false final finally float for goto\ + if implements import instanceof int interface long native new null package\ + private protected public return short static super switch synchronized this\ + throw throws true try void volatile while: +# Somewhere these come from, but they are not in my Java book. +# :kw=cast future generic inner rest transient var: + + +Kimwitu++|kimw:\ + :pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\ + :cb=/*:ce=*/:ab=//:ae=$:sb=":se=\e":lb=':le=\e':\ + :tl:id=_~\::\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=and and_eq asm auto bitand bitor bool break case catch char class\ + compl const const_cast continue default delete do double dynamic_cast\ + else enum explicit export extern false float for foreach friend goto\ + if inline int long mutable namespace new not not_eq operator or or_eq\ + private private\: protected protected\: provided public public\:\ + register reinterpret_cast return rview short signed sizeof static\ + static_cast struct switch template this throw true try typedef typeid\ + typename union unsigned using uview virtual void volatile wchar_t\ + while with xor xor_eq\ + static_cast const_cast dynamic_cast reinterpret_cast\ + #define #else #endif #if #ifdef #ifndef #include #undef #pragma #\ + define else endif if ifdef ifndef include undef defined: + +# JL - Jan 96 Added LaTeX +# JL - May 96 LaTeX-2e additions +LaTeX:\ + :tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :cb=%:ce=$:kw=\ + abstract addcontentsline addtocontents addtocounter address addtolength \ + addvspace alph appendix arabic array article author begin bf bfseries \ + bibitem bigskip book \ + cdots center centering circle cite cleardoublepage clearpage \ + cline closing color colorbox dashbox date ddots definecolor description \ + displaymath document documentclass documentstyle dotfill em emph end \ + enumerate eqnarray equation fbox fcolorbox figure flushbottom flushleft \ + flushright fnsymbol footnote footnotemark footnotesize footnotetext frac \ + frame framebox hfill hline hhline hrulefill hspace huge Huge hyphenation \ + include includeonly indent input it itemize itshape kill label large \ + Large LARGE ldots letter line linebreak linethickness list location \ + makebox maketitle mark mbox mdseries medskip minipage multicols \ + multicolumn multiput newcommand newcounter newenvironment newfont \ + newlength newline newpage newsavebox newtheorem nocite noindent \ + nolinebreak normalfont normalsize nopagebreak onecolumn opening oval \ + overbrace overline pagebreak pagecolor pagenumbering pageref pagestyle \ + par parbox picture put quotation quote raggedbottom raggedleft \ + raggedright raisebox ref report resizebox rm rmfamily roman rotatebox \ + rule savebox sc scriptsize setcounter setlength settowidth scalebox \ + sf sffamily shortstack signature sl slshape small smallskip sqrt \ + tabbing table tabular telephone \ + textbf textit textmd textrm textsc textsf textsl texttt textup \ + thanks thebibliography theorem thispagestyle tiny title titlepage \ + tt ttfamily twocolumn typeout typein \ + underbrace underline upshape usebox usecounter usepackage \ + value vdots vector verb \ + verbatim verse vfill vline vspace : + +LDL:\ + :pb=^\p\::bb=\::be=;:cb=/*:ce=*/:sb=":se=\e":\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=constant functions grammar reswords tokens add1 addste\ + car cdr check colno cond cons copy defun divide empty enter\ + eq equal findattr firstchild ge getattr getfield gt hash label\ + lambda lastchild le leftsibling lookone lookup lt minus name ne\ + newnode nextcom nil null parent plus precnl prevcom prog progn\ + quote reglob return rightsibling self set setattr setfield setq\ + stjoin sub1 t times tnull tokno ttype: + +Lex:\ + :lb=[|':le=]|\e':tc=C++: + +#Linda is just like C, with a couple of extra keywords. Note: The non- +#blocking operations are included, as are the pre-defined VAX Linda-C macros. +Linda:\ + :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:\ + :cb=/*:ce=*/:sb=":se=\e":lb=':\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :le=\e':tl:\ + :kw=asm auto break case char continue default do double else enum\ + extern float for fortran goto if int long register return short\ + sizeof static struct switch typedef union unsigned void while #define\ + #else #endif #if #ifdef #ifndef #include #undef # define else endif\ + if ifdef ifndef include undef\ + #pragma #elif pragma elif #line\ + #module #dictionary module dictionary\ + variant_struct variant_union\ + noshare readonly globaldef globalref globalvalue main_program\ + in inp rd rdp out eval newtype varying nchar\ + $ARR $ARRAY $ARRAY_TYPE $MAKE_ARRAY\ + $STR $STRING $STRING_TYPE $SET_DIM $MAKE_STRING\ + #ttcontext ttcontext: + +make:\ + :cb=#:ce=$:\ + :sb=':se=':lb=":le=":\ + :id=-_:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=define endef ifeq ifneq else endif include override export unexport vpath\ + subst patsubst strip findstring filter filter-out sort dir notdir suffix basename\ + addsuffix addprefix join word words firstword wildcard shell origin foreach: + +# JL - 'masm' (Microsoft Assembler) by way of +# modification of 'asm' style provided above. +# The instructions are *not* defined as keywords here. +MASM:\ + :oc:\ + :cb=;:ce=$:ab=/*:ae=*/:\ + :sb=':se=':lb=":le=":\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=ascii block globl even long\ + 286 386 486 \ + code data dosseg end endp equ \ + huge large medium model proc small stack tiny title : + +# JL - Added MATLAB Jan 96 +# Note: the string delimiter ' is also used as a transpose operator +# causing the rest of the line to be interpreted as a string. +MATLAB:\ + :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:\ + :cb=%:ce=$:sb=':se='|$|;:\ + :le=\e':tl:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw= \ + abs acos acosh acot acoth acsc acsch \ + airfoil all andrew angle angle ans any arith \ + asec asech asin asinh atan atan2 atanh auread \ + auwrite axes axis balance bar bartlett bench bessel \ + bessela besselap besself besseli besselj besselk bessely beta \ + betacore betainc betaln bilinear blackman blanks blt bone \ + boxcar break brighten bucky buttap butter buttonv buttord \ + cart2pol cart2sph caxis cceps cd cdf2rdf cedit ceil \ + census censusex cheb1ap cheb1ord cheb2ap cheb2ord chebwin cheby1 \ + cheby2 choices choicex chol cinvert cla clabel clc \ + clear clf clg clock close cohere colmmd colon \ + colormap colormenu colperm colstyle comet comet3 compan compass \ + computer cond condest conj contour contour3 contourc contrast \ + conv conv conv2 conv2 convmtx cool copper corrcoef \ + corrcoef cos cosh cot coth cov cov cplxdemo \ + cplxgrid cplxmap cplxpair cplxpair cplxroot cputime cross csc \ + csch csd cumprod cumsum cylinder czt cztdemo d \ + datalist date dbclear dbcont dbdown dbquit dbstack dbstatus \ + dbstep dbstop dbtype dbup dc2sc dct deblank debug \ + dec2hex decimate deconv deconv del2 delete delsq delsqdemo \ + delsqshow demo demod det detrend dftmtx diag diary \ + diff dir diric disp dmperm dos drawnow earthex \ + earthmap echo eig eigmovie ellip ellipap ellipj ellipk \ + ellipke ellipord else elseif end eps erf erfc \ + erfcore erfcx erfinv error errorbar etime etree etreeplot \ + eval exist exp expm expm1 expm2 expm3 eye \ + fclose feather feof ferror feval fft fft fft2 \ + fft2 fftdemo fftfilt fftshift fftshift fftshift fgetl fgets \ + figtext figure fill fill3 filtdemo filter filter filter2 \ + filtfilt filtic find findstr finite fir1 fir2 firls \ + fitdemo fitfun fix flag fliplr flipud floor flops \ + fmin fmins fopen foptions for format fourier fplot \ + fplotdemo fprintf fread freqs freqspace freqz frewind fscanf \ + fseek ftell full function funm fwrite fzero gallery \ + gamma gammainc gammaln gca gcd gcf get getenv \ + getframe ginput global gplot gradient gray graymon grid \ + griddata grpdelay gtext hadamard hamming hankel hanning hardcopy \ + help hess hex2dec hex2num hidden highlight hilb hilbert \ + hint hist hold home hostid hot hsv hsv2rgb \ + humps i icubic idct ident if ifft ifft \ + ifft2 ifft2 iffuse imag image imagedemo imageext imagesc \ + impinvar impz imread imtext imwrite inf info input \ + inquire int2str interp interp1 interp1 interp2 interp3 interp4 \ + interp5 interpft intfilt intro inv inverf invfreqs invfreqz \ + invhilb isempty isglobal ishold isieee isinf isletter isnan \ + issparse isstr isunix j jet kaiser keyboard knot \ + kron lalala lasterr lcm legend length levinson life lifeloop \ + lin2mu line linspace load loadwave log log10 log2 \ + loglog logm logspace lookfor lorenz lorenzeq lotka lower \ + lp2bp lp2bs lp2hp lp2lp lpc ls lscov lu \ + magic man mathlist matlabro max mean medfilt1 median \ + membrane memory menu mesh meshc meshdom meshgrid meshz \ + meta min mkpp mmove2 moddemo modulate more movie \ + moviein mu2lin nalist nan nargchk nargin nargout nestdiss \ + nested newplot nextpow2 nnls nnz nonzeros norm normest \ + null num2str numgrid nzmax ode23 ode23p ode45 odedemo \ + ones orient orth pack paren pascal patch path \ + pause pcolor peaks penny pi pink pinv planerot \ + plot plot3 pol2cart polar poly poly2rc polyder polyfit \ + polyline polymark polystab polyval polyvalm pow2 ppval print \ + printopt prism prod prony psd punct puzzle pwd \ + qr qrdelete qrinsert quad quad8 quad8stp quaddemo quadstp \ + quake quit quiver qz rand randn randperm rank \ + rat rats rbbox rc2poly rceps rcond readme real \ + realmax realmin relop rem remez remezord resample reset \ + reshape resi2 residue residuez return rgb2hsv rgbplot rjr \ + roots rose rosser rot90 round rref rrefmovie rsf2csf \ + save savewave sawtooth saxis sc2dc schur script sec \ + sech semilogx semilogy sepdemo sepplot set setstr shading \ + shg showwind sig1help sig2help sigdemo1 sigdemo2 sign sin \ + sinc sinh size slash slice sort sos2ss sos2tf \ + sos2zp sound sounddemo soundext spalloc sparlist sparse sparsfun \ + sparsity spaugment spconvert spdiags specgram specials spectrum specular \ + speye spfun sph2cart sphere spinmap spiral spline spline \ + spline2d spones spparms sprandn sprandsym sprank sprintf spy \ + spypart sqdemo sqrt sqrtm square ss2sos ss2tf ss2zp \ + sscanf stairs std stem stem stmcb str2mat str2num \ + strcmp strings strips subplot subscribe subspace sum sunspots \ + superquad surf surface surfc surfl surfnorm svd swapprev \ + symbfact symmmd symrcm table1 table2 tan tanh tempdir \ + tempname terminal text tf2ss tf2zp tfe tffunc tic \ + title toc toeplitz trace trapz treelayout treeplot triang \ + tril triu type uicontrol uigetfile uimenu uiputfile uisetcolor \ + uisetfont unix unmesh unmkpp unwrap unwrap upper vander \ + vco ver version vibes view viewmtx waterfall what \ + whatsnew which while white whitebg who whos why \ + wilkinson xcorr xcorr2 xcov xlabel xor xyzchk ylabel \ + yulewalk zerodemo zeros zlabel zp2sos zp2ss zp2tf zplane : + +# Courtesy of Dominique de Waleffe (ddw@miscrit.be) +Mercury:\ + :bb=\:-:be=.:cb=%:ce=$:ab=/*:ae=*/:\ + :zb=@:ze=@:tb=%*%:te=%*%:mb=%*\$:me=\*$%:vb=%*\|:ve=\|*%:\ + :sb=":se=\e":lb=':le=\e':oc:\ + :kw=pred type module import_module mode \:\: -> --> ---> \:-\ + pragma func lambda det semidet multi cc_multi failure nondet\ + true fail is in out di uo ui interface implementation: + +# This entry makes use of new capabilities added to support the description +# of lisp-like languages (id, pl, and px). The set of keywords given is a +# matter of taste. It would be reasonable to add all the wired functions to +# the list. +MLisp|Emacs Mock Lisp:\ + :cb=;:ce=$:lb=':le=\e':sb=":se=\e":bb=\(:be=\):\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :id=_-$#@./,%&?!^*+~`|;<>'\::\ + :kw=defun if progn while:pl:px=\d\(defun:pb=^\d\(\p($|(\d\a$)): + +SML/NJ:ML:\ + :cb=\(\*:ce=\*\):\ + :pb=fun:\ + :id=_':\ + :lb=(#)":le=":sb=":se=\e":\ + :kw=fun let in end if then else andalso orelse and val fun structure\ + exception infix infixr nonfix type abstype datatype withtype with\ + local rec open use sig eqtype functor signature handle raise fn while\ + do case of as \:\: ... => -> |: + +# Scheme has a funky character quoting mechanism, 'a' in C is #\a in +# Scheme. Lgrind doesn't deal with this well. I tried a few different +# things, and decided the best option was to punt. +Scheme|scm:\ + :cb=;:ce=$:\ + :lb=(#):le=(\\):\ + :sb=":se=\e":\ + :id=_-$#@./,%&?!^*+~`|;<>'\::\ + :pb=\(define\d\(:\ + :kw=define lambda let: + +model:\ + :pb=^\d(space\d\p\drep)|(\p\dis|inline|public\dbeginproc):\ + :bb=\dbeginproc|space|case\d:be=\dendproc|end\d|;:\ + :cb=\$:ce=\$|$:sb=":se=":lb=':le=\a|$:\ + :kw=abs and array beginproc boolean by case cdnl char copied dispose\ + div do dynamic else elsif end endproc entry external FALSE false\ + fi file for formal fortran global if iff ift\ + in integer include inline is lbnd\ + max min mod new NIL nil noresult not notin od of or procedure public\ + read readln readonly record recursive rem rep repeat res\ + result return set\ + space string subscript such then TRUE true type ubnd union until\ + varies while width: + +Modula2|mod2|m2:\ + :pb=(^\d?(PROCEDURE|MODULE)\d\p\d|\(|;|\:)|(=|\:\d?RECORD\d):\ + :np=FORWARD:id=_.:\ + :bb=\d(BEGIN|CASE|FOR|IF|LOOP|WHILE|WITH|CLASS)\d:\ + :be=\dEND\d|;:\ + :cb=\(*:ce=*\):\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=":se=":lb=':le=':\ + :kw=AND ARRAY BEGIN BY CASE CONST\ + DEFINITION DIV DO ELSE ELSIF END EXIT EXPORT\ + FOR FROM IF IMPLEMENTATION IMPORT IN\ + LOOP MOD MODULE NOT OF OR POINTER PROCEDURE QUALIFIED\ + RECORD REPEAT RETURN SET THEN TO TYPE\ + UNTIL VAR WHILE WITH: + +# Of course this is not simple Pascal anymore. Borland set THE standard +# for a modern Pascal. Available as Delphi or Free Pascal. +Pascal|pas|p|bp:\ + :pb=(^\d?procedure|function|constructor|destructor\d\p\d|\(|;|\:):\ + :np=forward:id=_.:\ + :bb=\d(case|begin|asm)\d:be=\dend\d|;:\ + :rb=(\=|\:|\d|^)(record|object(\(\a\))?)(\d|$):\ + :oc:\ + :cb={:ce=}:ab=\(*:ae=*\):\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=':se=':\ + :kw=and asm array begin case const constructor destructor div do\ + downto else end end. exports file for function goto if implementation\ + in inherited inline interface label library mod nil not object of or\ + packed procedure program record repeat set shl shr then to type unit\ + until uses var while with xor\ + $ifdef $ifndef $ifopt $else $endif\ + absolute assembler export external far forward index interrupt\ + name near private public resident virtual\ + break continue exit halt: +# The last four are not keywords, but procedures, but they are far more than +# normal and deserve to be treated as if (at least by a pretty printer). +# The 14 modifiers in the last two lines but one also should be treated +# specially though they are not keywords. "string", on the other hand, IS +# a keyword, but since "integer", "boolean" etc. are not, along with any +# self defined type whatsoever, it is not in this list. + +#Perl definition; snarfed from the net +PERL|pl:\ + :pb=^\d?sub\d\p(\d|{):\ + :bb={:be=}:cb=\d#:ce=$:sb=":se=\e":lb=':le=\e':\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :tl:\ + :kw=if until while elsif else unless for foreach continue sub\ + accept and atan2 bind chdir chmod chop chown chroot close\ + closedir cmp connect cos crypt dbmclose dbmopen defined delete die\ + do dump each eof eq eval exec exit exp fcntl fileno flock fork\ + getc getlogin getpeername getpgrp getppid getpriority getpwnam\ + getgrnam gethostbyname getnetbyname getprotobyname getpwuid getgrgid\ + getservbyname gethostbyaddr getnetbyaddr getprotobynumber\ + getservbyport getpwent getgrent gethostent getnetent getprotoent\ + getservent gt setpwent setgrent sethostent setnetent setprotoent\ + setservent endpwent endgrent endhostent endnetent endprotoent\ + endservent ge getsockname getsockopt gmtime goto grep hex ioctl\ + index int join keys kill last le length link listen local localtime\ + log lstat lt m mkdir ne next not oct open opendir or ord pack pop print printf\ + push q qq rand read readdir readlink recv redo rename reset return\ + reverse rewinddir rindex rmdir s seek seekdir select setpgrp send\ + setpriority setsockopt shift shutdown sin sleep socket socketpair\ + sort split sprintf sqrt srand stat study substr syscall system\ + symlink tell telldir time times tr y umask undef unlink unpack\ + unshift utime values vec wait wantarray warn write x xor: + +PostScript|ps:\ + :oc:\ + :cb=%:ce=$:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=\(:se=\e\):\ + :kw=forall array null dict begin end def store string \ + exec if ifelse repeat for loop exit stop stopped quit \ + start save restore gsave grestore grestoreall definefont \ + newpath initgraphics erasepage showpage copypage initclip \ + clip eoclip fill eofill stroke image imagemask: + +PROLOG:\ + :bb=\:-:be=.$:cb=%:ce=$:ab=/*:ae=*/:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=":se=\e":lb=':le=\e':oc:\ + :kw=op mod abort ancestors arg ascii ask assert asserta assertz\ + atom atomic char clause close concat consult ed ef em eof fail\ + file findall write functor getc integer is length listing load name\ + nl nonvar not numbervars op or pp prin print private prompt putc\ + ratom read read_from_this_file rename repeat retract retractall\ + save see seeing seen sh skip statistics subgoal_of system tab\ + tell telling time told trace true unload untrace var write: + +Python|py:\ + :pb=^\d?(def|class)\d\p(\d|\\|\(|\:):\ + :cb=#:ce=$:sb=":se=\e":lb=':le=\e':\ + :kw=accept and break class continue def del elif else except\ + exec finally for from global if import in is lambda not or\ + pass print raise return try while: + +RATFOR:\ + :pb=^\d?program|subroutine|function|(integer|real|complex|character\dfunction)\d\p\d|\(:\ + :bb={:be=}:cb=#:ce=$:sb=":se=":lb=':le=':oc:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw= break call case character common complex data default define\ + dimension do else end equivalence external false for function go\ + goto if implicit include integer logical next pause program read\ + real repeat return rewind stop string subroutine switch true until\ + while write: + +# RLaB language description for the LGrind pretty-printer +# Jim Green <j.j.green@shef.ac.uk> 10/15/96 +RLaB:\ + :pb=^\d?\p\d?=\d?function\d?\(:\ + :bb={:be=}:\ + :cb=//:ce=$:\ + :sb=":se=":\ + :tl:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw= \ + abs acos all any asin asinh atan atan2 atanh autospec \ + avsmooth backsub balance bandred banner besselj bessely \ + bodetf break cd ceil center chol choose chop class clear \ + clearall close command command_ compan compleme complex \ + conditio conj continua continue corr cos cosh cross cumprod \ + cumsum czt det detrend diag diary diff disp division dlopen \ + dot eig epsilon erf error errors eval examples exist exp \ + expm eye factor faxis fft fftplot files filter find finite \ + fix fliplr flipud floor fmin for format fprintf fread frexp \ + fseek function funm fvscope gamma getb getenv getline \ + getplot global hankel help hess hex hilb hilbert house if \ + ifft imag in inf input int int2str intersec intro inv isempty \ + isinf isnan isreal issymm join jordan keywords lagrange \ + lcheck length lininsrt linspace lintrp list lmsale load \ + loaddir local log log10 log2 logb logm logspace lu lyap max \ + max2 maxi mdsmax mdsmooth mean median members min min2 mini \ + mod mret nan nextpow2 nmsmax norm num2str ode ode4 ode78 \ + ones open operator pascal pause pclose pend pinv plalt \ + plaspect plaxis plaz plclose plcont plegend plend plerry \ + plfont plgrid plgrid3 plhist plhistx plhold plhold_o plimits \ + plline plmesh plot plot3 plplot plpoint plprint plptex \ + plscol0 plsfile plstart plstyle pltitle plwid plwin poly \ + printf printmat prod pstart ptitle putenv pwin qq_norma qr \ + quadr rand rank rcond read readb readm real redit \ + relation rem replot require reshape return rfile rk4 rlab roots \ + rot90 round save scalars schord schur section set set3d show \ + show_pro showpwin sign sin sinh size sizeof solve sort \ + spectrog sprintf sqrt srand static std steng stmag string \ + strsplt strtod stzcr subplot sum surspl svd sylv symm system \ + tan tanh temp tempacosh tempangle tic tmpnam toc toeplitz \ + trace transpos trapz trig tril triu type union variable \ + vector while window write writeb writem xlabel \ + ylabel zeros zlabel: + +# It's not obvious what constitutes a "procedure definition" in Russell. +# This entry doesn't even try... +Russell:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :cb=\(*:ce=*\):kw=cand cor do od if fi else enum record prod union\ + extend export hide with constants let use in ni val var func type\ + field characters readonly:sb=":se=":lb=':le=': + +SAS:\ + :pb=(^\d?(data|start|%macro)\d\p\d|\(|;):\ + :cb=/*:ce=*/:\ + :ab=^\d?*:ae=;:\ + :sb=":se=":lb=':le=':\ + :oc:\ + :bb=\d(do|select)\d:\ + :be=\dend;:\ + :kw=proc data by cards do drop else end file filename format go if \ + input infile keep label length libname merge options output put \ + retain rename run then title to select set stop until update \ + when where while %include %macro %mend %do %end %if %then %let: + +SDL:\ + :cb=/*:ce=*/:\ + :ab=comment:ae=;:\ + :sb=":se=":lb=':le=':\ + :oc:\ + :kw=task else nextstate in out with from interface to via env and use fpar \ + process procedure block system service type endprocess endprocedure endblock \ + endsystem endservice package endpackage channel endchannel signalroute connect \ + synonym dcl signal gate timer signallist create output set reset call operators \ + literals all state endstate input start stop return none decision enddecision \ + join virtual redefined finalized adding inherits remote exported imported: + +sh:\ + :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :le=\e':tl:\ + :kw=break case cd continue do done \ + elif else esac eval exec exit export \ + fi for if in then while until \ + read readonly set shift test trap umask wait: + +SICStus:\ + :bb=\:-:be=.$:cb=%:ce=$:ab=/*:ae=*/:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=":se=\e":lb=':le=\e':\ + :kw=abolish abort absolute_file_name ancestors arg assert\ + asserta assertz at_end_of_stream at_end_of_line atom\ + atom_chars atomic bagof block break call callable call_residue\ + character_count clause close compare compile compound consult\ + copy_term current_atom current_host current_input current_input\ + current_key current_module current_op current_output\ + current_predicate current_stream debug debugging depth dif\ + display dynamic ensure_loaded erase error_exception expand_term\ + fail false fcompile fileerrors findall float flush_output\ + foreign foreign_file format freeze frozen functor\ + garbage_collect gc get get0 ground halt help if\ + incore initialization instance integer is keysort leash\ + length library_directory line_count line_position listing\ + load load_foreign_files maxdepth meta_predicate mod\ + module mode multifile name nl nodebug nofileerrors nogc nonvar\ + nospy nospyall notrace number number_chars numbervars\ + on_exception op open open_null_stream otherwise peek_char\ + phrase plsys portray portray_clause portray_message\ + predicate_property prepare_foreign_files print print_message\ + profile_data profile_reset prolog_flag prompt put public\ + raise_exception read read_term reconsult recorda recorded\ + recordz reinitialize repeat require restore retract retractall\ + save save_program see seeing seek seen set_input set_output\ + set_stream_position setarg setof simple skip skip_line socket\ + socket_accept socket_bind socket_connect socket_interrupt\ + socket_listen socket_select sort source_file spy spypoint\ + statistics stream_code stream_position subgoal_of subsumes_chk\ + tab tell telling term_expansion term_hash term_subsume time_out\ + told trace true ttyflush ttyget ttyget0 ttynl ttyput ttyskip\ + ttytab undo unix unknown unknown_predicate_handler use_module\ + user_help var version when write write_canonical write_term\ + writeq: + +src:\ + :kw=: + +# Very incomplete... +SQL:\ + :oc:ab=/*:ae=*/:\ + :sb=':se=':lb=":le=":\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw=select where from as group by order asc desc union insert values\ + delete into create table integer varchar primary key not null float\ + default: + +# A.Bednarz@kfa-juelich.de +# Received Jan 97 +Tcl/Tk|tcl|tk:\ + :bb={:be=}:cb=\d#:ce=$:sb=":se=\e":lb=':\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :le=\e':tl:pb=\d?proc\d\p\d{:id=-$_.,:\ + :kw=after append array auto_execok auto_load auto_mkindex \ +auto_reset bell bind bindtags break button canvas case catch cd \ +checkbutton clipboard close concat continue destroy entry eof error \ +eval exec exit expr file fileevent flush focus for foreach format \ +frame gets glob global grab history if image incr info join label \ +lappend lindex linsert list listbox llength lower lrange lreplace \ +lsearch lsort menu menubutton message open option pack pid place \ +proc puts pwd radiobutton raise read regexp regsub rename return \ +scale scan scrollbar seek selection send set source split string \ +subst switch tell text time tk tkButtonDown tkButtonEnter tkButtonInvoke \ +tkButtonLeave tkButtonUp tkCancelRepeat tkCheckRadioInvoke tkEntryAutoScan \ +tkEntryBackspace tkEntryButton1 tkEntryClipboardKeysyms tkEntryInsert \ +tkEntryKeySelect tkEntryMouseSelect tkEntrySeeInsert tkEntrySetCursor \ +tkEntryTranspose tkFirstMenu tkListboxAutoScan tkListboxBeginExtend \ +tkListboxBeginSelect tkListboxBeginToggle tkListboxCancel tkListboxDataExtend \ +tkListboxExtendUpDown tkListboxMotion tkListboxSelectAll tkListboxUpDown \ +tkMbButtonUp tkMbEnter tkMbLeave tkMbMotion tkMbPost tkMenuButtonDown \ +tkMenuEscape tkMenuFind tkMenuFindName tkMenuFirstEntry tkMenuInvoke \ +tkMenuLeave tkMenuLeftRight tkMenuMotion tkMenuNextEntry tkMenuUnpost \ +tkPostOverPoint tkSaveGrabInfo tkScaleActivate tkScaleButton2Down \ +tkScaleButtonDown tkScaleControlPress tkScaleDrag tkScaleEndDrag \ +tkScaleIncrement tkScreenChanged tkScrollButton2Down tkScrollButtonDown \ +tkScrollButtonUp tkScrollByPages tkScrollByUnits tkScrollDrag \ +tkScrollEndDrag tkScrollSelect tkScrollStartDrag tkScrollToPos \ +tkScrollTopBottom tkTextAutoScan tkTextButton1 tkTextClipboardKeysyms \ +tkTextInsert tkTextKeyExtend tkTextKeySelect tkTextNextPara tkTextPrevPara \ +tkTextResetAnchor tkTextScrollPages tkTextSelectTo tkTextSetCursor \ +tkTextTranspose tkTextUpDownLine tkTraverseToMenu tkTraverseWithinMenu \ +tk_popup tkwait toplevel trace unknown unset update uplevel upvar while winfo wm: + + +# JL - Added visbasic 6 Aug 1996. Note: this is not complete! +VisualBasic|vbasic:\ + :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:\ + :cb=':ce=$:sb=":se=":\ + :le=\e':tl:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :kw= Access And As Asc Boolean Byte Call Case Chr Close Currency Debug \ + Declare Dim Do Double Else ElseIf End Exit False For Format Function \ + Get If Input Integer Left Len Line Long Loop Lset Ltrim Mid Mod Next \ + Not Object On Open Or Output Print Private Pset Public Put Read Right \ + Rset Rtrim Select Single Static Str String Sub Then To Trim True Type \ + Until Val Variant Wend While : + +VMSasm:\ + :pb=^\d?.entry\d\p(\d|,|$|;):\ + :oc:\ + :cb=;:ce=$:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :sb=(.ident|.asci(x|c|d|i|z))\d:se=$:\ + :kw=.address .align .ascix .ascic .ascid .ascii .asciz \ + .blkx .byte .cross .debug .default .d_floating .double \ + .disable .enable .end .endc .endm .endr .entry .error \ + .even .external .f_floating .float .g_floating .ident .if \ + .if_x .iff .irp .irpc .library .link .list .long .macro \ + .mask .mcall .mdelete .mexit .narg .nchr .nlist .nocross \ + .noshow .ntype .octa .odd .opdef .packed .page .print \ + .psect .quad .refn .repeat .restore_psect .save_psect \ + .show .signed_byte .signed_word .subtitle .title .transfer \ + .warn .weak .word: + +yacc|y:\ + :zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\ + :cb=/*:ce=*/:sb=":se=\e":lb=':le=\e':tl:\ + :kw=%{ %} %% %union %token %type\ + #else #endif #if #ifdef #ifndef #include #undef #define else endif\ + if ifdef ifndef include undef: + + +EndOfLanguageDefinitions: +# +# The following entries are NOT language definitions, +# but configuration specifications for the LGrind program +# +BeginOfConfigurationItems: + +# a list of extensions and the language that belongs to them +# these can be wrong or too system specific +# recommendations appreciated +extensions:\ + :c=c:\ + :C=c++:cpp=c++:cc=c++:h=c++:\ + :pas=pascal:\ + :ads=ada:adb=ada:\ + :tcl=tcl/tk:\ + :y=yacc:\ + :tex=latex:\ + :java=java:\ + :mod=modula2:\ + :bas=visualbasic:\ + :ps=postscript:eps=postscript:pfa=postscript:\ + :pro=prolog:\ + :scm=scheme:\ + :m=matlab:\ + :ml=sml/nj:\ + :f=f77:F=f77:for=f77:\ + :l=lex:\ + :k=kimwitu++:\ + :py=python: + +# character substitution table +chartab:\ +:84="a:94="o:81="u:e1="s:8e="A:99="O:9a="U:e0=$\\alpha$: + +# preamble to put at the beginning of a stand-alone listing +firstpreamble:\ +\\documentclass[a4paper,twoside]{article}\n\ +\\usepackage[procnames,noindent]{lgrind}\n\ +\\usepackage{fancyhdr,a4wide}\n\ +\\usepackage{german}\n\ +\\usepackage{makeidx}\n\ +\\pagestyle{fancy}\n\n\ +\\makeindex\n\n\ +\\begin{document}\n + +# postamble to put at the very end of a stand-alone listing +postamble:\ +\\printindex\n\ +\\end{document} + +# preamble to put before each file in a stand-alone listing +filepreamble:\ +\\renewcommand{\\footrulewidth}{0.4pt}\n\ +\\fancyhead[C]{\\lgrindhead}\n\ +\\fancyhead[LO,RE]{\\lgrindfilesize~Bytes\\\\\\lgrindmodtime}\n\ +\\fancyhead[RO,LE]{\\bfseries \\lgrindfilename\\\\\ +\\lgrindmodday.\\lgrindmodmonth.\\lgrindmodyear}\n\ +\\fancyfoot[C]{\\bfseries\\thepage}\n\ +\\setlength{\\headheight}{24pt}\n + +# preferences for line numbering, changing fonts etc. +# (comes after "\begin{lgrind}") +configuration: + diff --git a/support/lgrind/source/.cvsignore b/support/lgrind/source/.cvsignore new file mode 100644 index 0000000000..7726bfbebb --- /dev/null +++ b/support/lgrind/source/.cvsignore @@ -0,0 +1,2 @@ +lgrind + diff --git a/support/lgrind/source/Makefile b/support/lgrind/source/Makefile new file mode 100644 index 0000000000..b785122aae --- /dev/null +++ b/support/lgrind/source/Makefile @@ -0,0 +1,39 @@ +# Makefile for lgrind, a LaTeX prettyprinter +# make binaries +# $Id: Makefile,v 1.4 1999/12/18 21:54:29 mike Exp $ + +BINDIR=$(BASEDIR)/bin +MANDIR=$(BASEDIR)/man + +CC=gcc +MANPAGES1=lgrind.1 +MANPAGES5=lgrindef.5 +OBJS=lgrind.o regexp.o retest.o lgrindef.o v2lg.o + +CFLAGS=-O2 +# CFLAGS=-Dpopen=fopen -Dpclose=fclose +# There are operating systems and compilers without these... + +.PHONY: all install clean distribution + +all: lgrind + +lgrind: lgrind.o lgrindef.o regexp.o + $(CC) $(CFLAGS) -o lgrind lgrind.o lgrindef.o regexp.o + +lgrind.o: lgrind.c lgutil.c + $(CC) $(CFLAGS) -DDEFSFILE=\"$(DEFSFILE)\" -DVERSION=\"$(VERSION)\" -c lgrind.c + +v2lg: v2lg.o + $(CC) $(CFLAGS) -o v2lg v2lg.o + +retest: retest.o regexp.o + $(CC) $(CFLAGS) -o retest retest.o regexp.o + +install: all + $(INSTALL) -s lgrind $(BINDIR)/lgrind + $(INSTALL) -m 644 $(MANPAGES1) $(MANDIR)/man1 + $(INSTALL) -m 644 $(MANPAGES5) $(MANDIR)/man5 + +clean: + rm -f $(OBJS) lgrind retest v2lg diff --git a/support/lgrind/source/README b/support/lgrind/source/README new file mode 100644 index 0000000000..6762cd342e --- /dev/null +++ b/support/lgrind/source/README @@ -0,0 +1,10 @@ +These sources should compile without any problems. + +The "access" function is declared in "io.h" or "unistd.h", depending on your +system. Replace "unistd" in "lgrind.c" with "io" if necessary. If your +compiler issues only a warning for missing prototypes you can delete the +#include completely. + + +The -d! option is tested and works well. It writes a patched version of the +executable, run it at your own risk. diff --git a/support/lgrind/source/lgrind.1 b/support/lgrind/source/lgrind.1 new file mode 100644 index 0000000000..8963aad647 --- /dev/null +++ b/support/lgrind/source/lgrind.1 @@ -0,0 +1,228 @@ +'\" t +.\" @(#)lgrind.1 3.62 25/05/99 MPi; from UCB 4.3 +.\" $Id: lgrind.1,v 1.5 2000/12/27 21:42:42 mike Exp $ +.\" This man page was reverse engineered by George V. Reilly from the +.\" preformatted man page written by Tuna Ertemalp for Jerry Leichter's +.\" version of tgrind. gvr remains wilfully ignorant of troff. +.dS C C\" \" Fixed-width font +.TH lgrind 1 "25 May 1999" "TeX/LaTeX" +.SH NAME +lgrind \- grind nice program listings using LaTeX +.SH NOTE +This man page is not yet much outdated, but might be soon except somebody +asks me to work on it. Consider the LaTeX docs the real docs. +.SH SYNOPSIS +\fBlgrind\fR [ \fB-e\fP ] [ \fB-i\fP ] [ \fB-\fP ] [ \fB-n\fP ] [ \fB-c\fP ] +[ \fB-t\fP \fI<width>\fP ] +[ \fB-h\fP \fI<header>\fP ] [ \fB-d\fP \fI<description file>\fP ] +[ \fB-l\fP\fI<language>\fP ] [ \fB-s\fP ] \fI<name>\fP ... +.PP +.SH DESCRIPTION +LGrind formats program sources in a nice style using LaTeX(1). +Comments are placed in roman, keywords in bold face, variables in +italics, and strings in typewriter font. Source file line numbers +appear in the right margin (every 10 lines). +.PP +LGrind processes its input file(s) and writes the result to standard +output. This output can be saved for later editting, inclusion in a +larger document, etc. +.PP +The options are: +.IP "\fB\-e\fP" +process a LaTeX file for embedded code. +.IP "\fB\-i\fP" +process source code file for inclusion in a LaTeX document. +.IP "\fB\-\fP" +take input from standard input. +.IP "\fB\-n\fP" +don't boldface keywords. +.IP "\fB\-c\fP" +don't treat @, etc. specially in comments. +.IP "\fB\-t\fP" +change tab width (default 8). +.IP "\fB\-h\fP" +specifies text to go into the header. +.IP "\fB\-d\fP" +specifies the language definitions file (default is +\fB/usr/lib/texmf/tex/latex/lgrind/lgrindef\fP). +.IP "\fB\-d!\fP" +same as above, but write patched executable. +.IP "\fB\-l\fP" +specifies the language to use. +.IP "\fB\-s\fP" +shows a list of currently known languages. +.PP +If LGrind is called without parameters, a help screen will be shown. +If neither \fB\-e\fP nor \fB\-i\fP are specified, a complete LaTeX +file is produced. When no language is specified, LGrind tries to find +out the language used itself; C is used when this fails. +.SH USAGE +For example, to include a C file named \fBfoo.c\fP +into your LaTeX document, first give the command: +.IP "\fC lgrind -i -lc foo.c > foo.tex\fP" +.PP +This will generate \fCfoo.tex\fP, which will have the +pretty-printed version of \fCfoo.c\fP with a lot of LaTeX commands. +.PP +Then include \fClgrind.sty\fP as you include any other style, +namely with the \fC\eusepackage{lgrind}\fP line at +the beginning of your LaTeX document. Having done this, +within the document you can include \fCfoo.tex\fP using one of the +following commands: +.PP +.IP "\fC\elgrindfile{foo.tex}\fP" +which will simply include the file at that point +of text, and will draw horizontal lines before and +after the listing. +.PP +.IP "\fC\elagrind[htbp]{foo.tex}{caption}{label}\fP" +which will put the listing also within a figure +environment, using the float options, caption and +label you gave. +.PP +To produce a standalone LaTeX file from, say, a Yacc file: +.IP "\fC lgrind -ly bary.y > bary.tex\fP" +This uses Piet van Oostrum's \fCfancyhdr.sty\fP to make the +headers and footers. +.PP +For a more detailed explanation of these commands, refer to +\fC/usr/TeX/texmf/doc/latex/lgrind.dvi\fP. +.PP +.SH "EMBEDDED PROGRAMS WITHIN A LaTeX FILE" +(From Jerry Leichter's notes.) +.PP +Within the text of your LaTeX file, you mark groups of lines as +either text- or display-style program code: +.PP +Text style: +.TS +l l. +.fT \*C + The expression + %( + a + 3 + %) + produces 10. +.fT +.TE +prints something like: "The expression \fIa\fP + 3 produces 10." +(with "a + 3" set as a program.) +.PP +The same effect can be achieved with inline @'s. +.TS +l l. +.fT \*C + The expression @a + 3@ produces 10. +.TE +.PP +Display style: +.TS +l l. +.fT \*C + The statement + %[ + a += 3; + %] + is an example of an incrementing operator. +.fT +.TE +prints something like: +.TS +l l. + The statement + a += 3; + is an example of an incrementing operator. +.TE +.PP +Important rules: +.IP +\fC%\fP and the following character must be the first two characters on +the line to be recognized. +.IP +Put \fInothing\fR on the line after the \fC%\fR and the key character. +If you do that, LGrind will provide a default environment that will +produce an \fC\ehbox\fP for \fC%(\fP \fC)%\fP, and a \fC\evbox\fP for +\fC%[\fP \fC-\fP \fC%]\fP. If you put stuff on the line, LGrind +assumes you want to control the format completely. Doing this +requires understanding \fIexactly\fP what the code LGrind produces is +doing. (Sometimes I'm not sure I do!) +.IP +\fC%)\fP and \fC%]\fP are, if I remember right, simply ignored outside +of a code group, but any extra \fC%(\fP or \fC%[\fP produces a +warning, so a missing \fC%)\fP or \fC%]\fP is usually caught. +.PP +You can insert your own code by using a line starting with \fC%=\fP in +the program text. Whatever you enter after that is left in the +output, exactly as you typed it. It will be executed in a strange +environment, so doing anything fancy is very tricky. A macro, \fC\eLine\fP, +is provided to help you do simple things. For example, +.TS +tab (/); +l. +.fT \*C +%[ +%=\eLine{________\evdots} + a = 1; +%] +.fT +.TE +produces: +.TS +tab (/); +l. +.fT \*C + \. + \. + \. + a = 1; +.fT +.TE +.PP +(Within the program text, \fC_\fP is active and expands to a +fixed-width space. A whole bunch of macros are also defined. If you +understand how LGrind sets lines up, you can replace the 8 \fC_\fP's +with a call to \fC\eTab\fP \(em but I'll let you hang yourself on that one.) +.PP +The output of LGrind always contains exactly one output line for each input +line. Hence, you can look up line numbers in TeX error messages in your +original file, rather than in the lgrind'ed (lground?) file. (Of course, if +the problem is in the LGrind output....) +.PP +Many things are controllable by re-defining various macros. You can +change what fonts LGrind will use for various kinds of things, how +much it indents the output, whether it adds line numbers, and if so at +what interval it prints them and whether it sticks them on the left or +right, and so on. This stuff is all described in \fClgrind.dvi\fP, +though probably not very well. The default settings produce output +that looks reasonable to me, though I can't say I'm ecstatic about it. +Doing a \fIreally\fP good job would require defining some special fonts. +.PP +.SH FILES +.IP "\fC/usr/bin/lgrind\fP" +Executable +.PP +.IP "\fC/usr/doc/lgrind/lgrind.dvi\fP" +Documentation +.PP +.IP "\fC/usr/lib/texmf/tex/latex/lgrind/lgrind.sty\fP" +LaTeX style file +.PP +.IP "\fC/usr/lib/texmf/tex/latex/lgrind/lgrindef\fP" +Language descriptions +.PP +.SH AUTHORS +Van Jacobson, Lawrence Berkeley Laboratory (based on +"vgrind" by Dave Presotto & William Joy of UC Berkeley), +wrote it for TeX. +.PP +Jerry Leichter of Yale University modified it for LaTeX. +.PP +George V. Reilly of Brown University changed the name to lgrind, +fixed up the man page, and added the program-text-within-comments +and @-within-LaTeX features. +.PP +Michael Piefel of Humboldt-University Berlin adapted it to +LaTeX2e and wrote decent documentation. +.PP +.SH "SEE ALSO" +\fBlatex\fR(1), \fBtex\fR(1), \fBvgrind\fR(1), \fBlgrindef\fR(5) diff --git a/support/lgrind/source/lgrind.c b/support/lgrind/source/lgrind.c new file mode 100644 index 0000000000..272bc164e0 --- /dev/null +++ b/support/lgrind/source/lgrind.c @@ -0,0 +1,1769 @@ +#ifndef lint +static char sccsid[] = "@(#)lgrind.c 3.66 (MPi) 5/10/99"; +static char rcsid[] = + "$Id: lgrind.c,v 1.14 2000/12/27 21:42:42 mike Exp $"; +#endif + +/* + * Copyright %%\copyright%% 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* lgrind --- general purpose "pretty printer" for use with %%\LaTeX%%. + * A %%\LaTeX%% version of tgrind, which is a %%\TeX%% version + * of vgrind. Used to "grind nice program listings." + * + * Copyright %%\copyright%% 1985 by Van Jacobson, Lawrence Berkeley Laboratory + * This program may be freely used and copied but %%{\bf may not be sold}%% + * without the author's %%{\bf written permission}%%. This notice must remain + * in any copy or derivative. + * + * This program is an adaptation of "vfontedpr" v4.2 (12/11/84) from + * the 4.2bsd Unix distribution. Vfontedpr was written by Dave + * Presotto (based on an earlier program of the same name written by + * Bill Joy). + * + * I would welcome comments, enhancements, bug fixes, etc. Please + * mail them to: + * van@@lbl-rtsg.arpa (from arpanet, milnet, csnet, etc.) + * ..!ucbvax!lbl-csam!van (from Usenet/UUCP) + */ + +/*%%\par{\bf Thank you very much, Van. Due to the ``may not be sold'' clause%%*/ +/*%%this program has become non-free. And since the author of this licence%%*/ +/*%%cannot be contacted (address too old, apparently newer ones exist, but%%*/ +/*%%no answers from them), this cannot be changed.}\par%%*/ + +/* Copyright %%\copyright%% 1995-99 by Michael Piefel + * + * Modifications. + * -------------- + * 10 Feb 85 Van Written. + * 29 Mar 85 Chris Torek (chris@@maryland): Bug fixes for %|~|% and + * %|^L|% output. Most cpu-time eaters recoded + * to improve efficiency. + * 30 Mar 85 Chris & Van Fixed %|\C|% & %|\S|% (comment & string start + * indicators to really appear at the start of + * comments & strings. Changes for speeded-up + * @expmatch()@. + * 8 Oct 87 JSL Modified so as to compile on VMS. %|-i|% option + * Jan 88 JSL %|-e|% option for embedded code. + * Sep 91 George V Reilly Reformated and cleaned up code, including + * naughtiness with @NULL@. Added %|@|%, + * %|%%|%, %|%$|%, and %%\tt \%|%% features. + * Also the %|%<|%, %|%!|%, and %|%#|% features. + * Oct 94 Matthias Eckermann (%|ud311aa@@sunmail.lrz-muenchen.de|%) + * fixed a little bug, added: Internal_Help, + * Sep 95 Michael Piefel Modified for %%\LaTeXe%% + * Feb 96 Michael Piefel Restructured into ANSI C + * May 99 Michael Piefel Made it Y2K compliant + * Oct 99 Michael Piefel Space runs make tabstops + * Dec 99 Michael Piefel Version option, space allowed after '-l' + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <malloc.h> +#include <time.h> +/* One of the following two (depending on your system) */ +#include <unistd.h> +/* #include <io.h> */ +#include "lgrindef.h" +#include "regexp.h" + +#ifndef vms +# include <sys/types.h> +# include <sys/stat.h> +#else +# include <types.h> +# include <stat.h> +#endif + +#define STANDARD 0 +#define ALTERNATE 1 + +#define NOTCODE 0 /* the three states of @incode@ */ +#define INITCODE 1 +#define OTHERCODE 2 + +#define PNAMELEN 80 /* length of a function/procedure name */ +#define PSMAX 20 /* size of procedure name stacking */ + +#ifndef vms +# define OKEXIT 0 +# define BADEXIT 1 +# ifndef DEFSFILE +# define DEFSFILE "/usr/lib/texmf/tex/latex/lgrind/lgrindef" +# endif +#else +# define OKEXIT 1 +# define BADEXIT 0 +# define DEFSFILE "TEX$INPUTS:lgrindef.src" +#endif + +#ifndef unix +# define HELPOPTION "-?" +#else +# define HELPOPTION "--help" +#endif + +typedef struct varsubst { + char *var; + char *subst; + struct varsubst *next; +} varsubst; + +varsubst *varsubstlist; + +/* forward declarations */ + +int getredirection(int argc, char **argv); +void setlang(); +void Internal_Help(); +void Internal_Help_Language_List(); +void readfile(FILE *); +void putScp(char *); +boolean putKcp(char *, char *, boolean); +void putVcp(char *, char *); +void putstr(char *); +boolean (*isproc)(char *); +boolean isprocNorm(char *); +boolean isprocC(char *); +void outchar(int); +void parsechartab(void); +varsubst *parsevartab(char *); +void parsepreamble(char *); +void setpreambles(void); +void printpreamble(char *); +void writeDefsfileInExe(char *, char *); +int substvarname(char **, int); + +/* + * The state variables + */ + +boolean incomm; /* in a comment of the primary type */ +boolean instr; /* in a string constant */ +boolean inchr; /* in a character constant */ +int incode; /* in program text within a comment */ +int latexcode; /* in program text within %%\LaTeX%% */ +int latex_tt; /* in %|\texttt|% text within %%\LaTeX%% */ +boolean use_tt; /* use %|\texttt|% everywhere */ +boolean do_at; /* pay attention to %|@|%s in %%\LaTeX%% */ +boolean do_tt; /* pay attention to %|||%s in %%\LaTeX%% */ +boolean nokeyw = FALSE; /* no keywords being flagged */ +boolean prccont; /* continue last procedure */ +boolean code_cmnts = TRUE; /* Treat %|@|%, etc specially in comments */ +boolean code_latex = TRUE; /* Treat %|@|%, etc specially in %%\LaTeX%% */ +int lastout; /* (extended) last character to outchar */ +int comtype; /* type of comment */ +int psptr; /* the stack index of the current procedure */ +char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */ +int plstack[PSMAX]; /* the procedure nesting level stack */ +int blklevel; /* current nesting level */ +int reclevel; /* current @record@ nesting level */ +int procedures_pending; /* proc starts w/o block starts */ +char fname[200]=""; /* File being read */ +int lineno; /* Line number in that file */ +int linenocode; /* Line number of the source code worked on */ +char pname[BUFFERSIZE+1]; /* Current procedure name */ + +/* + * The language specific globals + */ +char defsbuf[200]="DeFsBuF"DEFSFILE; +char *defsfile=&defsbuf[7]; /* name of language definitions file */ +char language[PNAMELEN]="mPi"; /* the language indicator */ +char the_buf[BUFFERSIZE+1]; /* general purpose buffer */ +char *buf = the_buf + 1; /* @buf-1@ must be valid */ +char *strings; /* store the keywords */ +char *defs; /* language definitions from lgrindef */ +char preamble[BUFFERSIZE/4]; /* first preamble */ +char postamble[BUFFERSIZE/4]; /* first preamble */ +char preamble2[BUFFERSIZE/4]; /* file preamble */ +char config[BUFFERSIZE/4]; /* redefinitions within lgrind-environment */ +char chartab[BUFFERSIZE/4]; /* buffer for chartab modifications */ +char *l_keywds[BUFFERSIZE/2]; /* keyword table address */ +char *l_prcbeg; /* regular expr for procedure begin */ +char *l_noproc; /* regexp for lines with NO procedure begin */ +char *l_combeg; /* regexp introducing a comment */ +char *l_comend; /* regexp ending a comment */ +char *l_acmbeg; /* regexp introducing a comment */ +char *l_acmend; /* regexp ending a comment */ +char *l_blkbeg; /* regexp beginning of a block */ +char *l_blkend; /* regexp ending a block */ +char *l_strbeg; /* regexp starting string constant */ +char *l_strend; /* regexp ending string constant */ +char *l_chrbeg; /* regexp starting character constant */ +char *l_chrend; /* regexp ending character constant */ +char *l_cdebeg; /* regexp starting prog text within comment */ +char s_cdebeg[BUFFERSIZE/8]; /* actual string corresponding to @l_cdebeg@ */ +char *l_cdeend; /* regexp ending prog text within comment */ +char *l_texbeg; /* regexp starting %%\TeX%% text in comment */ +char *l_texend; /* regexp ending %%\TeX%% text in comment */ +char *l_txmbeg; /* regexp starting %%\TeX%% math in comment */ +char *l_txmend; /* regexp ending %%\TeX%% math in comment */ +char *l_tt_beg; /* regexp starting verbatim text in comment */ +char *l_tt_end; /* regexp ending typewriter text in comment */ +char *l_at; /* regexp for %|@|% in %%\LaTeX%% text */ +char *l_tt; /* regexp for %|||% in %%\LaTeX%% text */ +char *l_pc; /* regexp for %|%|% in %%\LaTeX%% text */ +char *l_id; /* string containing valid identifier chars */ +char *l_record; /* start of lexical block outside functions */ +char l_escape; /* character used to escape characters */ +boolean l_toplex; /* procedures only defined at top lex level */ +boolean l_onecase; /* upper & lower case equivalent */ +boolean l_cfunctions; /* special for C function search */ +boolean embed = FALSE; /* -e seen --- do embedded code */ +boolean code = TRUE; /* Looking at code */ +int TabWidth = 8; /* Default width of a tab */ + +/* + * global variables also used by expmatch + */ + +extern boolean _escaped; /* if last character was an escape */ +extern char *_sstart; /* start of the current string */ + +extern int (*re_strncmp)(const char*, const char*, size_t); + /* function to do string compares */ + +int main(int argc, char **argv) +{ + struct stat stbuf; + boolean hseen = FALSE; /* -h seen */ + char *hstring=""; /* header string to use */ + char *programname; /* the zeroeth argument */ + boolean iseen = FALSE; /* -i seen */ + int files_done = 0; + + defs=(char*)malloc(2*BUFFERSIZE); + strings=(char*)malloc(2*BUFFERSIZE); + argc = getredirection(argc, argv); + + /* abuse of programname */ + programname=getenv("LGRINDEF"); + if (programname) strcpy(defsfile, programname); + + programname=argv[0]; + argc--, argv++; + + if (argc==0) { + Internal_Help(); + return OKEXIT; + } + + do { + struct tm modtime = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + if (argc > 0) { + /* Help-facility */ + if (!strcmp(argv[0], HELPOPTION)) { + Internal_Help(); + return OKEXIT; + } + + if (!strcmp(argv[0], "-s")) { + Internal_Help_Language_List(); + return OKEXIT; + } + + if (!strcmp(argv[0], "--version")) { + printf("LGrind %s\n", VERSION); + return OKEXIT; + } + + + /* Header */ + if (!strcmp(argv[0], "-h")) { + hseen = TRUE; + if (argc == 1) { + argc--; + goto rest; + } + hstring = argv[1]; + argc--, argv++; + argc--, argv++; + if (argc > 0) + continue; + goto rest; + } + + /* take input from the standard place */ + if (!strcmp(argv[0], "-")) { + argc = 0; + goto rest; + } + + /* put output to non-standard place */ + if (!strcmp(argv[0], "-o")) { + if (freopen(argv[1], "w", stdout) == NULL) { + perror(argv[1]); + return BADEXIT; + } + argc--, argv++; + argc--, argv++; + continue; + } + + /* Process embedded text */ + if (!strcmp(argv[0], "-e")) { + embed = TRUE; + argc--, argv++; + continue; + } + + /* format for inclusion */ + if (!strcmp(argv[0], "-i")) { + iseen = TRUE; + argc--, argv++; + continue; + } + + /* indicate no keywords */ + if (!strcmp(argv[0], "-n")) { + nokeyw++; + argc--, argv++; + continue; + } + + /* Don't treat %|@|%, etc. specially in comments */ + if (!strcmp(argv[0], "-c")) { + code_cmnts = FALSE; + argc--, argv++; + continue; + } + + /* Do treat %|@|%, etc. specially in comments */ + if (!strcmp(argv[0], "+c")) { + code_cmnts = TRUE; + argc--, argv++; + continue; + } + + /* Don't treat %|@|%, etc. specially in + * %%\LaTeX%% text (@embed@ only) */ + if (!strcmp(argv[0], "-a")) { + code_latex = FALSE; + argc--, argv++; + continue; + } + + /* Do treat %|@|%, etc. specially in + * %%\LaTeX%% text (@embed@ only) */ + if (!strcmp(argv[0], "+a")) { + code_latex = TRUE; + argc--, argv++; + continue; + } + + /* Use %|\texttt|% for all fonts */ + if (!strcmp(argv[0], "-t")) { + sscanf(argv[1], "%d", &TabWidth); + argc--, argv++; + argc--, argv++; + continue; + } + + /* specify the language */ + if (!strncmp(argv[0], "-l", 2)) { + if (strlen(argv[0])==2) { + strcpy(language, argv[1]); + argc--, argv++; + argc--, argv++; + } else { + strcpy(language, argv[0]+2); + argc--, argv++; + continue; + } + } + + /* specify the language description file for permanent use */ + if (!strcmp(argv[0], "-d!")) { + writeDefsfileInExe(programname, argv[1]); + return OKEXIT; + } + + /* specify the language description file */ + if (!strncmp(argv[0], "-d", 2)) { /* TODO strncmp? */ + strcpy(defsfile, argv[1]); + argc--, argv++; + argc--, argv++; + continue; + } + + /* specify the file containing variable substitutions */ + if (!strcmp(argv[0], "-v")) { + varsubstlist=parsevartab(argv[1]); + argc--, argv++; + argc--, argv++; + continue; + } + + /* open the file for input */ + if (freopen(argv[0], "r", stdin) == NULL) { + perror(argv[0]); + return BADEXIT; + } + + strcpy(fname, argv[0]); + argc--, argv++; + } + rest: + + lineno = 0; + setpreambles(); + + /* get config data from %|lgrindef|% */ + if (tgetent(buf, "firstpreamble", defsfile)>0) + parsepreamble(preamble); + + if (tgetent(buf, "postamble", defsfile)>0) + parsepreamble(postamble); + + if (tgetent(buf, "filepreamble", defsfile)>0) + parsepreamble(preamble2); + + if (tgetent(buf, "configuration", defsfile)>0) + parsepreamble(config); + + if (tgetent(buf, "chartab", defsfile)>0) + parsechartab(); + + if (iseen && embed) { + fprintf(stderr, "-i makes no sense with -e; -e ignored\n"); + embed = FALSE; + } + + if (!iseen && !embed) { + if (files_done == 0) printpreamble(preamble); + printpreamble(preamble2); + printf("\\begin{lgrind}\n"); + printpreamble(config); + /* In case \BGfont was modified in config */ + printf("\\BGfont\n"); + } + + + if (embed) + printf("%% This document was generated automagically by lgrind. DO NOT EDIT.\n\n"); + if (iseen) + { + printf("%% Remember to use the lgrind style\n\n"); + printf("\\Head{"); + if (hseen) putstr(hstring); + printf("}\n"); + } + + setlang(); + + /* initialize the program */ + + incomm = instr = inchr = _escaped = FALSE; + incode = latexcode = latex_tt = NOTCODE; + do_at = do_tt = code_latex; + blklevel = 0; + reclevel = 0; + for (psptr = 0; psptr < PSMAX; psptr++) { + pstack[psptr][0] = '\0'; + plstack[psptr] = 0; + } + psptr = -1; + if (*fname=='\0') { + time_t tm; + strcpy(fname, "stdin"); + stbuf.st_size=0; + tm=time(NULL); + modtime = *localtime(&tm); + } + else { + stat(fname, &stbuf); + modtime = *localtime(&stbuf.st_mtime); + } + + if (!embed) { + printf("\\File{"); + putstr(fname); + printf("}{%d}{%d}{%d}{%d:%02d}{%ld}\n", modtime.tm_year+1900, modtime.tm_mon+1, + modtime.tm_mday, modtime.tm_hour, modtime.tm_min, stbuf.st_size); + } + + code = FALSE; + readfile(stdin); + files_done++; + + if (!iseen && !embed) { + printf("\\end{lgrind}\n"); + } + + if (code) + fprintf(stderr, "Reached EOF within code in file %s\n", fname); + } while (argc > 0); + + if (!iseen && !embed) { + printpreamble(postamble); + } + return OKEXIT; +} + + +/* + * @readfile()@ --- read and process a file + */ +void readfile(FILE *fp) +{ + register char *cp; + boolean LGinline=FALSE; /* Doing %( -- %) */ + char term; /* ']' or ')' */ + char *atptr; /* start of %|@|% within %%\LaTeX%% text */ + char *atendptr; /* end of %|@|% within %%\LaTeX%% text */ + char *pcptr; /* start of %|%|% within %%\LaTeX%% text */ + char *pcendptr; /* end of %|%|% within %%\LaTeX%% text */ + char temp[BUFFERSIZE]; + char fnamebak[200]; + int linenobak; + + while (fgets(buf, BUFFERSIZE, fp) != NULL) { + cp = &buf[strlen(buf)-1]; + if (*cp != '\n') {*(++cp) = '\n'; *(++cp) = '\0'; } + lineno++; + cp = buf; + lastout = '\0'; + if (embed) { + if (!code) { + if (buf[0] == '%' && + (buf[1] == '[' || buf[1] == '(' + || buf[1] == '#' || buf[1] == '<' || buf[1] == '!' + || buf[1] == '@' || buf[1] == '|')) { + + for (cp = buf + 2; *cp == ' ' || *cp == '\t'; cp++) + ; + + /* Change the language */ + if (buf[1] == '#') { + if (*cp == '\n') + fprintf(stderr, "no language seen after %%# in file\ + %s at line %d\n", fname, lineno); + else { + cp[strlen(cp) - 1] = '\0'; /* nuke the @'\n'@ */ + while ((*cp==' ') || (*cp=='\t')) cp++; + strcpy(language, cp); + printf("%% switching to %s\n", language); + setlang(); + } + continue; + } + + /* Turn %|@|% or %|||% processing within %%\LaTeX%% + * text on or off. */ + + if (buf[1] == '@' || buf[1] == '|') { + if (*cp == '\n') + fprintf(stderr, "no setting seen after %%%c in file\ + %s at line %d\n", buf[1], fname, lineno); + else { + int flag = (*cp == '1' || *cp == '+'); + if (buf[1] == '@') + do_at = flag; + else + do_tt = flag; + } + continue; + } + + code = TRUE; + + /* take input from another file or from a shell command */ + if (buf[1] == '<' || buf[1] == '!') { + FILE *fp; + char source = buf[1]; + + cp[strlen(cp) - 1] = '\0'; /* nuke the @'\n'@ */ + if (source == '<') + fp = fopen(cp, "r"); + else /* @source == '!'@ */ + fp = popen(cp, "r"); + + if (fp == NULL) { + sprintf(temp, "%%%c on `%s' failed", source, cp); + perror(temp); + } else { + strcpy(temp, cp); + printf("%% start of `%s'\n", temp); + /* printf("\\LGinlinefalse\\LGbegin\\lgrinde\n"); */ + /* the above was not %%all%% incorrect ... */ + printf("\\LGinlinefalse"); + printf("\\begin{lgrind}\n"); + printpreamble(config); + /* In case \BGfont was modified in config */ + printf("\\BGfont\n"); + embed = FALSE; + linenobak=lineno; strcpy(fnamebak, fname); + lineno=0; strcpy(fname, temp); + linenocode=0; + readfile(fp); + lineno=linenobak; strcpy(fname, fnamebak); + embed = TRUE; + printf("\\end{lgrind}\n"); + printf("%% end of `%s'\n", temp); + if (source == '<') + fclose(fp); + else + pclose(fp); + } + code = FALSE; + continue; + } + + /* embedded inline or displayed code */ + linenocode=0; + if (buf[1] == '(') { + LGinline = TRUE; + term = ')'; + printf("\\LGinlinetrue"); + } else { /* @buf[1] == '['@ */ + LGinline = FALSE; + term = ']'; + printf("\\LGinlinefalse"); + } + if (buf[2] == '\n') { + printf("\\LGbegin\\lgrinde\n"); + } else { + buf[strlen(buf)-1] = '\0'; + printf("%s\\lgrinde\n", &buf[2]); + } + continue; + + } /* @if (buf[0] == '%'@%%\dots%% (special comment) */ + else + { + while (do_at && (atendptr = expmatch(cp, l_at, &atptr, (char *) NULL)) != NULL + && ( (pcendptr = expmatch(cp, l_pc, &pcptr, (char *) NULL)) == NULL + || atptr < pcptr ) ) + { + putVcp(cp, atptr-1); + printf("\\LGinlinetrue\\LGbegin\\lgrinde"); + cp = atendptr; + atendptr = expmatch(cp, l_at, &atptr, (char *) NULL); + /* No %|@|%: implicit %|@|% just before NL */ + if (atptr == NULL) + atptr = atendptr = cp + strlen(cp) - 1; + strncpy(temp, cp, (size_t)(atptr-cp)); + temp[(int)(atptr-cp)] = '\0'; + cp = atendptr; + linenocode++; + putScp(temp); + printf("}}\\egroup\\endlgrinde\\LGend{}"); + } + fputs(cp, stdout); + continue; + } + } /* @if (!code)@ */ + + /* + * We're in embedded code. + */ + if (buf[0] == '%') { + if (buf[1] == '*') { + if (term != ']') + fprintf(stderr, "%%* only makes sense in display mode\ + in file %s at line %d\n", fname, lineno); + else { + printf("\\endlgrinde\\LGend\n"); + printf("\\LGinlinefalse\\LGbegin\\lgrinde[%d]\n", linenocode+1); + } + continue; + } else if (buf[1] == term) { + if (term == ')') printf("\\egroup"); + if (buf[2] == '\n') + printf("\\endlgrinde\\LGend\n"); + else + printf("\\endlgrinde%s", &buf[2]); + code = FALSE; + continue; + } else if (buf[1] == '=') { /* Send literal */ + fputs(&buf[2], stdout); + continue; + } else if (buf[1] == '[' || buf[1] == '(' + || buf[1] == ']' || buf[1] == ')') { + fprintf(stderr, + "Possible nested embedded code in file %s at line %d\n", + fname, lineno); + } + } + + /* + * Inline code --- suppress leading whitespace + */ + if (LGinline) { + while (isspace(*cp)) + cp++; + } + } /* @if (embed)@ */ + + if (*cp == '\f') { + printf("\\NewPage\n"); + cp++; + if (*cp == '\n') /* some people like ^Ls on their own line */ + continue; + } + prccont = FALSE; + linenocode++; + putScp(cp); + if (!embed && prccont && (psptr >= 0)) { + printf("\\ProcCont{"); + putstr(pstack[psptr]); + printf("}"); + } +#ifdef DEBUG + printf("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr); +#endif + } /* @while fgets()@ */ +} + + + +/* + * Set all of the language-dependent variables + */ +void setlang(void) +{ + char *p, *cp; + int i; + + /* + * get the language definition from the defs file + */ + if (strcmp(language, "mPi") == 0) /* none yet defined */ + { + i = tgetent(defs, "extensions", defsfile); + if (i == 0) strcpy(language, "c"); + else + { + cp = strrchr(fname, '.'); + if (cp !=NULL) + { + p=buf; cp = tgetstr(cp+1, &p); + } + if (cp != NULL) strcpy(language, cp); + else strcpy(language, "c"); + } + } + i = tgetent(defs, language, defsfile); + if (i == 0) { + fprintf(stderr, "no entry for language %s\n", language); + exit(BADEXIT); + } else if (i < 0) { + fprintf(stderr, "cannot find lgrindef file `%s'\n", defsfile); + exit(BADEXIT); + } + + p = strings; + if (tgetstr("kw", &p) == NULL) + nokeyw = TRUE; + else { + char **cpp; + + cpp = l_keywds; + cp = strings; + while (*cp) { + while (*cp == ' ' || *cp =='\t') + *cp++ = '\0'; + if (*cp) + *cpp++ = cp; + while (*cp != ' ' && *cp != '\t' && *cp) + cp++; + } + *cpp = NULL; + } + + p = buf; l_prcbeg = convexp(tgetstr("pb", &p)); + p = buf; l_noproc = convexp(tgetstr("np", &p)); + p = buf; l_combeg = convexp(tgetstr("cb", &p)); + p = buf; l_comend = convexp(tgetstr("ce", &p)); + p = buf; l_acmbeg = convexp(tgetstr("ab", &p)); + p = buf; l_acmend = convexp(tgetstr("ae", &p)); + p = buf; l_strbeg = convexp(tgetstr("sb", &p)); + p = buf; l_strend = convexp(tgetstr("se", &p)); + p = buf; l_blkbeg = convexp(tgetstr("bb", &p)); + p = buf; l_blkend = convexp(tgetstr("be", &p)); + p = buf; l_chrbeg = convexp(tgetstr("lb", &p)); + p = buf; l_chrend = convexp(tgetstr("le", &p)); + p = s_cdebeg; l_cdebeg = convexp(tgetstr("zb", &p)); + p = buf; l_cdeend = convexp(tgetstr("ze", &p)); + p = buf; l_texbeg = convexp(tgetstr("tb", &p)); + p = buf; l_texend = convexp(tgetstr("te", &p)); + p = buf; l_txmbeg = convexp(tgetstr("mb", &p)); + p = buf; l_txmend = convexp(tgetstr("me", &p)); + p = buf; l_tt_beg = convexp(tgetstr("vb", &p)); + p = buf; l_tt_end = convexp(tgetstr("ve", &p)); + p = buf; l_record = convexp(tgetstr("rb", &p)); + p = buf; cp = tgetstr("id", &p) ; + if (cp) + { + l_id = (char*)malloc(strlen(cp)); + strcpy(l_id, cp); + } + else l_id = "_"; + + l_tt = convexp("\\|"); + l_at = convexp("@"); + l_pc = convexp("%"); + + l_escape = '\\'; + l_cfunctions = tgetflag("cf"); + isproc = l_cfunctions ? isprocC : isprocNorm; + + l_onecase = tgetflag("oc"); + re_strncmp = l_onecase ? lc_strncmp : strncmp; + l_toplex = tgetflag("tl"); +} + + +/* + * Write out a line of TeX in comment verbatim + */ +void putVtc(char *stringstart, char *comacmptr) +{ + char *texptr, *texendptr; + char texline[BUFFERSIZE/8]; + texendptr = expmatch(stringstart, l_texend, &texptr, (char *) NULL); + if (texendptr == comacmptr) + { + strncpy(texline, stringstart, texptr-stringstart); + texline[texptr-stringstart]='\0'; + printf("%s\n", texline); + } +} + + +/* + * Write out a formatted line of program text + */ +void putScp(char *os) +{ + register char *s = os; /* pointer to unmatched string */ + register char *s1; /* temp. string */ + char *comptr; /* start of a comment delimiter */ + char *comendptr; /* end of a comment delimiter */ + char *acmptr; /* start of an alt. comment delimiter */ + char *acmendptr; /* end of an alt. comment delimiter */ + char *strptr; /* start of a string delimiter */ + char *strendptr; /* end of a string delimiter */ + char *chrptr; /* start of a char. const delimiter */ + char *chrendptr; /* end of a char. const delimiter */ + char *cdeptr; /* start of prog text delim within a comment */ + char *cdeendptr; /* end of prog text delim within a comment */ + char *cdbptr; /* start of prog text delim within a comment */ + char *cdbendptr; /* end of prog text delim within a comment */ + char *texptr; /* start of %%\TeX%% text delim within a comment */ + char *texendptr; /* end of %%\TeX%% text delim within a comment */ + char *txmptr; /* start of %%\TeX%% math delim within a comment */ + char *txmendptr; /* end of %%\TeX%% math delim within a comment */ + char *tt_ptr; /* start of typewriter delim within a comment */ + char *tt_endptr; /* end of typewriter delim within a comment */ + char *blksptr; /* start of a lexical block start */ + char *blksendptr; /* end of a lexical block start */ + char *recsptr; /* start of a lexical block outside functions start */ + char *recsendptr; /* end of a lexical block outside functions start */ + char *blkeptr; /* start of a lexical block end */ + char *blkeendptr; /* end of a lexical block end */ + + _sstart = os; /* remember the start for @expmatch()@ */ + _escaped = FALSE; + if (nokeyw || incomm || instr) + goto skip; + + /* check for complete comment TeX line */ + comendptr = expmatch(s, l_combeg, &comptr, (char *) NULL); + acmendptr = expmatch(s, l_acmbeg, &acmptr, (char *) NULL); + texendptr = expmatch(s, l_texbeg, &texptr, (char *) NULL); + if (texptr && comptr == s) + if (texptr == comendptr) + { + comendptr = expmatch(comendptr, l_comend, &comptr, (char *) NULL); + if (*comendptr=='\n') + { + putVtc(texendptr, comptr); + return; + } + } else if (texptr == acmendptr) + { + acmendptr = expmatch(acmendptr, l_acmend, &acmptr, (char *) NULL); + if (*acmendptr=='\n') + { + putVtc(texendptr, acmptr); + return; + } + } + + if ((*isproc)(s) && reclevel == 0) { + printf("\\index{"); putstr(pname); printf("}"); + printf("\\Proc{"); + if (strlen(pname)>30) + { + s1=pname+strlen(pname)-1; + while (s1>pname && (isalnum(*s1) || *s1=='_')) s1--; + if (s1!=pname) strcpy(pname, s1+1); + } + if (strlen(pname)>32) { + strcpy(pname, pname+strlen(pname)-28); + printf("\\dots "); } + putstr(pname); + printf("}"); + if (!embed && psptr < PSMAX-1) { + ++psptr; + strncpy(pstack[psptr], pname, PNAMELEN); + pstack[psptr][PNAMELEN] = '\0'; + plstack[psptr] = blklevel-1; + } + } + + skip: + printf("\\L{\\LB{"); + + do { + /* check for string, comment, blockstart, etc */ + if (!incomm && !instr && !inchr) { + + blkeendptr = expmatch(s, l_blkend, &blkeptr, (char *) NULL); + blksendptr = expmatch(s, l_blkbeg, &blksptr, (char *) NULL); + recsendptr = expmatch(s, l_record, &recsptr, (char *) NULL); + comendptr = expmatch(s, l_combeg, &comptr, (char *) NULL); + acmendptr = expmatch(s, l_acmbeg, &acmptr, (char *) NULL); + strendptr = expmatch(s, l_strbeg, &strptr, (char *) NULL); + chrendptr = expmatch(s, l_chrbeg, &chrptr, (char *) NULL); + + /* check for end of program text in comment */ + if (incode != NOTCODE) { + cdeendptr = expmatch(s, l_cdeend, &cdeptr, (char *) NULL); + + if ((cdeptr == NULL && (comptr != NULL || acmptr != NULL)) + || (cdeptr != NULL + && ((comptr != NULL && comptr < cdeptr) + || ((acmptr != NULL && acmptr < cdeptr))))) { + fprintf(stderr, "Comments may not be nested within\ + program text within comments in file %s at\ + line %d\n", fname, lineno); + s = (comptr != NULL) ? comptr : acmptr; + incode = NOTCODE; + continue; + } + + /* look to see if there's a \<zb> in the program text */ + cdbendptr = expmatch(s, l_cdebeg, &cdbptr, (char *) NULL); + if (cdeptr != NULL + && (strptr == NULL || cdbptr < strptr) + && (chrptr == NULL || cdbptr < chrptr) + && (blksptr == NULL || cdbptr < blksptr) + && (recsptr == NULL || cdbptr < recsptr) + && (blkeptr == NULL || cdbptr < blkeptr)) { + if (cdbptr > s && cdbptr[-1] == l_escape) { + putKcp(s, cdbptr-2, FALSE); + printf("\\C{}"); + putKcp(s_cdebeg, s_cdebeg + strlen(s_cdebeg) - 1, TRUE); + printf("\\CE{}"); + s = cdbendptr; + incode = OTHERCODE; + continue; + } + } + + comendptr = + expmatch(s, (comtype == STANDARD) ? l_comend : l_acmend, + &comptr, (char *) NULL); + + if ((cdeptr == NULL && comptr != NULL) + || (cdeptr != NULL && (comptr != NULL && comptr < cdeptr))) { + fprintf(stderr, "Unterminated program text within comment\ + in file %s at line %d\n", fname, lineno); + printf("\\C{}"); + s = comptr; + incode = NOTCODE; incomm = TRUE; + continue; + } + + + if (cdeendptr != NULL) { + if ((strptr == NULL || cdeptr < strptr) + && (chrptr == NULL || cdeptr < chrptr) + && (blksptr == NULL || cdeptr < blksptr) + && (recsptr == NULL || cdeptr < recsptr) + && (blkeptr == NULL || cdeptr < blkeptr)) { + if (incode == INITCODE && cdeptr == s) { + printf("\\C{}"); + putKcp(s_cdebeg, s_cdebeg + strlen(s_cdebeg) - 1, TRUE); + } else { + putKcp(s, cdeptr-1, FALSE); + printf("\\C{}"); + } + s = cdeendptr; + incode = NOTCODE; incomm = TRUE; + continue; + } + } else if (strptr == NULL && chrptr == NULL + && blksptr == NULL && recsptr == NULL + && blkeptr == NULL) { + cdeptr = s; + s += strlen(s); + putKcp(cdeptr, s-1, FALSE); + incode = OTHERCODE; + continue; + } /* else there is a string/char/block on this line */ + + incode = OTHERCODE; + } /* @if (incode)@ */ + + + /* start of a comment? */ + if (comptr != NULL + && (strptr == NULL || comptr < strptr) + && (acmptr == NULL || comptr < acmptr) + && (chrptr == NULL || comptr < chrptr) + && (blksptr == NULL || comptr < blksptr) + && (recsptr == NULL || comptr < recsptr) + && (blkeptr == NULL || comptr < blkeptr)) { + putKcp(s, comptr-1, FALSE); + printf("\\C{}"); + s = comendptr; + putKcp(comptr, comendptr-1, TRUE); + incomm = TRUE; + comtype = STANDARD; + continue; + } + + /* start of an alternate-form comment? */ + if (acmptr != NULL + && (strptr == NULL || acmptr < strptr) + && (chrptr == NULL || acmptr < chrptr) + && (blksptr == NULL || acmptr < blksptr) + && (recsptr == NULL || acmptr < recsptr) + && (blkeptr == NULL || acmptr < blkeptr)) { + putKcp(s, acmptr-1, FALSE); + printf("\\C{}"); + s = acmendptr; + putKcp(acmptr, acmendptr-1, TRUE); + incomm = TRUE; + comtype = ALTERNATE; + continue; + } + + /* start of a string? */ + if (strptr != NULL + && (chrptr == NULL || strptr < chrptr) + && (blksptr == NULL || strptr < blksptr) + && (recsptr == NULL || strptr < recsptr) + && (blkeptr == NULL || strptr < blkeptr)) { + putKcp(s, strptr-1, FALSE); + printf("\\S{}"); + s = strendptr; + putKcp(strptr, strendptr-1, FALSE); + instr = TRUE; + continue; + } + + /* start of a character string? */ + if (chrptr != NULL + && (blksptr == NULL || chrptr < blksptr) + && (recsptr == NULL || chrptr < recsptr) + && (blkeptr == NULL || chrptr < blkeptr)) { + putKcp(s, chrptr-1, FALSE); + printf("\\S{}"); + s = chrendptr; + putKcp(chrptr, chrendptr-1, FALSE); + inchr = TRUE; + continue; + } + + /* end of a lexical block */ + if (blkeptr != NULL) { + if ((blksptr == NULL || blkeptr < blksptr) && + (recsptr == NULL || blkeptr < recsptr)) { + putKcp(s, blkeendptr - 1, FALSE); + s = blkeendptr; + if (blklevel) blklevel--; + if (reclevel) reclevel--; + else if (psptr >= 0 && plstack[psptr] >= blklevel) { + + /* end of current procedure */ + blklevel = plstack[psptr]; + + /* see if we should print the last proc name */ + if (--psptr >= 0) + prccont = TRUE; + else + psptr = -1; + } + continue; + } + } + + /* start of a lexical block */ + if (blksptr != NULL) { + putKcp(s, blksendptr - 1, FALSE); + s = blksendptr; + if (procedures_pending) + procedures_pending--; + else + /* when C functions then not on top level */ + if (!l_cfunctions || blklevel) + blklevel++; + continue; + } + + /* start of a lexical block outside functions */ + if (recsptr != NULL) { + putKcp(s, recsendptr - 1, FALSE); + s = recsendptr; + if (procedures_pending) + procedures_pending--; + else + blklevel++; + reclevel++; + continue; + } + + /* check for end of comment */ + } else if (incomm) { + + cdeendptr = expmatch(s, l_cdebeg, &cdeptr, (char *) NULL); + texendptr = expmatch(s, l_texbeg, &texptr, (char *) NULL); + txmendptr = expmatch(s, l_txmbeg, &txmptr, (char *) NULL); + tt_endptr = expmatch(s, l_tt_beg, &tt_ptr, (char *) NULL); + + if (code_cmnts) { + + /* Check for program text within comment */ + if (cdeptr != NULL + && (texptr == NULL || cdeptr < texptr) + && (tt_ptr == NULL || cdeptr < tt_ptr) + && (txmptr == NULL || cdeptr < txmptr)) { + putKcp(s, cdeptr-1, TRUE); + printf("\\CE{}"); + s = cdeendptr; + incode = INITCODE; incomm = FALSE; + continue; + } + + /* Check for %%\TeX%% text within comment */ + if (texptr != NULL + && (tt_ptr == NULL || texptr < tt_ptr) + && (txmptr == NULL || texptr < txmptr)) { + putKcp(s, texptr-1, TRUE); + s = texendptr; + if ((texendptr = + expmatch(s, l_texend, &texptr, (char *) NULL)) != NULL) { + putchar('{'); putVcp(s, texptr-1); putchar('}'); + s = texendptr; + } else { + fprintf(stderr, "LaTeX text within a comment must all be\ + on one line (file %s at line %d)\n", fname, lineno); + s += strlen(s); + } + continue; + } + + /* Check for typewriter text within comment */ + if (tt_ptr != NULL + && (txmptr == NULL || tt_ptr < txmptr)) { + putKcp(s, tt_ptr-1, TRUE); + s = tt_endptr; + if ((tt_endptr = + expmatch(s, l_tt_end, &tt_ptr, (char *) NULL)) != NULL) { + printf("{\\TTfont "); + latex_tt=TRUE; + putKcp(s, tt_ptr-1, TRUE); + latex_tt=FALSE; + printf("}"); + s = tt_endptr; + } else { + fprintf(stderr, "typewriter text within a comment must all\ + be on one line (file %s at line %d)\n\t%s", + fname, lineno, s); + s += strlen(s); + } + continue; + } + + /* Check for %%\TeX%% math within comment */ + if (txmptr != NULL) { + putKcp(s, txmptr-1, TRUE); + s = txmendptr; + if ((txmendptr = + expmatch(s, l_txmend, &txmptr, (char *) NULL)) != NULL) { + putchar('$'); putVcp(s, txmptr-1); putchar('$'); + s = txmendptr; + } else { + fprintf(stderr, "TeX math within a comment must all be\ + on one line (file %s at line %d)\n", fname, lineno); + s += strlen(s); + } + continue; + } + } /* @if (code_cmnts)@ */ + + if ((comendptr = + expmatch(s, (comtype == STANDARD) ? l_comend : l_acmend, + (char **) NULL, (char *) NULL)) != NULL) { + putKcp(s, comendptr-1, TRUE); + s = comendptr; + incomm = FALSE; + printf("\\CE{}"); + } else { + comptr = s; + s += strlen(s); + putKcp(comptr, s-1, TRUE); + } + continue; + + /* check for end of string */ + } else if (instr) { + if ((strendptr = + expmatch(s, l_strend, (char **) NULL, (char *) NULL)) != NULL) { + putKcp(s, strendptr-1, TRUE); + s = strendptr; + instr = FALSE; + printf("\\SE{}"); + } else { + strptr = s; + s += strlen(s); + putKcp(strptr, s-1, TRUE); + } + continue; + + /* check for end of character string */ + } else if (inchr) { + if ((chrendptr = + expmatch(s, l_chrend, (char **) NULL, (char *) NULL)) != NULL) { + putKcp(s, chrendptr-1, TRUE); + s = chrendptr; + inchr = FALSE; + printf("\\SE{}"); + } else { + chrptr = s; + s += strlen(s); + putKcp(chrptr, s-1, TRUE); + } + continue; + } + + /* print out the line */ + chrptr = s; + s += strlen(s); + putKcp(chrptr, s-1, FALSE); + + } while (*s); +} + + +/* + * Output a %%\LaTeX%% command to tab to column "col" (see the documentation + * for a partial explanation of the bizarre brace arrangement). + */ +#define tabto(col) printf("}\\Tab{%d}{", col); + + +/* + * @islidchr()@ is @TRUE@ for things that can begin identifiers; + * @isidchr@ is @TRUE@ of identifier constituents. + */ +#define islidchr(c)(((isalpha(c) || (strchr(l_id, c))) && c!=0)) +#define isidchr(c)(((isalnum(c) || (strchr(l_id, c))) && c!=0)) + + +/* + * Get the identifier starting at @s@. It is assumed that @s@ may indeed + * start an identifier. Value is %$>0$% for a keyword --- the count of + * characters in the keyword --- and %$<0$% if not a keyword, in which + * case the value returned is the negative of the number of bytes in + * the matched identifier. + * + * This function checks @nokeyw@ and won't check to see if the + * identifier found is a keyword if it is @TRUE@. + */ +int getid(char *s) +{ + char **ss = l_keywds; + int i = 1; + char *cp = s; + int firstc = *s; + + while (++cp, isidchr(*cp)) + i++; + if (nokeyw) + return -i; + while ((cp = *ss++) != '\0') { + if (!l_onecase && firstc != *cp) + continue; + if ((*re_strncmp)(s, cp, i) == 0 && !isidchr(cp[i])) + return i; + } + return -i; +} + + +/* + * Calculate the width of a string, including tabs + */ +int width(register char *s, register char *os) +{ + register int i = 0, c; + + while (s < os) { + c = *s++; + if (c == '\t') { + /* i = (i + 8) &~ 7; */ + i = ((i + TabWidth) / TabWidth) * TabWidth; + continue; + } + if (c < ' ') + i += 2; + else + i++; + } + return i; +} + + +/* + * Write out a portion of the line + */ +boolean putKcp(char *start, char *end, boolean nix) +/* start Start of string to write + end End of string to write + nix Don't look for identifiers, numbers + returns whether we ate only as much as we ought to */ +{ + int i, c; + + while (start <= end) { + c = *start++; + /* + * take care of nice tab stops ... + * ... and of space runs + */ + if (c == '\t' || (c == ' ' && *start == ' ')) { + while (start <= end && ( *start == '\t' || *start == ' ' )) + start++; + tabto(width(_sstart, start)); + continue; + } + + /* + * First split off numbers. We have a rather ad hoc + * definition: A number is a digit followed by any number + * of digits or letters, and periods. + * (Additionally a number can start with %|$|% (e.g. hex numbers).) + * This produces meaningless parses --- %$.2$% is parsed as %|.|% + * followed by the number %|2|% --- but should produce decent + * results for most languages (outside of maybe FORTRAN and DCL). + */ + if (!nix) { + if (c == '#' || islidchr(c)) { + i = getid(--start); + if (i > 0) + printf("\\K{"); + else { + printf("\\V{"); + i = substvarname(&start, -i); + } + while (--i >= 0) { + c = *start++; + outchar(c); + } + putchar('}'); + continue; + } + else if (isdigit(c) || c == '$') { + printf("\\N{"); + do { + if (c == 'l') + printf("$\\ell$"); + else + outchar(c); + c = *start++; + } while (isalnum(c) || (c == '.' && *start != '.')); + putchar('}'); + start--; + continue; + } + } + outchar(c); + } + return (start-1)==end; +} + + + +/* + * Write out a portion of the line verbatim + */ +void putVcp(char *start, char *end) +/* start Start of string to write + end End of string to write */ +{ + for ( ; start <= end; start++) { + putchar(*start); + } +} + + +/* + * Output a string, escaping special characters + */ +void putstr(register char *cp) +{ + register int c; + + if (cp == NULL) + return; + while ((c = *cp++) != '\0') + outchar(c); +} + + +/* + * The following table converts ASCII characters to a printed + * representation, taking care of all the %%\LaTeX%% quoting. N.B.: all + * single-character strings are assumed to be equivalent to the + * character for that index (i.e., @printtab['c']@ can't be @"f"@). + * (This is purely for efficiency hacking.) + * + * Notes: + * Some pairs of characters are handled specially within @outchar()@; + * this table contains no indication when that happens. + * %|`|% is output as %|{`}|% to avoid various ligatures, such as %|!`|%. + * The %|''|% and %|--|% (and %|---|%) ligatures are not a problem + * because those characters are output as macros anyway. Using %|{`}|% + * is sufficient since nothing we put out will ever be given to the + * hyphenation algorithms anyway. + * + * @ttprinttab@ is the same for the emulated verbatim mode + */ + +char *printtab[256] = { + "\0x", "\\^A", "\\^B", "\\^C", "\\^D", "\\^E", "\\^F", "\\^G", + "\\^H", "\t", "}}\n", "\\^K", "\0x", "\\^M", "\\^N", "\\^O", + "\\^P", "\\^Q", "\\^R", "\\^S", "\\^T", "\\^U", "\\^V", "\\^W", + "\\^X", "\\^Y", "\\^Z", "\\^[", "\\^\\!","\\^]", "\\^\\^","\\^\\_", + " ", "!", "\\3", "\\#", "\\$", "\\%", "\\&", "{'}", + "(", ")", "*", "+", ",", "\\-", ".", "/", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", ":", ";", "\\<", "=", "\\>", "?", + "@", "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", "[", "\\2", "]", "\\5", "\\_", + "{`}", "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", "\\{", "\\|", "\\}", "\\~{}", "\\^?", + "\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207", + "\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217", + "\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227", + "\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237", + "\240", "\241", "\242", "\243", "\244", "\245", "\246", "\247", + "\250", "\251", "\252", "\253", "\254", "\255", "\256", "\257", + "\260", "\261", "\262", "\263", "\264", "\265", "\266", "\267", + "\270", "\271", "\272", "\273", "\274", "\275", "\276", "\277", + "\300", "\301", "\302", "\303", "\304", "\305", "\306", "\307", + "\310", "\311", "\312", "\313", "\314", "\315", "\316", "\317", + "\320", "\321", "\322", "\323", "\324", "\325", "\326", "\327", + "\330", "\331", "\332", "\333", "\334", "\335", "\336", "\337", + "\340", "\341", "\342", "\343", "\344", "\345", "\346", "\347", + "\350", "\351", "\352", "\353", "\354", "\355", "\356", "\357", + "\360", "\361", "\362", "\363", "\364", "\365", "\366", "\367", + "\370", "\371", "\372", "\373", "\374", "\375", "\376", "\377", +}; + +char *ttprinttab[256] = { + "\0x", "\\^A", "\\^B", "\\^C", "\\^D", "\\^E", "\\^F", "\\^G", + "\\^H", "\t", "}}\n", "\\^K", "\0x", "\\^M", "\\^N", "\\^O", + "\\^P", "\\^Q", "\\^R", "\\^S", "\\^T", "\\^U", "\\^V", "\\^W", + "\\^X", "\\^Y", "\\^Z", "\\^[", "\\^\\!","\\^]", "\\^\\^","\\^\\_", + " ", "!", "{34}", "{35}", "{36}", "{37}", "{38}", "{39}", + "(", ")", "*", "+", ",", "{45}", ".", "/", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", ":", ";", "{60}", "=", "{62}", "?", + "@", "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", "[", "{92}", "]", "{94}", "{95}", + "{96}", "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", "{123}", "{124}", "{125}", "{126}", "\\^?", + "\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207", + "\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217", + "\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227", + "\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237", + "\240", "\241", "\242", "\243", "\244", "\245", "\246", "\247", + "\250", "\251", "\252", "\253", "\254", "\255", "\256", "\257", + "\260", "\261", "\262", "\263", "\264", "\265", "\266", "\267", + "\270", "\271", "\272", "\273", "\274", "\275", "\276", "\277", + "\300", "\301", "\302", "\303", "\304", "\305", "\306", "\307", + "\310", "\311", "\312", "\313", "\314", "\315", "\316", "\317", + "\320", "\321", "\322", "\323", "\324", "\325", "\326", "\327", + "\330", "\331", "\332", "\333", "\334", "\335", "\336", "\337", + "\340", "\341", "\342", "\343", "\344", "\345", "\346", "\347", + "\350", "\351", "\352", "\353", "\354", "\355", "\356", "\357", + "\360", "\361", "\362", "\363", "\364", "\365", "\366", "\367", + "\370", "\371", "\372", "\373", "\374", "\375", "\376", "\377", +}; + + + +#define EMDASH (-1) +/* + * Output one character, fixed up as required. Since there is no call-back + * to tell @outchar()@ to flush what it has stored, it must always produce + * some output --- it can't simply retain state. This makes certain + * translations impossible, but we can live without them for now.... + */ +void outchar(int c) +{ + if (!latex_tt) + { + if (c == ' ') { + putchar('_'); + goto fin; + } + switch (lastout) { + case '.': + case '|': + if (c == lastout) + printf("\\,"); + break; + case ' ': +#if 0 /* gvr hates this trick */ + if (incomm && c == '-') { + printf("---"); + c = EMDASH; /* For future cleverness... */ + goto fin; + } +#endif + break; + case '[': + if (c == ']') + printf("\\,"); + break; + case '-': + if (c == '>') + printf("\\!"); + break; + case '<': + if (c == '-') + printf("\\!"); + break; + } + if (incomm && c == '-') { + putchar('-'); + goto fin; + } + printtab[(unsigned char)c][1] ? + printf("%s", printtab[(unsigned char)c]) : putchar(c); + fin: + lastout = c; + } + else + c==32 ? putchar('~') : + ttprinttab[(unsigned char)c][1] ? + printf("\\symbol%s", ttprinttab[(unsigned char)c]) : putchar(c); +} + + +/* + * Look for a procedure beginning on this line + */ +boolean isprocNorm(char *s) +{ + pname[0] = '\0'; + if ((!l_toplex || blklevel == 0) + && expmatch(s, l_prcbeg, (char **) NULL, pname) != NULL + && expmatch(s, l_noproc, (char **) NULL, (char *) NULL) == NULL) + { + procedures_pending++; + blklevel++; + return TRUE; + } + return FALSE; +} + +/* Special version of the above for C functions */ +boolean isprocC(char *s) +{ + char cheat[BUFFERSIZE]; + char *j=s, *i=cheat; + boolean comm=FALSE, string=FALSE, schar=FALSE; + int brack=0; + + if (blklevel!=0) return FALSE; + while (*j) + { + if (*j=='"' && !comm && !schar) string=(string+1)%2; + else if (*j=='\'' && !comm && !string) schar=(schar+1)%2; + else if (*j=='\\' && !comm) j++; + else if (!comm && !string && !schar && *j=='{') brack++; + else if (!comm && !string && !schar && *j=='}') brack--; + else if (!comm && !string && !schar && *j=='#') break; + else if (!comm && !string && !schar && *j=='/' && *(j+1)=='/') break; + else if (!comm && !string && !schar && *j=='/' && *(j+1)=='*') comm=TRUE; + else if ( !string && !schar && *j=='*' && *(j+1)=='/') + {comm=FALSE; j++;} + else if (!brack && !comm && !string && !schar) + *i++=*j; + j++; + } + *i = '\0'; + + return isprocNorm(cheat); +} + + +/* The VMS code below has been absolutely untested for the last few years. + * Don't ask me about it. Please. MPi + */ + +/* + * @getredirection()@ is intended to aid in porting C programs + * to VMS (Vax-11 C) which does not support %|>|% and %|<|% + * I/O redirection. With suitable modification, it may + * useful for other portability problems as well. + * + * Modified, 24-Jan-86 by Jerry Leichter + * When creating a new output file, force the maximum record size to + * 512; otherwise, it ends up as 0 (though the C I/O system won't write + * a record longer than 512 bytes anyway) which will cause problems if + * the file is later opened for @APPEND@ --- if the maximum record size + * is 0, C will use the length of the longest record written to the file + * for its buffer! + */ + +#ifdef vms +# include <stdio.h> +# include <errno.h> + + int +getredirection(argc, argv) + int argc; + char **argv; +/* + * Process VMS redirection args. Exit if any error is seen. + * If @getredirection()@ processes an argument, it is erased + * from the vector. @getredirection()@ returns a new @argc@ value. + * + * Warning: do not try to simplify the code for VMS. The code + * presupposes that @getredirection()@ is called before any data is + * read from @stdin@ or written to @stdout@. + * + * Normal usage is as follows: + * + *@ main(argc, argv) + * int argc; + * char *argv[]; + * { + * argc = getredirection(argc, argv); + * }@ + */ +{ + register char *ap; /* Argument pointer */ + int i; /* @argv[]@ index */ + int j; /* Output index */ + int file; /* File_descriptor */ + + for (j = i = 1; i < argc; i++) { /* Do all arguments */ + switch (*(ap = argv[i])) { + case '<': /* %|<file|% */ + if (freopen(++ap, "r", stdin) == NULL) { + perror(ap); /* Can't find file */ + exit(errno); /* Is a fatal error */ + } + break; + + case '>': /* %|>file|% or %|>>file|% */ + if (*++ap == '>') { /* %|>>file|% */ + /* + * If the file exists, and is writable by us, + * call @freopen()@ to append to the file (using the + * file's current attributes). Otherwise, create + * a new file with "vanilla" attributes as if + * the argument was given as %|>filename|%. + * @access(name, 2)@ is @TRUE@ if we can write on + * the specified file. + */ + if (access(++ap, 2) == 0) { + if (freopen(ap, "a", stdout) != NULL) + break; /* Exit @case@ statement */ + perror(ap); /* Error, can't append */ + exit(errno); /* After @access@ test */ + } /* If file accessable */ + } + /* + * On VMS, we want to create the file using "standard" + * record attributes. @create(...)@ creates the file + * using the caller's default protection mask and + * "variable length, implied carriage return" + * attributes. @dup2()@ associates the file with @stdout@. + */ + if ((file = creat(ap, 0, "rat=cr", "rfm=var", "mrs=512")) == -1 + || dup2(file, fileno(stdout)) == -1) { + perror(ap); /* Can't create file */ + exit(errno); /* is a fatal error */ + } /* If %|>|% creation */ + break; /* Exit @case@ test */ + + default: + argv[j++] = ap; /* Not a redirector */ + break; /* Exit @case@ test */ + } + } /* For all arguments */ + argv[j] = NULL; /* Terminate @argv[]@ */ + return j; /* Return new @argc@ */ +} + +#else /* @!vms@ */ + +int getredirection(int argc, char **argv) + /* + * Dummy routine. + */ +{ + return argc; +} + +#endif /* @!vms@ */ + +#include "lgutil.c" +/* Helper functions */ + diff --git a/support/lgrind/source/lgrindef.5 b/support/lgrind/source/lgrindef.5 new file mode 100644 index 0000000000..3606fd3666 --- /dev/null +++ b/support/lgrind/source/lgrindef.5 @@ -0,0 +1,248 @@ +.\" @(#)lgrindef.5 3.62 11/2/97 MPi; from UCB 4.3 +.\" Copyright (c) 1983 Regents of the University of California. +.\" All rights reserved. The Berkeley software License Agreement +.\" specifies the terms and conditions for redistribution. +.\" +.\" $Id: lgrindef.5,v 1.4 1999/10/05 17:41:35 mike Exp $ +.\" +.\" This is the standard SunOS vgrindefs(5) manpage, with a few +.\" additions to describe the extra capabilities needed by lgrind, +.\" viz.: zb, ze, tb, te, mb, me, vb, ve, cf, rb. +.\" +.tr || +.TH LGRINDEF 5 "11 February 1997" "TeX/LaTeX" +.SH NAME +lgrindef \- LGrind's language definition data base +.SH NOTE +This man page is not yet much outdated, but might be soon except somebody +asks me to work on it. Consider the LaTeX docs the real docs. +.SH SYNOPSIS +.B /usr/TeX/texmf/tex/latex/lgrind/lgrindef +.SH DESCRIPTION +.IX "lgrindef file" "" "\fLlgrindef\fP \(em LGrind language definitions" +.B lgrindef +contains all language definitions for +.BR lgrind (1). +The data base is very similar to +.BR vgrind (5) +and +.BR termcap (5), +and it is upward-compatible with that of +.BR vgrind (5). +Capabilities in +.B lgrindef +are of two types: +Boolean capabilities which indicate that the language has +some particular feature +and string +capabilities which give a regular expression or +keyword list. +Entries may continue onto multiple lines by giving a \e as the last +character of a line. +Lines starting with # are comments. +.SS Capabilities +The following table names and describes each capability. +.PP +.PD 0 +.ta \w'\fBName\fP 'u +.nr Xx \w'\fBName\fP \fBType\fP 'u +.TP \n(Xxu +.B +Name Type +.B Description +.TP +.B ab \fRstr +Regular expression for the start of an alternate form comment +.TP +.B ae \fRstr +Regular expression for the end of an alternate form comment +.TP +.B bb \fRstr +Regular expression for the start of a block +.TP +.B be \fRstr +Regular expression for the end of a lexical block +.TP +.B cb \fRstr +Regular expression for the start of a comment +.TP +.B ce \fRstr +Regular expression for the end of a comment +.TP +.B cf \fRbool +(Boolean) Use specialized C function detection +.TP +.B id \fRstr +String giving characters other than letters and digits +that may legally occur in identifiers (default `_') +.TP +.B kw \fRstr +A list of keywords separated by spaces +.TP +.B lb \fRstr +Regular expression for the start of a character constant +.TP +.B le \fRstr +Regular expression for the end of a character constant +.TP +.B mb \fRstr +Regular expression for the start of TeX math within a comment +.TP +.B me \fRstr +Regular expression for the end of TeX math within a comment +.TP +.B np \fRstr +Regular expression for a line +.B not +containing the start of a procedure +.TP +.B oc \fRbool +Present means upper and lower case are equivalent +.TP +.B pb \fRstr +Regular expression for start of a procedure +.TP +.B pl \fRbool +Procedure definitions are constrained to the lexical level +matched by the `px' capability +.TP +.B px \fRstr +A match for this regular expression indicates +that procedure definitions may occur at the next lexical level. +Useful for lisp-like languages in which procedure definitions +occur as subexpressions of defuns. +.TP +.B rb \fRstr +Regular expression for the start of a block outside the actual code +.TP +.B sb \fRstr +Regular expression for the start of a string +.TP +.B se \fRstr +Regular expression for the end of a string +.TP +.B rb \fRstr +Regular expression for the end of a block outside a funtion +(e. g. records in Pascal and Modula-2) +.TP +.B tb \fRstr +Regular expression for the start of TeX text within a comment +.TP +.B tc \fRstr +Use the named entry as a continuation of this one +.TP +.B te \fRstr +Regular expression for the end of TeX text within a comment +.TP +.B tl \fRbool +Present means procedures are only defined at the top lexical level +.TP +.B vb \fRstr +Regular expression for the start of typewriter text within a comment +.TP +.B ve \fRstr +Regular expression for the end of typewriter text within a comment +.TP +.B zb \fRstr +Regular expression for the start of program text within a comment +.TP +.B ze \fRstr +Regular expression for the end of program text within a comment +.PD +.DT +.SS "Regular Expressions" +.B lgrindef +uses regular expressions similar to those of +.BR ex (1) +and +.BR lex (1). +The characters `^', +`$', +`\^|', +`:', +and `\e' +are reserved characters and must be +`quoted' with a preceding \e if they +are to be included as normal characters. +The metasymbols and their meanings are: +.IP $ +The end of a line +.PD 0.2v +.IP ^ +The beginning of a line +.IP \ed +A delimiter (space, tab, newline, start of line) +.IP \ea +Matches any string of symbols +(like `.*' in lex) +.IP \ep +Matches any identifier. +In a procedure definition +(the `pb' capability) +the string that matches this symbol is used as the procedure name. +.IP (\^) +Grouping +.IP | +Alternation +.IP ? +Last item is optional +.IP \ee +Preceding any string means that the string will not match an +input string if the input string is preceded by an escape character (\e). +This is typically used for languages (like C) that can include the +string delimiter in a string by escaping it. +.PD +.PP +Unlike other regular expressions in the system, +these match words and not characters. +Hence something like `(tramp\^|\^steamer)flies?' +would match `tramp', +`steamer', +`trampflies', +or `steamerflies'. +Contrary to some forms of regular expressions, +.B lgrindef +alternation binds very tightly. +Grouping parentheses are likely to be necessary in expressions +involving alternation. +.SS "Keyword List" +The keyword list is just a list of keywords in the language separated +by spaces. +If the `oc' boolean is specified, +indicating that upper and lower case are equivalent, +then all the keywords should be specified in lower case. +.SH EXAMPLE +The following entry, +which describes the C language, +is typical of a language entry. +.IP +.ft B +.nf +C\^|\^the C programming language:\e + :pb=^\ed?*?\ed?\ep\ed?\(\ea?\):bb={:be=}:cb=/*:ce=*/:\e + :sb=":se=\ee":lb=':le=\ee':tl:\e + :zb=@:ze=@:tb=%%:te=%%:mb=%\e$:me=\e$%:vb=%\e\^|:ve=\e\^|%:\e + :kw=asm auto break case char continue default do double\e + else enum extern float for fortran goto if int long\e + register return short sizeof static struct switch typedef\e + union unsigned while #define #else #endif #if #ifdef\e + #ifndef #include #undef # define else endif if ifdef\e + ifndef include undef: +.fi +.ft +.PP +Note that the first field is just the language name +(and any variants of it). +Thus the C language could be specified to +.BR lgrind (1) +as `c' or `C', since case is not significant here. +.SH FILES +.ta \w'/usr/TeX/texmf/tex/latex/lgrind/lgrindef 'u +\fB/usr/TeX/texmf/tex/latex/lgrind/lgrindef\fR file containing terminal descriptions +.SH "SEE ALSO" +.BR latex (1), +.BR lgrind (1), +.BR vgrindefs (5), +For full documentation, refer to the package itself; it comes as a .dtx +containing both the documentation and the LaTeX-files. + diff --git a/support/lgrind/source/lgrindef.c b/support/lgrind/source/lgrindef.c new file mode 100644 index 0000000000..c096010a97 --- /dev/null +++ b/support/lgrind/source/lgrindef.c @@ -0,0 +1,330 @@ +#ifndef lint +static char sccsid[] = "@(#)lgrindef.c 4.3 (Berkeley) 11/12/84"; +static char rcsid[] = + "$Id: lgrindef.c,v 1.3 1999/05/28 11:00:16 mike Exp $"; +#endif + +/* Copyright %%\copyright%% 1979 Regents of the University of California + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define MAXHOP 32 /* max number of %|tc=|% indirections */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include "lgrindef.h" + +/* + * grindcap --- routines for dealing with the language definitions data base + * (code stolen almost totally from termcap) + * + * BUG: Should use a "last" pointer in @tbuf@, so that searching + * for capabilities alphabetically would not be a %$n^2/2$% + * process when large numbers of capabilities are given. + * Note: If we add a last pointer now we will screw up the + * %|tc|% capability. We really should compile termcap. + * + * Essentially all the work here is scanning and decoding escapes + * in string capabilities. We don't use stdio because the editor + * doesn't, and because living w/o it is not hard. + */ + +static char *tbuf; +static char *filename; +static int hopcount = 0; /* detect infinite loops in termcap */ + +static char *tskip(char *); +static char *tdecode(char *, char **); + +/* + * @tnchktc@: check the last entry, see if it's %|tc=xxx|%. If so, + * recursively find %|xxx|% and append that entry (minus the names) + * to take the place of the %|tc=xxx|% entry. This allows termcap + * entries to say "like an HP2621 but doesn't turn on the labels". + * Note that this works because of the left to right scan. + */ +static int tnchktc(void) +{ + register char *p, *q; + char tcname[16]; /* name of similar terminal */ + char tcbuf[BUFFERSIZE]; + char *holdtbuf = tbuf; + int l; + + p = tbuf + strlen(tbuf) - 2; /* before the last colon */ + while (*--p != ':') + if (p < tbuf) { + /* Not very informative. Wrong BTW (for the configs). Shut up. */ + /* write(2, "Bad lgrind entry\n", 18); */ + return 0; + } + p++; + /* @p@ now points to beginning of last field */ + if (p[0] != 't' || p[1] != 'c') + return 1; + strcpy(tcname,p+3); + q = tcname; + while (q && *q != ':') + q++; + *q = '\0'; + if (++hopcount > MAXHOP) { + fprintf(stderr, "Infinite tc= loop\n"); + return 0; + } + if (tgetent(tcbuf, tcname, filename) != 1) + return 0; + for (q = tcbuf; *q != ':'; q++) + ; + l = (int)(p - holdtbuf + strlen(q)); + if (l > BUFFERSIZE) { + fprintf(stderr, "LGrind entry too long\n"); + q[(int)(BUFFERSIZE - (p-tbuf))] = '\0'; + } + strcpy(p, q+1); + tbuf = holdtbuf; + return 1; +} + + +/* + * @tnamatch@ deals with name matching. The first field of the termcap + * entry is a sequence of names separated by %|||%'s, so we compare + * against each such name. The normal %|:|% terminator after the last + * name (before the first field) stops us. + */ +static int tnamatch(char *np) +{ + register char *Np, *Bp; + + Bp = tbuf; + if (*Bp == '#') + return 0; + for (;;) { + for (Np = np; *Np && toupper(*Bp) == toupper(*Np); Bp++, Np++) + continue; + if (*Np == '\0' && (*Bp == '|' || *Bp == ':' || *Bp == '\0')) + return 1; + while (*Bp != '\0' && *Bp != ':' && *Bp != '|') + Bp++; + if (*Bp == '\0' || *Bp == ':') + return 0; + Bp++; + } +} + + +/* + * Skip to the next field. Notice that this is very dumb, not + * knowing about %|\:|% escapes or any such. If necessary, %|:|%'s can + * be put into the termcap file in octal. + */ +static char *tskip(register char *bp) +{ + while (*bp && *bp != ':') + bp++; + if (*bp == ':') + bp++; + return bp; +} + + +/* + * Return the (numeric) option id. + * Numeric options look like + * %|li#80|% + * i.e. the option string is separated from the numeric value by + * a %|#|% character. If the option is not found we return %$-1$%. + * Note that we handle octal numbers beginning with %$0$%. + */ +int tgetnum(char *id) +{ + register int i, base; + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (*bp == '\0') + return -1; + if (*bp++ != id[0] || *bp == '\0' || *bp++ != id[1]) + continue; + if (*bp == '@') + return -1; + if (*bp != '#') + continue; + bp++; + base = 10; + if (*bp == '0') + base = 8; + i = 0; + while (isdigit(*bp)) + i *= base, i += *bp++ - '0'; + return i; + } +} + + + +/* + * Handle a flag option. + * Flag options are given "naked", i.e. followed by a %|:|% or the end + * of the buffer. Return 1 if we find the option, or 0 if it is + * not given. + */ +int tgetflag(char *id) +{ + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (!*bp) + return 0; + if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { + if (!*bp || *bp == ':') + return 1; + else if (*bp == '@') + return 0; + } + } +} + + +/* + * Get a string valued option. + * These are given as + * %|cl=^Z|% + * Much decoding is done on the strings, and the strings are + * placed in area, which is a ref parameter which is updated. + * No checking on area overflow. + */ +char *tgetstr(char *id, char **area) +{ + register char *bp = tbuf, *i; + register int eq; + + for (;;) { + bp = tskip(bp); + if (!*bp) + return 0; + eq=1; + for (i=id; *i;) + if (*i++!=*bp++) { eq=0; break; } + if (!eq) + continue; + if (*bp == '@') + return 0; + if (*bp != '=') + continue; + bp++; + return tdecode(bp, area); + } +} + + +/* + * @tdecode@ does the grunge work to decode the + * string capability escapes. + */ +static char *tdecode(register char *str, char **area) +{ + char *cp = *area, c; + + while ((c = *str++) != 0) { + if (c == ':') { + if (*(cp-1) == '\\') + cp--; + else + break; + } + *cp++ = c; + } + *cp++ = '\0'; + str = *area; + *area = cp; + return str; +} + +/* + * Get an entry for terminal name in buffer @bp@, + * from the termcap file. Parse is very rudimentary; + * we just notice escaped newlines. + */ +int tgetent(char *bp, char *name, char *file) +{ + register char *cp; + register char c; /* 30.7.96 -- tryal [sic] */ + register int i = 0, cnt = 0; + char ibuf[BUFFERSIZE]; + FILE *tf; + + tbuf = bp; + tf = 0; + filename = file; + tf = fopen(filename, "rt"); + if (tf == NULL) + return -1; + for (;;) { + cp = bp; + for (;;) { + if (i == cnt) { + cnt = fread(ibuf, 1, BUFFERSIZE, tf); + if (cnt <= 0) { + fclose(tf); + return 0; + } + i = 0; + } + c = ibuf[i++]; + if (c == '\n') { + if (cp > bp && cp[-1] == '\\'){ + cp--; + continue; + } + break; + } + if (cp >= bp+BUFFERSIZE) { + fprintf(stderr, "LGrind entry too long\n"); + break; + } else + *cp++ = c; + } + *cp = '\0'; + + /* + * The real work for the match. + */ + if (tnamatch(name)) { + fclose(tf); + return tnchktc(); + } + } +} diff --git a/support/lgrind/source/lgrindef.h b/support/lgrind/source/lgrindef.h new file mode 100644 index 0000000000..f213d9b948 --- /dev/null +++ b/support/lgrind/source/lgrindef.h @@ -0,0 +1,12 @@ +/* sccsid[] = "@(#)lgrindef.h 3.6 (MPi) 3/8/98"; + * rcsid[] = + * "$Id: lgrindef.h,v 1.3 1999/05/26 07:30:03 mike Exp $"; + * + * Created 19 February 1996 + */ + +#define BUFFERSIZE 8192 +int tgetent(char *bp, char *name, char *file); +int tgetnum(char *id); +int tgetflag(char *id); +char *tgetstr(char *id, char **area); diff --git a/support/lgrind/source/lgutil.c b/support/lgrind/source/lgutil.c new file mode 100644 index 0000000000..121ba366a0 --- /dev/null +++ b/support/lgrind/source/lgutil.c @@ -0,0 +1,323 @@ +#ifndef lint +#ifdef standalone_lgutil +static char sccsid[] = "@(#)lgutil.c 3.6 (MPi) 24/3/98"; +static char rcsid[] = + "$Id: lgutil.c,v 1.7 1999/12/18 21:54:29 mike Exp $"; +#endif /* standalone_lgutil */ +#endif + +/* lgutil.c + * Utility Functions for LGrind + * This file is @#include@d from lgrind.c (likely to change) + */ + +/* Copyright %%\copyright%% 1998,1999 Michael Piefel + * + * This file is something like GPL, though LGrind is BSD. + * I don't want to become a lawyer. + */ + +/* + * Internal_Help() --- show help + */ + +void Internal_Help() +{ + printf("lgrind -- general purpose \"pretty printer\" for use with LaTeX.\n"); + printf("usage: lgrind [options] <name> ...\n"); + printf("-e process embedded text in a LaTeX file\n"); + printf("-i format source code for inclusion in a LaTeX document.\n"); + printf("-n don't boldface keywords.\n"); + printf("-a don't treat @, etc. specially in LaTeX.\n"); + printf("-c don't treat @, etc. specially in comments.\n"); + printf("- take input from standard input.\n"); + printf("-o <file> write to file (instead of standard output).\n"); + printf("-t <width> change tab width (default 8).\n"); + printf("-h <header> specifies text in header (default: none).\n"); + printf("-v <varfile> take variable substitutions from file.\n"); + printf("-d <deffile> use a different language definitions file, default:\ +\n \"%s\"\n", defsfile); + printf("-l<language> choose the language to use.\n"); + printf("-s show a list of currently known languages.\n\n"); + printf("If neither -e nor -i are specified, a complete LaTeX-file is produced.\n\n"); + printf("Direct comments and questions to lgrind@gmx.net\n"); +} + + +typedef struct langRec { + char *name; + char *alternatives; + struct langRec *next; } langRec; + +void AddToLList(char *line, langRec **into, int *chainLength) +{ + char *token, *item, *alts; + + if (*line!='#' && *line!='\n') + { + item=strdup(line); + if ((token=strtok(item, "|:\\\n")) == NULL) return; + (**into).next=(langRec*)malloc(sizeof(langRec)); + *into=(**into).next; + (**into).name=strdup(token); + (*chainLength)++; + if ((token=strtok(NULL, "|:\\\n")) == NULL) + { + (**into).alternatives="\0"; + return; + } + (**into).alternatives=strdup(token); + while ((token=strtok(NULL, "|:\\\n")) != NULL) + { + alts=(**into).alternatives; + (**into).alternatives=(char*)malloc( + strlen((**into).alternatives)+strlen(token)+1); + /* This is extremely poor style and dangerous. I leave memory + * allocated here because after invocation of this help facility + * the program will stop anyway. In this context it is safe. */ + strcpy((**into).alternatives, alts); + strcat((**into).alternatives, ", "); + strcat((**into).alternatives, token); + } + } +} + +void Internal_Help_Language_List() +{ + FILE *tf; + int check, i, llch; + langRec *lch, *rch, *currlch; + /* @lch2@ was originally "language chain", but I guess + it's "left" as well */ + + printf("When specifying a language case is insignificant. You can use the\n"); + printf("name of the language, or, where available, one of the synonyms in\n"); + printf("parantheses. Thus the following are legal and mark Tcl/Tk, Pascal\n"); + printf("and Fortran input, respectively:\n"); + printf(" lgrind -ltcl/tk ...\n"); + printf(" lgrind -lpaSCAL ...\n"); + printf(" lgrind -lf ...\n"); + printf("The list of languages currently available in your lgrindef file:\n"); + tf = fopen(defsfile, "rt"); + if (tf == NULL) + { + fprintf(stderr, "cannot find lgrindef file `%s'\n", defsfile); + return; + } + + llch=0; + currlch=lch=(langRec*)malloc(sizeof(langRec)); + (*currlch).name=""; + *config='\n'; + do { + check=0; + if (*config=='\n' || config[strlen(config)-2]!='\\') + check=1; + if (fgets(config, BUFFERSIZE, tf)==NULL) break; + if (check!=0) AddToLList(config, &currlch, &llch); + } while (strcmp((*currlch).name, "EndOfLanguageDefinitions")!=0); + rch=lch; + for (check=0; check<llch/2; check++) + rch=(*rch).next; + for (check=0; check<llch/2; check++) + { + lch=(*lch).next; + rch=(*rch).next; + printf(" %s", (*lch).name); + if (*((*lch).alternatives)) printf(" (%s)", (*lch).alternatives); + else printf(" "); + for (i=strlen((*lch).name)+strlen((*lch).alternatives); + i<30; i++) putchar(' '); + if (rch!=currlch) + { + printf("%s", (*rch).name); + if (*((*rch).alternatives)) printf(" (%s)", (*rch).alternatives); + } + printf("\n"); + } +} + + +/* + * Redefine Chartab from lgrindef file + */ +void parsechartab(void) +{ + char *i=buf, *j=chartab, c; + int charnum=0; + + while (*i++!=':') {} + while ((c=*i++)!='\0') { + if (c==':') continue; + charnum=(c>='0' && c<='9') ? (int)c-48 : tolower(c)-87; + charnum=charnum << 4; c=*i++; + charnum+=(c>='0' && c<='9') ? (int)c-48 : tolower(c)-87; + i++; + + printtab[charnum]=j; + while (*i!=':') + if (*i=='\\') { + switch (*++i) { + case ':': *j++=':'; break; + case '\\': *j++='\\'; break; + }; i++; + } else *j++=*i++; + *j++='\0'; + } + +} + +/* + * Parses the %|lgrindef|% file for a preamble + */ +void parsepreamble(char *destination) +{ + char *i=buf, *j=destination; + + while (*i++!=':') ; + while (*i) { + if (*i=='\\') { + switch (*++i) { + case 'n': *j++='\n'; break; + case 't': *j++='\t'; break; + case 'f': *j++='\f'; break; + case '\\': *j++='\\'; break; + default: fprintf(stderr, "Bad preamble entry: incorrect '\\'\n"); + }; i++; + } else *j++=*i++; + *j='\0'; + } +} + +/* + * Sets the default preambles + */ +void setpreambles(void) +{ + strcpy(preamble, +"\\documentclass[a4paper]{article}\n\ +\\usepackage[procnames,noindent]{lgrind}\n\ +\\usepackage{fancyhdr}\n\ +\\pagestyle{fancy}\n\ +\\begin{document}\n"); + strcpy(postamble, "\\end{document}\n"); + strcpy(preamble2, +"\\lhead[\\fancyplain{}{\\bf\\thepage}]\ +{\\fancyplain{}{\\bf \f}}\n\ +\\rhead[\\fancyplain{}{\\bf \f}]\ +{\\fancyplain{}{\\bf\\thepage}}\n\ +\\cfoot{}\n"); + strcpy(config, ""); +} + +/* + * prints a preamble, substituting %|\f|% with the current + * file's name (sorry, no more form feeds) + */ +void printpreamble(char *string) +{ + char *i; + while (*string) + if (*string=='\f') + { i=fname-1; + while (*(++i)) outchar(*i); + string++; + } + else putchar(*string++); +} + +/* + * try to create an executable file to store the new lgrindef-file + */ +void writeDefsfileInExe(char *progname, char *newdefsfile) +{ + char *buffer, *i; + FILE *progfile, *newfile; + long pos=0; + int ret; + + buffer = (char*) malloc(30000); + /* So small? Why in chunks? Well, it's gotta run on machines with + only limited access to their resources (you know, the IBM PC) */ + progfile=fopen(progname, "rb"); + newfile=fopen("lgrind.new", "wb"); + + if (buffer && progfile && newfile) + { + fread(buffer, 1, 200, progfile); + do { + ret=fread(buffer+200, 1, 29500, progfile); + for(i=buffer; i<buffer+ret; i++) + if (*i=='D' && + *(i+1)=='e' && + *(i+2)=='F' && + *(i+3)=='s' && + *(i+4)=='B' && + *(i+5)=='u' && + *(i+6)=='F' && + strcmp(defsfile, i+7)==0) { + memcpy(i+7, newdefsfile, strlen(newdefsfile)+1); + } + fwrite(buffer, 1, ret==29500 ? ret : ret+200, newfile); + memcpy(buffer, buffer+29500, 200); + pos+=29500; + } while (ret==29500); + fclose(progfile); + fclose(newfile); + } + free(buffer); +} + +/* + * Reads a variable substitution table from a file + */ +varsubst *parsevartab(char* fname) +{ + FILE *f = fopen(fname, "rt"); + char linebuf[201], *cp; + varsubst *varsubsts=NULL, *substitem, *substlistpos; + + if (f==NULL) return; + while (!feof(f)) + { + fscanf(f, "%200[^\n]", linebuf); + fscanf(f, "\n"); + cp=strchr(linebuf, '='); + if (cp==NULL) continue; + *cp++='\0'; + substitem=(varsubst*)malloc(sizeof(varsubst)); + substitem->var=strdup(linebuf); + substitem->subst=strdup(cp); + substitem->next=NULL; + if (varsubsts==NULL) + { + varsubsts=substitem; + substlistpos=substitem; + } else { + substlistpos->next=substitem; + substlistpos=substitem; + } + } + fclose(f); + return varsubsts; +} + +/* + * Replaces a variable by alternate representation + */ +int substvarname(char **ident, int i) +{ + varsubst *substlistpos = varsubstlist; + + while (substlistpos!=NULL) + { + if (re_strncmp(*ident, substlistpos->var, i)==0) + { + *ident+=i; /* skip i characters in input */ + printf("%s", substlistpos->subst); + return 0; + } + substlistpos=substlistpos->next; + } + return i; +} diff --git a/support/lgrind/source/makefile.dos b/support/lgrind/source/makefile.dos new file mode 100644 index 0000000000..540e1337e7 --- /dev/null +++ b/support/lgrind/source/makefile.dos @@ -0,0 +1,34 @@ +# Makefile for lgrind, a LaTeX prettyprinter + +# $Id: makefile.dos,v 1.1.1.1 1999/05/13 13:02:55 mike Exp $ + +# You will possibly want to change this +DEFSFILE=$(EMTEXDIR:\\=\\\\)\\\\texinput\\\\lgrind\\\\lgrindef +# if you encounter problems with the last line, enter the path +# directly; if all else fails, modify lgrind.c + +CC=bcc +SOURCES=lgrind.c regexp.c regexp.h lgrindef.c lgrindef.h retest.c v2lg.c +TEXFILES=lgrind.dtx lgrind.sty lgrind.ins +CMDS=lgrind.exe +OBJS=lgrind.obj regexp.obj retest.obj lgrindef.obj v2lg.obj + +HELPOPTION=-? +# popen? pclose? This is DOS! +#CFLAGS=-v -mc -Dpopen=fopen -Dpclose=fclose +CFLAGS=-O2 -mc -Dpopen=fopen -Dpclose=fclose +# Well, the DEFSFILE is still (semi-)fixed in the EXE... + +.c.obj: + $(CC) $(CFLAGS) -DDEFSFILE="$(DEFSFILE)" -DHELPOPTION="$(HELPOPTION)" -c $< + +all: $(CMDS) + +lgrind.exe: lgrind.obj lgrindef.obj regexp.obj + $(CC) $(CFLAGS) lgrind.obj lgrindef.obj regexp.obj + +v2lg: v2lg.c + $(CC) $(CFLAGS) v2lg + +retest: retest.c regexp.c + $(CC) $(CFLAGS) retest regexp diff --git a/support/lgrind/source/makefile.emx b/support/lgrind/source/makefile.emx new file mode 100644 index 0000000000..3cbdbbb381 --- /dev/null +++ b/support/lgrind/source/makefile.emx @@ -0,0 +1,55 @@ +# Makefile for lgrind, a LaTeX prettyprinter +# for EMX+GCC with DMAKE, bound DOS-extender + +# $Id: makefile.emx,v 1.1.1.1 1999/05/13 13:02:55 mike Exp $ + +# You will almost certainly want to change these +DESTDIR=c:\\emtex\\bin +DEFSFILE=c:\\emtex\\texinput\\lgrind\\lgrindef +TEXINPUTS=c:\\emtex\\texinput\\lgrind + +SOURCES=lgrind.c regexp.c regexp.h lgrindef.c lgrindef.h retest.c v2lg.c +TEXFILES=lgrind.doc lgrind.sty lgrind.ins +MANPAGES=lgrind.1 lgrindef.5 +EXAMPLES=doc-lgrind.lg +CMDS=lgrind.exe +OBJS=lgrind.o regexp.o retest.o lgrindef.o v2lg.o + +CC=gcc +HELPOPTION=-? +CFLAGS=-O2 -DOS2 +# CFLAGS=-g +# CFLAGS=-O2 -Dpopen=fopen -Dpclose=fclose +# There are operating systems and compilers without these... + +.SUFFIXES: .o .c + +.c.o: + $(CC) -c $(CFLAGS) $< + +all: $(CMDS) + +lgrind.exe: lgrind.o lgrindef.o regexp.o + $(CC) $(CFLAGS) -o lgrind.exe lgrind.o lgrindef.o regexp.o -s +# alternatively you can bind the DOS-extender permanently: +# $(CC) $(CFLAGS) -o lgrind lgrind.o lgrindef.o regexp.o -s +# emxbind c:\emx\bin\emx.exe lgrind lgrind.exe -p + +lgrind.o: lgrind.c + $(CC) $(CFLAGS) -DDEFSFILE=\"${DEFSFILE}\" -DHELPOPTION=\"${HELPOPTION}\"\ + -c lgrind.c + +v2lg.exe: v2lg.o + $(CC) $(CFLAGS) -o v2lg.exe v2lg.o + +retest.exe: retest.o regexp.o + $(CC) $(CFLAGS) -o retest.exe retest.o regexp.o + +install: all + -copy lgrind.exe $(DESTDIR)\\lgrind.exe + -copy lgrindef $(DEFSFILE) + -copy lgrind.dtx $(TEXINPUTS)\\lgrind.dtx + -copy lgrind.sty $(TEXINPUTS)\\lgrind.sty + +clean: + -del $(CMDS) $(OBJS) retest.exe v2lg.exe diff --git a/support/lgrind/source/regexp.c b/support/lgrind/source/regexp.c new file mode 100644 index 0000000000..87b19433ce --- /dev/null +++ b/support/lgrind/source/regexp.c @@ -0,0 +1,648 @@ +#ifndef lint +static char sccsid[] = "@(#)regexp.c 1.2 (LBL) 12/4/85"; +static char rcsid[] = + "$Id: regexp.c,v 1.3 1999/05/27 16:17:43 mike Exp $"; +#endif + +/* + * Copyright %%\copyright%% 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Regular expression matching routines for lgrind/tgrind/tfontedpr. + * + * These routines were written by Dave Presotto (I think) for vgrind. + * Minor mods & attempts to improve performance by Van Jacobson + * (van@@lbl-rtsg) and Chris Torek (chris@@maryland). + * + * Modifications. + * -------------- + * Sep 91 George V Reilly Fixed up some bogus uses of @NIL@ and @NULL@. + * 30 Mar 85 Van & Chris Changed @expmatch()@ to return pointer to + * start of what was matched in addition to + * pointer to match end. Several changes to + * improve performance (too numerous to mention). + * 11 Dec 84 Dave Presotto Written. + */ + + +#include <stdio.h> +#include <malloc.h> +#include <ctype.h> +#include <string.h> +#include "regexp.h" + +#define makelower(c) (isupper((c)) ? tolower((c)) : (c)) + +extern char *l_id; +static void expconv(void); /* forward declaration */ + +int (*re_strncmp)(const char *, const char *, size_t); + /* function used by @expmatch()@ to compare + * strings. The caller should make it point to + * @strncmp()@ if case is significant & + * @lc_strncmp()@ otherwise. + */ + + +/* @lc_strncmp()@ --- like @strncmp()@ except that we convert the + * first string to lower case before comparing. + */ +int lc_strncmp(register const char *s1, register const char *s2, register size_t len) +{ + while (len-- > 0) + if (*s2 - makelower(*s1)) + return 1; + else + s2++, s1++; + + return 0; +} + + +/* The following routine converts an irregular expression to + * internal format. + * + * Either meta symbols (%|\a|%, %|\d|%, or %|\p|%) or character strings + * or operations (alternation or parenthesizing) can be specified. + * Each starts with a descriptor byte. The descriptor byte + * has @STR@ set for strings, @META@ set for meta symbols, + * and @OPER@ set for operations. The descriptor byte can also have + * the @OPT@ bit set if the object defined is optional. Also @ALT@ + * can be set to indicate an alternation. + * + * For metasymbols, the byte following the descriptor byte identities + * the meta symbol (containing an ASCII @'a'@, @'d'@, @'p'@, @'|'@, + * or @'('@). For strings, the byte after the descriptor is a + * character count for the string: + *@ + * meta symbols := descriptor + * symbol + * + * strings := descriptor + * character count + * the string + * + * operations := descriptor + * symbol + * character count@ + */ + + +/* + * handy macros for accessing parts of match blocks + */ +#define MSYM(A) (*(A+1)) /* symbol in a meta symbol block */ +#define MNEXT(A) (A+2) /* character following a metasymbol block */ + +#define OSYM(A) (*(A+1)) /* symbol in an operation block */ +#define OCNT(A) (*(A+2)) /* character count */ +#define ONEXT(A) (A+3) /* next character after the operation */ +#define OPTR(A) (A+*(A+2)) /* place pointed to by the operator */ + +#define SCNT(A) (*(A+1)) /* byte count of a string */ +#define SSTR(A) (A+2) /* address of the string */ +#define SNEXT(A) (A+2+*(A+1)) /* character following the string */ + + +/* + * bit flags in the descriptor + */ +#define OPT 1 +#define STR 2 +#define META 4 +#define ALT 8 +#define OPER 16 + +char *ure; /* pointer current position in unconverted exp */ +char *ccre; /* pointer to current position in converted exp */ + + + +/* + * Convert an irregular expression to the internal form + */ +char *convexp(char *re) +/* re unconverted irregular expression */ +{ + register char *cre; /* pointer to converted regular expression */ + + /* allocate room for the converted expression */ + if (re == NULL) + return NULL; + if (*re == '\0') + return NULL; + cre = (char*)malloc(4 * strlen(re) + 3); + ccre = cre; + ure = re; + + /* start the conversion with a %|\a|% */ + *cre = META | OPT; + MSYM(cre) = 'a'; + ccre = MNEXT(cre); + + /* start the conversion (it's recursive) */ + expconv(); + *ccre = 0; + return cre; +} + + +/* + * Actually do the conversion + */ +static void expconv(void) +{ + register char *cs; /* pointer to current symbol in converted exp */ + register char c; /* character being processed */ + register char *acs; /* pointer to last alternate */ + register int temp; + + /* let the conversion begin */ + acs = NULL; + cs = NULL; + while (*ure != '\0') { + switch (c = *ure++) { + + case '\\': + switch (c = *ure++) { + + /* escaped characters are just characters */ + default: + if (cs == NULL || (*cs & STR) == 0) { + cs = ccre; + *cs = STR; + SCNT(cs) = 1; + ccre += 2; + } else + SCNT(cs)++; + *ccre++ = c; + break; + + /* normal(?) metacharacters */ + case 'a': + case 'd': + case 'e': + case 'p': + if (acs != NULL && acs != cs) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NULL; + } + cs = ccre; + *cs = META; + MSYM(cs) = c; + ccre = MNEXT(cs); + break; + } + break; + + /* just put the symbol in */ + case '^': + case '$': + if (acs != NULL && acs != cs) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NULL; + } + cs = ccre; + *cs = META; + MSYM(cs) = c; + ccre = MNEXT(cs); + break; + + /* mark the last match sequence as optional */ + case '?': + if (cs) + *cs = *cs | OPT; + break; + + /* recurse and define a subexpression */ + case '(': + if (acs != NULL && acs != cs) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NULL; + } + cs = ccre; + *cs = OPER; + OSYM(cs) = '('; + ccre = ONEXT(cs); + expconv(); + OCNT(cs) = ccre - cs; /* offset to next symbol */ + break; + + /* return from a recursion */ + case ')': + if (acs != NULL) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NULL; + } + cs = ccre; + *cs = META; + MSYM(cs) = c; + ccre = MNEXT(cs); + return; + + /* Mark the last match sequence as having an alternate. */ + /* The third byte will contain an offset to jump over the */ + /* alternate match in case the first did not fail */ + case '|': + if (acs != NULL && acs != cs) + OCNT(ccre) = ccre - acs; /* make a back pointer */ + else + OCNT(ccre) = 0; + *cs |= ALT; + cs = ccre; + *cs = OPER; + OSYM(cs) = '|'; + ccre = ONEXT(cs); + acs = cs; /* remember that the pointer is to be filled */ + break; + + /* if it's not a metasymbol, just build a character string */ + default: + if (cs == NULL || (*cs & STR) == 0) { + cs = ccre; + *cs = STR; + SCNT(cs) = 1; + ccre = SSTR(cs); + } else + SCNT(cs)++; + *ccre++ = c; + break; + } + } + if (acs != NULL) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NULL; + } + return; +} /* end of @expconv()@ */ + + +/* + * The following routine recognises an irregular expression + * with the following special characters: + * + * %|\?|% means last match was optional + * %|\a|% matches any number of characters + * %|\d|% matches any number of spaces and tabs + * %|\p|% matches any number of alphanumeric characters. + * The characters matched will be copied into + * the area pointed to by @mstring@. + * %|\||% alternation + * %|\( \)|% grouping used mostly for alternation and + * optionality + * + * The irregular expression must be translated to internal form + * prior to calling this routine + * + * The value returned is the pointer to the last character matched. + * If @strtptr@ is non-@NULL@, a pointer to the start of the string matched + * (excluding %|\a|% matches) will be returned at @*strtptr@. + * If @mstring@ is non-@NULL@, the string matched by a %|\p|% will be copied + * into @mstring@. + */ + +boolean _escaped; /* true if we are currently @_escaped@ */ +char *_sstart; /* start of string. Set in @putScp()@. */ + + +char *expmatch( + register char *s, /* string to check for a match in */ + register char *re, /* a converted irregular expression */ + char **strtptr, /* where to put ptr to start of match */ + char *mstring) /* where to put whatever matches a %|\p|% */ +{ + register char *cs; /* the current symbol */ + register char *ptr, *s1; /* temporary pointer */ + register char c; /* temporary */ + boolean matched; /* a temporary @boolean@ */ + + /* initial conditions */ + if (strtptr) + *strtptr = '\0'; + if (re == NULL) + return NULL; + cs = re; + matched = FALSE; + + /* loop till expression string is exhausted (or at least pretty tired) */ + while (*cs) { + switch (*cs & (OPER | STR | META)) { + + /* try to match a string */ + case STR: + matched = !((*re_strncmp)(s, SSTR(cs), SCNT(cs))); + if (matched) { + + /* hoorah: it matches */ + s += SCNT(cs); + cs = SNEXT(cs); + } else if (*cs & ALT) { + + /* alternation: skip to next expression */ + cs = SNEXT(cs); + } else if (*cs & OPT) { + + /* the match is optional */ + cs = SNEXT(cs); + matched = 1; /* indicate a successful match */ + } else { + + /* no match: error return */ + return NULL; + } + break; + + /* an operator: do something fancy */ + case OPER: + switch (OSYM(cs)) { + + /* this is an alternation */ + case '|': + if (matched) + + /* last thing in the alternation was a match: skip ahead */ + cs = OPTR(cs); + else + + /* no match: keep trying */ + cs = ONEXT(cs); + break; + + /* this is a grouping: recurse */ + case '(': + ptr = expmatch(s, ONEXT(cs), strtptr, mstring); + if (ptr != NULL) { + + /* the subexpression matched */ + matched = 1; + s = ptr; + } else if (*cs & ALT) { + + /* alternation: skip to next expression */ + matched = 0; + } else if (*cs & OPT) { + + /* the match is optional */ + matched = 1; /* indicate a successful match */ + } else { + + /* no match: error return */ + return NULL; + } + cs = OPTR(cs); + break; + } + break; + + /* try to match a metasymbol */ + case META: + switch (MSYM(cs)) { + + /* try to match anything and remember what was matched */ + case 'p': + /* + * This is really the same as trying the match the + * remaining parts of the expression to any subset + * of the string. + */ + s1 = s; + do { + ptr = expmatch(s1, MNEXT(cs), strtptr, mstring); + if (ptr != NULL && s1 != s) { + + /* we have a match: remember the match */ + if (mstring) { + strncpy(mstring, s, (size_t)(s1 - s)); + mstring[(int)(s1 - s)] = '\0'; + } + return ptr; + + } else if (ptr != NULL && (*cs & OPT)) { + + /* %|\p|% was optional, so no match is ok */ + return ptr; + + } else if (ptr != NULL) { + + /* not optional and we still matched */ + return NULL; + } + if (!isalnum(*s1) && !strchr(l_id, *s1)) + return NULL; + if (*s1 == '\\') + _escaped = _escaped ? FALSE : TRUE; + else + _escaped = FALSE; + } while (*s1++); + return NULL; + + /* try to match anything */ + case 'a': + /* + * This is really the same as trying the match the + * remaining parts of the expression to any subset + * of the string. + */ + s1 = s; + do { + /* + * Hack for an important special case: if the next thing + * in the pattern is a string, just gobble characters until + * we find something that matches that string (this saves + * the cost of a recursive call on @expmatch()@ while scanning + * for the start of comments or strings). Since many + * patterns end with a string, we also treat that as a + * special case. + */ + if(*(ptr = MNEXT(cs)) == STR) { + c = *SSTR(ptr); + while(*s1 && *s1 != c) + s1++; + + if (*s1 == 0) + return NULL; + + if (SNEXT(ptr) == 0 && (s1 != s || *cs & OPT)) { + /* next item is a string, it's the last item and + * the %|\a|% match is ok --- just loop to try & match + * the string. + */ + if (strtptr) + *strtptr = s1; + + cs = ptr; + s = s1; + break; + } + } + ptr = expmatch(s1, MNEXT(cs), strtptr, mstring); + if (ptr != NULL && (s1 != s || *cs & OPT)) { + + /* we have a match */ + if (strtptr) + *strtptr = s1; + + return ptr; + + } else if (ptr != NULL) { + + /* not optional and we still matched */ + return NULL; + } + if (*s1 == '\\') + _escaped = _escaped ? FALSE : TRUE; + else + _escaped = FALSE; + } while (*s1++); + return NULL; + + /* fail if we are currently @_escaped@ */ + case 'e': + if (_escaped) + return NULL; + cs = MNEXT(cs); + break; + + /* match any number of tabs and spaces */ + case 'd': + ptr = s; + while (*s == ' ' || *s == '\t') + s++; + + if (s != ptr || s == _sstart) { + + /* match: be happy */ + matched = 1; + cs = MNEXT(cs); + } else if (*s == '\n' || *s == '\0') { + + /* match: be happy */ + matched = 1; + cs = MNEXT(cs); + } else if (*cs & ALT) { + + /* try the next part */ + matched = 0; + cs = MNEXT(cs); + } else if (*cs & OPT) { + + /* doesn't matter */ + matched = 1; + cs = MNEXT(cs); + } else + + /* no match: error return */ + return NULL; + + break; + + /* check for end of line */ + case '$': + if (*s == '\0' || *s == '\n') { + + /* match: be happy */ + /* s++; was here + * removed; now $ is left in stream to be matched again, which + * is not bad (EOL can end several things at once. Also it + * leaves things like CE on the same line. + */ + matched = 1; + cs = MNEXT(cs); + } else if (*cs & ALT) { + + /* try the next part */ + matched = 0; + cs = MNEXT(cs); + } else if (*cs & OPT) { + + /* doesn't matter */ + matched = 1; + cs = MNEXT(cs); + } else + + /* no match: error return */ + return NULL; + break; + + /* check for start of line */ + case '^': + if (s == _sstart) { + + /* match: be happy */ + matched = 1; + cs = MNEXT(cs); + } else if (*cs & ALT) { + + /* try the next part */ + matched = 0; + cs = MNEXT(cs); + } else if (*cs & OPT) { + + /* doesn't matter */ + matched = 1; + cs = MNEXT(cs); + } else + + /* no match: error return */ + return NULL; + break; + + /* end of a subexpression: return success */ + case ')': + return s; + } + break; + } + } + return s; +} diff --git a/support/lgrind/source/regexp.h b/support/lgrind/source/regexp.h new file mode 100644 index 0000000000..048a2840e5 --- /dev/null +++ b/support/lgrind/source/regexp.h @@ -0,0 +1,13 @@ +/* sccsid[] = "@(#)regexp.h 3.6 (MPi) 3/8/98"; + * rcsid[] = + * "$Id: regexp.h,v 1.3 1999/05/26 07:30:03 mike Exp $"; + * + * Created 19 February 1996 + */ + +typedef int boolean; +#define TRUE 1 +#define FALSE 0 +int lc_strncmp(const char *s1, const char *s2, size_t len); +char *convexp(char *re); +char *expmatch(register char *s, register char *re, char **strtptr, char *mstring); diff --git a/support/lgrind/source/retest.c b/support/lgrind/source/retest.c new file mode 100644 index 0000000000..9ff3572532 --- /dev/null +++ b/support/lgrind/source/retest.c @@ -0,0 +1,75 @@ +/* Test program for the regular expression routines */ + +#ifndef lint +static char sccsid[] = "@(#)retest.c 1.1 (LBL) 29/3/85"; +static char rcsid[] = + "$Id: retest.c,v 1.3 1999/05/26 07:30:03 mike Exp $"; +#endif + +#include <stdio.h> +#include <ctype.h> + +int l_onecase = 0; +char *_start; +char *_escaped; +char *convexp(); +char *expmatch(); +char *l_id="_"; + + + +main() +{ + char reg[132]; + char *ireg; + char str[132]; + char *match; + char matstr[132]; + char c; + + for (;;) { + printf ("\nexpr: "); + scanf ("%s", reg); + ireg = convexp(reg); + match = ireg; + while(*match) { + switch (*match) { + + case '\\': + case '(': + case ')': + case '|': + printf ("%c", *match); + break; + + default: + if (isalnum(*match)) + printf("%c", *match); + else + printf ("<%03o>", *match); + break; + } + match++; + } + printf("\n"); + getchar(); + for (;;) { + printf ("string: "); + match = str; + while ((c = getchar()) != '\n') + *match++ = c; + *match = 0; + if (str[0] == '#') + break; + matstr[0] = 0; + _start = str; + _escaped = 0; + match = expmatch (str, ireg, matstr); + if (match == 0) + printf ("FAILED\n"); + else + printf ("match\nmatstr = %s\n", matstr); + } + + } +} diff --git a/support/lgrind/source/v2lg.c b/support/lgrind/source/v2lg.c new file mode 100644 index 0000000000..5aa5df206f --- /dev/null +++ b/support/lgrind/source/v2lg.c @@ -0,0 +1,78 @@ +/* + * Filter a LaTeX file into an lgrind file. Convert + * \begin{verbatim}-\end{verbatim} pairs into %[ - %] pairs. Tabify + * the former verbatim environments. Convert \verb|stuff| into @stuff@. + */ + +#ifndef lint +static char sccsid[] = "@(#)v2lg.c 1.1 20/3/85"; +static char rcsid[] = + "$Id: v2lg.c,v 1.2 1999/05/25 17:01:36 mike Exp $"; +#endif + + +#include <stdio.h> +#include <string.h> + +#define FALSE 0 +#define TRUE 1 + +#define STREQ(s,t) ((*(s) == *(t)) && (!*(s) || !strcmp((s),(t)))) + + +int main(int argc, char **argv) +{ + int in_verbatim = FALSE, col, start_col; + char in[256], out[256], *ic, *oc, *verb, delim; + + while (fgets(in, sizeof(in), stdin) != NULL) { + if (in_verbatim) { + if (STREQ(in, "\\end{verbatim}\n")) { + fputs("%]\n", stdout); + in_verbatim = FALSE; + continue; + } + for (col = 0, ic = in, oc = out; *ic != '\n'; ) { + if (*ic != ' ' && *ic != '\t') { + *oc++ = *ic++; col++; + } else { /* \t == ' ' in a verbatim environment */ + start_col = col; + while (*ic == ' ' || *ic == '\t') { + if (((++col) & 7) == 0) { + *oc++ = '\t'; start_col = col; + } + ic++; + } + if ((col & 7) != 0) + for ( ; start_col < col; start_col++) + *oc++ = ' '; + } + } + *oc++ = '\n'; *oc++ = '\0'; + fputs(out, stdout); + continue; + } + if (STREQ(in, "\\begin{verbatim}\n")) { + fputs("%[\n", stdout); + in_verbatim = TRUE; + continue; + } + for (ic = in; (verb = strstr(ic, "\\verb")) != NULL; ) { + for ( ; ic < verb; ic++) + putchar(*ic); + ic += 5; /* Skip over \verb */ + if (*ic == '*') /* \verb* => funny-looking spaces */ + ic++; + delim = *ic++; /* the delimiter char */ + putchar('@'); + while (*ic != delim) { + putchar(*ic); ic++; + } + ic++; /* Skip the other delimiter */ + putchar('@'); + } + fputs(ic, stdout); + } + return 0; +} + |