diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2008-06-26 10:30:34 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2008-06-26 10:30:34 +0000 |
commit | 9569af41158bac35010885fa91fb29cb01c2c958 (patch) | |
tree | 3ee56a5e1e1e9d2066f417a1f5661fdecab25085 /Build/source/utils/vlna/vlna.tex | |
parent | 28d18100f79c2fb370f3490062257b88fb57043e (diff) |
added utils/vlna to TL build
git-svn-id: svn://tug.org/texlive/trunk@9056 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/vlna/vlna.tex')
-rw-r--r-- | Build/source/utils/vlna/vlna.tex | 1316 |
1 files changed, 1316 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..58095ba8727 --- /dev/null +++ b/Build/source/utils/vlna/vlna.tex @@ -0,0 +1,1316 @@ +\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 +\X26: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.2,\ (c)\ }\)\.{1995,\ 2002\ Petr% +\ Olsa}\)\.{k\\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, 15, 16, 20, 25\ETs33. +\U1.\fi + +\M{5}Základní rozvržení funkce \PB{\\{main}}. +\Y\B\4\X5:Hlavní program\X${}\E{}$\6 +\&{int} ${}\\{main}(\\{argc},\39\\{argv}){}$\1\1\6 +\&{int} \\{argc};\6 +\&{char} ${}{*}{*}\\{argv};\2\2{}$\6 +${}\{{}$\1\6 +\X9:Lokální proměnné funkce \PB{\\{main}}\X;\6 +${}\\{prog\_name}\K\\{argv}[\T{0}];{}$\6 +${}\\{status}\K\.{OK};{}$\6 +\X8:Načtení parametrů příkazového řádku\X;\6 +\&{if} ${}(\R\\{silent}){}$\1\5 +${}\\{fprintf}(\\{stderr},\39\.{BANNER});{}$\2\6 +\X21:Inicializace datových struktur\X;\6 +\X11: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{$\X11: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ě. +* \.{-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 +\&{void} \\{printusage}(\,)\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"}\.{"\ \ \ \ \ \ -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, 17, 18, 19, 22, 23, 36, 38, 41, 42, 44, 45, 47, 49, 51, 52, 53\ETs55. +\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}\B\X8:Načtení parametrů příkazového řádku\X${}\E{}$\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} \.{'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 + +\N{1}{9}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\X9:Lokální proměnné funkce \PB{\\{main}}\X${}\E{}$\6 +\&{FILE} ${}{*}\\{infile},{}$ ${}{*}\\{outfile};{}$\6 +\&{char} \\{backup}[\.{MAXLEN}];\6 +\&{int} \|j;\par +\U5.\fi + +\M{10}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 +\&{void} \\{ioerr}(\|f)\1\1\6 +\&{char} ${}{*}\|f;\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{11}Způsob zpracování souborů rozlišíme podle režimu daným přepínačem \.{-f}. +\Y\B\4\X11:Zpracování souborů\X${}\E{}$\6 +\&{if} (\\{isfilter}) \X12:Zpracování v režimu filter\X\6 +\&{else} \X13:Zpracování všech souborů příkazové řádky\X\par +\Q6. +\U5.\fi + +\M{12}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\X12: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\.{"w"});{}$\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 +\U11.\fi + +\M{13}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\X13: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 +\X14: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\.{"w"});{}$\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 +\U11.\fi + +\M{14}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\X14: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 +\U13.\fi + +\N{1}{15}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})(\,){}$;\C{ procedura spustena pri souhlasu patternu }\7 +\&{struct} \&{PATTERN} ${}{*}\\{next}{}$;\C{ nasledujici v seznamu vsech +patternu }\2\6 +${}\}{}$ \&{PATTERN};\par +\fi + +\M{16}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} ${}{*}\\{pi},{}$ ${}{*}\\{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{17}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 +\&{void} ${}{*}\\{myalloc}(\\{size}){}$\1\1\6 +\&{int} \\{size};\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{18}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 +\&{PATTERN} ${}{*}{}$\\{setpattern}(\\{proc})\6 +${}\&{void}({*}\\{proc})(\,);{}$\7 +${}\{{}$\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{19}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 +\&{void} ${}\\{setpi}(\\{str},\39\\{flag}){}$\1\1\6 +\&{char} ${}{*}\\{str};{}$\6 +\&{int} \\{flag};\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{20}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{21}Inicializujeme toto pole (znak, nula, znak, nula, atd...). +\Y\B\4\X21: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 +\As34, 37, 39, 40, 43, 46, 48, 50\ETs54. +\U5.\fi + +\M{22}Definujme funkci \PB{\\{normalpattern}}. +\Y\B\4\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{PATTERN} ${}{*}\\{normalpattern}(\\{proc},\39\\{str}{}$)\6 +${}\&{void}({*}\\{proc})(\,);{}$\6 +\&{char} ${}{*}\\{str};{}$\7 +${}\{{}$\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{23}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 +\&{int} \\{match}(\|p)\1\1\6 +\&{PATITEM} ${}{*}\|p;\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 +\X24: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{24}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\X24: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 +\U23.\fi + +\N{1}{25}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{26}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\X26:Vlnkovací funkce \PB{\\{tie}}\X${}\E{}$\6 +\&{void} ${}\\{tie}(\\{input},\39\\{output}){}$\1\1\6 +\&{FILE} ${}{*}\\{input},{}$ ${}{*}\\{output};\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 +\X27:Inicializace proměnných při startu funkce \PB{\\{tie}}\X;\6 +\&{while} ${}(\R\\{feof}(\\{input})){}$\5 +${}\{{}$\1\6 +\X30:Otevři nové patterny\X;\6 +\&{if} ${}(\\{ap}\E\T{0}\W\\{ind}>\.{BUFI}\W\|c\I\.{'\\\\'}){}$\1\5 +\X28:Vyprázdni buffer\X;\2\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\.{'\\n'}){}$\1\5 +${}\\{numline}\PP,\39\\{listpatt}\K\\{normallist};{}$\2\6 +\&{if} ${}(\|c\E\.{'\%'}\W\\{mode}\I\.{VERBMODE}\W\\{buff}[\\{ind}-\T{2}]\I\.{'% +\\\\'}){}$\1\5 +${}\\{listpatt}\K\\{commentlist};{}$\2\6 +\X29:Projdi otevřené patterny\X;\6 +\4${}\}{}$\2\6 +\X28:Vyprázdni buffer\X;\6 +\&{if} ${}(\R\\{web}){}$\1\5 +\\{checkmode}(\,);\C{ zaverecna kontrola modu }\2\6 +\&{if} ${}(\R\\{silent}){}$\1\5 +\X32:Tiskni závěrečnou zprávu\X;\2\6 +\4${}\}{}$\2\par +\U1.\fi + +\M{27}\B\X27: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\\{mode}\K\\{ap}\K\T{0};{}$\6 +${}\\{ind}\K\T{1};{}$\6 +${}\\{numline}\K\T{1};{}$\6 +${}\\{numchanges}\K\T{0};{}$\6 +${}\\{mode}\K\.{TEXTMODE}{}$;\par +\A35. +\U26.\fi + +\M{28}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. +\Y\B\4\X28:Vyprázdni buffer\X${}\E{}$\6 +${}\{{}$\1\6 +${}\\{buff}[\\{ind}]\K\T{0};{}$\6 +${}\\{fputs}({\AND}\\{buff}[\T{1}],\39\\{output});{}$\6 +${}\\{ind}\K\T{1};{}$\6 +\4${}\}{}$\2\par +\U26.\fi + +\M{29}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\X29: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 +\U26.\fi + +\M{30}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\X30:Otevři nové patterny\X${}\E{}$\6 +$\\{pp}\K\\{listpatt};{}$\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 +\X31:Vytvoř ukazatel na nový pattern a \PB{\&{break}}\X;\6 +\4${}\}{}$\2\6 +${}\\{pp}\K\\{pp}\MG\\{next};{}$\6 +\4${}\}{}$\2\par +\U26.\fi + +\M{31}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\X31: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 +\U30.\fi + +\M{32}Poslední věcí ve funci \PB{\\{tie}} je tisk závěrečné statistiky +zpracování. +\Y\B\4\X32: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 +\U26.\fi + +\N{1}{33}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{34}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\X21: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{35}\B\X27:Inicializace proměnných při startu funkce \PB{\\{tie}}\X${}% +\mathrel+\E{}$\6 +$\\{listpatt}\K\\{normallist}\K\\{vlnkalist}{}$;\par +\fi + +\M{36}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{void} \\{vlnkain}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +\&{char} \|p;\7 +${}\\{ind}\MM;{}$\6 +${}\|p\K\\{buff}[\\{ind}\MM];{}$\6 +\&{while} ${}(\\{strchr}(\\{blanks},\39\\{buff}[\\{ind}])\I\NULL){}$\1\5 +${}\\{ind}\MM;{}$\2\6 +${}\\{ind}\PP;{}$\6 +${}\\{buff}[\\{ind}\PP]\K\.{'\~'};{}$\6 +${}\\{buff}[\\{ind}\PP]\K\|p;{}$\6 +${}\\{numchanges}\PP;{}$\6 +\4${}\}{}$\2\par +\fi + +\M{37}Podobně pro tvorbu vlnky \uv{přes řádek} vytvoříme pattern a kód +procedury. +\Y\B\4\X21: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{38}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 +\&{void} \\{vlnkacr}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +\&{char} \|p;\6 +\&{int} \|i${},{}$ \|j;\7 +${}\\{ind}\MM;{}$\6 +${}\|p\K\\{buff}[\\{ind}\MM];{}$\6 +\&{while} ${}(\\{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(\\{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 +${}\\{ind}\PP;{}$\6 +${}\\{buff}[\\{ind}\PP]\K\.{'\~'};{}$\6 +${}\\{buff}[\\{ind}\PP]\K\|p;{}$\6 +${}\\{numchanges}\PP;{}$\6 +\4${}\}{}$\2\par +\fi + +\M{39}Nyní vytvoříme patterny pro případy typu \.{\char92uv\char`\{v lese\char`% +\}}. +\Y\B\4\X21: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{40}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\X21: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{41}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 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 +\&{void} \\{tielock}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +${}\|c\K\T{1};{}$\6 +\4${}\}{}$\2\par +\fi + +\M{42}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 +\&{void} \\{printwarning}(\,)\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{43}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\X21: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{44}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{void} \\{mathin}(\,)\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 +\&{void} \\{mathout}(\,)\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{45}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 +\&{void} \\{onedollar}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +\&{if} ${}(\\{buff}[\\{ind}-\T{3}]\E\.{'\\\\'}\V(\\{buff}[\\{ind}-\T{3}]\E\.{'% +\$'}\W\\{buff}[\\{ind}-\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{46}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\X21: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{47}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{void} \\{checkmode}(\,)\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{48}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\X21: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{49}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{void} \\{displayin}(\,)\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 +\&{void} \\{displayout}(\,)\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 +\&{void} \\{twodollars}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +\&{if} ${}(\\{buff}[\\{ind}-\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{50}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\X21: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{51}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 +\&{void} \\{verbinchar}(\,)\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{52}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 +\&{void} \\{verbin}(\,)\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} ${}(\\{buff}[\\{ind}-\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{53}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{void} \\{verbout}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +\&{if} ${}(\\{mode}\I\.{VERBMODE}){}$\1\5 +\&{return};\2\6 +\&{if} ${}(\\{web}\W\\{buff}[\\{ind}-\T{2}]\E\.{'@'}\W\\{buff}[\\{ind}-\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{54}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\X21: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{55}\B\X6:Pomocné funkce\X${}\mathrel+\E{}$\6 +\&{void} \\{tieoff}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +${}\\{normallist}\K\NULL;{}$\6 +\4${}\}{}$\2\7 +\&{void} \\{tieon}(\,)\1\1\2\2\6 +${}\{{}$\1\6 +${}\\{normallist}\K\\{vlnkalist};{}$\6 +\4${}\}{}$\2\par +\fi + +\M{56}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}{57}Rejstřík. + + +\fi + + +\inx +\fin +\con |