summaryrefslogtreecommitdiff
path: root/Build/source/utils/vlna
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:16:42 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:16:42 +0000
commita3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (patch)
treef4a8a34f904c1bb86adcc3ae0e14434badc6dbe4 /Build/source/utils/vlna
parent6c0eafbb1395d426a72a74538e0b2a95e8344ca6 (diff)
utils 1
git-svn-id: svn://tug.org/texlive/trunk@1484 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/vlna')
-rw-r--r--Build/source/utils/vlna/Makefile53
-rw-r--r--Build/source/utils/vlna/README68
-rw-r--r--Build/source/utils/vlna/csmac.tex63
-rw-r--r--Build/source/utils/vlna/depend.mak3
-rw-r--r--Build/source/utils/vlna/vlna.c827
-rw-r--r--Build/source/utils/vlna/vlna.dvibin0 -> 6968 bytes
-rwxr-xr-xBuild/source/utils/vlna/vlna.exebin0 -> 13666 bytes
-rw-r--r--Build/source/utils/vlna/vlna.man130
-rw-r--r--Build/source/utils/vlna/vlna.txt121
-rw-r--r--Build/source/utils/vlna/vlna.w1003
-rw-r--r--Build/source/utils/vlna/win32.mak56
11 files changed, 2324 insertions, 0 deletions
diff --git a/Build/source/utils/vlna/Makefile b/Build/source/utils/vlna/Makefile
new file mode 100644
index 00000000000..4b6c40e0c4a
--- /dev/null
+++ b/Build/source/utils/vlna/Makefile
@@ -0,0 +1,53 @@
+
+DESTDIR=/usr/local
+MANEXT=1
+BINDIR=$(DESTDIR)/bin
+MANDIR=$(DESTDIR)/man/man$(MANEXT)
+
+CC=cc
+INSTALL=install
+MKDIR=mkdir -p
+INSTPROGFLAGS=-s -m755
+INSTDATAFLAGS=-m644
+
+CFLAGS=-O
+LFLAGS=
+
+CTANGLE=ctangle
+CWEAVE=cweave
+TEX=csplain
+
+all: vlna
+
+vlna: vlna.c
+ $(CC) $(CFLAGS) $(LFLAGS) $? -o $@
+
+install: all install.man
+ @if [ -d $(BINDIR) ]; then \
+ set +x; else (set -x; $(MKDIR) $(BINDIR)); fi
+ $(INSTALL) $(INSTPROGFLAGS) vlna $(BINDIR)/vlna
+
+install.man:
+ sed -e "s|@BINDIR@|$(BINDIR)|;\
+ s|@MANDIR@|$(MANDIR)|;\
+ s|@MANEXT@|$(MANEXT)|" vlna.man > vlna.$(MANEXT)
+ @if [ -d $(MANDIR) ]; then \
+ set +x; else (set -x; $(MKDIR) $(MANDIR)); fi
+ $(INSTALL) $(INSTDATAFLAGS) vlna.$(MANEXT) $(MANDIR)/vlna.$(MANEXT)
+
+vlna.c: vlna.w
+ $(CTANGLE) $? - $@
+
+vlna.tex: vlna.w
+ $(CWEAVE) $? - $@
+
+vlna.dvi: vlna.tex
+ $(TEX) $?
+
+clean:
+ rm -f *.o *~ *.bak core a.out vlna vlna.$(MANEXT)
+ rm -f vlna.idx vlna.scn vlna.toc vlna.log vlna.tex
+
+cleanall: clean
+ rm -f vlna.c vlna.dvi
+
diff --git a/Build/source/utils/vlna/README b/Build/source/utils/vlna/README
new file mode 100644
index 00000000000..d8770c53099
--- /dev/null
+++ b/Build/source/utils/vlna/README
@@ -0,0 +1,68 @@
+
+VLNA v1.2
+=========
+
+Program vlna přidává vlnky (místo původních mezer) za neslabičné předložky
+ve vstupních souborech pro TeX. To zabrání zlomu řádku v nežádoucím místě.
+
+Obsah distribuce:
+-----------------
+
+README ... tento soubor (formát UNIX, ISO 8859-2),
+vlna.txt ... manuál k programu (formát UNIX, ISO 8859-2),
+Makefile ... soubor pro program make
+vlna.w ... zdrojový text programu v jazyce CWEB (formát UNIX, ISO 8859-2),
+vlna.c ... výstup z ctangle vlna (program v jazyce C),
+vlna.dvi ... listing programu (vyžaduje csfonty),
+ listing je vytvořen takto:
+ cweave vlna
+ csplain vlna
+vlna.man ... kostra manuálové stránky
+csmac.tex ... makra potřebná při zpracování dokumentace (formát ISO 8859-2).
+vlna.exe ... už zkompilovaný program pro DOS
+
+Instalace v DOSu:
+-----------------
+
+1) Převedení textových souborů z ISO 8859-2 do použitého kódování
+ (například programem cstocs).
+2) Je možné přímo použít připravený program vlna.exe.
+3) S vhodným překladačem a při troše štěstí lze též kompilovat program
+ jako ze zdrojových textů (například s gcc a několika UNIXovými
+ utilitami).
+
+Instalace v UNIXu:
+------------------
+
+1) Případná úprava Makefile pro přizpůsobení překladu a instalace
+ na cílovému systému.
+2) Překlad a instalace:
+ make
+ su
+ make install
+
+Šíření programu:
+----------------
+
+Program poskytuji k veřejnému použití. Pokud někdo udělá užitečné
+změny ve zdrojovém textu CWEB, chtěl bych být o tom informován. Bez
+souhlasu autora nemůže být změněný program šířen pod stejným názvem.
+Program ani jeho modifikace se nesmí prodávat.
+
+Nedávám žádnou záruku, že program nepoškodí mnohahodinovou práci,
+kterou uživatelé editovali. Program sice vytváří zálohové soubory, ale
+ty se při dalším použití programu mažou.
+
+Poděkování:
+-----------
+
+Děkuji panu Rudolfu Čejkovi za vytvoření Makefile a manuálové stranky
+k programu. Rovněž mu děkuji za odstranění drobných chyb programu, které
+se vyskytly ve verzi 1.0.
+
+28. 2. 1995 Petr Olšák
+
+verze 1.2 (20. 5. 2002):
+ oprava chyby "v<space><cr>lese" -> "v~~lese"
+ a přidání patternu pro "\uv{v lese}" -> "\uv{v~lese}".
+
diff --git a/Build/source/utils/vlna/csmac.tex b/Build/source/utils/vlna/csmac.tex
new file mode 100644
index 00000000000..0860a70f4f0
--- /dev/null
+++ b/Build/source/utils/vlna/csmac.tex
@@ -0,0 +1,63 @@
+\chyph
+\font\ninerm=csr9
+\font\eightrm=csr8
+\let\sc=\eightrm % small caps (NOT a caps-and-small-caps font)
+\font\titlefont=csr7 scaled\magstep4 % title on the contents page
+\font\ttitlefont=cstt10 scaled\magstep2 % typewriter type in title
+\def\postATL#1 #2 {\bf písmeno \\{\uppercase{\char"#1}}
+ v~.c kódu jako \tentex "#2"\egroup\par}
+\def\ATH{\X\kern-.5em:Definice pro preprocesor\X}
+\def\A{\note{Viz také sekci}} % xref for doubly defined section name
+\def\As{\note{Viz také sekce}} % xref for multiply defined section name
+\def\ET{ a~} % conjunction between two section numbers
+\def\ETs{ a~} % conjunction between the last two of several section numbers
+\def\Q{\note{Tento kód je citován v~sekci}} % xref for mention of a section
+\def\Qs{\note{Tento kód je citován v~sekcích}} % xref for mentions of a section
+\def\U{\note{Tento kód je použit v~sekci}} % xref for use of a section
+\def\Us{\note{Tento kód je použit v~sekcích}} % xref for uses of a section
+\def\ch{\note{Následující sekce byly změněny prostřednictvím změnového
+ souboru:} \let\*=\relax}
+\def\fin{\par\vfill\eject % this is done when we are ending the index
+ \ifpagesaved\null\vfill\eject\fi % output a null index column
+ \if L\lr\else\null\vfill\eject\fi % finish the current page
+ \parfillskip 0pt plus 1fil
+ \def\grouptitle{NÁZVY SEKCÍ}
+ \let\topsecno=\nullsec
+ \message{Section names:}
+ \output={\normaloutput\page\lheader\rheader}
+ \setpage
+ \def\note##1##2.{\quad{\eightrm##1~##2.}}
+ \def\Q{\note{Citováno v~sekci}} % crossref for mention of a section
+ \def\Qs{\note{Citováno v~sekcích}} % crossref for mentions of a section
+ \def\U{\note{Použito v~sekci}} % crossref for use of a section
+ \def\Us{\note{Použito v~sekcích}} % crossref for uses of a section
+ \def\I{\par\hangindent 2em}\let\*=*
+ \readsections}
+\def\contentsline#1#2#3#4{\ifnum#2=0 \smallbreak\fi
+ \line{\consetup{#2}#1
+ \rm\leaders\hbox to .5em{.\hfil}\hfil\ #3\hbox to4em{\hss#4}}}
+\def\con{\par\vfill\eject % finish the section names
+% \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
+ \rightskip 0pt \hyphenpenalty 50 \tolerance 200
+ \setpage \output={\normaloutput\page\lheader\rheader}
+ \titletrue % prepare to output the table of contents
+ \pageno=\contentspagenumber
+ \def\grouptitle{OBSAH}
+ \message{Table of contents:}
+ \topofcontents
+ \line{\hfil Sekce\hbox to4em{\hss Strana}}
+ \let\ZZ=\contentsline
+ \readcontents\relax % read the contents info
+ \botofcontents \end} % print the contents page(s) and terminate
+\def\today{\number\day.~\ifcase\month\or ledna\or února\or března\or
+ dubna\or května\or června\or července\or srpna\or září\or října\or
+ listopadu\or prosince\fi \space\number\year}
+\def\datethis{\def\startsection{\leftline{\sc\today\ v~\hours}\bigskip
+ \let\startsection=\stsec\stsec}}
+\def\datecontentspage{%
+ \def\topofcontents{\leftline{\sc\today\ v~\hours}\bigskip
+ \centerline{\titlefont\title}\vfill}} % timestamps the contents page
+
+\def\allowhyphens{\nobreak\hskip0pt\relax}
+\def \uv#1{\char254 \allowhyphens#1\allowhyphens\char255 }
+
diff --git a/Build/source/utils/vlna/depend.mak b/Build/source/utils/vlna/depend.mak
new file mode 100644
index 00000000000..1a3ea97100b
--- /dev/null
+++ b/Build/source/utils/vlna/depend.mak
@@ -0,0 +1,3 @@
+$(objdir)/vlna.obj: \
+
+
diff --git a/Build/source/utils/vlna/vlna.c b/Build/source/utils/vlna/vlna.c
new file mode 100644
index 00000000000..6e4ae12493c
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.c
@@ -0,0 +1,827 @@
+#define BANNER "This is program vlna, version 1.2, (c) 1995, 2002 Petr Olsak\n" \
+
+#define OK 0
+#define WARNING 1
+#define IO_ERR 2
+#define BAD_OPTIONS 3
+#define BAD_PROGRAM 4
+#define MAXLEN 120
+#define ONE 1
+#define ANY 2
+#define ONE_NOT -1
+#define ANY_NOT -2 \
+
+#define MAXPATT 200
+#define MAXBUFF 500
+#define BUFI 300
+#define FOUND -1
+#define NOFOUND -2
+#define TEXTMODE 0
+#define MATHMODE 1
+#define DISPLAYMODE 2
+#define VERBMODE 3
+/*1:*/
+#line 19 "vlna.w"
+
+/*3:*/
+#line 39 "vlna.w"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*:3*/
+#line 20 "vlna.w"
+
+/*4:*/
+#line 56 "vlna.w"
+
+char*prog_name;
+int status;
+
+/*:4*//*7:*/
+#line 133 "vlna.w"
+
+int isfilter= 0,silent= 0,rmbackup= 0,nomath= 0,noverb= 0,web= 0,latex= 0;
+char charsetdefault[]= "KkSsVvZzOoUuAI";
+char*charset= charsetdefault;
+
+/*:7*//*15:*/
+#line 291 "vlna.w"
+
+typedef struct PATITEM{
+char*str;
+int flag;
+struct PATITEM*next;
+}PATITEM;
+typedef struct PATTERN{
+PATITEM*patt;
+void(*proc)();
+struct PATTERN*next;
+}PATTERN;
+
+/*:15*//*16:*/
+#line 343 "vlna.w"
+
+PATITEM*lapi[MAXPATT];
+PATTERN*lapt[MAXPATT];
+PATTERN*listpatt,*normallist,*commentlist,*pt,*lastpt= NULL;
+PATITEM*pi,*lastpi= NULL;
+char c;
+char buff[MAXBUFF];
+int ind;
+
+/*:16*//*20:*/
+#line 417 "vlna.w"
+
+char strings[512];
+int i;
+
+/*:20*//*25:*/
+#line 505 "vlna.w"
+
+char*filename;
+long int numline,numchanges;
+int mode;
+
+/*:25*//*33:*/
+#line 636 "vlna.w"
+
+char tblanks[]= " ~\t";
+char blanks[]= " \t";
+char blankscr[]= " \t\n";
+char tblankscr[]= " ~\t\n";
+char nochar[]= "%~\n";
+char cr[]= "\n";
+char prefixes[]= "[({~";
+char dolar[]= "$";
+char backslash[]= "\\";
+char openbrace[]= "{";
+char letters[]= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+PATTERN*vlnkalist,*mathlist,*parcheck,*verblist;
+
+/*:33*/
+#line 21 "vlna.w"
+
+/*6:*/
+#line 110 "vlna.w"
+
+void printusage()
+{
+fprintf(stderr,
+"usage: vlna [opt] [filenames]\n"
+" opt -f : filter mode: file1 file2 ... file1->file2\n"
+" file1 ... file1->stdout\n"
+" ... stdin->stdout\n"
+" nofilter: file1 [file2 file3 ...] all are in/out\n"
+" -s : silent: no messages to stderr\n"
+" -r : rmbackup: if nofilter, removes temporary files\n"
+" -v charset : set of lettres to add tie, default: KkSsVvZzOoUuAI\n"
+" -m : nomath: ignores math modes\n"
+" -n : noverb: ignores verbatim modes\n"
+" -l : LaTeX mode\n"
+" -w : web mode\n");
+}
+
+/*:6*//*10:*/
+#line 167 "vlna.w"
+
+void ioerr(f)
+char*f;
+{
+fprintf(stderr,"%s: cannot open file %s\n",prog_name,f);
+}
+
+/*:10*//*17:*/
+#line 356 "vlna.w"
+
+void*myalloc(size)
+int size;
+{
+void*p;
+p= malloc(size);
+if(p==NULL)
+{
+fprintf(stderr,"%s, no memory, malloc failed\n",prog_name);
+exit(BAD_PROGRAM);
+}
+return p;
+}
+
+/*:17*//*18:*/
+#line 374 "vlna.w"
+
+PATTERN*setpattern(proc)
+void(*proc)();
+{
+PATTERN*pp;
+pp= myalloc(sizeof(PATTERN));
+pp->proc= proc;
+pp->next= NULL;
+pp->patt= NULL;
+if(lastpt!=NULL)lastpt->next= pp;
+lastpt= pp;
+lastpi= NULL;
+return pp;
+}
+
+/*:18*//*19:*/
+#line 393 "vlna.w"
+
+void setpi(str,flag)
+char*str;
+int flag;
+{
+PATITEM*p;
+p= myalloc(sizeof(PATITEM));
+p->str= str;p->flag= flag;
+p->next= NULL;
+if(lastpi==NULL)lastpt->patt= p;
+else lastpi->next= p;
+lastpi= p;
+}
+
+/*:19*//*22:*/
+#line 428 "vlna.w"
+
+PATTERN*normalpattern(proc,str)
+void(*proc)();
+char*str;
+{
+PATTERN*pp;
+int j= 0;
+pp= setpattern(proc);
+while(str[j]){
+if(str[j]=='.'){
+j++;
+if(str[j]!='.'){
+setpi(blankscr,ANY);
+continue;
+}
+}
+setpi(&strings[(unsigned char)str[j]*2],ONE);
+j++;
+}
+return pp;
+}
+
+/*:22*//*23:*/
+#line 466 "vlna.w"
+
+int match(p)
+PATITEM*p;
+{
+int m;
+if(strchr(p->str,c)!=NULL)m= 1;
+else m= -1;
+switch(m*p->flag){
+case ANY:return 0;
+case ONE:if(p->next==NULL)return FOUND;
+return 1;
+case ONE_NOT:return NOFOUND;
+case ANY_NOT:/*24:*/
+#line 485 "vlna.w"
+
+switch(m= match(p->next)){
+case NOFOUND:return NOFOUND;
+case FOUND:return FOUND;
+default:return 1+m;
+}
+
+/*:24*/
+#line 478 "vlna.w"
+;
+}
+return 0;
+}
+
+/*:23*//*36:*/
+#line 669 "vlna.w"
+
+void vlnkain()
+{
+char p;
+ind--;
+p= buff[ind--];
+while(strchr(blanks,buff[ind])!=NULL)ind--;
+ind++;
+buff[ind++]= '~';
+buff[ind++]= p;
+numchanges++;
+}
+
+/*:36*//*38:*/
+#line 708 "vlna.w"
+
+void vlnkacr()
+{
+char p;
+int i,j;
+ind--;
+p= buff[ind--];
+while(strchr(blankscr,buff[ind])!=NULL)ind--;
+i= ind;
+while(i>=0&&(strchr(blankscr,buff[i])==NULL))i--;
+j= i;
+while(i>=0&&(strchr(blanks,buff[i])!=NULL))i--;
+if(i>=0&&buff[i]=='\n')j= -1;
+if(j>=0)buff[j]= '\n';
+else numline--;
+ind++;
+buff[ind++]= '~';
+buff[ind++]= p;
+numchanges++;
+}
+
+/*:38*//*41:*/
+#line 774 "vlna.w"
+
+void tielock()
+{
+c= 1;
+}
+
+/*:41*//*42:*/
+#line 783 "vlna.w"
+
+void printwarning()
+{
+if(!silent)
+fprintf(stderr,
+"~!~ warning: text/math/verb mode mismatch, file: %s, line: %ld\n",
+filename,numline-(c=='\n'?1:0));
+status= WARNING;
+}
+
+/*:42*//*44:*/
+#line 808 "vlna.w"
+
+void mathin()
+{
+if(mode!=TEXTMODE)printwarning();
+mode= MATHMODE;
+normallist= listpatt= mathlist;
+}
+void mathout()
+{
+if(mode!=MATHMODE)printwarning();
+mode= TEXTMODE;
+normallist= listpatt= vlnkalist;
+}
+
+/*:44*//*45:*/
+#line 826 "vlna.w"
+
+void onedollar()
+{
+if(buff[ind-3]=='\\'||(buff[ind-3]=='$'&&buff[ind-4]!='\\'))return;
+if(mode==DISPLAYMODE)printwarning();
+else{
+if(mode==TEXTMODE)mathin();
+else mathout();
+}
+}
+
+/*:45*//*47:*/
+#line 845 "vlna.w"
+
+void checkmode()
+{
+if(mode!=TEXTMODE){
+printwarning();
+mode= TEXTMODE;
+normallist= listpatt= vlnkalist;
+}
+}
+
+/*:47*//*49:*/
+#line 871 "vlna.w"
+
+void displayin()
+{
+if(mode!=TEXTMODE)printwarning();
+mode= DISPLAYMODE;normallist= listpatt= parcheck;
+}
+void displayout()
+{
+if(mode!=DISPLAYMODE)printwarning();
+mode= TEXTMODE;normallist= listpatt= vlnkalist;
+}
+void twodollars()
+{
+if(buff[ind-3]=='\\')return;
+if(mode==DISPLAYMODE)displayout();
+else displayin();
+}
+
+/*:49*//*51:*/
+#line 920 "vlna.w"
+
+int prevmode;
+PATTERN*prevlist,*verboutlist[4];
+char verbchar[2];
+void verbinchar()
+{
+prevmode= mode;
+verbchar[0]= c;
+c= 1;
+listpatt= normallist= verboutlist[0];
+prevlist= listpatt->next;
+listpatt->next= NULL;
+mode= VERBMODE;
+}
+
+/*:51*//*52:*/
+#line 941 "vlna.w"
+
+void verbin()
+{
+int i;
+i= 0;
+prevmode= mode;
+switch(c){
+case't':i= 1;break;
+case'm':i= 2;break;
+case'<':;
+case'd':i= 3;
+if(buff[ind-3]=='@')return;
+break;
+}
+listpatt= normallist= verboutlist[i];
+prevlist= listpatt->next;
+if(c!='<'&&c!='d')listpatt->next= NULL;
+mode= VERBMODE;
+}
+
+/*:52*//*53:*/
+#line 961 "vlna.w"
+
+void verbout()
+{
+if(mode!=VERBMODE)return;
+if(web&&buff[ind-2]=='@'&&buff[ind-3]=='@')return;
+mode= prevmode;
+normallist->next= prevlist;
+switch(mode){
+case DISPLAYMODE:normallist= listpatt= parcheck;break;
+case MATHMODE:normallist= listpatt= mathlist;break;
+case TEXTMODE:normallist= listpatt= vlnkalist;break;
+}
+}
+
+/*:53*//*55:*/
+#line 983 "vlna.w"
+
+void tieoff()
+{
+normallist= NULL;
+}
+void tieon()
+{
+normallist= vlnkalist;
+}
+
+/*:55*/
+#line 22 "vlna.w"
+
+/*26:*/
+#line 514 "vlna.w"
+
+void tie(input,output)
+FILE*input,*output;
+{
+int ap;
+register int k,m,n;
+int ic;
+PATTERN*pp;
+PATITEM*pi;
+
+/*27:*/
+#line 545 "vlna.w"
+
+for(k= 0;k<MAXPATT;k++)lapi[k]= NULL;
+c= '\n';
+buff[0]= mode= ap= 0;ind= 1;
+numline= 1;numchanges= 0;
+mode= TEXTMODE;
+
+/*:27*//*35:*/
+#line 666 "vlna.w"
+
+listpatt= normallist= vlnkalist;
+
+/*:35*/
+#line 524 "vlna.w"
+;
+
+while(!feof(input)){
+/*30:*/
+#line 590 "vlna.w"
+
+pp= listpatt;
+while(pp!=NULL){
+switch(m= match(pp->patt)){
+case FOUND:(*pp->proc)();
+case NOFOUND:break;
+default:/*31:*/
+#line 605 "vlna.w"
+
+pi= pp->patt;
+while(m--)pi= pi->next;
+n= ap;k= 0;
+while(n){
+if(lapi[k]==pi)break;
+if(lapi[k++]!=NULL)n--;
+}
+if(!n){
+k= 0;
+while(lapi[k]!=NULL)k++;
+if(k>=MAXPATT){
+fprintf(stderr,"I cannot allocate pp, is anything wrong?\n");
+exit(BAD_PROGRAM);
+}
+lapt[k]= pp;lapi[k]= pi;ap++;
+}
+
+/*:31*/
+#line 596 "vlna.w"
+;
+}
+pp= pp->next;
+}
+
+/*:30*/
+#line 527 "vlna.w"
+;
+if(ap==0&&ind> BUFI&&c!='\\')/*28:*/
+#line 560 "vlna.w"
+
+{
+buff[ind]= 0;
+fputs(&buff[1],output);
+ind= 1;
+}
+
+/*:28*/
+#line 528 "vlna.w"
+;
+if(ind>=MAXBUFF){
+fprintf(stderr,"Operating buffer overflow, is anything wrong?\n");
+exit(BAD_PROGRAM);
+}
+if((ic= getc(input))==EOF)
+break;
+buff[ind++]= c= ic;
+if(c=='\n')numline++,listpatt= normallist;
+if(c=='%'&&mode!=VERBMODE&&buff[ind-2]!='\\')listpatt= commentlist;
+/*29:*/
+#line 573 "vlna.w"
+
+n= ap;k= 0;
+while(n){
+while(lapi[k]==NULL)k++;
+switch(m= match(lapi[k])){
+case FOUND:(*lapt[k]->proc)();
+case NOFOUND:lapi[k]= NULL;
+ap--;break;
+default:while(m--)lapi[k]= lapi[k]->next;
+}
+k++;n--;
+}
+
+/*:29*/
+#line 538 "vlna.w"
+;
+}
+/*28:*/
+#line 560 "vlna.w"
+
+{
+buff[ind]= 0;
+fputs(&buff[1],output);
+ind= 1;
+}
+
+/*:28*/
+#line 540 "vlna.w"
+;
+if(!web)checkmode();
+if(!silent)/*32:*/
+#line 624 "vlna.w"
+
+fprintf(stderr,"~~~ file: %s\t lines: %ld, changes: %ld\n",
+filename,numline,numchanges);
+
+/*:32*/
+#line 542 "vlna.w"
+;
+}
+
+/*:26*/
+#line 23 "vlna.w"
+
+/*5:*/
+#line 61 "vlna.w"
+
+int main(argc,argv)
+int argc;
+char**argv;
+{
+/*9:*/
+#line 160 "vlna.w"
+
+FILE*infile,*outfile;
+char backup[MAXLEN];
+int j;
+
+/*:9*/
+#line 66 "vlna.w"
+;
+prog_name= argv[0];status= OK;
+/*8:*/
+#line 138 "vlna.w"
+
+while(argc> 1&&argv[1][0]=='-'){
+if(argv[1][2]!=0)printusage(),exit(BAD_OPTIONS);
+switch(argv[1][1]){
+case'f':isfilter= 1;break;
+case's':silent= 1;break;
+case'r':rmbackup= 1;break;
+case'v':argv++;argc--;charset= argv[1];break;
+case'm':nomath= 1;break;
+case'n':noverb= 1;break;
+case'l':latex= 1;break;
+case'w':web= 1;break;
+default:printusage(),exit(BAD_OPTIONS);
+
+}
+argc--;argv++;
+}
+
+/*:8*/
+#line 68 "vlna.w"
+;
+if(!silent)fprintf(stderr,BANNER);
+/*21:*/
+#line 422 "vlna.w"
+
+for(i= 0;i<256;i++){
+strings[2*i]= (char)i;strings[2*i+1]= 0;
+}
+
+/*:21*//*34:*/
+#line 656 "vlna.w"
+
+vlnkalist= setpattern(vlnkain);
+setpi(tblankscr,ONE);
+setpi(tblanks,ANY);
+setpi(prefixes,ANY);
+setpi(charset,ONE);
+setpi(blanks,ONE);
+setpi(blanks,ANY);
+setpi(nochar,ONE_NOT);
+
+/*:34*//*37:*/
+#line 684 "vlna.w"
+
+setpattern(vlnkacr);
+setpi(tblankscr,ONE);
+setpi(tblanks,ANY);
+setpi(prefixes,ANY);
+setpi(charset,ONE);
+setpi(blanks,ANY);
+setpi(cr,ONE);
+setpi(blanks,ANY);
+setpi(nochar,ONE_NOT);
+
+/*:37*//*39:*/
+#line 730 "vlna.w"
+
+setpattern(vlnkain);
+setpi(tblankscr,ONE);
+setpi(backslash,ONE);
+setpi(letters,ONE);
+setpi(letters,ANY);
+setpi(openbrace,ONE);
+setpi(prefixes,ANY);
+setpi(charset,ONE);
+setpi(blanks,ONE);
+setpi(blanks,ANY);
+setpi(nochar,ONE_NOT);
+
+setpattern(vlnkacr);
+setpi(tblankscr,ONE);
+setpi(backslash,ONE);
+setpi(letters,ONE);
+setpi(letters,ANY);
+setpi(openbrace,ONE);
+setpi(prefixes,ANY);
+setpi(charset,ONE);
+setpi(blanks,ANY);
+setpi(cr,ONE);
+setpi(blanks,ANY);
+setpi(nochar,ONE_NOT);
+
+
+
+/*:39*//*40:*/
+#line 763 "vlna.w"
+
+normalpattern(tielock,"\\TeX");
+setpi(blankscr,ONE);
+normalpattern(tielock,"\\LaTeX");
+setpi(blankscr,ONE);
+
+/*:40*//*43:*/
+#line 797 "vlna.w"
+
+if(!nomath){
+mathlist= setpattern(onedollar);
+setpi(dolar,ONE);
+setpi(dolar,ONE_NOT);
+if(latex){
+normalpattern(mathin,"\\begin.{math}");
+normalpattern(mathout,"\\end.{math}");
+}
+}
+
+/*:43*//*46:*/
+#line 839 "vlna.w"
+
+parcheck= setpattern(checkmode);
+setpi(cr,ONE);
+setpi(blanks,ANY);
+setpi(cr,ONE);
+
+/*:46*//*48:*/
+#line 860 "vlna.w"
+
+if(!nomath){
+normalpattern(twodollars,"$$");
+if(latex){
+normalpattern(displayin,"\\begin.{displaymath");
+normalpattern(displayin,"\\begin.{equation");
+normalpattern(displayout,"\\end.{displaymath");
+normalpattern(displayout,"\\end.{equation");
+}
+}
+
+/*:48*//*50:*/
+#line 892 "vlna.w"
+
+if(!noverb){
+verblist= normalpattern(verbinchar,"\\verb");
+setpi(blankscr,ANY);
+setpi(blankscr,ONE_NOT);
+normalpattern(verbin,"\\begtt");
+if(latex)normalpattern(verbin,"\\begin.{verbatim");
+}
+if(web){
+normalpattern(verbin,"@<");
+normalpattern(verbin,"@d");
+}
+if(!noverb){
+verboutlist[0]= setpattern(verbout);
+setpi(verbchar,ONE);
+verboutlist[1]= normalpattern(verbout,"\\endtt");
+if(latex)verboutlist[2]= normalpattern(verbout,"\\end{verbatim");
+}
+if(web){
+verboutlist[3]= normalpattern(verbout,"@ ");
+normalpattern(verbout,"@*");
+normalpattern(verbout,"@>|");
+}
+
+
+/*:50*//*54:*/
+#line 978 "vlna.w"
+
+lastpt= 0;
+commentlist= normalpattern(tieoff,"%.~.-");
+normalpattern(tieon,"%.~.+");
+
+/*:54*/
+#line 70 "vlna.w"
+;
+/*11:*/
+#line 175 "vlna.w"
+
+if(isfilter)/*12:*/
+#line 187 "vlna.w"
+
+{
+if(argc> 3)printusage(),exit(BAD_OPTIONS);
+infile= stdin;outfile= stdout;
+if(argc>=2)infile= fopen(argv[1],"r");
+if(infile==NULL)ioerr(argv[1]),exit(IO_ERR);
+if(argc==3)outfile= fopen(argv[2],"w");
+if(outfile==NULL)ioerr(argv[2]),exit(IO_ERR);
+if(argc>=2)filename= argv[1];
+else filename= NULL;
+tie(infile,outfile);
+if(outfile!=stdout)fclose(outfile);
+if(infile!=stdin)fclose(infile);
+}
+
+/*:12*/
+#line 176 "vlna.w"
+
+else/*13:*/
+#line 210 "vlna.w"
+
+{
+if(argc==1)printusage(),exit(BAD_OPTIONS);
+while(argc> 1){
+argc--;argv++;
+/*14:*/
+#line 241 "vlna.w"
+
+infile= NULL;
+j= strlen(argv[0])-1;
+if(j>=MAXLEN||argv[0][j]=='~'){
+if(!silent)fprintf(stderr,"%s: the conflict of file name %s\n",
+prog_name,argv[0]);
+}
+else{
+strcpy(backup,argv[0]);
+backup[j]= '~';
+remove(backup);
+j= rename(argv[0],backup);
+if(j==0)infile= fopen(backup,"r");
+}
+
+/*:14*/
+#line 215 "vlna.w"
+;
+if(infile==NULL){
+ioerr(argv[0]);continue;
+}
+outfile= fopen(argv[0],"w");
+if(outfile==NULL){
+ioerr(argv[0]);
+rename(backup,argv[0]);
+status= WARNING;
+continue;
+}
+filename= argv[0];
+tie(infile,outfile);
+fclose(outfile),fclose(infile);
+if(rmbackup)remove(backup);
+}
+}
+
+/*:13*/
+#line 177 "vlna.w"
+
+
+/*:11*/
+#line 71 "vlna.w"
+;
+return status;
+}
+
+/*:5*/
+#line 24 "vlna.w"
+
+
+/*:1*/
diff --git a/Build/source/utils/vlna/vlna.dvi b/Build/source/utils/vlna/vlna.dvi
new file mode 100644
index 00000000000..0bf8718cd48
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.dvi
Binary files differ
diff --git a/Build/source/utils/vlna/vlna.exe b/Build/source/utils/vlna/vlna.exe
new file mode 100755
index 00000000000..b096673d835
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.exe
Binary files differ
diff --git a/Build/source/utils/vlna/vlna.man b/Build/source/utils/vlna/vlna.man
new file mode 100644
index 00000000000..0470461370a
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.man
@@ -0,0 +1,130 @@
+.\" $Id$
+.TH VLNA 1 "4. unora 1998"
+.nh
+.SH NAZEV
+vlna \- pridani vlnek za neslabicne predlozky v TeXu
+.SH POUZITI
+.B vlna
+[\fIvolby\fP]
+[\fIsoubory\fP]
+.SH POPIS
+Program
+.B vlna
+pridava vlnky (misto puvodnich mezer) za neslabicne predlozky
+ve vstupnich souborech pro TeX, coz zabrani zlomu radku v nezadoucich mistech.
+.PP
+Veskere aktivity programu je mozne vypnout sekvenci \fB%~-\fP a zapnout
+sekvenci \fB%~+\fP (mezi uvedenymi znaky muze byt libovolne mnozstvi mezer).
+.PP
+Pred predlozkou se muze nachazet libovolne mnozstvi oteviracich zavorek,
+pred kterymi se musi nachazet mezera nebo zacatek radku. Pred
+oteviraci svorkou muze byt take misto mezery TeXova
+\(lq\\sekvence\(rq (od verze 1.2).
+Napr. za \(lq([{(V\(rq na pocatku radku bude vlnka pridana.
+Stejne tak se text \(lq\\uv{V lese}\(rq promeni na
+\(lq\\uv{V~lese}\(rq.
+.PP
+Program kontroluje konzistenci matematickych prostredi (neni-li uveden
+parametr \fB\-m\fP).
+Vstup do \fIdisplay\fP rezimu (\fB$$\fP) uvnitr \fItext\fP rezimu (\fB$\fP)
+(napr. \fB$\fP...\fB$$\fP...\fB$\fP) znamena varovani a prechod do
+\fIdisplay\fP.
+Podobne prazdny radek uvnitr \fItext\fP nebo \fIdisplay\fP rezimu znamena
+vypis varovani a prechod do nematematickeho (standardniho) rezimu.
+Uvnitr rezimu \fIdisplay\fP se ignoruji vyskyty samostatneho znaku \fB$\fP,
+jelikoz byva vetsinou soucasti konstrukce \fB\\hbox\fP.
+.PP
+Program kontroluje konzistenci verbatim rezimu na konci souboru.
+Nebyl-li ukoncen, vypise se varovani.
+Kontrola se neprovadi, pokud je pouzita volba \fB\-n\fP nebo \fB\-w\fP.
+.PP
+Program nedoplnuje vlnky za samostatna pismena, ktera jako predlozky vypadaji,
+ale nasleduji bezprostredne za sekvencemi \fB\\TeX\fP nebo \fB\\LaTeX\fP.
+Napr. do textu \(lq\fBVlastnosti \\TeX u jsou\fP\(rq nebude zadna vlnka
+doplnena.
+.SH VOLBY
+Volby jsou nepovinne a mohou byt uvedeny v libovolnem poradi, ale nemohou
+byt spojovany.
+.TP
+.B \-f
+Filtr. Jmena souboru jsou interpretovana takto:
+.RS
+.TP 4
+.B vlna \-f \fIsoubor1 soubor2\fP
+Vstup je \fIsoubor1\fP, vystup \fIsoubor2\fP.
+.TP 4
+.B vlna \-f \fIsoubor1\fP
+Vstup je \fIsoubor1\fP, vystup \fIstdout\fP.
+.TP 4
+.B vlna \-f
+Vstup je \fIstdin\fP, vystup \fIstdout\fP.
+.TP 4
+\fBvlna\fP \fIsoubor1\fP [\fIsoubor2\fP [\fIsoubor3\fP ...]]
+Neni-li uveden parametr \fB\-f\fP, kazdy soubor je zpracovavan samostatne.
+.RE
+.TP
+.B \-s
+Tichy rezim. Program potlaci vypis uvodni zpravy, varovnych zprav a
+statistik o zmenach v souborech
+(bez uvedeni parametru jsou zpravy vypisovany na \fIstderr\fP).
+V tichem rezimu se vypise jen chyba, ktera predcasne ukonci
+cinnost programu.
+.TP
+.B \-r
+Nevytvaret (mazat) zalohy.
+Parametr \fB\-r\fP nema vliv, pokud je uveden spolu s \fB\-f\fP.
+V opacnem pripade se ke kazdemu souboru vytvari zaloha s vlnkou na konci jmena
+a parametr \fB\-r\fP zpusobi, ze na konci zpracovani jsou tyto zalohy mazany.
+.TP
+.B \-v \fIznaky\fP
+Znaky povazovane za neslabicne predlozky, za ktere ma byt pridavana
+vlnka. Implicitni hodnota je \fB\-v\ KkSsVvZzOoUuAI\fP. (Mezi
+\fB\-v\fP a skupinou znaku musi byt mezera.)
+.TP
+.B \-m
+Ignorovani prechodu do matematickych prostredi
+(\fB$\fP...\fB$\fP a \fB$$\fP...\fB$$\fP).
+Parametr \fB\-m\fP zpusobi vlnkovani i v matematickych prostredich, ktera
+se implicitne vynechavaji.
+.TP
+.B \-n
+Ignorovani verbatim rezimu (\fB\\verb\fP\fI<znak>\fP...\fI<znak>\fP,
+\fB\\begtt\fP...\fB\\endtt\fP).
+Parametr \fB\-n\fP zpusobi vlnkovani i ve verbatim rezimu, ktery se
+implicitne vynechava.
+.TP
+.B \-l
+LaTeX. Pro rozpoznani matematickeho rezimu jsou pridana prostredi
+\fB\\begin{display}\fP...\fB\\end{display}\fP a
+\fB\\begin{equation}\fP...\fB\\end{equation}\fP.
+Pro rozpoznani verbatim rezimu je pridano LaTeXove prostredi
+\fB\\begin{verbatim}\fP...\fB\\end{verbatim}\fP.
+.TP
+.B \-w
+Web. Pro rozpoznani verbatim rezimu jsou pridany sekvence
+\fB@<\fP, \fB@d\fP...\fB@*\fP, \fB@\fP\fImezera\fP nebo \fB@>|\fP.
+Ve zdrojovem kodu se tedy nevlnkuje program, ale jen komentare.
+.SH PRIKLADY
+.TP
+.B vlna \-m \-n \-s \-r \fIsoubor\fP
+Volani priblizne odpovida volani puvodniho programu \fBvlna\fP.
+(Navic se neprovadi vlnkovani za sekvencemi \fB\\TeX\fP a \fB\\LaTeX\fP.)
+.TP
+.B vlna *.tex
+Vlnkovani vsech souboru s priponou \fBtex\fP.
+(Pouze na UNIXu.)
+.TP
+.B vlna \-f soubor > /dev/null
+Test konzistence matematickeho a verbatim rezimu bez provedeni zmen.
+(Pouze na UNIXu.)
+.SH SOUBORY
+.PD 0
+.TP
+.I @BINDIR@/vlna
+spustitelny program
+.TP
+.I @MANDIR@/vlna.@MANEXT@
+manualova stranka
+.PD
+.SH AUTOR
+Petr Olsak <olsak@math.feld.cvut.cz>. Manualovou stranku a Makefile vytvoril Rulolf Cejka
diff --git a/Build/source/utils/vlna/vlna.txt b/Build/source/utils/vlna/vlna.txt
new file mode 100644
index 00000000000..2e50fab9e73
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.txt
@@ -0,0 +1,121 @@
+
+ Program VLNA
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ verze 1.2 Petr Olšák
+
+Program vlna přidává vlnky (místo původních mezer) za neslabičné předložky
+ve vstupních souborech pro TeX. To zabrání zlomu řádku v nežádoucím místě.
+
+Není použit název "vlnka", abychom odlišili původní program vlnka
+(autoři O. Ulrych, Š. Kasal) od tohoto programu vlna. Jedná se o
+vylepšenou a zcela nově napsanou verzi, která není důsledně zpětně
+kompatibilní s původním programem vlnka.
+
+POUŽITÍ:
+--------
+
+vlna [opt] [jména souborů]
+
+[opt] jsou nepovinné přepínače, které musí být odděleny mezerou a uvozeny
+znakem "-". Mohou být uvedeny v libovolném pořadí.
+
+PŘEPÍNAČE:
+----------
+
+-f : Režim "filtr". V tomto režimu jsou jména souborů interpretována takto:
+ vlna -f soubor1 soubor2 ... soubor1 -> soubor2 (musí: in!=out)
+ vlna -f soubor1 ... soubor1 -> stdout
+ vlna -f ... stdin -> stdout
+ Není-li program v režimu filtr, pak jsou jména souborů interpretována
+ takto:
+ vlna soubor1 [soubor2 [soubor3...]]
+ Zde je každý soubor "ovlnkován" samostatně, tj. soubory jsou měněny.
+ Není-li uveden parametr -r, jsou vytvářeny zálohy k souborům
+ s vlnkou na konci jména.
+-s : Tichý režim. Program nevypisuje úvodní zprávu, varovné zprávy a
+ statistiky o změnách v souborech. Tyto texty se vypisují do stderr,
+ takže v režimu filtr není nutné -s zapínat, pokud umíme oddělit stderr
+ od stdout. V tichém režimu se vypíše jen chyba, která předčasně ukončí
+ činnost programu.
+-r : Nevytvářet (mazat) zálohy. Není-li program v režimu filtr, pak se ke
+ každému souboru vytváří záloha s vlnkou na konci jména. Takové soubory
+ se interně vytvářejí vždy při běhu programu v režimu ne-filtr. Je-li
+ uveden parametr -r, jsou na konci zpracování tyto zálohy mazány.
+ V režimu filtr nemá -r žádný vliv.
+-v znaky : Definice znaků, které budeme považovat za neslabičné předložky,
+ tj. k ovlnkování. Implicitní hodnota -v KkSsVvZzOoUuAI je použitím
+ tohoto parametru přepsána. Mezi -v a skupinou znaků musí být mezera.
+-m : Ignoruje přechody do matematického režimu ($...$ a $$...$$) a vlnkuje
+ i v těchto prostředích. Imlicitně v matematických prostředích nevlnkuje.
+-n : Ignoruje přechody do verbatim režimu (\verb<zn>...<zn>, \begtt...\endtt)
+ a vlnkuje i v těchto prostředích.
+-l : LaTeX mód. K výše uvedeným sekvencím ohraničující display math
+ mód je přidáno \begin{display}...\end{display} a
+ \begin{equation}...\end{equation}. K sekvencím ohraničující
+ verbatim mód je přidáno \begin{verbatim}...\end{verbatim}
+-w : web mód. K sekvencím ohraničujícím verbatim mód je přidáno
+ @< nebo @d ... @* nebo @mezera nebo @>| . To způsobí, že není
+ provlnkovaný kód programu ve web souborech, ale jenom komentáře.
+
+POZNÁMKY:
+---------
+
+* Před předložkou může být libovolné množství otevíracích závorek,
+ před kterými musí být mezera nebo začátek řádku. Před otevírací
+ svorkou může také být místo mezery TeXova "\sekvence" (od verze 1.2).
+ Např. ([{(V tomto případě bude vlnka za V. Stejně tak
+ se vlnka objeví \boldfont{V tomto případě}.
+* Veškeré aktivity programu je možné vypnout sekvencí %~- a zapnout
+ sekvencí %~+ (mezi uvedenými znaky může být libovoné množství mezer)
+* Program kontroluje konzistenci matematických režimů. Dá varování
+ v těchto případech:
+ Vstup do display uvnitř t-math (např. $ ...$$... $). -- přejde do display.
+ Prázdný řádek uvnitř t-math nebo display -- přejde do standardního režimu.
+ Poznamenejme, že uvnitř display se ignorují výskyty jednoho dolaru
+ naprosto bez varování, protože ty většinou mohou být součástí \hbox-u.
+ Při -m není konzistence math. módů kontrolována.
+* Program kontroluje konzistenci verbatim módů na konci souboru.
+ Nebyl-li verbatim mód ukončen, objeví se varování. Tento test
+ neprobíhá, pokud je nastaven přepínač -n nebo -w.
+* Program nedoplňuje vlnky za písmena, která vypadají "jako"
+ předložky, ale následují bezprostředně za sekvencemi \TeX nebo
+ \LaTeX, tj. např. v textu "Vlastnosti \TeX u jsou" nepřidá vlnku
+ mezi u a j. Sekvence \TeX a \LaTeX jsou zatím natvrdo implementovány
+ do programu. Otázka čtení množiny takových sekvencí z konf. souboru
+ (nebo odjinud) bude (možná) zahrnuta v další verzi.
+
+TIPY K POUŽITÍ PROGRAMU:
+------------------------
+
+vlna -m -n -s -r soubor ... odpovídá zhruba volání původního vlnka.
+Není to zcela přesné, protože program navíc nevlnkuje za slovy \TeX a
+\LaTeX a to se nedá vypnout.
+
+vlna *.tex ... provlnkuje všechny soubory s příponou .tex.
+Pracuje pouze na UNIXu.
+
+vlna -f soubor > /dev/null ... provede test konzistence math a
+verbatim módů a neudělá žádnou změnu.
+
+HISTORIE TOHOTO PRODUKTU:
+-------------------------
+
+Původní verzi programu vlnka vytvořil zhruba v roce 1990 Oldřich Ulrych
+v Pascalu. Další vylepšení v Pascalském programu udělal Štěpán Kasal.
+Tento Pascalský program je šířen v balíku CSTeX.
+
+Zde uvedená varianta programu (vlna) byla napsána v únoru 1995 pro
+použití v UNIXových prostředích, a proto v jazyce C. Přesněji byl
+použit prostředek CWEB, který umožňuje snadno číst zdrojový text a
+snadno jej modifikovat. Program byl zcela přepracován (z původního
+Pascalského kódu nebylo použito vůbec nic) a byl do něj implementován
+algoritmus rozpoznávání tzv. patternů (jednoduchých regulárních
+výrazů).
+
+Tato varianta programu byla testována na SUN OS a na MS DOS.
+
+V únoru 1998 mi poslal pan Rudof Čejka Makefile a manuálovou stránku
+k programu a ve zdrojovém kódu poravil drobné chyby.
+
+23.2.1995 Petr Olšák.
+
diff --git a/Build/source/utils/vlna/vlna.w b/Build/source/utils/vlna/vlna.w
new file mode 100644
index 00000000000..e366bffb146
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.w
@@ -0,0 +1,1003 @@
+
+\input csmac % Makra pro češtinu
+\pageheight=9.5in \fullpageheight=9.8in \setpage
+%\nocon % omit table of contents
+\datethis % print date on listing
+
+\def\begitems{\medskip\bgroup\catcode`\*=13 \narrower\narrower}
+\def\enditems{\par\egroup\medskip}
+{\catcode`\*=13 \gdef*{\par\noindent\llap{$\bullet$\ }\ignorespaces}}
+
+
+@* PROGRAM VLNA.
+Program čte vstupní textový soubor a nahrazuje za specifikovanými
+jednopísmennými slovy (např.~v, k, u) mezery symbolem \uv{\.{\char126}}. To
+zabrání při následném zpracování \TeX{}em zlomit řádek na nevhodných
+místech, která jsou v rozporu s typografickou normou.
+
+Program sestává z těchto hlavních celků:
+@c
+@<Hlavičkové soubory k načtení@>@/
+@<Globální deklarace@>@/
+@<Pomocné funkce@>@/
+@<Vlnkovací funkce |tie|@>@/
+@<Hlavní program@>
+
+@ Definujeme |BANNER|, což je text, který se objevi při startu
+programu a obsahuje číslo verze programu.
+Zde je názorně vidět, že míchání dvou jazyků se nevyhneme. Při tisku
+textů na terminál nesmíme předpokládat, že tam budou české fonty.
+V~této dokumentaci se setkáme se třemi jazyky: angličtinou (většinou
+v~kódu programu, cestinou v~/* komentářích */ a češtinou jinde.
+Tu cestinu si vynutil fakt, že DOS-ovská varianta \.{tangle} a
+\.{weave} se nesnáší s~akcentovanými písmeny v~/* komentářích */.
+A~nyní už slíbený (vícejazyčný) |BANNER|.
+@d BANNER "This is program vlna, version 1.2, (c) 1995, 2002 Petr Olsak\n"
+
+@ V programu jsou použity knihovní funkce, jejíchž prototypy jsou
+definovány ve třech standardních hlavičkových souborech.
+@<Hlavičkové ...@>=
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+@ Definujeme konstanty pro návratový kód. |OK| pro úspěšný běh,
+|WARNING| při výskytu aspoň jedné varovné zprávy, |IO_ERR| pro chybu
+v~přístupu ke vtupním nebo výstupním souborům, |BAD_OPTIONS| pro
+syntaktickou chybu na příkazové řádce a |BAD_PROGRAM| pro případ
+havárie programu. Ta by neměla nikdy nastat. Proměnná |status| bude
+obsahovat návratový kód a proměnná |prog_name| bude ukazovat na text
+nultého parametru příkazové řádky.
+@d OK 0
+@d WARNING 1
+@d IO_ERR 2
+@d BAD_OPTIONS 3
+@d BAD_PROGRAM 4
+@<Globální deklarace@>=
+char *prog_name;
+int status;
+
+@ Základní rozvržení funkce |main|.
+@<Hlavní program@>=
+int main (argc,argv)
+ int argc;
+ char **argv;
+{
+ @<Lokální proměnné funkce |main|@>;
+ prog_name=argv[0]; status = OK;
+ @<Načtení parametrů příkazového řádku@>;
+ if (!silent) fprintf (stderr, BANNER);
+ @<Inicializace datových struktur@>;
+ @<Zpracování souborů@>;
+ return status;
+}
+
+@* Parametry příkazového řádku.
+Program čte z~příkazového řádku postupně (nepovinné) parametry,
+které začínají znakem \uv{\.{-}}. Pak následují jména vstupních a výstupních
+souborů.
+\begitems
+* \.{-f} \dots\ program pracuje jako filtr (viz sekce |@<Zpracování
+ souborů@>|). Není-li tento parametr použit, program pracuje v tzv.
+ standardním režimu, kdy jednotlivé soubory jsou vstupní i výstupní.
+* \.{-s} \dots\ program nevypíše |BANNER|, ani sumarizaci, ani varování,
+ při nichž není program předčasně ukončen. Všechny tyto výpisy
+ směřují do |stderr|, takže pokud program pracuje v režimu \uv{filtr},
+ není nutné tento parametr použít.
+* \.{-r} \dots\ program maže pracovní soubor (soubory), které vytváří
+ ve standardním režimu (tj. není použit \.{-f}). V reřimu filter nemá
+ tento parametr vliv.
+* \.{-v} \dots\ parametr definuje skupinu písmen, které budou
+ interpretovány jako neslabičné předložky.
+ Např. \.{-v KkSsVvZzOoUuAI}. Pokud není parametr uveden, je použita
+ skupina uvedená v tomto příkladě.
+* \.{-m} \dots\ program neprovádí kontrolu math/text módů, tj. vlnkuje i
+ uvnitř matematického módu \TeX{}u. (Implicite tam nevlnkuje).
+* \.{-n} \dots\ prorgram neprovádí kontrolu verbatim módu, tj. vlnkuje i
+ uvnitř verbatim módu definovaném běžnými prostředími. Imlicite ve
+ verbatim prostředí nevlnkuje.
+* \.{-l} \dots\ La\TeX{} režim. Při kontrole text-math-verbatim módů jsou
+ brány v úvahu další sekvence, obvyklé v La\TeX{}ových dokumentech.
+* \.{-w} \dots\ WEB režim. Ohraničení verbatim módu je doplněno znaky
+ používanými v dokumentech WEB (např. tento dokument). Důsledek: program
+ vlnkuje dokumentační část každé sekce, ale nikoli kód.
+\enditems
+
+Definujeme funkci |printusage|, které tiskne (při chybě) stručný přehled
+možných parametrů. Nepodařilo se mi zjistit, jak se ve WEBu napíše
+kulturně dlouhý string obsahující \.{\char92n} s formátovacími
+požadavky. Byl jsem nucen to takto nehezky zapsat.
+@<Pomocné funkce@>=
+void printusage ()
+{
+ fprintf(stderr,
+ "usage: vlna [opt] [filenames]\n"
+ " opt -f : filter mode: file1 file2 ... file1->file2\n"
+ " file1 ... file1->stdout\n"
+ " ... stdin->stdout\n"
+ " nofilter: file1 [file2 file3 ...] all are in/out\n"
+ " -s : silent: no messages to stderr\n"
+ " -r : rmbackup: if nofilter, removes temporary files\n"
+ " -v charset : set of lettres to add tie, default: KkSsVvZzOoUuAI\n"
+ " -m : nomath: ignores math modes\n"
+ " -n : noverb: ignores verbatim modes\n"
+ " -l : LaTeX mode\n"
+ " -w : web mode\n");
+}
+
+@ Proměnné |isfilter|, |silent|, |rmbackup|, |nomath|, |noverb|,
+|latex|, resp. |web| říkají, že je nastaven parametr \.{-f}, \.{-s},
+\.{-r}, \.{-m}, \.{-n}, \.{-l}, resp. \.{-w}. Proměnná |charset|
+ukazuje buď na implicitní skupinu znaků |charsetdefault|, nebo (při
+použití parametru \.{-v}) na text uvedený v příkazovém řádku.
+@<Globální deklarace@>=
+int isfilter=0, silent=0, rmbackup=0, nomath=0, noverb=0, web=0, latex=0;
+char charsetdefault[]="KkSsVvZzOoUuAI";
+char *charset=charsetdefault;
+
+@ @<Načtení parametrů ...@>=
+while (argc>1 && argv[1][0] == '-') {
+ if (argv[1][2] != 0) printusage (), exit (BAD_OPTIONS);
+ switch(argv[1][1]) {
+ case 'f': isfilter = 1; break;
+ case 's': silent = 1; break;
+ case 'r': rmbackup = 1; break;
+ case 'v': argv++; argc--; charset = argv[1]; break;
+ case 'm': nomath = 1; break;
+ case 'n': noverb = 1; break;
+ case 'l': latex = 1; break;
+ case 'w': web = 1; break;
+ default: printusage (), exit (BAD_OPTIONS);
+ /* nezn\'am\'y parametr */
+ }
+ argc--; argv++;
+}
+
+@* Zpracování souborů. Parametr |MAXLEN| definuje maximální možnou
+délku jména souboru, který vytvoříme jako přechodný, nebo zálohový.
+Dále deklarujeme proměnné typu \uv{stream}.
+@d MAXLEN 120
+@<Lokální proměnné funkce...@>=
+FILE *infile, *outfile;
+char backup[MAXLEN];
+int j;
+
+@ Definujeme funkci pro výpis chybového hlášení při neúspěšném otevření
+souboru.
+@<Pomocné funkce@>=
+void ioerr (f)
+ char *f;
+{
+ fprintf(stderr, "%s: cannot open file %s\n", prog_name, f);
+}
+
+@ Způsob zpracování souborů rozlišíme podle režimu daným přepínačem \.{-f}.
+@<Zpracování souborů@>=
+if (isfilter) @<Zpracování v režimu filter@> @/
+else @<Zpracování všech souborů příkazové řádky@>
+
+@ V režimu |isfilter==1| je další zpracování závislé na počtu souborů v
+příkazové řádce:
+\begitems
+* nula souborů -- vstup je |stdin| a výstup je |stdout|,
+* jeden soubor -- je vstupní, výstup je |stdout|,
+* dva soubory -- první je vstupní, druhý výstupní,
+* více souborů -- program skončí s chybou.
+\enditems
+@<Zpracování v režimu filter@>=
+{
+ if (argc > 3) printusage (), exit (BAD_OPTIONS) ;
+ infile = stdin; outfile = stdout;
+ if (argc >= 2) infile = fopen (argv[1], "r");
+ if (infile == NULL) ioerr (argv[1]), exit (IO_ERR);
+ if (argc == 3) outfile = fopen(argv[2], "w");
+ if (outfile == NULL) ioerr (argv[2]), exit (IO_ERR);
+ if (argc >= 2) filename = argv[1];
+ else filename = NULL;
+ tie (infile, outfile);
+ if (outfile != stdout) fclose (outfile);
+ if (infile != stdin) fclose (infile);
+}
+
+@ V~režimu |isfilter==0| jsou jednotlivé soubory v~příkazovém řádku
+interpretovány jako vstupní i výstupní. Více souborů v~příkazovém řádku má
+stejný efekt, jako opakované volání programu na jednotlivé soubory.
+V~\UNIX/u lze tedy např. napsat \.{\jobname\ *.tex} a program doplní vlnky do
+všech souborů s~příponou~\.{tex}. Toto neplatí v~DOSu, protože interpretace
+masky je v~\UNIX/u starostí shellu a nikoli programu samotného. Náš program
+masku nebude interpretovat. Je-li v~tomto režimu nulový počet souborů,
+program se ukončí s~chybou.
+@<Zpracování všech souborů příkazové řádky@>=
+{
+ if (argc==1) printusage (), exit(BAD_OPTIONS);
+ while (argc>1) {
+ argc--; argv++;
+ @<Přejmenuj vstup |argv[0]| na |backup| a otevři jej jako |infile|@>;
+ if (infile == NULL) {
+ ioerr (argv[0]); continue;
+ }
+ outfile = fopen (argv[0], "w");
+ if (outfile == NULL) {
+ ioerr (argv[0]);
+ rename (backup, argv[0]);
+ status = WARNING;
+ continue;
+ }
+ filename = argv[0];
+ tie (infile, outfile);
+ fclose (outfile), fclose (infile);
+ if (rmbackup) remove (backup);
+ }
+}
+
+@ Při |isfilter==0| program přejmenuje každý zpracovávaný soubor tak, že
+změní poslední písmeno názvu souboru na znak \.{\char126}. Tento
+přejmenovaný soubor bude otevřen jako vstupní a výstupem bude původní
+soubor. Vstupní soubor při |rmbackup==0| zůstane zachován jako záloha.
+
+Proč vlnku nepřidáváme na konec názvu souboru, ale měníme ji za poslední
+znak souboru? Protože chceme, aby program fungoval i v tak nemožných
+systémech, jako je DOS.
+@<Přejmenuj vstup...@>=
+infile = NULL;
+j = strlen (argv[0]) - 1;
+if (j >= MAXLEN || argv[0][j] == '~') {
+ if (!silent) fprintf (stderr, "%s: the conflict of file name %s\n",
+ prog_name, argv[0]);
+}
+else {
+ strcpy (backup, argv[0]);
+ backup[j] = '~';
+ remove (backup);
+ j = rename (argv[0], backup);
+ if (j == 0) infile = fopen (backup, "r");
+}
+
+@* Patterny. Abychom mohli účelně definovat chování programu
+v~různých situacích, zavedeme datovou strukturu |PATTERN|. Zhruba
+řečeno, budeme sledovat vstup znak po znaku a pokud bude část vstupu
+souhlasit s~definovaným patternem, provedeme námi požadovanou
+akci. Například nejčastější aktivitu, přidání vlnky uvnitř řádku,
+spustíme v~okamžiku, kdy vstupní text odpovídá patternu \uv{\.{\ (v\
+p}}, kde \uv{\.{\ }} znamená jedna nebo více mezer a tabelátorů,
+\uv{\.{(}} je nula nebo více otevíracích závorek všeho druhu,
+\uv{\.{v}} znamená jedno písmeno z~množiny předložek (viz |charset|) a
+\uv{\.{p}} zde znamená libovolné písmeno. Příklad zde není zcela přesný.
+Přesně jsou všechny patterny pro náš program definovány v~závěrečných
+sekcích tohoto povídání.
+
+Pattern bude znamenat konečnou sekvenci tzv. pozic patternu (|PATITEM|).
+Cykly uvnitř pozic pro jednoduchost nepřipustíme. Každá pozice obsahuje
+řetězec znaků, uvažovaný pro danou pozici (v~příkladu pozice~\uv{\.{\ }} by
+obsahovala mezeru a tabelátor, zatímco pozice \.{v} odpovídá |charset|).
+Každá pozice má svůj přepínač (|flag|), který obsahuje informaci o~tom,
+zda shodu testovaného znaku s~některým prvkem v~množině znaků
+budeme považovat za úspěch či neúspěch a zda pozice se ve zkoumaném
+řetězci může vyskytovat právě jednou nebo opakovaně. Jako druhý případ
+stačí implementovat \uv{nula nebo více} protože \uv{jedna nebo více} lze
+popsat pomocí dvou pozic, první \uv{právě jednou} a následující \uv{nula
+nebo více}. Jednotlivé pozice jsou zřetězeny ukazatelem |next|, poslední
+pozice má |next==NULL|. Stejně tak jednotlivé patterny budeme
+sestavovat do seznamů a budou rovněž zřetězeny ukazatelem |next|.
+
+Pattern kromě řetězu pozic obsahuje ukazatel na funkci (proceduru) |proc|,
+která se má vykonat v~případě, že testovaný řetězec vyhovuje patternu.
+
+@d ONE 1 /* flag: prave jeden vyskyt */
+@d ANY 2 /* flag: nula nebo vice */
+@d ONE_NOT -1 /* flag: prave jednou, znak nesmi byt v mnozine */
+@d ANY_NOT -2 /* flag: nula nebo vice, znak nesmi byt v mnozine */
+
+@<Globální deklarace@>=
+typedef struct PATITEM { /* jedna pozice patternu */
+ char *str; /* seznam znaku na teto pozici */
+ int flag; /* vyznam seznamu znaku */
+ struct PATITEM *next ; /* nasledujici pozice patternu */
+} PATITEM;
+typedef struct PATTERN { /* jeden pattern */
+ PATITEM *patt; /* ukazatel na prvni pozici */
+ void (*proc)(); /* procedura spustena pri souhlasu patternu */
+ struct PATTERN *next ; /* nasledujici v seznamu vsech patternu */
+} PATTERN;
+
+@ Deklarujeme některé globální proměnné pro práci s~patterny. |lapi| je pole
+obsahující ukazatele na aktuální pozice v~otevřených patternech. Říkáme,
+že \uv{pattern je otevřen}, pokud zkoumaný řetězec s~ním {\it začíná\/}
+souhlasit. Pattern se uzavře, pokud nastane jedna ze dvou možností:
+zkoumaný řetězec s~mím souhlasí až do konce (v~takovém případě se provede
+procedura |proc|), nebo při vyšetřování dalších znaků ze zkoumaného
+řetězce přestane řetězec s~patternem souhlasit.
+
+V~dané chvíli může být pattern otevřen několikrát. Např. pattern \.{abac}
+je při stringu \.{aba} při výskytu druhého \.{a} otevřen podruhé. Proto
+pole obsahuje ukazatele na právě aktuální pozici patternu a nikoli na
+pattern jako takový.
+
+V~poli |lapi| budou na počátku samá |NULL| (to se při překladu inicializuje
+samo) a přemazání ukazatele na pozici konstantou |NULL| budeme považovat
+za zavření patternu. Vedle pole |lapi| souměrně udržujeme pole |lapt|,
+do něhož budeme ukládat ukazatele na odpovídající otevřený pattern. Tuto
+informaci použijeme v~případě, že potřebujeme např, znát |proc|
+patternu.
+
+|listpatt| bude ukazovat na začátek aktuálního seznamu patternů. Seznamy
+budeme mít dva. Jeden se použije, nacházíme-li se mimo komentář a druhý
+v~případě, že se nacházíme v~prostoru \TeX{}ovského komentáře (tj. za
+procentem). Starty těchto seznamů patternů jsou |normallist| a
+|commentlist| a aktivní |listpatt| má vždy jednu z~těchto dvou hodnot.
+
+Proměnné |lastpt| a |lastpi| použijeme pro budování řetězové struktury
+patternů.
+
+Proměnná |c| obsahuje právě testovaný znak ze vstupu (který se rovněž
+přepíše do bufferu |buff|). Z~bufferu občas ukládáme data do výstupního
+proudu. Děláme to ale vždy jen v~okamžiku, kdy není otevřen žádný
+pattern. Tehdy totiž \uv{nehrozí} situace, že by nějaká procedura vyvolaná
+souhlasem patternu požadovala v~tomto bufferu nějaké změny se zpětnou
+platností. O~vyprázdnění bufferu se začneme zajímat až v~okamžiku, kdy je
+zaplněn aspoň na hodnotu |BUFI|, abychom proceduru přepisu bufferu do
+výstupního proudu neaktivovali zbytečně často.
+@d MAXPATT 200 /* maximalni pocet patternu */
+@d MAXBUFF 500 /* velikost bufferu pro operace */
+@d BUFI 300 /* velikost stredniho zaplneni */
+@<Globální deklarace@>=
+PATITEM *lapi[MAXPATT]; /* pole ukazatelu na aktualni pozice */
+PATTERN *lapt[MAXPATT]; /* pole odpovidajicich ukazatelu na patterny */
+PATTERN *listpatt, *normallist, *commentlist, *pt, *lastpt=NULL;
+PATITEM *pi, *lastpi=NULL;
+char c; /* zrovna nacetny znak */
+char buff[MAXBUFF]; /* prechodny buffer */
+int ind; /* aktualni pozice prechodneho bufferu */
+
+@ Nyní definujeme pomocné funkce |setpattern|, |setpi| a |normalpattern|.
+Tyto funkce alokují paměť pomocí standardní funkce |malloc|. Abychom mohli
+ohlídat případnou chybu při alokaci, budeme allokovat paměť zprostředkovaně
+pomocí funkce |myalloc|.
+@<Pomocné funkce@>=
+void *myalloc (size)
+ int size;
+{
+ void *p;
+ p = malloc (size);
+ if (p == NULL)
+ {
+ fprintf (stderr, "%s, no memory, malloc failed\n", prog_name);
+ exit (BAD_PROGRAM) ;
+ }
+ return p;
+}
+
+@ Funkce |setpattern| alokuje paměťové místo struktury |PATTERN| a napojí
+ji pomocí proměnné |lastpt| na už alokovaný řetěz patternů.
+Vrátí ukazatel na nově alokované místo. Jednotlivé pozice patternu se musí
+následovně alokovat pomocí |setpi|.
+@<Pomocné funkce@>=
+PATTERN *setpattern (proc) @/
+ void (*proc)();
+{
+ PATTERN *pp;
+ pp = myalloc (sizeof (PATTERN));
+ pp->proc = proc;
+ pp->next = NULL;
+ pp->patt = NULL;
+ if (lastpt != NULL) lastpt->next = pp;
+ lastpt = pp;
+ lastpi = NULL;
+ return pp;
+}
+
+@ Funkce |setpi| alokuje paměťové místo pro jednu pozici patternu. Provede
+zřetězení tak, aby první pozice řetězu pozic byla zaznamenána v položce
+|patt| ve struktuře |PATTERN| a další byly provázány položkou |next| ve
+struktuře |PATITEM|. Poslední pozice má |next==NULL|.
+@<Pomocné funkce@>=
+void setpi (str, flag)
+ char *str;
+ int flag;
+{
+ PATITEM* p;
+ p = myalloc (sizeof (PATITEM));
+ p->str = str; p->flag = flag;
+ p->next = NULL;
+ if (lastpi == NULL) lastpt->patt = p;
+ else lastpi->next = p;
+ lastpi = p;
+}
+
+@ Připravme si půdu pro funkci |normalpattern|. Tato funkce alokuje
+strukturu pro jeden pattern včetně pozic patternu na základě vstupního
+stringu. Každá pozice patternu obsahuje v~množině znaků jediný znak a má
+|flag=ONE|. Znaky ve vstupním stringu odpovídají po řadě jednotlivým
+pozicím. Vytvoří se vlastně jakýsi absolutní pattern, tj. testovaný řetězec
+se musí přesně shodovat s~uvedeným stringem. Výjimku tvoří znak |"."|,
+který se interpretuje jako nula nebo více mezer. Chceme-li tečku
+vnutit do patternu, napíšeme dvě tečky za sebou.
+
+Nejdříve deklarujeme pole všech možných jednopísmenných stringů.
+@<Globální deklarace@>=
+char strings[512];
+int i;
+
+@ Inicializujeme toto pole (znak, nula, znak, nula, atd...).
+@<Inicializace datových struktur@>=
+for (i=0; i<256; i++) {
+ strings[2*i] = (char) i; strings[2*i+1] = 0;
+}
+
+@ Definujme funkci |normalpattern|.
+@<Pomocné funkce@>=
+PATTERN *normalpattern (proc, str) @/
+ void (*proc)();
+ char *str;
+{
+ PATTERN *pp;
+ int j=0;
+ pp = setpattern (proc);
+ while (str[j]) {
+ if (str[j]=='.') {
+ j++;
+ if (str[j]!='.') {
+ setpi (blankscr, ANY);
+ continue;
+ }
+ }
+ setpi (&strings[(unsigned char)str[j]*2], ONE);
+ j++;
+ }
+ return pp;
+}
+
+@ Funkce |match|. Definujeme funkci, která na základě hodnoty znaku |c|
+(proměnná |c| je definována jako globální), a pozice patternu |p| (parametr
+funkce) vrátí informaci o tom, zda znak souhlasí s patternem. Záporná čísla
+|FOUND|, resp. |NOFOUND| znamenají, že je třeba uzavřít pattern s tím, že
+vzor odpovídá, resp. neodpovídá patternu. Nezáporné číslo vrátí v případě,
+že zkoumaný vstup stále souhlasí s patternem, ale není ještě
+rozhodnuto. Velikost návratové hodnoty v takovém případě udává, o kolik
+pozic je třeba se posunout v patternu, abychom měli ukazatel na pozici
+patternu v souhlase s novou situací, způsobenou znakem |c|.
+
+Pokud je |c| v množině znaků pro danou pozici |p->str|, bude |m==1|, jinak
+je |m==-1|. Pokud tímto číslem pronásobíme hodnotu |p->flag|, nemusíme
+větvení podle |p->flag| programovat dvakrát. Hodnoty |flag| jsou totiž
+symetrické podle nuly, např. |ANY==-ANY_NOT|.
+@d FOUND -1
+@d NOFOUND -2
+@<Pomocné funkce@>=
+int match (p)
+ PATITEM *p;
+{
+ int m;
+ if (strchr (p->str, c) != NULL) m = 1; /* Znak nalezen */
+ else m = -1; /* Znak nenalezen */
+ switch (m * p->flag) {
+ case ANY: return 0; /* Souhas, neni nutny posun */
+ case ONE: if (p->next == NULL) return FOUND;
+ return 1; /* Souhas, nutny posun o 1 */
+ case ONE_NOT: return NOFOUND; /* Nesouhlas */
+ case ANY_NOT: @<Vrať hodnotu podle následující...@>;
+ }
+ return 0; /* Tady bychom nikdy nemeli byt, return pro potlaceni varovani */
+}
+
+@ O kolik pozic je třeba se posunout a s jakým výsledkem zjistíme
+rekurzivním voláním funkce |match|.
+@<Vrať hodnotu podle následující pozice patternu@>=
+switch (m = match (p->next)) {
+case NOFOUND: return NOFOUND;
+case FOUND: return FOUND;
+default: return 1 + m;
+}
+
+@* Vlnkovací funkce.
+Nejprve připravíme globální deklarace pro \uv{vlnkovací} funkci |tie|.
+Funkce |tie| \uv{ovlnkuje} vstupní soubor |infile| a vytvoří soubor
+|outfile|. Při |silent=0| tiskne závěrečnou zprávu o zpracování. V této
+zprávě se objeví jméno souboru, které se funkce \uv{dozví} prostřednictvím
+globální proměnné |filename|. Proměnná |numline| počítá řádky, proměnná
+|numchanges| sčítá změny, tj. počet doplněných vlnek.
+Proměnná |mode| nabývý některé z hodnot |TEXTMODE|, |MATHMODE|,
+|DISPLAYMODE| a |VERBMODE| podle stavu ve čteném textu.
+@d TEXTMODE 0
+@d MATHMODE 1
+@d DISPLAYMODE 2
+@d VERBMODE 3
+@<Globální deklarace@>=
+char *filename; /* jmeno zpracovavaneho souboru */
+long int numline, numchanges; /* pro zaverecnou statistiku */
+int mode;
+
+@ Nyní definujeme vlnkovací funkci |tie|. Veškerá činnost se opírá o
+strukturu patternů. Výhodné je (z důvodu rychlosti) \uv{natvrdo} zde
+implementovat jen přepínání mezi stavem čtení z oblasti komentáře
+(|listpatt==commentlist|) a mimo komentář (|listpatt==normallist|);
+@<Vlnkovací funkce |tie|@>=
+void tie (input, output)
+ FILE *input, *output;
+{
+ int ap; /* ap je pocet otevrenych patternu */
+ register int k, m, n;
+ int ic;
+ PATTERN *pp;
+ PATITEM *pi;
+
+ @<Inicializace proměnných při startu funkce |tie|@>;
+
+ while (!feof(input)) {
+ @<Otevři nové patterny@>;
+ if (ap == 0 && ind > BUFI && c !='\\') @<Vyprázdni buffer@>;
+ if (ind >= MAXBUFF) {
+ fprintf (stderr, "Operating buffer overflow, is anything wrong?\n");
+ exit (BAD_PROGRAM);
+ }
+ if ((ic = getc(input)) == EOF) /* opravil Cejka Rudolf */
+ break;
+ buff[ind++] = c = ic;
+ if (c == '\n') numline++, listpatt = normallist;
+ if (c == '%' && mode!=VERBMODE && buff[ind-2] != '\\') listpatt = commentlist;
+ @<Projdi otevřené patterny@>;
+ }
+ @<Vyprázdni buffer@>;
+ if (!web) checkmode (); /* zaverecna kontrola modu */
+ if (!silent) @<Tiskni závěrečnou zprávu@>;
+}
+
+@ @<Inicializace proměnných při ...@>=
+for (k=0; k<MAXPATT; k++) lapi[k] = NULL;
+c = '\n';
+buff[0] = mode = ap = 0; ind = 1;
+numline = 1; numchanges = 0;
+mode = TEXTMODE;
+
+@ Při manipulaci s bufferem byl použit jeden trik. Veškeré načtené znaky
+začínají až od |buff[1]|, zatímco |buff[0]| je rovno nule. Je to proto, že
+některé algoritmy se vrací o jeden znak zpět za svůj pattern, aby zjistily,
+zda tam není symbol \uv{\.{\char92}} (například na výskyt sekvence
+\.{\char92\char37} je třeba reagovat jinak, než na výskyt obyčejného
+procenta). Kdybychm zazačali od |buff[0]|, v některých situacích
+bychom se ptali, zda |buff[-1]=='\\'|, tj. sahali bychom na neošetřené
+místo v paměti.
+@<Vyprázdni buffer@>=
+{
+ buff[ind] = 0;
+ fputs (&buff[1], output);
+ ind = 1;
+}
+
+@ Při procházení otevřenými patterny posunujeme v poli |lapi| pozice
+jednotlivých patternů podle pokynů funkce |match|, případně pattern zavřeme
+a případně vyvoláme proceduru patternu.
+
+Některé patterny v poli |lapi| už mohou být zavřeny, takže je nutno s tímto
+polem pracovat jako s jakýmsi děravým sýrem.
+@<Projdi otevřené patterny@>=
+n = ap; k = 0;
+while (n) {
+ while (lapi[k]==NULL) k++; /* zastav se na prvnim ukazateli na pattern */
+ switch (m = match (lapi[k])) {
+ case FOUND: (*lapt[k]->proc)(); /* Pattern nalezen, spustit proceduru */
+ case NOFOUND: lapi[k] = NULL; /* Deaktivace patternu */
+ ap--; break;
+ default: while (m--) lapi[k] = lapi[k]->next; /* dalsi pozice patternu */
+ }
+ k++; n--;
+}
+
+@ Při otevírání nových patternů, které nejsou v tuto chvíli zablokovány,
+se hned vypořádáme s takovými patterny, které nám dávají rovnou odpověď
+typu |FOUND| nebo |NOFOUND|. V takových případech ani nezanášíme ukazatel
+na pozici do pole |lapi|.
+@<Otevři nové patterny@>=
+pp = listpatt;
+while (pp != NULL) {
+ switch (m = match (pp->patt)) {
+ case FOUND: (*pp->proc)(); /* spustit proceduru */
+ case NOFOUND: break;
+ default: @<Vytvoř ukazatel na nový pattern a |break|@>;
+ }
+ pp=pp->next;
+}
+
+@ Není-li hned známa odpověď, zda pattern vyhovuje či nikoli,
+překontrolujeme nejdříve, zda už není pattern ve stejné pozici otevřený.
+Pak najdeme první \uv{díru} v tabulce |lapi| a tam uhnízdíme nový ukazatel
+na pozici v patternu.
+@<Vytvoř ukazatel na nový pattern...@>=
+pi = pp->patt;
+while (m--) pi = pi->next;
+n = ap; k = 0;
+while (n) {
+ if (lapi[k]==pi) break;
+ if (lapi[k++] != NULL) n--;
+}
+if (!n) {
+ k = 0;
+ while (lapi[k] != NULL) k++;
+ if (k >= MAXPATT) {
+ fprintf (stderr, "I cannot allocate pp, is anything wrong?\n");
+ exit (BAD_PROGRAM);
+ }
+ lapt[k] = pp; lapi[k] = pi; ap++;
+}
+
+@ Poslední věcí ve funci |tie| je tisk závěrečné statistiky zpracování.
+@<Tiskni závěrečnou zprávu@>=
+fprintf (stderr, "~~~ file: %s\t lines: %ld, changes: %ld\n",
+ filename, numline, numchanges);
+
+@* Inicializace patternů.
+Po vytvoření předchozího kódu opírajícího se o~patterny máme nyní v~ruce
+poměrně silný nástroj na definování různých činností programu prostým
+vytvořením patternu a příslušné jeho procedury. Pokud budeme chtít
+v~budoucnu nějaký rys programu přidat, pravděpodobně to bude snadné.
+
+Nejprve deklarujeme některé často používané skupiny znaků v~patternech.
+
+@<Globální deklarace@>=
+char tblanks[] = " ~\t";
+char blanks[] = " \t";
+char blankscr[] = " \t\n";
+char tblankscr[] = " ~\t\n";
+char nochar[] = "%~\n";
+char cr[] = "\n";
+char prefixes[] = "[({~";
+char dolar[] = "$";
+char backslash[] = "\\";
+char openbrace[] = "{";
+char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+PATTERN *vlnkalist, *mathlist, *parcheck, *verblist ;
+
+@ Začneme definicí nejčastěji používaného patternu na vlnkování uvnitř
+řádku. Připomeňme, že opakované volání funkce |setpattern| vytváří interně
+seznam patternů, přičemž o~jejich propojení se nemusíme starat. Vyzvedneme
+si z~návratového kódu funkce pouze ukazatel na první položku seznamu
+|normallist|. Stejně tak opakované volání funkce |setpi| vytváří seznam
+pozic pro naposledy deklarovaný pattern.
+@<Inicializace datových struktur@>=
+vlnkalist = setpattern (vlnkain);
+setpi (tblankscr, ONE);
+setpi (tblanks, ANY);
+setpi (prefixes, ANY);
+setpi (charset, ONE);
+setpi (blanks, ONE);
+setpi (blanks, ANY);
+setpi (nochar, ONE_NOT);
+
+@ @<Inicializace proměnných při ...@>=
+listpatt = normallist = vlnkalist;
+
+@ @<Pomocné funkce@>=
+void vlnkain()
+{
+ char p;
+ ind--;
+ p = buff[ind--];
+ while (strchr(blanks, buff[ind]) !=NULL) ind--;
+ ind++;
+ buff[ind++] = '~';
+ buff[ind++] = p;
+ numchanges++;
+}
+
+@ Podobně pro tvorbu vlnky \uv{přes řádek} vytvoříme pattern a kód
+procedury.
+@<Inicializace dat...@>=
+setpattern (vlnkacr);
+setpi (tblankscr, ONE);
+setpi (tblanks, ANY);
+setpi (prefixes, ANY);
+setpi (charset, ONE);
+setpi (blanks, ANY);
+setpi (cr, ONE);
+setpi (blanks, ANY);
+setpi (nochar, ONE_NOT);
+
+@ V proceduře k tomuto patternu musíme ošetřit případ typu
+\uv{\.{a\char126v\char92np}},
+kdy nelze prostě přehodit \uv{\.{\char92n}} za \uv{\.{v}}, protože
+bychom roztrhli
+mezeru svázanou vlnkou už dříve. Proto musíme vyhledat vhodné místo pro
+roztržení řádku, které bude až {\it před\/} znakem \uv{\.{a}}. Při důsledném
+ošetření tohoto fenoménu můžeme dokonce narazit na situaci
+\uv{\.{\char92n\ v\char126v\char126v\char92np}}, kde nemůžeme vložit
+\uv{\.{\char92n}} před první výskyt \uv{\.{v}}, protože bychom dostali
+\uv{\.{\char92n\char92n}}, tedy prázdný
+řádek. Ten je v \TeX{}u interperetován odlišně. V této výjimečné
+situaci pouze zrušíme stávající (v pořadí druhé) \uv{\.{\char92n}} a
+nebudeme vytvářet nové. Na výstupu bude soubor o jeden řádek kratší.
+@<Pomocné funkce@>=
+void vlnkacr()
+{
+ char p;
+ int i, j;
+ ind--;
+ p = buff[ind--];
+ while (strchr(blankscr, buff[ind]) !=NULL) ind--;
+ i = ind; /* misto predlozky, kterou chceme vazat */
+ while (i >= 0 && (strchr(blankscr, buff[i]) == NULL)) i--;
+ j = i;
+ while (i >= 0 && (strchr(blanks, buff[i]) != NULL)) i--;
+ if (i >= 0 && buff[i] == '\n') j = -1;
+ if (j >= 0) buff[j] = '\n';
+ else numline--;
+ ind++;
+ buff[ind++] = '~';
+ buff[ind++] = p;
+ numchanges++;
+}
+
+@ Nyní vytvoříme patterny pro případy typu \.{\char92uv\char`\{v lese\char`\}}.
+@<Inicializace dat...@>=
+setpattern (vlnkain); /* na radku */
+setpi (tblankscr, ONE);
+setpi (backslash, ONE);
+setpi (letters, ONE);
+setpi (letters, ANY);
+setpi (openbrace, ONE);
+setpi (prefixes, ANY);
+setpi (charset, ONE);
+setpi (blanks, ONE);
+setpi (blanks, ANY);
+setpi (nochar, ONE_NOT);
+
+setpattern (vlnkacr); /* pres radek */
+setpi (tblankscr, ONE);
+setpi (backslash, ONE);
+setpi (letters, ONE);
+setpi (letters, ANY);
+setpi (openbrace, ONE);
+setpi (prefixes, ANY);
+setpi (charset, ONE);
+setpi (blanks, ANY);
+setpi (cr, ONE);
+setpi (blanks, ANY);
+setpi (nochar, ONE_NOT);
+
+
+
+@ Vytvoříme patterny a proceduru pro potlatčení tvorby vlnky u písmen těsně
+následujících sekvence \.{\char92TeX} a \.{\char92LaTeX}. Tj. nechceme, aby
+např z textu \uv{\.{Vlastnosti~\char92TeX~u~jsou...}} jsme dostali text
+s nesprávně vázaným písmenem
+\uv{\.{Vlastnosti~\char92TeX~u\char126jsou...}}.
+@<Inicializace dat...@>=
+normalpattern (tielock, "\\TeX");
+setpi (blankscr, ONE);
+normalpattern (tielock, "\\LaTeX");
+setpi (blankscr, ONE);
+
+@ Procedura |tielock| obsahuje nečistý trik. Při provádění procedury je
+právě načten znak z |blankscr| a je uložen do buff. Testy na otevírání
+nových patternů pro tento znak teprve budou následovat a testují se na
+hodnotu proměnné |c|. Stačí tedy změnit hodnotu |c| a vlnkovací patterny se
+neotevřou.
+@<Pomocné funkce@>=
+void tielock ()
+{
+ c = 1;
+}
+
+@ Ošetříme nyní přechod do/z matematického režimu \TeX{}u. Uvnitř math
+módu vlnky neděláme. Při zjištěném nesouladu v přechodech mezi
+math-módy spustíme následující proceduru.
+@<Pomocné funkce@>=
+void printwarning ()
+{
+ if (!silent)
+ fprintf (stderr,
+ "~!~ warning: text/math/verb mode mismatch, file: %s, line: %ld\n",
+ filename, numline - (c=='\n'?1:0));
+ status = WARNING;
+}
+
+@ Začneme patterny pro přechod do/z matematického režimu, ohraničeného
+jedním dolarem, nebo v La\TeX{}u příslušnými sekvencemi. Sekvence
+La\TeX{}u \.{\char92(} a \.{\char92)} nejsou zahrnuty, protože bývají
+často předefinovány k jiným užitečnějším věcem.
+@<Inicializace datových ...@>=
+if (!nomath) {
+ mathlist = setpattern (onedollar);
+ setpi (dolar, ONE);
+ setpi (dolar, ONE_NOT);
+ if (latex) {
+ normalpattern (mathin, "\\begin.{math}");
+ normalpattern (mathout, "\\end.{math}");
+ }
+}
+
+@ @<Pomocné funkce@>=
+void mathin ()
+{
+ if (mode!=TEXTMODE) printwarning ();
+ mode = MATHMODE;
+ normallist = listpatt = mathlist;
+}
+void mathout ()
+{
+ if (mode!=MATHMODE) printwarning ();
+ mode = TEXTMODE;
+ normallist = listpatt = vlnkalist;
+}
+
+@ Při programování procedury |onedollar| nesmíme zapomenout na výskyt
+sekvence \.{\char92\$}. V tom případě akci ignorujeme. Podobně u sekvence
+\.{\$\$} souhlasí ten druhý dolar s naším patternem, ale to už jsme uvnitř
+display módu. V takovém případě také nic neděláme.
+@<Pomocné funkce@>=
+void onedollar ()
+{
+ if (buff[ind-3]=='\\' || (buff[ind-3]=='$' && buff[ind-4]!='\\')) return;
+ if (mode==DISPLAYMODE) printwarning ();
+ else {
+ if (mode==TEXTMODE) mathin();
+ else mathout();
+ }
+}
+
+@ Pokud najdeme prázdný řádek, překontrolujeme, zda náhodou nejsme v
+math-módu. Pokud ano, vypíšeme varování a přejdeme do textového módu.
+@<Inicializace dat...@>=
+parcheck = setpattern (checkmode);
+setpi (cr, ONE);
+setpi (blanks, ANY);
+setpi (cr, ONE);
+
+@ @<Pomocné funkce@>=
+void checkmode ()
+{
+ if (mode!=TEXTMODE) {
+ printwarning ();
+ mode = TEXTMODE;
+ normallist = listpatt = vlnkalist;
+ }
+}
+
+@ Nyní ošetříme výskyt dvou dolarů, tj. vstup do/z display módu.
+Rovněž mysleme na La\TeX{}isty a jejich prostředí pro display-mód. Protože
+je možná alternativa s hvězdičkou na konci názvu prostředí, raději už
+uzavírací závorku do patternu nezahrnujeme.
+
+@<Inicializace dat...@>=
+if (!nomath) {
+ normalpattern (twodollars, "$$");
+ if (latex) {
+ normalpattern (displayin, "\\begin.{displaymath");
+ normalpattern (displayin, "\\begin.{equation");
+ normalpattern (displayout, "\\end.{displaymath");
+ normalpattern (displayout, "\\end.{equation");
+ }
+}
+
+@ @<Pomocné funkce@>=
+void displayin ()
+{
+ if (mode!=TEXTMODE) printwarning ();
+ mode = DISPLAYMODE; normallist = listpatt = parcheck;
+}
+void displayout ()
+{
+ if (mode!=DISPLAYMODE) printwarning();
+ mode = TEXTMODE; normallist = listpatt = vlnkalist;
+}
+void twodollars ()
+{
+ if (buff[ind-3]=='\\') return;
+ if (mode==DISPLAYMODE) displayout ();
+ else displayin ();
+}
+
+@ Následuje ošetření tzv. verbatim módu. Pro plain i La\TeX{} jsou nejčastější
+závorky pro verbatim mod tyto (variantu s \.{\char92begtt} používám
+s oblibou já).
+@<Inicializace dat...@>=
+if (!noverb) {
+ verblist = normalpattern (verbinchar, "\\verb");
+ setpi (blankscr, ANY);
+ setpi (blankscr, ONE_NOT);
+ normalpattern (verbin, "\\begtt");
+ if (latex) normalpattern (verbin, "\\begin.{verbatim");
+}
+if (web) {
+ normalpattern (verbin, "@@<");
+ normalpattern (verbin, "@@d");
+}
+if (!noverb) {
+ verboutlist[0] = setpattern (verbout);
+ setpi (verbchar, ONE);
+ verboutlist[1] = normalpattern (verbout, "\\endtt");
+ if (latex) verboutlist[2] = normalpattern (verbout, "\\end{verbatim");
+}
+if (web) {
+ verboutlist[3] = normalpattern (verbout, "@@ ");
+ normalpattern (verbout, "@@*");
+ normalpattern (verbout, "@@>|");
+}
+
+
+@ Procedura |verbinchar| se od \uv{společné} procedury |verbin| liší v
+tom, že zavede do stringu |verbchar| momentální hodnotu proměnné |c|.
+Proto druhý výskyt této hodnoty verbatim režim ukončí.
+@<Pomocné funkce@>=
+int prevmode;
+PATTERN *prevlist, *verboutlist[4];
+char verbchar[2];
+void verbinchar ()
+{
+ prevmode = mode;
+ verbchar[0] = c;
+ c = 1;
+ listpatt = normallist = verboutlist[0];
+ prevlist = listpatt->next;
+ listpatt->next = NULL;
+ mode = VERBMODE;
+}
+
+@ Při programování \uv{obecné} funkce |verbin| musíme dbát na to, aby
+zůstal aktivní pouze odpovídající \uv{výstupní} pattern k danému
+vstupnímu. Také si zapamatujeme mód, ze kterého jsme do verbatim
+oblasti vstoupili, abychom se k němu mohli vrátit (např. uvnitř
+math. módu může být
+\.{\char92hbox} a v něm lokálně verbatim konstrukce).
+@<Pomocné funkce@>=
+void verbin ()
+{
+ int i;
+ i = 0;
+ prevmode = mode;
+ switch (c) {
+ case 't': i = 1; break;
+ case 'm': i = 2; break;
+ case '<': ;
+ case 'd': i = 3;
+ if (buff[ind-3]=='@@') return; /* dvojity @@ ignorovat */
+ break;
+ }
+ listpatt = normallist = verboutlist[i];
+ prevlist = listpatt->next;
+ if (c != '<' && c != 'd') listpatt->next = NULL;
+ mode = VERBMODE;
+}
+
+@ @<Pomocné funkce@>=
+void verbout ()
+{
+ if (mode!=VERBMODE) return;
+ if (web && buff[ind-2] == '@@' && buff[ind-3] == '@@') return;
+ mode = prevmode;
+ normallist->next = prevlist;
+ switch (mode) {
+ case DISPLAYMODE: normallist = listpatt = parcheck; break;
+ case MATHMODE: normallist = listpatt = mathlist; break ;
+ case TEXTMODE: normallist = listpatt = vlnkalist; break;
+ }
+}
+
+@ Nyní implementujeme vlastnost dříve používaného programu vlnka, tj. že
+lze jeho činnost vypnout a opět zapnout v komentářích. Vytváříme druhý
+nezávislý seznam patternů a proto nejprve pronulujeme |lastpt|.
+@<Inicializace dat...@>=
+lastpt = 0;
+commentlist = normalpattern (tieoff, "%.~.-");
+normalpattern (tieon, "%.~.+");
+
+@ @<Pomocné funkce@>=
+void tieoff ()
+{
+ normallist = NULL;
+}
+void tieon ()
+{
+ normallist = vlnkalist;
+}
+
+@ Další plánovaná vylepšení. Program by mohl číst definici svého chování
+nejen z~příkazové řádky, ale v~mnohem kompletnější podobě, včetně
+uživatelsky definovaných patternů, z komentářové oblasti ve čteném souboru.
+Parametry zde uvedené by mohly mít vyšší prioritu, než parametry
+z~příkazové řádky a mohl by se třeba rozšiřovat seznam sekvencí, za nimiž
+písmena nemají být vázana vlnkou (zatím je implemenováno na pevno jen
+\.{\char92TeX} a \.{\char92LaTeX}).
+
+@* Rejstřík.
+
+
diff --git a/Build/source/utils/vlna/win32.mak b/Build/source/utils/vlna/win32.mak
new file mode 100644
index 00000000000..a3b16760f1f
--- /dev/null
+++ b/Build/source/utils/vlna/win32.mak
@@ -0,0 +1,56 @@
+################################################################################
+#
+# Makefile : Vlna
+# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources
+# Time-stamp: <02/06/03 15:10:30 popineau>
+#
+################################################################################
+root_srcdir = ..\..
+!ifdef DEVELOPMENT
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk.development
+!else
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk
+!endif
+
+USE_GNUW32 = 1
+
+!include <msvc/common.mak>
+
+programs = $(objdir)\vlna.exe
+manfiles = vlna.1
+infofiles =
+installinfoflags =
+
+objects= $(objdir)\vlna.obj
+
+default: all
+
+all: $(objdir) $(programs)
+
+$(objdir)\vlna.exe: $(objdir)\vlna.obj
+ $(link) $(**) $(conlibs)
+
+!include <msvc/config.mak>
+!include <msvc/install.mak>
+
+vlna.1: vlna.man
+ -@$(sed) -e "s|@BINDIR@|$(bindir)|;\
+ s|@MANDIR@|$(mandir)|;\
+ s|@MANEXT@|$(manext)|" vlna.man > vlna.$(manext)
+
+install:: install-exec install-man
+
+
+!include <msvc/clean.mak>
+
+clean::
+ -@$(del) sample1.rb2 sample2.rb2 sample1.tst sample2.tst
+
+!include <msvc/rdepend.mak>
+!include "./depend.mak"
+
+#
+# Local Variables:
+# mode: makefile
+# End: \ No newline at end of file