summaryrefslogtreecommitdiff
path: root/Build/source/utils/vlna/vlna.tex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
committerKarl Berry <karl@freefriends.org>2021-02-25 19:22:25 +0000
commitad547a6b5986815fda458221149728d9d9ab1d87 (patch)
tree16296910eb3eca724371474ea9aea3994dc69614 /Build/source/utils/vlna/vlna.tex
parent947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff)
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/vlna/vlna.tex')
-rw-r--r--Build/source/utils/vlna/vlna.tex1434
1 files changed, 1434 insertions, 0 deletions
diff --git a/Build/source/utils/vlna/vlna.tex b/Build/source/utils/vlna/vlna.tex
new file mode 100644
index 00000000000..1e2660c1bae
--- /dev/null
+++ b/Build/source/utils/vlna/vlna.tex
@@ -0,0 +1,1434 @@
+\input cwebmac
+
+\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}}
+
+
+
+\N{1}{1}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ů:
+\Y\B\X3:Hlavičkové soubory k načtení\X\6
+\X4:Globální deklarace\X\6
+\X6:Pomocné funkce\X\6
+\X29:Vlnkovací funkce \PB{\\{tie}}\X\6
+\X5:Hlavní program\X\par
+\fi
+
+\M{2}Definujeme \PB{\.{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ý) \PB{\.{BANNER}}.
+\Y\B\4\D$\.{BANNER}$ \5
+\.{"This\ is\ program\ vln}\)\.{a,\ version\ 1.5,\ (c)\ }\)\.{1995,\ 2002,\
+2009,\ 20}\)\.{10\ Petr\ Olsak\\n"}\par
+\fi
+
+\M{3}V programu jsou použity knihovní funkce, jejíchž prototypy jsou
+definovány ve třech standardních hlavičkových souborech.
+\Y\B\4\X3:Hlavičkové soubory k načtení\X${}\E{}$\6
+\8\#\&{include} \.{<stdio.h>}\6
+\8\#\&{include} \.{<string.h>}\6
+\8\#\&{include} \.{<stdlib.h>}\par
+\U1.\fi
+
+\M{4}Definujeme konstanty pro návratový kód. \PB{\.{OK}} pro úspěšný běh,
+\PB{\.{WARNING}} při výskytu aspoň jedné varovné zprávy, \PB{\.{IO\_ERR}} pro
+chybu
+v~přístupu ke vtupním nebo výstupním souborům, \PB{\.{BAD\_OPTIONS}} pro
+syntaktickou chybu na příkazové řádce a \PB{\.{BAD\_PROGRAM}} pro případ
+havárie programu. Ta by neměla nikdy nastat. Proměnná \PB{\\{status}} bude
+obsahovat návratový kód a proměnná \PB{\\{prog\_name}} bude ukazovat na text
+nultého parametru příkazové řádky.
+\Y\B\4\D$\.{OK}$ \5
+\T{0}\par
+\B\4\D$\.{WARNING}$ \5
+\T{1}\par
+\B\4\D$\.{IO\_ERR}$ \5
+\T{2}\par
+\B\4\D$\.{BAD\_OPTIONS}$ \5
+\T{3}\par
+\B\4\D$\.{BAD\_PROGRAM}$ \5
+\T{4}\par
+\Y\B\4\X4:Globální deklarace\X${}\E{}$\6
+\&{char} ${}{*}\\{prog\_name};{}$\6
+\&{int} \\{status};\par
+\As7, 8, 17, 18, 19, 23, 28\ETs36.
+\U1.\fi
+
+\M{5}Základní rozvržení funkce \PB{\\{main}}.
+\Y\B\4\X5:Hlavní program\X${}\E{}$\6
+\&{int} \\{main}(\&{int} \\{argc}${},\39{}$\&{char} ${}{*}{*}\\{argv}){}$\1\1\2%
+\2\6
+${}\{{}$\1\6
+\X11:Lokální proměnné funkce \PB{\\{main}}\X;\6
+${}\\{prog\_name}\K\\{argv}[\T{0}];{}$\6
+${}\\{status}\K\.{OK};{}$\6
+\X9:Načtení parametrů příkazového řádku\X;\6
+\&{if} ${}(\R\\{silent}){}$\1\5
+${}\\{fprintf}(\\{stderr},\39\.{BANNER});{}$\2\6
+\X24:Inicializace datových struktur\X;\6
+\X13:Zpracování souborů\X;\6
+\&{return} \\{status};\6
+\4${}\}{}$\2\par
+\U1.\fi
+
+\N{1}{6}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 \PB{$\X13:Zpracování
+souborů\X$}). 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 \PB{\.{BANNER}}, ani sumarizaci, ani varování,
+při nichž není program předčasně ukončen. Všechny tyto výpisy
+směřují do \PB{\\{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ě.
+* \.{-x} \dots\ parametr vymezuje pomocí hexadecimálního zápisu string,
+který program vkládá na vyhledaná místa. Implicitně vkládá vlnku.
+Například \.{-x C2A0} způsobí, že program bude vkládat místo vlnky dva byty,
+první s kódem \.{C2} a druhý s kódem \.{A0}.
+* \.{-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 \PB{\\{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.
+\Y\B\4\X6:Pomocné funkce\X${}\E{}$\6
+\&{static} \&{void} \\{printusage}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"usage:\ vlna\ [opt]\ [}\)\.{filenames]\\n"}%
+\.{"\ \ opt\ -f\ :\ \ filter\ }\)\.{mode:\ file1\ file2\ ..}\)\.{.\
+file1->file2\\n"}\.{"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ }\)\.{\ \ \ \ \ \
+file1\ \ \ \ \ \ \ ..}\)\.{.\ file1->stdout\\n"}\.{"\ \ \ \ \ \ \ \ \ \ \ \ \ \
+\ \ \ \ \ }\)\.{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ..}\)\.{.\ stdin->stdout%
+\\n"}\.{"\ \ \ \ \ \ \ \ \ \ \ \ nofilte}\)\.{r:\ file1\ [file2\ file}\)\.{3\
+...]\ all\ are\ in/ou}\)\.{t\\n"}\.{"\ \ \ \ \ \ -s\ :\ \ silent:}\)\.{\ no\
+messages\ to\ stde}\)\.{rr\\n"}\.{"\ \ \ \ \ \ -r\ :\ \ rmbacku}\)\.{p:\ if\
+nofilter,\ remo}\)\.{ves\ temporary\ files\\}\)\.{n"}\.{"\ \ \ \ \ \ -v\
+charset\ :\ }\)\.{\ set\ of\ lettres\ to\ a}\)\.{dd\ tie,\ default:\ KkS}\)%
+\.{sVvZzOoUuAI\\n"}\.{"\ \ \ \ \ \ -x\ code\ :\ cod}\)\.{e\ for\ tie\ symbol,\
+de}\)\.{fault:\ 7E,\ example\ -}\)\.{x\ C2A0\\n"}\.{"\ \ \ \ \ \ -m\ :\ \
+nomath:}\)\.{\ ignores\ math\ modes\\}\)\.{n"}\.{"\ \ \ \ \ \ -n\ :\ \ noverb:}%
+\)\.{\ ignores\ verbatim\ mo}\)\.{des\\n"}\.{"\ \ \ \ \ \ -l\ :\ \ LaTeX\ m}\)%
+\.{ode\\n"}\.{"\ \ \ \ \ \ -w\ :\ \ web\ mod}\)\.{e\\n"});{}$\6
+\4${}\}{}$\2\par
+\As10, 12, 20, 21, 22, 25, 26, 39, 41, 44, 45, 47, 48, 50, 52, 54, 55, 56\ETs58.
+\U1.\fi
+
+\M{7}Proměnné \PB{\\{isfilter}}, \PB{\\{silent}}, \PB{\\{rmbackup}}, \PB{%
+\\{nomath}}, \PB{\\{noverb}},
+\PB{\\{latex}}, resp. \PB{\\{web}} říkají, že je nastaven parametr \.{-f}, %
+\.{-s},
+\.{-r}, \.{-m}, \.{-n}, \.{-l}, resp. \.{-w}. Proměnná \PB{\\{charset}}
+ukazuje buď na implicitní skupinu znaků \PB{\\{charsetdefault}}, nebo (při
+použití parametru \.{-v}) na text uvedený v příkazovém řádku.
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{int} \\{isfilter}${}\K\T{0},{}$ \\{silent}${}\K\T{0},{}$ \\{rmbackup}${}\K%
+\T{0},{}$ \\{nomath}${}\K\T{0},{}$ \\{noverb}${}\K\T{0},{}$ \\{web}${}\K%
+\T{0},{}$ \\{latex}${}\K\T{0};{}$\6
+\&{char} \\{charsetdefault}[\,]${}\K\.{"KkSsVvZzOoUuAI"};{}$\6
+\&{char} ${}{*}\\{charset}\K\\{charsetdefault}{}$;\par
+\fi
+
+\M{8}String \PB{\\{tiestr}} obsahuje string, kterým se má nahradit vyhledané
+místo. Pokud není použit parametr \.{-u}, je tento string jadnoznakový
+a obsahuje vlnku. Jinak obsahuje string konvertovaný z parametru \.{-u}.
+String má délku \PB{\\{tiestrlen}} bez ohledu na to, zda obsahuje nebo
+neobsahuje nulové znaky (C-čková konvence pro stringy není použita).
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{unsigned} \&{char} \\{tiestr}[\.{MAXLEN}];\6
+\&{int} \\{tiestrlen};\par
+\fi
+
+\M{9}\B\X9:Načtení parametrů příkazového řádku\X${}\E{}$\6
+$\\{tiestr}[\T{0}]\K\.{'\~'};{}$\6
+${}\\{tiestrlen}\K\T{1};{}$\6
+\&{while} ${}(\\{argc}>\T{1}\W\\{argv}[\T{1}][\T{0}]\E\.{'-'}){}$\5
+${}\{{}$\1\6
+\&{if} ${}(\\{argv}[\T{1}][\T{2}]\I\T{0}){}$\1\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\2\6
+\&{switch} (\\{argv}[\T{1}][\T{1}])\5
+${}\{{}$\1\6
+\4\&{case} \.{'f'}:\5
+${}\\{isfilter}\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'s'}:\5
+${}\\{silent}\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'r'}:\5
+${}\\{rmbackup}\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'v'}:\6
+\&{if} ${}(\\{argc}<\T{2}){}$\1\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\2\6
+${}\\{argv}\PP;{}$\6
+${}\\{argc}\MM;{}$\6
+${}\\{charset}\K\\{argv}[\T{1}];{}$\6
+\&{break};\6
+\4\&{case} \.{'x'}:\6
+\&{if} ${}(\\{argc}<\T{2}){}$\1\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\2\6
+${}\\{argv}\PP;{}$\6
+${}\\{argc}\MM;{}$\6
+\\{settiestr}(\\{argv}[\T{1}]);\6
+\&{break};\6
+\4\&{case} \.{'m'}:\5
+${}\\{nomath}\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'n'}:\5
+${}\\{noverb}\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'l'}:\5
+${}\\{latex}\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'w'}:\5
+${}\\{web}\K\T{1};{}$\6
+\&{break};\6
+\4\&{default}:\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS}){}$;\C{ nezn\'am\'y parametr
+}\6
+\4${}\}{}$\2\6
+${}\\{argc}\MM;{}$\6
+${}\\{argv}\PP;{}$\6
+\4${}\}{}$\2\par
+\U5.\fi
+
+\M{10}Vyřešíme konverzi kódu zapsaného za parametrem \.{-x} na string \PB{%
+\\{tiestr}}.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{unsigned} \&{char} \\{hexnum}(\&{char} \|c)\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\|c\G\.{'0'}\W\|c\Z\.{'9'}){}$\1\5
+\&{return} \|c${}-\.{'0'};{}$\2\6
+\&{if} ${}(\|c\G\.{'A'}\W\|c\Z\.{'F'}){}$\1\5
+\&{return} \|c${}-\.{'A'}+\T{10};{}$\2\6
+\&{if} ${}(\|c\G\.{'a'}\W\|c\Z\.{'f'}){}$\1\5
+\&{return} \|c${}-\.{'a'}+\T{10};{}$\2\6
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\6
+\4${}\}{}$\2\7
+\&{static} \&{void} \\{settiestr}(\&{char} ${}{*}\|s){}$\1\1\2\2\6
+${}\{{}$\1\6
+\&{int} \|i${},{}$ \|j;\7
+${}\|i\K\\{strlen}(\|s);{}$\6
+\&{if} ${}((\|i>\T{2}*\.{MAXLEN})\V\|i\MOD\T{2}\E\T{1}){}$\1\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\2\6
+${}\\{tiestrlen}\K\|i/\T{2};{}$\6
+${}\|j\K\T{0};{}$\6
+\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{tiestrlen};{}$ ${}\|i\PP){}$\5
+${}\{{}$\1\6
+${}\\{tiestr}[\|i]\K\\{hexnum}(\|s[\|j\PP])\LL\T{4};{}$\6
+${}\\{tiestr}[\|i]\MRL{+{\K}}\\{hexnum}(\|s[\|j\PP]);{}$\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\fi
+
+\N{1}{11}Zpracování souborů. Parametr \PB{\.{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}.
+\Y\B\4\D$\.{MAXLEN}$ \5
+\T{120}\par
+\Y\B\4\X11:Lokální proměnné funkce \PB{\\{main}}\X${}\E{}$\6
+\&{FILE} ${}{*}\\{infile},{}$ ${}{*}\\{outfile};{}$\6
+\&{char} \\{backup}[\.{MAXLEN}];\6
+\&{int} \|j;\par
+\U5.\fi
+
+\M{12}Definujeme funkci pro výpis chybového hlášení při neúspěšném otevření
+souboru.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{ioerr}(\&{char} ${}{*}\|f){}$\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ cannot\ open\ fil}\)\.{e\ \%s\\n"},\39%
+\\{prog\_name},\39\|f);{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{13}Způsob zpracování souborů rozlišíme podle režimu daným přepínačem \.{-f}.
+\Y\B\4\X13:Zpracování souborů\X${}\E{}$\6
+\&{if} (\\{isfilter}) \X14:Zpracování v režimu filter\X\6
+\&{else} \X15:Zpracování všech souborů příkazové řádky\X\par
+\Q6.
+\U5.\fi
+
+\M{14}V režimu \PB{$\\{isfilter}\E\T{1}$} je další zpracování závislé na počtu
+souborů v
+příkazové řádce:
+\begitems
+* nula souborů -- vstup je \PB{\\{stdin}} a výstup je \PB{\\{stdout}},
+* jeden soubor -- je vstupní, výstup je \PB{\\{stdout}},
+* dva soubory -- první je vstupní, druhý výstupní,
+* více souborů -- program skončí s chybou.
+\enditems
+\Y\B\4\X14:Zpracování v režimu filter\X${}\E{}$\6
+${}\{{}$\1\6
+\&{if} ${}(\\{argc}>\T{3}){}$\1\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\2\6
+${}\\{infile}\K\\{stdin};{}$\6
+${}\\{outfile}\K\\{stdout};{}$\6
+\&{if} ${}(\\{argc}\G\T{2}){}$\1\5
+${}\\{infile}\K\\{fopen}(\\{argv}[\T{1}],\39\.{"r"});{}$\2\6
+\&{if} ${}(\\{infile}\E\NULL){}$\1\5
+${}\\{ioerr}(\\{argv}[\T{1}]),\39\\{exit}(\.{IO\_ERR});{}$\2\6
+\&{if} ${}(\\{argc}\E\T{3}){}$\1\5
+${}\\{outfile}\K\\{fopen}(\\{argv}[\T{2}],\39\.{"wb"});{}$\2\6
+\&{if} ${}(\\{outfile}\E\NULL){}$\1\5
+${}\\{ioerr}(\\{argv}[\T{2}]),\39\\{exit}(\.{IO\_ERR});{}$\2\6
+\&{if} ${}(\\{argc}\G\T{2}){}$\1\5
+${}\\{filename}\K\\{argv}[\T{1}];{}$\2\6
+\&{else}\1\5
+${}\\{filename}\K\NULL;{}$\2\6
+${}\\{tie}(\\{infile},\39\\{outfile});{}$\6
+\&{if} ${}(\\{outfile}\I\\{stdout}){}$\1\5
+\\{fclose}(\\{outfile});\2\6
+\&{if} ${}(\\{infile}\I\\{stdin}){}$\1\5
+\\{fclose}(\\{infile});\2\6
+\4${}\}{}$\2\par
+\U13.\fi
+
+\M{15}V~režimu \PB{$\\{isfilter}\E\T{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.
+\Y\B\4\X15:Zpracování všech souborů příkazové řádky\X${}\E{}$\6
+${}\{{}$\1\6
+\&{if} ${}(\\{argc}\E\T{1}){}$\1\5
+${}\\{printusage}(\,),\39\\{exit}(\.{BAD\_OPTIONS});{}$\2\6
+\&{while} ${}(\\{argc}>\T{1}){}$\5
+${}\{{}$\1\6
+${}\\{argc}\MM;{}$\6
+${}\\{argv}\PP;{}$\6
+\X16:Přejmenuj vstup \PB{\\{argv}[\T{0}]} na \PB{\\{backup}} a otevři jej jako %
+\PB{\\{infile}}\X;\6
+\&{if} ${}(\\{infile}\E\NULL){}$\5
+${}\{{}$\1\6
+\\{ioerr}(\\{argv}[\T{0}]);\6
+\&{continue};\6
+\4${}\}{}$\2\6
+${}\\{outfile}\K\\{fopen}(\\{argv}[\T{0}],\39\.{"wb"});{}$\6
+\&{if} ${}(\\{outfile}\E\NULL){}$\5
+${}\{{}$\1\6
+\\{ioerr}(\\{argv}[\T{0}]);\6
+${}\\{rename}(\\{backup},\39\\{argv}[\T{0}]);{}$\6
+${}\\{status}\K\.{WARNING};{}$\6
+\&{continue};\6
+\4${}\}{}$\2\6
+${}\\{filename}\K\\{argv}[\T{0}];{}$\6
+${}\\{tie}(\\{infile},\39\\{outfile});{}$\6
+${}\\{fclose}(\\{outfile}),\39\\{fclose}(\\{infile});{}$\6
+\&{if} (\\{rmbackup})\1\5
+\\{remove}(\\{backup});\2\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\U13.\fi
+
+\M{16}Při \PB{$\\{isfilter}\E\T{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 \PB{$\\{rmbackup}\E\T{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.
+\Y\B\4\X16:Přejmenuj vstup \PB{\\{argv}[\T{0}]} na \PB{\\{backup}} a otevři jej
+jako \PB{\\{infile}}\X${}\E{}$\6
+$\\{infile}\K\NULL;{}$\6
+${}\|j\K\\{strlen}(\\{argv}[\T{0}])-\T{1};{}$\6
+\&{if} ${}(\|j\G\.{MAXLEN}\V\\{argv}[\T{0}][\|j]\E\.{'\~'}){}$\5
+${}\{{}$\1\6
+\&{if} ${}(\R\\{silent}){}$\1\5
+${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ the\ conflict\ of}\)\.{\ file\ name\ \%s%
+\\n"},\39\\{prog\_name},\39\\{argv}[\T{0}]);{}$\2\6
+\4${}\}{}$\2\6
+\&{else}\5
+${}\{{}$\1\6
+${}\\{strcpy}(\\{backup},\39\\{argv}[\T{0}]);{}$\6
+${}\\{backup}[\|j]\K\.{'\~'};{}$\6
+\\{remove}(\\{backup});\6
+${}\|j\K\\{rename}(\\{argv}[\T{0}],\39\\{backup});{}$\6
+\&{if} ${}(\|j\E\T{0}){}$\1\5
+${}\\{infile}\K\\{fopen}(\\{backup},\39\.{"r"});{}$\2\6
+\4${}\}{}$\2\par
+\U15.\fi
+
+\N{1}{17}Patterny. Abychom mohli účelně definovat chování programu
+v~různých situacích, zavedeme datovou strukturu \PB{\.{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 \PB{\\{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 (\PB{\.{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á \PB{\\{charset}}).
+Každá pozice má svůj přepínač (\PB{\\{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 \PB{\\{next}}, poslední
+pozice má \PB{$\\{next}\E\NULL$}. Stejně tak jednotlivé patterny budeme
+sestavovat do seznamů a budou rovněž zřetězeny ukazatelem \PB{\\{next}}.
+
+Pattern kromě řetězu pozic obsahuje ukazatel na funkci (proceduru) \PB{%
+\\{proc}},
+která se má vykonat v~případě, že testovaný řetězec vyhovuje patternu.
+
+\Y\B\4\D$\.{ONE}$ \5
+\T{1}\C{ flag: prave jeden vyskyt }\par
+\B\4\D$\.{ANY}$ \5
+\T{2}\C{ flag: nula nebo vice }\par
+\B\4\D$\.{ONE\_NOT}$ \5
+${-}{}$\T{1}\C{ flag: prave jednou, znak nesmi byt v mnozine }\par
+\B\4\D$\.{ANY\_NOT}$ \5
+${-}{}$\T{2}\C{ flag: nula nebo vice, znak nesmi byt v mnozine }\par
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{typedef} \&{struct} \&{PATITEM} ${}\{{}$\C{ jedna pozice patternu }\1\6
+\&{char} ${}{*}\\{str}{}$;\C{ seznam znaku na teto pozici }\6
+\&{int} \\{flag};\C{ vyznam seznamu znaku }\6
+\&{struct} \&{PATITEM} ${}{*}\\{next}{}$;\C{ nasledujici pozice patternu }\2\6
+${}\}{}$ \&{PATITEM};\6
+\&{typedef} \&{struct} \&{PATTERN} ${}\{{}$\C{ jeden pattern }\1\6
+\&{PATITEM} ${}{*}\\{patt}{}$;\C{ ukazatel na prvni pozici }\7
+${}\&{void}({*}\\{proc})(\&{void}){}$;\C{ procedura spustena pri souhlasu
+patternu }\7
+\&{struct} \&{PATTERN} ${}{*}\\{next}{}$;\C{ nasledujici v seznamu vsech
+patternu }\2\6
+${}\}{}$ \&{PATTERN};\par
+\fi
+
+\M{18}Deklarujeme některé globální proměnné pro práci s~patterny. \PB{\\{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 \PB{\\{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 \PB{\\{lapi}} budou na počátku samá \PB{$\NULL$} (to se při překladu
+inicializuje
+samo) a přemazání ukazatele na pozici konstantou \PB{$\NULL$} budeme považovat
+za zavření patternu. Vedle pole \PB{\\{lapi}} souměrně udržujeme pole \PB{%
+\\{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 \PB{\\{proc}}
+patternu.
+
+\PB{\\{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 \PB{\\{normallist}} a
+\PB{\\{commentlist}} a aktivní \PB{\\{listpatt}} má vždy jednu z~těchto dvou
+hodnot.
+
+Proměnné \PB{\\{lastpt}} a \PB{\\{lastpi}} použijeme pro budování řetězové
+struktury
+patternů.
+
+Proměnná \PB{\|c} obsahuje právě testovaný znak ze vstupu (který se rovněž
+přepíše do bufferu \PB{\\{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 \PB{\.{BUFI}}, abychom proceduru přepisu bufferu do
+výstupního proudu neaktivovali zbytečně často.
+\Y\B\4\D$\.{MAXPATT}$ \5
+\T{200}\C{ maximalni pocet patternu }\par
+\B\4\D$\.{MAXBUFF}$ \5
+\T{500}\C{ velikost bufferu pro operace }\par
+\B\4\D$\.{BUFI}$ \5
+\T{300}\C{ velikost stredniho zaplneni }\par
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{PATITEM} ${}{*}\\{lapi}[\.{MAXPATT}]{}$;\C{ pole ukazatelu na aktualni
+pozice }\6
+\&{PATTERN} ${}{*}\\{lapt}[\.{MAXPATT}]{}$;\C{ pole odpovidajicich ukazatelu na
+patterny }\6
+\&{PATTERN} ${}{*}\\{listpatt},{}$ ${}{*}\\{normallist},{}$ ${}{*}%
+\\{commentlist},{}$ ${}{*}\\{pt},{}$ ${}{*}\\{lastpt}\K\NULL;{}$\6
+\&{PATITEM} ${}{*}\\{lastpi}\K\NULL;{}$\6
+\&{char} \|c;\C{ zrovna nacetny znak }\6
+\&{char} \\{buff}[\.{MAXBUFF}];\C{ prechodny buffer }\6
+\&{int} \\{ind};\C{ aktualni pozice prechodneho bufferu }\par
+\fi
+
+\M{19}Dne 30. 4. 2009 jsem přidal možnost čtení vstupu, který obsahuje nulové
+byty.
+Takové nuly se přepisují do výstupu, ale program si jich nevšímá při
+procházení patternů. Tím je možno program použít na soubory kódované
+v UTF16, ačkoli patterny obsahují jen jednobytové ASCII znaky.
+Buffer \PB{\\{buff}} může obsahovat i nulové byty, které je třeba přepsat do
+výstupu.
+Na druhé straně buffer \PB{\\{buffnz}} obsahuje jen nenulové byty, na které se
+někdy ptáme při pohledu dozadu. Nejdelší pohled dozadu je o čtyři byty.
+Udělám tedy \PB{\\{buffnz}} osmibytový, začnu jej plnit od \PB{\\{buffnz}}[4]
+a kdykoli je buffer zcela zaplněn, přesunu horní čtyři byty na spodní a dále
+pokračuji v plnění bufferu od pozice \PB{\\{buffnz}}[4].
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{char} \\{buffnz}[\T{8}];\6
+\&{int} \\{inz};\par
+\fi
+
+\M{20}Nyní definujeme pomocné funkce \PB{\\{setpattern}}, \PB{\\{setpi}} a \PB{%
+\\{normalpattern}}.
+Tyto funkce alokují paměť pomocí standardní funkce \PB{\\{malloc}}. Abychom
+mohli
+ohlídat případnou chybu při alokaci, budeme allokovat paměť zprostředkovaně
+pomocí funkce \PB{\\{myalloc}}.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} ${}{*}{}$\\{myalloc}(\&{int} \\{size})\1\1\2\2\6
+${}\{{}$\1\6
+\&{void} ${}{*}\|p;{}$\7
+${}\|p\K\\{malloc}(\\{size});{}$\6
+\&{if} ${}(\|p\E\NULL){}$\5
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"\%s,\ no\ memory,\ mall}\)\.{oc\ failed\\n"},%
+\39\\{prog\_name});{}$\6
+\\{exit}(\.{BAD\_PROGRAM});\6
+\4${}\}{}$\2\6
+\&{return} \|p;\6
+\4${}\}{}$\2\par
+\fi
+
+\M{21}Funkce \PB{\\{setpattern}} alokuje paměťové místo struktury \PB{%
+\&{PATTERN}} a napojí
+ji pomocí proměnné \PB{\\{lastpt}} na už alokovaný řetěz patternů.
+Vrátí ukazatel na nově alokované místo. Jednotlivé pozice patternu se musí
+následovně alokovat pomocí \PB{\\{setpi}}.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{PATTERN} ${}{*}\\{setpattern}(\&{void}({*}\\{proc})(\&{void})){}$%
+\1\1\2\2\6
+${}\{{}$\1\6
+\&{PATTERN} ${}{*}\\{pp};{}$\7
+${}\\{pp}\K\\{myalloc}(\&{sizeof}(\&{PATTERN}));{}$\6
+${}\\{pp}\MG\\{proc}\K\\{proc};{}$\6
+${}\\{pp}\MG\\{next}\K\NULL;{}$\6
+${}\\{pp}\MG\\{patt}\K\NULL;{}$\6
+\&{if} ${}(\\{lastpt}\I\NULL){}$\1\5
+${}\\{lastpt}\MG\\{next}\K\\{pp};{}$\2\6
+${}\\{lastpt}\K\\{pp};{}$\6
+${}\\{lastpi}\K\NULL;{}$\6
+\&{return} \\{pp};\6
+\4${}\}{}$\2\par
+\fi
+
+\M{22}Funkce \PB{\\{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
+\PB{\\{patt}} ve struktuře \PB{\&{PATTERN}} a další byly provázány položkou %
+\PB{\\{next}} ve
+struktuře \PB{\&{PATITEM}}. Poslední pozice má \PB{$\\{next}\E\NULL$}.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{setpi}(\&{char} ${}{*}\\{str},\39{}$\&{int} \\{flag})\1%
+\1\2\2\6
+${}\{{}$\1\6
+\&{PATITEM} ${}{*}\|p;{}$\7
+${}\|p\K\\{myalloc}(\&{sizeof}(\&{PATITEM}));{}$\6
+${}\|p\MG\\{str}\K\\{str};{}$\6
+${}\|p\MG\\{flag}\K\\{flag};{}$\6
+${}\|p\MG\\{next}\K\NULL;{}$\6
+\&{if} ${}(\\{lastpi}\E\NULL){}$\1\5
+${}\\{lastpt}\MG\\{patt}\K\|p;{}$\2\6
+\&{else}\1\5
+${}\\{lastpi}\MG\\{next}\K\|p;{}$\2\6
+${}\\{lastpi}\K\|p;{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{23}Připravme si půdu pro funkci \PB{\\{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á
+\PB{$\\{flag}\K\.{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 \PB{\.{"."}},
+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ů.
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{char} \\{strings}[\T{512}];\6
+\&{int} \|i;\par
+\fi
+
+\M{24}Inicializujeme toto pole (znak, nula, znak, nula, atd...).
+\Y\B\4\X24:Inicializace datových struktur\X${}\E{}$\6
+\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\T{256};{}$ ${}\|i\PP){}$\5
+${}\{{}$\1\6
+${}\\{strings}[\T{2}*\|i]\K{}$(\&{char}) \|i;\6
+${}\\{strings}[\T{2}*\|i+\T{1}]\K\T{0};{}$\6
+\4${}\}{}$\2\par
+\As37, 40, 42, 43, 46, 49, 51, 53\ETs57.
+\U5.\fi
+
+\M{25}Definujme funkci \PB{\\{normalpattern}}.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{PATTERN} ${}{*}\\{normalpattern}(\&{void}({*}\\{proc})(\&{void}),%
+\39{}$\&{const} \&{char} ${}{*}\\{str}){}$\1\1\2\2\6
+${}\{{}$\1\6
+\&{PATTERN} ${}{*}\\{pp};{}$\6
+\&{int} \|j${}\K\T{0};{}$\7
+${}\\{pp}\K\\{setpattern}(\\{proc});{}$\6
+\&{while} (\\{str}[\|j])\5
+${}\{{}$\1\6
+\&{if} ${}(\\{str}[\|j]\E\.{'.'}){}$\5
+${}\{{}$\1\6
+${}\|j\PP;{}$\6
+\&{if} ${}(\\{str}[\|j]\I\.{'.'}){}$\5
+${}\{{}$\1\6
+${}\\{setpi}(\\{blankscr},\39\.{ANY});{}$\6
+\&{continue};\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\6
+${}\\{setpi}({\AND}\\{strings}{}$[(\&{unsigned} \&{char}) \\{str}[\|j]${}*%
+\T{2}],\39\.{ONE});{}$\6
+${}\|j\PP;{}$\6
+\4${}\}{}$\2\6
+\&{return} \\{pp};\6
+\4${}\}{}$\2\par
+\fi
+
+\M{26}Funkce \PB{\\{match}}. Definujeme funkci, která na základě hodnoty znaku %
+\PB{\|c}
+(proměnná \PB{\|c} je definována jako globální), a pozice patternu \PB{\|p}
+(parametr
+funkce) vrátí informaci o tom, zda znak souhlasí s patternem. Záporná čísla
+\PB{\.{FOUND}}, resp. \PB{\.{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 \PB{\|c}.
+
+Pokud je \PB{\|c} v množině znaků pro danou pozici \PB{$\|p\MG\\{str}$}, bude %
+\PB{$\|m\E\T{1}$}, jinak
+je \PB{$\|m\E{-}\T{1}$}. Pokud tímto číslem pronásobíme hodnotu \PB{$\|p\MG%
+\\{flag}$}, nemusíme
+větvení podle \PB{$\|p\MG\\{flag}$} programovat dvakrát. Hodnoty \PB{\\{flag}}
+jsou totiž
+symetrické podle nuly, např. \PB{$\.{ANY}\E{-}\.{ANY\_NOT}$}.
+\Y\B\4\D$\.{FOUND}$ \5
+${-}{}$\T{1}\par
+\B\4\D$\.{NOFOUND}$ \5
+${-}{}$\T{2}\par
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{int} \\{match}(\&{PATITEM} ${}{*}\|p){}$\1\1\2\2\6
+${}\{{}$\1\6
+\&{int} \|m;\7
+\&{if} ${}(\\{strchr}(\|p\MG\\{str},\39\|c)\I\NULL){}$\1\5
+${}\|m\K\T{1}{}$;\C{ Znak nalezen }\2\6
+\&{else}\1\5
+${}\|m\K{-}\T{1}{}$;\C{ Znak nenalezen }\2\6
+\&{switch} ${}(\|m*\|p\MG\\{flag}){}$\5
+${}\{{}$\1\6
+\4\&{case} \.{ANY}:\5
+\&{return} \T{0};\C{ Souhas, neni nutny posun }\6
+\4\&{case} \.{ONE}:\6
+\&{if} ${}(\|p\MG\\{next}\E\NULL){}$\1\5
+\&{return} \.{FOUND};\2\6
+\&{return} \T{1};\C{ Souhas, nutny posun o 1 }\6
+\4\&{case} \.{ONE\_NOT}:\5
+\&{return} \.{NOFOUND};\C{ Nesouhlas }\6
+\4\&{case} \.{ANY\_NOT}:\5
+\X27:Vrať hodnotu podle následující pozice patternu\X;\6
+\4${}\}{}$\2\6
+\&{return} \T{0};\C{ Tady bychom nikdy nemeli byt, return pro potlaceni
+varovani }\6
+\4${}\}{}$\2\par
+\fi
+
+\M{27}O kolik pozic je třeba se posunout a s jakým výsledkem zjistíme
+rekurzivním voláním funkce \PB{\\{match}}.
+\Y\B\4\X27:Vrať hodnotu podle následující pozice patternu\X${}\E{}$\6
+\&{switch} ${}(\|m\K\\{match}(\|p\MG\\{next})){}$\5
+${}\{{}$\1\6
+\4\&{case} \.{NOFOUND}:\5
+\&{return} \.{NOFOUND};\6
+\4\&{case} \.{FOUND}:\5
+\&{return} \.{FOUND};\6
+\4\&{default}:\5
+\&{return} \T{1}${}+\|m;{}$\6
+\4${}\}{}$\2\par
+\U26.\fi
+
+\N{1}{28}Vlnkovací funkce.
+Nejprve připravíme globální deklarace pro \uv{vlnkovací} funkci \PB{\\{tie}}.
+Funkce \PB{\\{tie}} \uv{ovlnkuje} vstupní soubor \PB{\\{infile}} a vytvoří
+soubor
+\PB{\\{outfile}}. Při \PB{$\\{silent}\K\T{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é \PB{\\{filename}}. Proměnná \PB{\\{numline}} počítá řádky,
+proměnná
+\PB{\\{numchanges}} sčítá změny, tj. počet doplněných vlnek.
+Proměnná \PB{\\{mode}} nabývý některé z hodnot \PB{\.{TEXTMODE}}, \PB{%
+\.{MATHMODE}},
+\PB{\.{DISPLAYMODE}} a \PB{\.{VERBMODE}} podle stavu ve čteném textu.
+\Y\B\4\D$\.{TEXTMODE}$ \5
+\T{0}\par
+\B\4\D$\.{MATHMODE}$ \5
+\T{1}\par
+\B\4\D$\.{DISPLAYMODE}$ \5
+\T{2}\par
+\B\4\D$\.{VERBMODE}$ \5
+\T{3}\par
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{char} ${}{*}\\{filename}{}$;\C{ jmeno zpracovavaneho souboru }\6
+\&{long} \&{int} \\{numline}${},{}$ \\{numchanges};\C{ pro zaverecnou
+statistiku }\6
+\&{int} \\{mode};\par
+\fi
+
+\M{29}Nyní definujeme vlnkovací funkci \PB{\\{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
+(\PB{$\\{listpatt}\E\\{commentlist}$}) a mimo komentář (\PB{$\\{listpatt}\E%
+\\{normallist}$});
+\Y\B\4\X29:Vlnkovací funkce \PB{\\{tie}}\X${}\E{}$\6
+\&{static} \&{void} \\{tie}(\&{FILE} ${}{*}\\{input},\39{}$\&{FILE} ${}{*}%
+\\{output}){}$\1\1\2\2\6
+${}\{{}$\1\6
+\&{int} \\{ap};\C{ ap je pocet otevrenych patternu }\6
+\&{register} \&{int} \|k${},{}$ \|m${},{}$ \|n;\6
+\&{int} \\{ic};\6
+\&{PATTERN} ${}{*}\\{pp};{}$\6
+\&{PATITEM} ${}{*}\\{pi};{}$\7
+\X30:Inicializace proměnných při startu funkce \PB{\\{tie}}\X;\6
+\&{while} ${}(\R\\{feof}(\\{input})){}$\5
+${}\{{}$\1\6
+\&{if} ${}(\\{ap}\E\T{0}\W\\{ind}>\.{BUFI}\W\|c\I\.{'\\\\'}){}$\1\5
+\X31:Vyprázdni buffer\X;\2\6
+\X33:Otevři nové patterny\X;\C{ 1. 2. 2010: prohozene poradi }\6
+\&{if} ${}(\\{ind}\G\.{MAXBUFF}){}$\5
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"Operating\ buffer\ ov}\)\.{erflow,\ is\
+anything\ }\)\.{wrong?\\n"});{}$\6
+\\{exit}(\.{BAD\_PROGRAM});\6
+\4${}\}{}$\2\6
+\&{if} ${}((\\{ic}\K\\{getc}(\\{input}))\E\.{EOF}{}$)\C{ opravil Cejka Rudolf }%
+\1\6
+\&{break};\2\6
+${}\\{buff}[\\{ind}\PP]\K\|c\K\\{ic};{}$\6
+\&{if} ${}(\|c\E\T{0}){}$\1\5
+\&{continue};\C{ 30. 4. 2009 }\2\6
+\&{if} ${}(\\{inz}\G\T{8}){}$\5
+${}\{{}$\1\6
+\&{for} ${}(\\{inz}\K\T{0};{}$ ${}\\{inz}<\T{4};{}$ ${}\\{inz}\PP){}$\1\5
+${}\\{buffnz}[\\{inz}]\K\\{buffnz}[\\{inz}+\T{4}];{}$\2\6
+${}\\{inz}\K\T{4};{}$\6
+\4${}\}{}$\2\6
+${}\\{buffnz}[\\{inz}\PP]\K\|c;{}$\6
+\&{if} ${}(\|c\E\.{'\\n'}){}$\1\5
+${}\\{numline}\PP,\39\\{listpatt}\K\\{normallist};{}$\2\6
+\&{if} ${}(\|c\E\.{'\%'}\W\\{mode}\I\.{VERBMODE}\W\\{buffnz}[\\{inz}-\T{2}]\I%
+\.{'\\\\'}){}$\1\5
+${}\\{listpatt}\K\\{commentlist};{}$\2\6
+\X32:Projdi otevřené patterny\X;\6
+\4${}\}{}$\2\6
+\X31:Vyprázdni buffer\X;\6
+\&{if} ${}(\R\\{web}){}$\1\5
+\\{checkmode}(\,);\C{ zaverecna kontrola modu }\2\6
+\&{if} ${}(\R\\{silent}){}$\1\5
+\X35:Tiskni závěrečnou zprávu\X;\2\6
+\4${}\}{}$\2\par
+\U1.\fi
+
+\M{30}\B\X30:Inicializace proměnných při startu funkce \PB{\\{tie}}\X${}\E{}$\6
+\&{for} ${}(\|k\K\T{0};{}$ ${}\|k<\.{MAXPATT};{}$ ${}\|k\PP){}$\1\5
+${}\\{lapi}[\|k]\K\NULL;{}$\2\6
+${}\|c\K\.{'\\n'};{}$\6
+${}\\{buff}[\T{0}]\K\T{1};{}$\6
+${}\\{mode}\K\\{ap}\K\T{0};{}$\6
+${}\\{ind}\K\T{1};{}$\6
+\&{for} ${}(\\{inz}\K\T{0};{}$ ${}\\{inz}<\T{4};{}$ ${}\\{inz}\PP){}$\1\5
+${}\\{buffnz}[\\{inz}]\K\T{0};{}$\2\6
+${}\\{inz}\K\T{4};{}$\6
+${}\\{numline}\K\T{1};{}$\6
+${}\\{numchanges}\K\T{0};{}$\6
+${}\\{mode}\K\.{TEXTMODE}{}$;\par
+\A38.
+\U29.\fi
+
+\M{31}Při manipulaci s bufferem byl použit jeden trik. Veškeré načtené znaky
+začínají až od \PB{\\{buff}[\T{1}]}, zatímco \PB{\\{buff}[\T{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 \PB{\\{buff}[\T{0}]}, v některých situacích
+bychom se ptali, zda \PB{$\\{buff}[{-}\T{1}]\E\.{'\\\\'}$}, tj. sahali bychom
+na neošetřené
+místo v paměti. Od 30. 4. 2009 tento problém pominul, protože se ptáme dozadu
+pouze
+v~\PB{\\{buffnz}}, ale vlastnost dříve implementovanou v \PB{\\{buff}} jsem
+ponechal beze změny.
+\Y\B\4\X31:Vyprázdni buffer\X${}\E{}$\6
+${}\{{}$\1\6
+${}\\{fwrite}({\AND}\\{buff}[\T{1}],\39\\{ind}-\T{1},\39\T{1},\39%
+\\{output});{}$\6
+${}\\{ind}\K\T{1};{}$\6
+\4${}\}{}$\2\par
+\U29.\fi
+
+\M{32}Při procházení otevřenými patterny posunujeme v poli \PB{\\{lapi}} pozice
+jednotlivých patternů podle pokynů funkce \PB{\\{match}}, případně pattern
+zavřeme
+a případně vyvoláme proceduru patternu.
+
+Některé patterny v poli \PB{\\{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.
+\Y\B\4\X32:Projdi otevřené patterny\X${}\E{}$\6
+$\|n\K\\{ap};{}$\6
+${}\|k\K\T{0};{}$\6
+\&{while} (\|n)\5
+${}\{{}$\1\6
+\&{while} ${}(\\{lapi}[\|k]\E\NULL){}$\1\5
+${}\|k\PP{}$;\C{ zastav se na prvnim ukazateli na pattern }\2\6
+\&{switch} ${}(\|m\K\\{match}(\\{lapi}[\|k])){}$\5
+${}\{{}$\1\6
+\4\&{case} \.{FOUND}:\5
+${}({*}\\{lapt}[\|k]\MG\\{proc})(\,){}$;\C{ Pattern nalezen, spustit proceduru
+}\6
+\4\&{case} \.{NOFOUND}:\5
+${}\\{lapi}[\|k]\K\NULL{}$;\C{ Deaktivace patternu }\6
+${}\\{ap}\MM;{}$\6
+\&{break};\6
+\4\&{default}:\6
+\&{while} ${}(\|m\MM){}$\1\5
+${}\\{lapi}[\|k]\K\\{lapi}[\|k]\MG\\{next}{}$;\C{ dalsi pozice patternu }\2\6
+\4${}\}{}$\2\6
+${}\|k\PP;{}$\6
+${}\|n\MM;{}$\6
+\4${}\}{}$\2\par
+\U29.\fi
+
+\M{33}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 \PB{\.{FOUND}} nebo \PB{\.{NOFOUND}}. V takových případech ani nezanášíme
+ukazatel
+na pozici do pole \PB{\\{lapi}}.
+\Y\B\4\X33:Otevři nové patterny\X${}\E{}$\6
+$\\{pp}\K\\{listpatt};{}$\6
+\&{if} (\|c)\1\6
+\&{while} ${}(\\{pp}\I\NULL){}$\5
+${}\{{}$\1\6
+\&{switch} ${}(\|m\K\\{match}(\\{pp}\MG\\{patt})){}$\5
+${}\{{}$\1\6
+\4\&{case} \.{FOUND}:\5
+${}({*}\\{pp}\MG\\{proc})(\,){}$;\C{ spustit proceduru }\6
+\4\&{case} \.{NOFOUND}:\5
+\&{break};\6
+\4\&{default}:\5
+\X34:Vytvoř ukazatel na nový pattern a \PB{\&{break}}\X;\6
+\4${}\}{}$\2\6
+${}\\{pp}\K\\{pp}\MG\\{next};{}$\6
+\4${}\}{}$\2\2\par
+\U29.\fi
+
+\M{34}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 \PB{\\{lapi}} a tam uhnízdíme nový
+ukazatel
+na pozici v patternu.
+\Y\B\4\X34:Vytvoř ukazatel na nový pattern a \PB{\&{break}}\X${}\E{}$\6
+$\\{pi}\K\\{pp}\MG\\{patt};{}$\6
+\&{while} ${}(\|m\MM){}$\1\5
+${}\\{pi}\K\\{pi}\MG\\{next};{}$\2\6
+${}\|n\K\\{ap};{}$\6
+${}\|k\K\T{0};{}$\6
+\&{while} (\|n)\5
+${}\{{}$\1\6
+\&{if} ${}(\\{lapi}[\|k]\E\\{pi}){}$\1\5
+\&{break};\2\6
+\&{if} ${}(\\{lapi}[\|k\PP]\I\NULL){}$\1\5
+${}\|n\MM;{}$\2\6
+\4${}\}{}$\2\6
+\&{if} ${}(\R\|n){}$\5
+${}\{{}$\1\6
+${}\|k\K\T{0};{}$\6
+\&{while} ${}(\\{lapi}[\|k]\I\NULL){}$\1\5
+${}\|k\PP;{}$\2\6
+\&{if} ${}(\|k\G\.{MAXPATT}){}$\5
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"I\ cannot\ allocate\ p}\)\.{p,\ is\ anything\
+wrong}\)\.{?\\n"});{}$\6
+\\{exit}(\.{BAD\_PROGRAM});\6
+\4${}\}{}$\2\6
+${}\\{lapt}[\|k]\K\\{pp};{}$\6
+${}\\{lapi}[\|k]\K\\{pi};{}$\6
+${}\\{ap}\PP;{}$\6
+\4${}\}{}$\2\par
+\U33.\fi
+
+\M{35}Poslední věcí ve funci \PB{\\{tie}} je tisk závěrečné statistiky
+zpracování.
+\Y\B\4\X35:Tiskni závěrečnou zprávu\X${}\E{}$\6
+$\\{fprintf}(\\{stderr},\39\.{"\~\~\~\ file:\ \%s\\t\ \ lin}\)\.{es:\ \%ld,\
+changes:\ \%l}\)\.{d\\n"},\39\\{filename},\39\\{numline},\39\\{numchanges}){}$;%
+\par
+\U29.\fi
+
+\N{1}{36}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.
+
+\Y\B\4\X4:Globální deklarace\X${}\mathrel+\E{}$\6
+\&{char} \\{tblanks}[\,]${}\K\.{"\ \~\\t"};{}$\6
+\&{char} \\{blanks}[\,]${}\K\.{"\ \\t"};{}$\6
+\&{char} \\{blankscr}[\,]${}\K\.{"\ \\t\\n"};{}$\6
+\&{char} \\{tblankscr}[\,]${}\K\.{"\ \~\\t\\n"};{}$\6
+\&{char} \\{nochar}[\,]${}\K\.{"\%\~\\n"};{}$\6
+\&{char} \\{cr}[\,]${}\K\.{"\\n"};{}$\6
+\&{char} \\{prefixes}[\,]${}\K\.{"[(\{\~"};{}$\6
+\&{char} \\{dolar}[\,]${}\K\.{"\$"};{}$\6
+\&{char} \\{backslash}[\,]${}\K\.{"\\\\"};{}$\6
+\&{char} \\{openbrace}[\,]${}\K\.{"\{"};{}$\6
+\&{char} \\{letters}[\,]${}\K\.{"abcdefghijklmnopqrs}\)\.{tuvwxyzABCDEFGHIJKLM}%
+\)\.{NOPQRSTUVWXYZ"};{}$\6
+\&{PATTERN} ${}{*}\\{vlnkalist},{}$ ${}{*}\\{mathlist},{}$ ${}{*}%
+\\{parcheck},{}$ ${}{*}\\{verblist}{}$;\par
+\fi
+
+\M{37}Začneme definicí nejčastěji používaného patternu na vlnkování uvnitř
+řádku. Připomeňme, že opakované volání funkce \PB{\\{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
+\PB{\\{normallist}}. Stejně tak opakované volání funkce \PB{\\{setpi}} vytváří
+seznam
+pozic pro naposledy deklarovaný pattern.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+$\\{vlnkalist}\K\\{setpattern}(\\{vlnkain});{}$\6
+${}\\{setpi}(\\{tblankscr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{tblanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{prefixes},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{charset},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{nochar},\39\.{ONE\_NOT}){}$;\par
+\fi
+
+\M{38}\B\X30:Inicializace proměnných při startu funkce \PB{\\{tie}}\X${}%
+\mathrel+\E{}$\6
+$\\{listpatt}\K\\{normallist}\K\\{vlnkalist}{}$;\par
+\fi
+
+\M{39}Vložení vlnky znamená vykonat následující práci: Zapamatovat si znak za
+skupinou mezer
+(do proměnné \PB{\|p}). Pokud před tímto znakem předchází nulový byte,
+použijeme ho později, proto
+si jej uložíme do proměnné \PB{\|z}. Dále se posuneme v bufferu vlevo přes
+všechny mezery, tabelátory
+(přesněji \PB{\\{blanks}}) a přeskakujeme přitom všechny nulové byty. Index %
+\PB{\\{ind}} se zastaví
+na předložce. Posuneme jej doprava za předložku (++\PB{\\{ind}}) a pokud tam je
+nulový byte a první znak
+\PB{\\{tiestr}} není nulový, posuneme se až za tento nulový byte. Dále vložíme
+string \PB{\\{tiestr}},
+neboli vlnku. Nakonec připojíme zapamatovaný znak \PB{\|p}, ovšem pokud před
+ním byla nula,
+vložíme ji ještě před znak \PB{\|p}.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{vlnkain}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{int} \|i;\6
+\&{char} \|p${},{}$ \|z;\7
+${}\\{ind}\MM;{}$\6
+${}\|p\K\\{buff}[\\{ind}\MM];{}$\6
+${}\|z\K\\{buff}[\\{ind}];{}$\6
+\&{while} ${}(\R\\{buff}[\\{ind}]\V(\\{strchr}(\\{blanks},\39\\{buff}[\\{ind}])%
+\I\NULL)){}$\1\5
+${}\\{ind}\MM;{}$\2\6
+\&{if} ${}(\R\\{buff}[\PP\\{ind}]\W\\{tiestr}[\T{0}]){}$\1\5
+${}\\{ind}\PP;{}$\2\6
+\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{tiestrlen};{}$ ${}\|i\PP){}$\1\5
+${}\\{buff}[\\{ind}\PP]\K\\{tiestr}[\|i];{}$\2\6
+${}\|i\K\\{tiestrlen}{}$;\C{ nulu pred p vlozime, pokud je z==0 a }\6
+\&{if} ${}(\R\\{tiestr}[\T{0}]){}$\1\5
+${}\|i\MM{}$;\C{ pocet vlozenych znaku z tiestr }\2\6
+\&{if} ${}(\R\|z\W(\|i\MOD\T{2})){}$\1\5
+${}\\{buff}[\\{ind}\PP]\K\T{0}{}$;\C{ je sudy }\2\6
+${}\\{buff}[\\{ind}\PP]\K\|p;{}$\6
+${}\\{numchanges}\PP;{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{40}Podobně pro tvorbu vlnky \uv{přes řádek} vytvoříme pattern a kód
+procedury.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+\\{setpattern}(\\{vlnkacr});\6
+${}\\{setpi}(\\{tblankscr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{tblanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{prefixes},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{charset},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{cr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{nochar},\39\.{ONE\_NOT}){}$;\par
+\fi
+
+\M{41}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ší.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{vlnkacr}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{char} \|p${},{}$ \|z;\6
+\&{int} \|i${},{}$ \|j;\7
+${}\\{ind}\MM;{}$\6
+${}\|p\K\\{buff}[\\{ind}\MM];{}$\6
+${}\|z\K\\{buff}[\\{ind}];{}$\6
+\&{while} ${}(\R\\{buff}[\\{ind}]\V(\\{strchr}(\\{blankscr},\39\\{buff}[%
+\\{ind}])\I\NULL)){}$\1\5
+${}\\{ind}\MM;{}$\2\6
+${}\|i\K\\{ind}{}$;\C{ misto predlozky, kterou chceme vazat }\6
+\&{while} ${}(\|i\G\T{0}\W(\\{strchr}(\\{blankscr},\39\\{buff}[\|i])\E%
+\NULL)){}$\1\5
+${}\|i\MM;{}$\2\6
+${}\|j\K\|i;{}$\6
+\&{while} ${}(\|i\G\T{0}\W(\R\\{buff}[\\{ind}]\V(\\{strchr}(\\{blanks},\39%
+\\{buff}[\|i])\I\NULL))){}$\1\5
+${}\|i\MM;{}$\2\6
+\&{if} ${}(\|i\G\T{0}\W\\{buff}[\|i]\E\.{'\\n'}){}$\1\5
+${}\|j\K{-}\T{1};{}$\2\6
+\&{if} ${}(\|j\G\T{0}){}$\1\5
+${}\\{buff}[\|j]\K\.{'\\n'};{}$\2\6
+\&{else}\1\5
+${}\\{numline}\MM;{}$\2\6
+\&{if} ${}(\R\\{buff}[\PP\\{ind}]\W\\{tiestr}[\T{0}]){}$\1\5
+${}\\{ind}\PP;{}$\2\6
+\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{tiestrlen};{}$ ${}\|i\PP){}$\1\5
+${}\\{buff}[\\{ind}\PP]\K\\{tiestr}[\|i];{}$\2\6
+${}\|i\K\\{tiestrlen};{}$\6
+\&{if} ${}(\R\\{tiestr}[\T{0}]){}$\1\5
+${}\|i\MM;{}$\2\6
+\&{if} ${}(\R\|z\W(\|i\MOD\T{2})){}$\1\5
+${}\\{buff}[\\{ind}\PP]\K\T{0};{}$\2\6
+${}\\{buff}[\\{ind}\PP]\K\|p;{}$\6
+${}\\{numchanges}\PP;{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{42}Nyní vytvoříme patterny pro případy typu \.{\char92uv\char`\{v lese\char`%
+\}}.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+\\{setpattern}(\\{vlnkain});\C{ na radku }\6
+${}\\{setpi}(\\{tblankscr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{backslash},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{letters},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{letters},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{openbrace},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{prefixes},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{charset},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{nochar},\39\.{ONE\_NOT});{}$\6
+\\{setpattern}(\\{vlnkacr});\C{ pres radek }\6
+${}\\{setpi}(\\{tblankscr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{backslash},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{letters},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{letters},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{openbrace},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{prefixes},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{charset},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{cr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{nochar},\39\.{ONE\_NOT}){}$;\par
+\fi
+
+\M{43}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...}}.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+$\\{normalpattern}(\\{tielock},\39\.{"\\\\TeX"});{}$\6
+${}\\{setpi}(\\{blankscr},\39\.{ONE});{}$\6
+${}\\{normalpattern}(\\{tielock},\39\.{"\\\\LaTeX"});{}$\6
+${}\\{setpi}(\\{blankscr},\39\.{ONE}){}$;\par
+\fi
+
+\M{44}Procedura \PB{\\{tielock}} obsahuje nečistý trik. Při provádění procedury
+je
+právě načten znak z \PB{\\{blankscr}} a je uložen do \PB{\\{buff}}. Testy na
+otevírání
+nových patternů pro tento znak teprve budou následovat a testují se na
+hodnotu proměnné \PB{\|c}. Stačí tedy změnit hodnotu \PB{\|c} a vlnkovací
+patterny se
+neotevřou.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{tielock}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+${}\|c\K\T{1};{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{45}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.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{printwarning}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\R\\{silent}){}$\1\5
+${}\\{fprintf}(\\{stderr},\39\.{"\~!\~\ warning:\ text/m}\)\.{ath/verb\ mode\
+mismat}\)\.{ch,\ \ file:\ \%s,\ \ line}\)\.{:\ \%ld\\n"},\39\\{filename},\39%
+\\{numline}-(\|c\E\.{'\\n'}\?\T{1}:\T{0}));{}$\2\6
+${}\\{status}\K\.{WARNING};{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{46}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.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+\&{if} ${}(\R\\{nomath}){}$\5
+${}\{{}$\1\6
+${}\\{mathlist}\K\\{setpattern}(\\{onedollar});{}$\6
+${}\\{setpi}(\\{dolar},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{dolar},\39\.{ONE\_NOT});{}$\6
+\&{if} (\\{latex})\5
+${}\{{}$\1\6
+${}\\{normalpattern}(\\{mathin},\39\.{"\\\\begin.\{math\}"});{}$\6
+${}\\{normalpattern}(\\{mathout},\39\.{"\\\\end.\{math\}"});{}$\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\fi
+
+\M{47}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{mathin}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\I\.{TEXTMODE}){}$\1\5
+\\{printwarning}(\,);\2\6
+${}\\{mode}\K\.{MATHMODE};{}$\6
+${}\\{normallist}\K\\{listpatt}\K\\{mathlist};{}$\6
+\4${}\}{}$\2\7
+\&{static} \&{void} \\{mathout}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\I\.{MATHMODE}){}$\1\5
+\\{printwarning}(\,);\2\6
+${}\\{mode}\K\.{TEXTMODE};{}$\6
+${}\\{normallist}\K\\{listpatt}\K\\{vlnkalist};{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{48}Při programování procedury \PB{\\{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.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{onedollar}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{buffnz}[\\{inz}-\T{3}]\E\.{'\\\\'}\V(\\{buffnz}[\\{inz}-\T{3}]\E%
+\.{'\$'}\W\\{buffnz}[\\{inz}-\T{4}]\I\.{'\\\\'})){}$\1\5
+\&{return};\2\6
+\&{if} ${}(\\{mode}\E\.{DISPLAYMODE}){}$\1\5
+\\{printwarning}(\,);\2\6
+\&{else}\5
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\E\.{TEXTMODE}){}$\1\5
+\\{mathin}(\,);\2\6
+\&{else}\1\5
+\\{mathout}(\,);\2\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\fi
+
+\M{49}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.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+$\\{parcheck}\K\\{setpattern}(\\{checkmode});{}$\6
+${}\\{setpi}(\\{cr},\39\.{ONE});{}$\6
+${}\\{setpi}(\\{blanks},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{cr},\39\.{ONE}){}$;\par
+\fi
+
+\M{50}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{checkmode}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\I\.{TEXTMODE}){}$\5
+${}\{{}$\1\6
+\\{printwarning}(\,);\6
+${}\\{mode}\K\.{TEXTMODE};{}$\6
+${}\\{normallist}\K\\{listpatt}\K\\{vlnkalist};{}$\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\fi
+
+\M{51}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.
+
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+\&{if} ${}(\R\\{nomath}){}$\5
+${}\{{}$\1\6
+${}\\{normalpattern}(\\{twodollars},\39\.{"\$\$"});{}$\6
+\&{if} (\\{latex})\5
+${}\{{}$\1\6
+${}\\{normalpattern}(\\{displayin},\39\.{"\\\\begin.\{displaymat}\)\.{h"});{}$\6
+${}\\{normalpattern}(\\{displayin},\39\.{"\\\\begin.\{equation"});{}$\6
+${}\\{normalpattern}(\\{displayout},\39\.{"\\\\end.\{displaymath"});{}$\6
+${}\\{normalpattern}(\\{displayout},\39\.{"\\\\end.\{equation"});{}$\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\fi
+
+\M{52}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{displayin}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\I\.{TEXTMODE}){}$\1\5
+\\{printwarning}(\,);\2\6
+${}\\{mode}\K\.{DISPLAYMODE};{}$\6
+${}\\{normallist}\K\\{listpatt}\K\\{parcheck};{}$\6
+\4${}\}{}$\2\7
+\&{static} \&{void} \\{displayout}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\I\.{DISPLAYMODE}){}$\1\5
+\\{printwarning}(\,);\2\6
+${}\\{mode}\K\.{TEXTMODE};{}$\6
+${}\\{normallist}\K\\{listpatt}\K\\{vlnkalist};{}$\6
+\4${}\}{}$\2\7
+\&{static} \&{void} \\{twodollars}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{buffnz}[\\{inz}-\T{3}]\E\.{'\\\\'}){}$\1\5
+\&{return};\2\6
+\&{if} ${}(\\{mode}\E\.{DISPLAYMODE}){}$\1\5
+\\{displayout}(\,);\2\6
+\&{else}\1\5
+\\{displayin}(\,);\2\6
+\4${}\}{}$\2\par
+\fi
+
+\M{53}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á).
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+\&{if} ${}(\R\\{noverb}){}$\5
+${}\{{}$\1\6
+${}\\{verblist}\K\\{normalpattern}(\\{verbinchar},\39\.{"\\\\verb"});{}$\6
+${}\\{setpi}(\\{blankscr},\39\.{ANY});{}$\6
+${}\\{setpi}(\\{blankscr},\39\.{ONE\_NOT});{}$\6
+${}\\{normalpattern}(\\{verbin},\39\.{"\\\\begtt"});{}$\6
+\&{if} (\\{latex})\1\5
+${}\\{normalpattern}(\\{verbin},\39\.{"\\\\begin.\{verbatim"});{}$\2\6
+\4${}\}{}$\2\6
+\&{if} (\\{web})\5
+${}\{{}$\1\6
+${}\\{normalpattern}(\\{verbin},\39\.{"@<"});{}$\6
+${}\\{normalpattern}(\\{verbin},\39\.{"@d"});{}$\6
+\4${}\}{}$\2\6
+\&{if} ${}(\R\\{noverb}){}$\5
+${}\{{}$\1\6
+${}\\{verboutlist}[\T{0}]\K\\{setpattern}(\\{verbout});{}$\6
+${}\\{setpi}(\\{verbchar},\39\.{ONE});{}$\6
+${}\\{verboutlist}[\T{1}]\K\\{normalpattern}(\\{verbout},\39\.{"%
+\\\\endtt"});{}$\6
+\&{if} (\\{latex})\1\5
+${}\\{verboutlist}[\T{2}]\K\\{normalpattern}(\\{verbout},\39\.{"\\\\end%
+\{verbatim"});{}$\2\6
+\4${}\}{}$\2\6
+\&{if} (\\{web})\5
+${}\{{}$\1\6
+${}\\{verboutlist}[\T{3}]\K\\{normalpattern}(\\{verbout},\39\.{"@\ "});{}$\6
+${}\\{normalpattern}(\\{verbout},\39\.{"@*"});{}$\6
+${}\\{normalpattern}(\\{verbout},\39\.{"@>|"});{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{54}Procedura \PB{\\{verbinchar}} se od \uv{společné} procedury \PB{%
+\\{verbin}} liší v
+tom, že zavede do stringu \PB{\\{verbchar}} momentální hodnotu proměnné \PB{%
+\|c}.
+Proto druhý výskyt této hodnoty verbatim režim ukončí.
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{int} \\{prevmode};\6
+\&{PATTERN} ${}{*}\\{prevlist},{}$ ${}{*}\\{verboutlist}[\T{4}];{}$\6
+\&{char} \\{verbchar}[\T{2}];\7
+\&{static} \&{void} \\{verbinchar}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{prevmode}\K\\{mode};{}$\6
+${}\\{verbchar}[\T{0}]\K\|c;{}$\6
+${}\|c\K\T{1};{}$\6
+${}\\{listpatt}\K\\{normallist}\K\\{verboutlist}[\T{0}];{}$\6
+${}\\{prevlist}\K\\{listpatt}\MG\\{next};{}$\6
+${}\\{listpatt}\MG\\{next}\K\NULL;{}$\6
+${}\\{mode}\K\.{VERBMODE};{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{55}Při programování \uv{obecné} funkce \PB{\\{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).
+\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{verbin}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{int} \|i;\7
+${}\|i\K\T{0};{}$\6
+${}\\{prevmode}\K\\{mode};{}$\6
+\&{switch} (\|c)\5
+${}\{{}$\1\6
+\4\&{case} \.{'t'}:\5
+${}\|i\K\T{1};{}$\6
+\&{break};\6
+\4\&{case} \.{'m'}:\5
+${}\|i\K\T{2};{}$\6
+\&{break};\6
+\4\&{case} \.{'<'}:\5
+;\6
+\4\&{case} \.{'d'}:\5
+${}\|i\K\T{3};{}$\6
+\&{if} ${}(\\{buffnz}[\\{inz}-\T{3}]\E\.{'@'}){}$\1\5
+\&{return};\C{ dvojity @ ignorovat }\2\6
+\&{break};\6
+\4${}\}{}$\2\6
+${}\\{listpatt}\K\\{normallist}\K\\{verboutlist}[\|i];{}$\6
+${}\\{prevlist}\K\\{listpatt}\MG\\{next};{}$\6
+\&{if} ${}(\|c\I\.{'<'}\W\|c\I\.{'d'}){}$\1\5
+${}\\{listpatt}\MG\\{next}\K\NULL;{}$\2\6
+${}\\{mode}\K\.{VERBMODE};{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{56}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{verbout}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+\&{if} ${}(\\{mode}\I\.{VERBMODE}){}$\1\5
+\&{return};\2\6
+\&{if} ${}(\\{web}\W\\{buffnz}[\\{inz}-\T{2}]\E\.{'@'}\W\\{buffnz}[\\{inz}-%
+\T{3}]\E\.{'@'}){}$\1\5
+\&{return};\2\6
+${}\\{mode}\K\\{prevmode};{}$\6
+${}\\{normallist}\MG\\{next}\K\\{prevlist};{}$\6
+\&{switch} (\\{mode})\5
+${}\{{}$\1\6
+\4\&{case} \.{DISPLAYMODE}:\5
+${}\\{normallist}\K\\{listpatt}\K\\{parcheck};{}$\6
+\&{break};\6
+\4\&{case} \.{MATHMODE}:\5
+${}\\{normallist}\K\\{listpatt}\K\\{mathlist};{}$\6
+\&{break};\6
+\4\&{case} \.{TEXTMODE}:\5
+${}\\{normallist}\K\\{listpatt}\K\\{vlnkalist};{}$\6
+\&{break};\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\par
+\fi
+
+\M{57}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 \PB{\\{lastpt}}.
+\Y\B\4\X24:Inicializace datových struktur\X${}\mathrel+\E{}$\6
+$\\{lastpt}\K\T{0};{}$\6
+${}\\{commentlist}\K\\{normalpattern}(\\{tieoff},\39\.{"\%.\~.-"});{}$\6
+${}\\{normalpattern}(\\{tieon},\39\.{"\%.\~.+"}){}$;\par
+\fi
+
+\M{58}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6
+\&{static} \&{void} \\{tieoff}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{normallist}\K\NULL;{}$\6
+\4${}\}{}$\2\7
+\&{static} \&{void} \\{tieon}(\&{void})\1\1\2\2\6
+${}\{{}$\1\6
+${}\\{normallist}\K\\{vlnkalist};{}$\6
+\4${}\}{}$\2\par
+\fi
+
+\M{59}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}).
+
+\fi
+
+\N{1}{60}Rejstřík.
+
+
+\fi
+
+
+\inx
+\fin
+\con