\chapter{Analýza a implementace}\label{AnalImpl}
\section{\'{U}prava do kompilovateln\'{e} formy}\label{PortaceAnsi}

Jeliko\v{z} se zdrojov\'{e} k\'{o}dy Espressa nepovedlo zkompilovat, bylo
potřeba je před započet\'{\i}m samotn\'{e} anal\'{y}zy přev\'{e}st do
funkčn\'{\i} podoby. Tomu br\'{a}nilo jednak pou\v{z}it\'{\i} star\'{e}
,,normy`` jazyka a jednak pou\v{z}it\'{\i} v\'{y}\v{s}e zm\'{\i}něn\'{y}ch
bal\'{\i}čků, ve kter\'{y}ch byly implementov\'{a}ny i knihovn\'{\i} funkce.
V~n\'{a}sleduj\'{\i}c\'{\i}ch odstavc\'{\i}ch budou pops\'{a}ny oba
zm\'{\i}něn\'{e} probl\'{e}my.

\subsection{K{\&}R C}

Pojmem K{\&}R C se označuje jazyk C, kter\'{y} byl pops\'{a}n Brianem
Kernighanem a Dennisem Ritchiem v~roce 1987 v knize \uv{The C Programming
Language} \cite{FirstC}. Jednalo se o jej\'{\i} prvn\'{\i}
vyd\'{a}n\'{\i} a pro mnoh\'{e} program\'{a}tory se stala učebnic\'{\i}. O
deset let později -- tedy v~roce 1988 -- byl jazyk standardizov\'{a}n a
doznal několik změn. Tento standard se označuje jako ANSI \footnote{American
National Standardization Institute} C nebo někdy i ISO \footnote{International Standardization Organization} C.
K~tomuto počinu byla
vyd\'{a}na druh\'{a} edice knihy \uv{The C Programming Language}
\cite{SecondC}, ve kter\'{e} jazyk C odpov\'{\i}dal nově
vzniknut\'{e} normě.

V~n\'{a}sleduj\'{\i}c\'{\i} kapitole je uvedeno několik podstatn\'{y}ch
rozd\'{\i}lů mezi těmito edicemi.

\subsubsection{Rozd\'{\i}ly oproti ANSI C}\label{AnsiC}
Někter\'{e} rozd\'{\i}ly se t\'{y}kaj\'{\i} viz\'{a}\v{z}e, jin\'{e}
preprocesoru a dal\v{s}\'{\i} roz\v{s}\'{\i}řen\'{\i}, př\'{\i}padně
omezen\'{\i} jazyka samotn\'{e}ho.

Zde je uvedeno několik př\'{\i}kladů t\'{y}kaj\'{\i}c\'{\i}ch se:

\begin{itemize}
\item {\bf definic funkc\'{\i}} -- v K{\&}R C jsou typy parametrů určeny a\v{z} za ,,hlavičkou`` funkce, tedy v~prostoru mezi kulat\'{y}mi z\'{a}vorkami a slo\v{z}en\'{y}mi z\'{a}vorkami. V~ANSI C mus\'{\i} b\'{y}t parametry i jejich typy určeny u\v{z} v~kulat\'{y}ch z\'{a}vork\'{a}ch.
\item {\bf deklarac\'{\i} funkc\'{\i}} -- v K{\&}R C se funkce deklarovaly bez parametrů. ANSI C se sna\v{z}\'{\i} o typovou bezpečnost, a tak počet a typ parametrů mus\'{\i} b\'{y}t stejn\'{y} v~definici i deklaraci funkce.
\item {\bf implicitn\'{\i}ho typu }{\bf {\it int}} -- v K{\&}R C se při neuveden\'{\i} typu proměnn\'{e} nebo n\'{a}vratov\'{e} hodnoty funkce doplnil implicitn\'{\i} typ {\it int. }ANSI něco takov\'{e}ho nedovoluje a ohl\'{a}s\'{\i} to jako chybu.
\item {\bf z\'{a}niku někter\'{y}ch kl\'{\i}čov\'{y}ch slov} -- původně kl\'{\i}čov\'{a} slova {\it asm} a {\it fortran} v~ANSI C ji\v{z} kl\'{\i}čov\'{y}mi slovy nejsou a jejich pou\v{z}it\'{\i} je zak\'{a}z\'{a}n\'{e}.
\item {\bf vzniku nov\'{y}ch kl\'{\i}čov\'{y}ch slov} -- norma přidala tři nov\'{a} kl\'{\i}čov\'{a} slova: {\it const}, {\it volatile }a {\it signed.}
\item {\bf přid\'{a}n\'{\i} sufixů za č\'{\i}seln\'{e} konstanty} -- ANSI C umo\v{z}ňuje určit typ č\'{\i}seln\'{e} konstanty přid\'{a}n\'{\i}m jednoho ze sufixů: u, U, l, L, f, F (znač\'{\i}c\'{\i} postupně {\it int, long, float})
\item {\bf přeproceroru} -- přeprocesor K{\&}R C byl původně rekurzivn\'{\i}. Tato jeho vlastnost se v~normě odstranila. Dal\v{s}\'{\i} rozd\'{\i}ly jsou u\v{z} jen ve prospěch normy a přid\'{a}vaj\'{\i} vlastnosti, kter\'{e} původně nebyly implementov\'{a}ny, např. sp\'{a}jen\'{\i} řetězců,{\ldots}
\end{itemize}

\'{U}pln\'{y} v\'{y}čet v\v{s}ech rozd\'{\i}lů lze nal\'{e}zt na str\'{a}nce
\cite{KRC}.


\subsection{Pou\v{z}it\'{\i} vlastn\'{\i}ch knihoven}
V~době vzniku programu je\v{s}tě neexistovala standardn\'{\i} knihovna, jak
je tomu nyn\'{\i}, a autor si vět\v{s}inu jej\'{\i}ch funkc\'{\i}
implementoval do zm\'{\i}něn\'{y}ch bal\'{\i}čků (p\v{r}\'{i}loha \ref{Balicky})
s\'{a}m. Nyn\'{\i} jsou ale jeho funkce na obt\'{\i}\v{z}, proto\v{z}e jsou
při překladu v~konfliktu s~funkcemi deklarovan\'{y}mi ve~standardn\'{\i}ch
hlavičkov\'{y}ch souborech. Překladač ohl\'{a}s\'{\i} chybu a kompilace
skonč\'{\i}.
Proto je potřeba v\v{s}echny tyto funkce z~projektu odstranit.

\subsection{Volba n\'{a}stroje na \'{u}pravu}
Zdrojov\'{e} k\'{o}dy bylo potřeba pozměnit. Prvn\'{\i} tři zm\'{\i}něn\'{e}
rozd\'{\i}ly (kap. \ref{AnsiC}) oproti normě jsou jednodu\v{s}e
naleziteln\'{e} a upraviteln\'{e}. Nev\'{y}hodou je monot\'{o}nnost a
zdlouhavost t\'{e}to \'{u}pravy. (původně se Espresso skl\'{a}dalo z~91
souborů se zdrojov\'{y}mi k\'{o}dy a 19 hlavičkov\'{y}ch souborů). Proto
bylo jedn\'{\i}m z~c\'{\i}lů nalezen\'{\i} nebo vytvořen\'{\i} programu,
kter\'{y} by provedl změnu definic a deklarac\'{\i} funkc\'{\i}.

Hled\'{a}n\'{\i} na internetu odhalilo několik programů, kter\'{e} byly
schopny doplnit typy parametrů do deklarac\'{\i} a tak\'{e} přepsat hlavičky
funkc\'{\i} podle normy. Jak se později uk\'{a}zalo, jedin\'{y}
pou\v{z}iteln\'{y} byl n\'{a}stroj {\it protoize, } kter\'{y} je určen pro operačn\'{\i}
syst\'{e}m Linux. Ke sv\'{e} činnosti nicm\'{e}ně potřeboval
kompilovateln\'{y} k\'{o}d, kter\'{y} v~tuto chv\'{\i}li nebyl k~dispozici.

Původn\'{\i} idea byla \uv{překlopit} k\'{o}d do normalizovan\'{e} formy a
a\v{z} pak se zab\'{y}vat odstraňov\'{a}n\'{\i}m vlastnoručně
implementovan\'{y}ch funkc\'{\i}. Tato my\v{s}lenka nakonec neuspěla,
proto\v{z}e v~semestr\'{a}ln\'{\i}m projektu, kter\'{y} si stanovil tento
c\'{\i}l, se velice obt\'{\i}\v{z}ně povedlo implementovat překladač z
\uv{čist\'{e}ho} \footnote{My\v{s}leno forma bez direktiv preprocesoru}
K{\&}R C do ANSI C. Po konzultaci s Ing. Ne\v{s}věrou se do\v{s}lo k
z\'{a}věru, \v{z}e implementace preprocesoru, kter\'{y} dok\'{a}\v{z}e
navr\'{a}tit proveden\'{e} změny je velice obt\'{\i}\v{z}n\'{a}. Tato
vlastnost byla ale kl\'{\i}čov\'{a}, proto\v{z}e zdrojov\'{y} k\'{o}d po
zpracov\'{a}n\'{\i} preprocesorem je m\'{e}ně přehledn\'{y} a bez
koment\'{a}řů. N\'{a}slednou anal\'{y}zu by to učinilo obt\'{\i}\v{z}nou a
zdlouhavou. Proto se přistoupilo k alternativě
vyu\v{z}\'{\i}vaj\'{\i}c\'{\i} n\'{a}stroj {\it protoize}.


\subsection{Samotn\'{a} \'{u}prava}
K~\'{u}pravě zdrojov\'{y}ch k\'{o}dů byl vybr\'{a}n n\'{a}stroj {\it protoize,} kter\'{y}
je určen pro operačn\'{\i} syst\'{e}my Linux a vět\v{s}inou b\'{y}v\'{a}
př\'{\i}mou souč\'{a}st\'{\i} syst\'{e}mu, neboť je pevně spjat s~GCC
\footnote{GNU C Compiler}. V\'{y}jimkou nebyla ani stanice {\it sunray1}
nach\'{a}zej\'{\i}c\'{\i} se na akademick\'{e} půdě Fakulty
elektrotechnick\'{e} ČVUT na Karlově n\'{a}měst\'{\i}, na kter\'{e} byl
cel\'{y} port proveden.

Před zač\'{a}tkem samotn\'{e}ho zpracov\'{a}v\'{a}n\'{\i} se soubory ze
v\v{s}ech bal\'{\i}čků um\'{\i}stily do jednoho adres\'{a}ře, aby se
nemusely upravovat cesty pro vkl\'{a}dan\'{e} hlavičkov\'{e} soubory.
Tak\'{e} se odhadovalo, \v{z}e dojde k~značn\'{e}mu zredukov\'{a}n\'{\i}
počtu souborů, a rozdělen\'{\i} do bal\'{\i}čků bude t\'{\i}m p\'{a}dem
zbytečn\'{e}.

Port byl děl\'{a}n iterativně, tj. při ka\v{z}d\'{e}m spu\v{s}těn\'{\i}
program modifikoval č\'{a}st zdrojov\'{y}ch k\'{o}dů, kter\'{e} dok\'{a}zal
zpracovat, a n\'{a}sledně vypsal seznam chyb (kvůli kter\'{y}m nemohl
pokračovat) a jejich v\'{y}skyt. Pochopen\'{\i} př\'{\i}činy a
n\'{a}sledn\'{e} odstraněn\'{\i} těchto chyb bylo ryze na lidsk\'{e}
obsluze, jej\'{\i}ch zku\v{s}enostech a ch\'{a}p\'{a}n\'{\i}
programovac\'{\i}ch z\'{a}le\v{z}itost\'{\i}. V~př\'{\i}loze \ref{PrilohaAnsi}
jsou uvedeny př\'{\i}klady někter\'{y}ch chyb a jejich korekce.
Jedn\'{a} se jen o \'{u}tr\v{z}ek změn, kompletn\'{\i} v\'{y}pis je
dlouh\'{y} a pro čitatele nenese důle\v{z}itou informaci.

Na z\'{a}věr nutno podotknou, \v{z}e v tomto kroku byly učiněny oba
potřebn\'{e} kroky: převeden\'{\i} do ANSI C a z\'{a}roveň odstraněn\'{\i}
ne\v{z}\'{a}douc\'{\i}ch funkc\'{\i}. Bylo toho doc\'{\i}leno pr\'{a}vě
d\'{\i}ky tomu, \v{z}e {\it protoize} vy\v{z}adovalo kompilovateln\'{y} k\'{o}d. A
jeliko\v{z} konfliktn\'{\i} funkce, kter\'{e} se měly původně odstranit
později, byly odstraněny ji\v{z} nyn\'{\i}, byl v\'{y}sledn\'{y} k\'{o}d
kompilovateln\'{y}. Pro dal\v{s}\'{\i} postup bylo potřeba prov\'{e}st
testy (kapitola \ref{TestyAnsi}), kter\'{e} potvrd\'{\i} korektnost \'{u}prav.


\section{Vlastn\'{\i} anal\'{y}za Espressa}\label{Analyza}
Anal\'{y}za teď ji\v{z} funkčn\'{\i}ho Espressa se musela prov\'{e}st
postupně. Nejdř\'{\i}ve bylo potřeba prostudovat manu\'{a}l Espressa a
obezn\'{a}mit se s~druhy a~funkc\'{\i} přep\'{\i}načů. Pak se mohlo
přistoupit k~rozboru samotn\'{e}ho k\'{o}du a na z\'{a}věr se hledaly
př\'{\i}činy p\'{a}dů odhalen\'{y}ch při testov\'{a}n\'{\i} (kapitova \ref{TestyAnsi}).


\subsection{Studie manu\'{a}lu Espressa}\label{ManualEspressa}
Ovl\'{a}d\'{a}n\'{\i} Espressa je vcelku jednoduch\'{e}. Do
př\'{\i}kazov\'{e} ř\'{a}dky se nejdř\'{\i}ve zadaj\'{\i} přep\'{\i}nače a
n\'{a}sledně jm\'{e}no souboru obsahuj\'{\i}c\'{\i} logickou funkci.
Kdy\v{z} se jm\'{e}no nezad\'{a}, program oček\'{a}v\'{a} zad\'{a}n\'{\i}
logick\'{e} funkce př\'{\i}mo z~kl\'{a}vesnice.

Přep\'{\i}nače Espressa lze rozdělit do n\'{a}sleduj\'{\i}c\'{\i}ch skupin:
\begin{itemize}
\item {\bf funkčn\'{\i}} -- určuj\'{\i}, co se bude s~logickou funkc\'{\i} prov\'{a}dět
\item {\bf upřesňuj\'{\i}c\'{\i}} -- ovlivňuj\'{\i} průběh minimalizace
\item {\bf debugovac\'{\i}} -- určuj\'{\i}, kolik přebytečn\'{y}ch informac\'{\i} u\v{z}ivatel obdr\v{z}\'{\i}
\item {\bf v\'{y}stupn\'{\i}} -- určuj\'{\i} form\'{a}t v\'{y}stupn\'{\i} logick\'{e} funkce
\end{itemize}
Jednotliv\'{e} skupiny maj\'{\i} vliv v~různ\'{y}ch f\'{a}z\'{\i}ch
programu, co\v{z} je potřeba zohlednit při n\'{a}vrhu knihovny.


\subsection{Rozbor vnitřn\'{\i}ch pochodů Espressa}\label{VnitrniPochody}
N\'{a}sledoval rozbor hlavn\'{\i} funkce {\it main(). }Bylo zji\v{s}těno, \v{z}e program
ve velik\'{e} m\'{\i}ře pracuje se řadou glob\'{a}ln\'{\i}ch proměnn\'{y}ch
a dokonce i s~glob\'{a}ln\'{\i}mi strukturami. Proto musela b\'{y}t
provedena hloubkov\'{a} anal\'{y}za v\v{s}ech 42 hlavn\'{\i}ch větv\'{\i}
funkce {\it main()}. Ka\v{z}d\'{a} větev představovala jeden funkčn\'{\i} přep\'{\i}nač
(viz. předch\'{a}zej\'{\i}c\'{\i} odstavec). Manu\'{a}l Espressa \cite{EspressoMan}
popisoval přibli\v{z}ně 20 těchto přep\'{\i}načů, operace
vykon\'{a}ny zbyl\'{y}mi přep\'{\i}nači musely b\'{y}t dohled\'{a}ny
v~zdrojov\'{e}m k\'{o}du. Bylo zji\v{s}těno, \v{z}e někter\'{e}
vykon\'{a}vaj\'{\i} izolovan\'{e} kroky Espresso algoritmu, co\v{z} vedlo
k~č\'{a}stečn\'{e}mu splněn\'{\i} po\v{z}adavku na zpř\'{\i}stupněn\'{\i}
těchto funkc\'{\i} (viz. kapitola \ref{Pozadavky}).

Proto\v{z}e popis v\v{s}ech větv\'{\i} je dlouh\'{y} a nen\'{\i} důvod, proč
s~n\'{\i}m čitatele zatě\v{z}ovat, nebude uveden ani v~př\'{\i}loze.

Při t\'{e}to anal\'{y}ze je nutn\'{e} zdůraznit, \v{z}e dělat ručně rozbor
v\v{s}ech zm\'{\i}něn\'{y}ch větv\'{\i} a o ka\v{z}d\'{e} si vytv\'{a}řet
z\'{a}znam vol\'{a}n\'{\i} je pracn\'{e} a nen\'{a}zorn\'{e}. Pro tento typ
\'{u}kolu bylo vhodn\'{e} pou\v{z}\'{\i}t nějak\'{y} n\'{a}stroj na
statickou anal\'{y}zu a vizualizaci zdrojov\'{y}ch k\'{o}dů. \v{S}lo hlavně
o zobrazen\'{\i} vz\'{a}jemn\'{e}ho vol\'{a}n\'{\i} mezi funkcemi, co\v{z}
se označuje jako {\it callgraph. }Po prohled\'{a}n\'{\i} internetu se jako nejlep\v{s}\'{\i}
favorit\'{e} jevili programy {\it CodeViz} (vyu\v{z}\'{\i}vaj\'{\i}c\'{\i} program
{\it Graphviz }pro vizualizaci grafů ) a {\it Flow for C}. Svobodn\'{y} projekt {\it Codeviz} určen\'{y} pro Linux se
z~nezn\'{a}m\'{e}ho důvodu nepovedlo zprovoznit. Byla proto pou\v{z}ita
10-denn\'{\i} trialverze komerčn\'{\i}ho n\'{a}stroje {\it Flow for C}. Mezi jeho
nev\'{y}hody patř\'{\i} kromě limitovan\'{e}ho pou\v{z}it\'{\i}
neplacen\'{e} verze neschopnost generovat tak přehledn\'{e} grafy jak\'{e}
jsou zobrazeny na str\'{a}nk\'{a}ch projektu {\it Graphviz }. Na
druhou stranu poskytuje tento n\'{a}stroj o analyzovan\'{e}m zdrojov\'{e}m
k\'{o}du v\'{\i}c informac\'{\i} ne\v{z} projekt {\it CodeViz} a proto byl opětovně
pou\v{z}it v~kapitole \ref{PortaceCpp}.


\subsection{Dynamick\'{a} anal\'{y}za}
V~předchoz\'{\i} podkapitole jsme se spokojili se statickou anal\'{y}zou
programu -- ke~zji\v{s}těn\'{\i} pochodů Espressa n\'{a}m stačilo
n\'{a}sledovat jednotliv\'{a} vol\'{a}n\'{\i} mezi funkcemi a t\'{\i}m jsme
z\'{\i}skali přehled o vz\'{a}jemn\'{y}ch vztaz\'{\i}ch mezi funkcemi i
rolemi glob\'{a}ln\'{\i}ch proměnn\'{y}ch.

Nyn\'{\i} bylo potřeba zjistit, proč doch\'{a}z\'{\i} k~p\'{a}dům Espressa u
specifick\'{y}ch př\'{\i}padů uveden\'{y}ch v~tabulce \ref{tabulkaPadu}. Na
to je nutn\'{e} zn\'{a}t hodnoty proměnn\'{y}ch bezprostředně před a
v~okam\v{z}iku p\'{a}du.

Tento druh anal\'{y}zy je bez pou\v{z}it\'{\i} debugovac\'{\i}ho
n\'{a}stroje prakticky nemo\v{z}n\'{y}, proto je zde odstavec věnovan\'{y}
v\'{y}běru tohoto n\'{a}stroje.


\subsubsection{Volba n\'{a}stroje}
Při porovn\'{a}n\'{\i} komerčn\'{\i}ch a freewarov\'{y}ch n\'{a}strojů se
zřetelem k~jejich mo\v{z}nostem a spolehlivosti vy\v{s}lo v\'{\i}tězně
Visual Studio od firmy Microsoft. Jeho integrovan\'{y} debugger disponuje
v\v{s}emi potřebn\'{y}mi funkcemi (sledov\'{a}n\'{\i} proměnn\'{y}ch,
zobrazen\'{\i} z\'{a}sobn\'{\i}ku vol\'{a}n\'{\i}, synchronizace
instrukc\'{\i} v assembleru s~př\'{\i}kazy vy\v{s}\v{s}\'{\i}ho
programovac\'{\i}ho jazyka) a tak\'{e} dok\'{a}\v{z}e detekovat
neuvolněn\'{\i} paměti na konci programu -- tzv. {\it memory-leaky}. Někter\'{e}
freewarov\'{e} programovac\'{\i} prostřed\'{\i} maj\'{\i} tak\'{e} debugger,
ale ten buď nem\'{a} v\v{s}echny potřebn\'{e} funkce, nebo je jeho
fungov\'{a}n\'{\i} v\'{\i}ce ne\v{z} z\'{a}hadn\'{e} (testov\'{a}no
{\it DevC++}, {\it Code::Blocks}, {\it Ultimate++})

Po v\'{y}běru vhodn\'{e}ho n\'{a}stroje pro dynamickou anal\'{y}zu programu
se přistoupilo k~samotn\'{e}mu rozboru. Jeliko\v{z} jsme narazili na
v\'{\i}ce různ\'{y}ch př\'{\i}čin p\'{a}du, člen\'{\i} se
n\'{a}sleduj\'{\i}c\'{\i} text na podkapitoly věnuj\'{\i}c\'{\i} se
jednotliv\'{y}m chyb\'{a}m.


\subsubsection{\v{S}patn\'{a} kontrola alokovan\'{e} paměti}
Budeme se sna\v{z}it zjistit, proč byla logick\'{a} funkce $o64$ jedin\'{a}, u
kter\'{e} do\v{s}lo v~z\'{a}kladn\'{\i}m nastaven\'{\i} Espressa k chybě
(rozdělen\'{\i} testovac\'{\i}ch skupin viz kapitola \ref{TestyAnsi}).
Podezřen\'{\i} padlo na nekontrolov\'{a}n\'{\i} n\'{a}vratov\'{e} hodnoty
při alokaci paměti. Po prohl\'{e}dnut\'{\i} zdrojov\'{e}ho k\'{o}du programu
se zjistilo, \v{z}e paměť se v~programu alokuje dvěma způsoby:

\begin{itemize}
\item {\bf Př\'{\i}m\'{y}m vol\'{a}n\'{\i}m} funkc\'{\i} {\it malloc()} a {\it realloc()}. U tohoto způsobu alokace paměti byla n\'{a}vratov\'{a} hodnota v\v{z}dy kontrolov\'{a}na.
\item {\bf Nepř\'{\i}mo} -- funkce {\it malloc()} a {\it realloc()} byly souč\'{a}st\'{\i} maker. N\'{a}vratov\'{a} hodnota se u tohoto způsobu alokace nekontrolovala a tud\'{\i}\v{z} zde mohlo doj\'{\i}t k~nezachycen\'{\i} vzniknut\'{e} chyby.
\end{itemize}
Do těchto podezřel\'{y}ch maker bylo vlo\v{z}eno vol\'{a}n\'{\i}
kontroln\'{\i} funkce {\it valid()}, kter\'{a} ověřila nenulovost n\'{a}vratov\'{e}
hodnoty alokačn\'{\i} funkce. V~př\'{\i}padě, \v{z}e n\'{a}vratov\'{a}
hodnota byla nulov\'{a}, funkce {\it valid()} ukončila program s~chybov\'{y}m
ozn\'{a}men\'{\i}m. Funkce {\it valid() }uspěla -- potvrdila na\v{s}e podezřen\'{\i} na
vr\'{a}cen\'{\i} nulov\'{e}ho ukazatele.

Na zji\v{s}těn\'{\i} konkr\'{e}tn\'{\i}ho m\'{\i}sta p\'{a}du programu bylo
pou\v{z}ito vestavěn\'{e}ho debuggeru v\'{y}vojov\'{e}ho prostřed\'{\i} {\it MS Visual Studio 2005}.
S~jeho pomoc\'{\i} bylo odhaleno, \v{z}e chyba nastane uvnitř funkce
c{\it omplement().} Jak bylo při konzultaci se zadavatelem zji\v{s}těno, tato funkce mů\v{z}e
m\'{\i}t velik\'{e} paměťov\'{e} po\v{z}adavky, zvl\'{a}\v{s}tě kdy\v{z}
zpracov\'{a}v\'{a} takovou rozs\'{a}hlou logickou funkci jakou je
zm\'{\i}něna funkce {\it o64.pla}.

Podezřen\'{\i} na \v{s}patnou alokaci paměti se tud\'{\i}\v{z} potvrdilo a
s~pomoc\'{\i} vhodn\'{y}ch n\'{a}strojů se odhalilo konkr\'{e}tn\'{\i}
m\'{\i}sto vzniku probl\'{e}mu.

Dal\v{s}\'{\i}m krokem bylo zjistit, proč dojde k~,,p\'{a}du`` programu,
ani\v{z} by byla vyčerp\'{a}na dostupn\'{a} operačn\'{\i} paměť.


\subsubsection{Př\'{\i}stup k~neinicializovan\'{y}m ukazatelům}
Dal\v{s}\'{\i} debugov\'{a}n\'{\i} odhalilo, \v{z}e zbyl\'{e} p\'{a}dy
(p\'{a}dy v~komplexn\'{\i}m testu byly způsobeny př\'{\i}stupem k~neinicializovan\'{e}mu ukazateli. Jak
ji\v{z} bylo shrnuto v~tabulce \ref{tabulkaPadu}, k~p\'{a}dům doch\'{a}zelo
jen v~určit\'{e} kombinaci vstupn\'{\i}ho nastaven\'{\i} Espressa a
,,druhu`` logick\'{e} funkce. Debugov\'{a}n\'{\i} odhalilo, \v{z}e dojde
k~př\'{\i}stupu k~neinicializovan\'{y}m polo\v{z}k\'{a}m. Tato situace je
důsledkem chybně zadan\'{e}ho vstupu od u\v{z}ivatele, na z\'{a}kladě
čeho\v{z} program pova\v{z}uje dan\'{e} polo\v{z}ky za inicializovan\'{e}.


\subsection{Shrnut\'{\i} anal\'{y}zy}\label{ZaverAnalyzy}
Po obezn\'{a}men\'{\i} se s~vnitřn\'{\i}mi pochody původn\'{\i}ho Espressa
se anal\'{y}za zaměřila na hled\'{a}n\'{\i} nedostatků a pou\v{z}it\'{y}ch
konstrukc\'{\i}, kter\'{e} by br\'{a}nily implementaci knihovny.

N\'{a}sleduj\'{\i}c\'{\i} odstavce popisuj\'{\i} největ\v{s}\'{\i}
probl\'{e}my a jejich důsledky v~n\'{a}sledn\'{e} implementaci, kter\'{e}
byly anal\'{y}zou objeveny. Odstavce jsou označeny podle
z\'{a}le\v{z}itosti, kter\'{a} je v~nich bl\'{\i}\v{z}e specifikov\'{a}na.

{\bf \v{S}patn\'{a} kontrola alokace paměti:}
Jedn\'{a} se o nejhor\v{s}\'{\i} mo\v{z}n\'{e} chyby, kter\'{e} se
v~programu mohou vyskytnout. Jako př\'{\i}tě\v{z} působ\'{\i} i fakt, \v{z}e
se nach\'{a}zej\'{\i} v~rekurzivn\'{\i}ch funkc\'{\i}ch, z~čeho\v{z} plyne
velice obt\'{\i}\v{z}n\'{a} dealokace paměti při n\'{a}vratu. Jeliko\v{z}
jsou alokačn\'{\i} makra pou\v{z}ita ve vět\v{s}ině př\'{\i}padů, nebude
mo\v{z}no o\v{s}etřit v\v{s}echny vol\'{a}n\'{\i}. Mno\v{z}stv\'{\i} a
slo\v{z}itost proveden\'{y}ch změn by rozsahem postačovalo na samostatnou
bakal\'{a}řskou pr\'{a}ci.

{\bf Neinicializovan\'{e} ukazatele:}
O\v{s}etřen\'{\i} těchto chyb v~implementaci by nemělo b\'{y}t tak
problematick\'{e} jako je tomu u předchoz\'{\i}ho př\'{\i}padu, jeliko\v{z}
se tyto chyby nach\'{a}zej\'{\i} v nerekurzivn\'{\i}ch funkc\'{\i}ch. Na
tomto m\'{\i}stě bude postačovat přid\'{a}n\'{\i} kontroly kritick\'{y}ch
ukazatelů a ukončen\'{\i} prov\'{a}děn\'{e} funkce doprov\'{a}zen\'{e}
n\'{a}vratovou hodnotou indikuj\'{\i}c\'{\i} chybu.

{\bf Vnitřn\'{\i} reprezentace logick\'{y}ch funkc\'{\i}:}
Logick\'{a} funkce je v~programu reprezentov\'{a}na třemi hlavn\'{\i}mi
strukturami. Data jsou v~těchto struktur\'{a}ch dynamicky alokov\'{a}na a
neodborn\'{e} zach\'{a}zen\'{\i} s~jejich obsahem mů\v{z}e m\'{\i}t
fat\'{a}ln\'{\i} důsledky pro funkci cel\'{e} navrhovan\'{e} knihovny. Je
tud\'{\i}\v{z} nevyhnutn\'{e} ochr\'{a}nit data před neopr\'{a}vněn\'{y}m
př\'{\i}stupem. Jin\'{y}mi slovy -- je potřeba ochr\'{a}nit data před
jak\'{y}mkoliv př\'{\i}stupem mimo př\'{\i}stup funkc\'{\i} původn\'{\i}ho
Espressa a navrhovan\'{e} knihovn\'{\i} nadstavby.

Dal\v{s}\'{\i} v\'{y}sledek anal\'{y}zy se opětovně t\'{y}k\'{a}
v\'{y}\v{s}e zm\'{\i}něn\'{y}ch tř\'{\i} struktur popisuj\'{\i}c\'{\i}ch
logickou funkci. Jen jedna z~těchto struktur je mezi funkcemi programu
před\'{a}v\'{a}na pomoc\'{\i} ukazatele, přičem\v{z} zbyl\'{e} dvě
vystupuj\'{\i} jako glob\'{a}ln\'{\i} proměnn\'{e}. Jeliko\v{z} jedn\'{\i}m
z~po\v{z}adavků je, aby se nač\'{\i}tan\'{e} logick\'{e} funkce mohly
uchov\'{a}vat, bude potřeba zajistit, aby nedoch\'{a}zelo
k~přepisov\'{a}n\'{\i} těchto struktur při zpracov\'{a}n\'{\i} jin\'{e}
logick\'{e} funkce.

{\bf Glob\'{a}ln\'{\i} proměnn\'{e}}:
Vět\v{s}inu glob\'{a}ln\'{\i}ch proměnn\'{y}ch Espressa představuj\'{\i}
upřesňuj\'{\i}c\'{\i} a debugovac\'{\i} přep\'{\i}nače (rozdělen\'{\i}
přep\'{\i}načů viz kapitola \ref{ManualEspressa}, kter\'{e} u\v{z}ivatel
zadal při spu\v{s}těn\'{\i} programu. Zkoum\'{a}n\'{\i} odhalilo, \v{z}e
někter\'{e} z~nich jsou modifikov\'{a}ny i uvnitř funkc\'{\i} Espressa,
ani\v{z} by byly po skončen\'{\i} dan\'{e} funkce obnoveny jejich
původn\'{\i} hodnoty. Při vněj\v{s}\'{\i}m pohledu na knihovnu se
oček\'{a}v\'{a}, \v{z}e se zvolen\'{a} nastaven\'{\i} nebudou samovolně
měnit, a proto je potřeba i tento nov\'{y} po\v{z}adavek zohlednit při
n\'{a}vrhu zvolen\'{e} knihovny.


\section{Volba implementačn\'{\i}ho prostřed\'{\i}}\label{VolbaRozhrani}
Doposud byl n\'{a}vrh knihovny takov\'{y}, \v{z}e jej\'{\i} rozhran\'{\i}
bude implementov\'{a}no pomoc\'{\i} funkc\'{\i} a struktur jazyka C. Důvod
byl ten, aby byla v\'{y}sledn\'{a} knihovna pou\v{z}iteln\'{a} jak
v~programech psan\'{y}ch v jazyce C, tak v~jazyce C++.

Z~v\'{y}sledků anal\'{y}zy ov\v{s}em plyne potřeba zaměřit se
v~navrhovan\'{e} knihovně na bezpečnost, proto\v{z}e původn\'{\i} Espresso
je n\'{a}chyln\'{e} jak na chybn\'{e} \'{u}daje z\'{\i}skan\'{e} od
u\v{z}ivatele, tak na ne\'{u}spě\v{s}nou alokaci paměti.

Bezpečnost dat je jazykem C potlačen\'{a} do největ\v{s}\'{\i} mo\v{z}n\'{e}
m\'{\i}ry, proto\v{z}e př\'{\i}stup k~polo\v{z}k\'{a}m struktur se ned\'{a}
omezit a kdokoliv mů\v{z}e modifikovat jejich obsah. Kdyby u\v{z}ivatel
schv\'{a}lně (nebo omylem) modifikoval některou polo\v{z}ku těchto struktur,
data by se stala nekonzistentn\'{\i} a n\'{a}sledně by do\v{s}lo k~p\'{a}du
nebo v~nejlep\v{s}\'{\i}m př\'{\i}padě ke \v{s}patn\'{e}mu
fungov\'{a}n\'{\i} programu.

Jeliko\v{z} ok\'{a}zal\'{e} chov\'{a}n\'{\i} u\v{z}ivatele se ned\'{a}
zaručit, rozhodlo se, \v{z}e rozhran\'{\i} bude implementov\'{a}no
tř\'{\i}dami v~jazyce C++.

Kromě ji\v{z} zmiňovan\'{y}ch v\'{y}hod (priv\'{a}tn\'{\i} data,
pou\v{z}it\'{\i} v\'{y}jimek) přin\'{a}\v{s}\'{\i} pou\v{z}it\'{\i} jazyka
C++ jedinou nev\'{y}hodu -- nemo\v{z}nost pou\v{z}\'{\i}t tuto knihovnu
v~programech psan\'{y}ch v~jazyce C.


\section{Portace k\'{o}du do C++}\label{PortaceCpp}
Zvolen\'{\i} jazyka C++ jako implementačn\'{\i}ho rozhran\'{\i}
navrhovan\'{e} knihovny umo\v{z}nilo transformaci samotn\'{e}ho z\'{a}kladu
knihovny (původn\'{\i} funkce Espressa) do jazyka C++.

Jazyk C se prakticky chov\'{a} jako podmno\v{z}ina jazyka C++. Probl\'{e}m
při přechodu by mohl nastat u knihoven, kter\'{e} Espresso
pou\v{z}\'{\i}valo. Na\v{s}těst\'{\i} to byly jen standardn\'{\i} knihovny,
kter\'{e} maj\'{\i} sv\'{e} ekvivalenty v jazyce C++. Změna jazyku by
znamenala přeps\'{a}n\'{\i} n\'{a}zvů vkl\'{a}dan\'{y}ch hlavičkov\'{y}ch
souborů, hlub\v{s}\'{\i} \'{u}pravy zdrojov\'{e}ho k\'{o}du by neměly
b\'{y}t zapotřeb\'{\i}.

Kromě programovac\'{\i}ch v\'{y}hod, jako je např. mo\v{z}nost
pou\v{z}it\'{\i} v\'{y}jimek i v~samotn\'{e}m z\'{a}kladu vytv\'{a}řen\'{e}
knihovny, by tato transformace nepřinesla \v{z}\'{a}dn\'{e} nev\'{y}hody a
proto byla navrhovan\'{a} změna vykon\'{a}na.


\subsection {Změny při portaci do C++}
Jak se předt\'{\i}m odhadovalo, během \'{u}prav se nevyskytly
\v{z}\'{a}dn\'{e} vět\v{s}\'{\i} pot\'{\i}\v{z}e. Kromě přeps\'{a}n\'{\i}
n\'{a}zvů hlavičkov\'{y}ch souborů bylo potřeba ře\v{s}it jmenn\'{e}
konflikty u nov\'{y}ch maker, funkc\'{\i} a kl\'{\i}čov\'{y}ch slov,
kter\'{e} byly zavedeny jazykem C++ nebo v j\'{\i}m pou\v{z}it\'{y}ch
knihovn\'{a}ch. Podrobněj\v{s}\'{\i} popis a rozdělen\'{\i} vykonan\'{y}ch
\'{u}prav lze nal\'{e}zt v~př\'{\i}loze \ref{PrilohaCpp}

Nov\'{a} verze programu byla posl\'{e}ze otestov\'{a}na a v\'{y}sledky testů
dopadly bez chyb.

Při t\'{e}to \'{u}pravě bylo vyu\v{z}ito freewarov\'{e}ho n\'{a}stroje
{\it TextCrawler} pro
vyhled\'{a}v\'{a}n\'{\i} a n\'{a}hradu textov\'{y}ch řetězců ve v\'{\i}ce
souborech současně. N\'{a}stroj se velice osvědčil a lze jej doporučit jako
alternativu ke komerčn\'{\i}m programům v~t\'{e}to skupině n\'{a}strojů.


\section{Odstraněn\'{\i} redundantn\'{\i}ho k\'{o}du}\label{Redundance}
Posledn\'{\i} učiněn\'{y} krok před ře\v{s}en\'{\i}m a
implementov\'{a}n\'{\i}m interfacu knihovny bylo odstraněn\'{\i}
nepou\v{z}it\'{y}ch funkc\'{\i} a glob\'{a}ln\'{\i}ch proměnn\'{y}ch ve
zdrojov\'{y}ch k\'{o}dech Espressa.

Tato \'{u}prava nebyla nezbytně nutn\'{a}, ale měla za n\'{a}sledek
zjednodu\v{s}en\'{\i} implementace. Největ\v{s}\'{\i}m př\'{\i}nosem bylo
odstraněn\'{\i} glob\'{a}ln\'{\i}ch z\'{a}lo\v{z}n\'{\i}ch struktur,
kter\'{e} nebyly nikdy pou\v{z}ity a implementace se jimi nemusela
zab\'{y}vat. Eliminac\'{\i} redundantn\'{\i}ho k\'{o}du se rovně\v{z}
zmen\v{s}ila konečn\'{a} velikost knihovny.

Na anal\'{y}zu zdrojov\'{y}ch k\'{o}dů a hled\'{a}n\'{\i} redundantn\'{\i}ch
funkc\'{\i} byl pou\v{z}it n\'{a}stroj {\it Flow for C}, kter\'{y} ji\v{z} byl pou\v{z}it
v~kapitole \ref{VnitrniPochody}.

Na z\'{a}věr je mo\v{z}no dodat, \v{z}e během v\v{s}ech \'{u}prav byly
zdrojov\'{e} soubory původn\'{\i}ho Espressa značně zredukov\'{a}ny. Na
zač\'{a}tku \'{u}prav byl program tvořen 91 implementačn\'{\i}mi soubory a
19 hlavičkov\'{y}mi soubory. Na konci \'{u}prav klesl tento počet na 50
definičn\'{y}ch a 10 hlavičkov\'{y}ch souborů, co\v{z} potvrdilo
původn\'{\i} odhady.

V\'{y}čet v\v{s}ech změn proveden\'{y}ch ve zdrojov\'{y}ch k\'{o}dech od
zač\'{a}tku pr\'{a}ce nebude uveden z~důvodu značn\'{e} rozs\'{a}hlosti.


\section{N\'{a}vrh a ře\v{s}en\'{\i} interfacu}\label{ReseniInterfacu}
Původn\'{\i} n\'{a}vrh byl oddělit funkcionalitu Espressa od nastaven\'{\i}.
K~tomu \'{u}čelu byly vytvořeny 2 tř\'{\i}dy:

\begin{itemize}
\item {\bf PLA} -- představuje samotnou logickou funkci a jej\'{\i} metody nahrazuj\'{\i} funkčn\'{\i} a v\'{y}stupn\'{\i} přep\'{\i}nače původn\'{\i}ho Espressa.
\item {\bf EspressoOptions} -- koncentruje v~sobě upřesňuj\'{\i}c\'{\i} a debugovac\'{\i} informace. Důvod jej\'{\i}ho vzniku byl po\v{z}adavek, aby se objektu tř\'{\i}dy PLA nemusely nastaven\'{\i} zad\'{a}vat po jednotliv\'{y}ch parametrech, n\'{y}br\v{z} najednou prostřednictv\'{\i}m objektu t\'{e}to tř\'{\i}dy.
\end{itemize}
Tento n\'{a}vrh se postupně upřesňoval a přizpůsoboval nově objeven\'{y}m
probl\'{e}mům a po\v{z}adavkům, av\v{s}ak z\'{a}sadn\'{\i}ch změn nebylo
učiněno.

Během implementace se ře\v{s}ili probl\'{e}my dvou druhů:
\begin{enumerate}
\item Jak uzpůsobit původn\'{\i} Espresso, aby bylo pou\v{z}iteln\'{e} pro rozhran\'{\i}
\item Jak implementovat někter\'{e} slo\v{z}it\'{e} v\'{y}stupy Espressa, aby byly př\'{\i}stupn\'{e} v~jin\'{e} ne\v{z} jen původn\'{\i} textov\'{e} formě
\end{enumerate}

\subsection{Změny proveden\'{e} v původn\'{\i}m Espressu}
{\bf Glob\'{a}ln\'{\i} struktury}\\
Jak ji\v{z} bylo zm\'{\i}něno, logick\'{a} funkce je v~původn\'{\i}m
Espressu pops\'{a}na třemi strukturami. Kromě samotn\'{e} struktury
{\it PLA{\_}t}, ve kter\'{e} jsou ulo\v{z}en\'{e} informace načten\'{e} ze vstupu,
pou\v{z}\'{\i}v\'{a} je\v{s}tě pomocn\'{e} struktury {\it cube{\_}struct} a {\it cdata{\_}struct.} Při
zpracov\'{a}n\'{\i} se struktura PLA{\_}t nebo jej\'{\i} č\'{a}st
před\'{a}v\'{a} funkc\'{\i}m pomoci ukazatele. Zbyl\'{e} dvě struktury
vystupuj\'{\i} jako glob\'{a}ln\'{\i} proměnn\'{e} s~n\'{a}zvem {\it cube} a {\it cdata.}
Muselo se zabezpečit, aby tyto dvě struktury n\'{a}le\v{z}ely pr\'{a}vě
zpracov\'{a}van\'{e} logick\'{e} funkci, přičem\v{z} mezi načten\'{\i}m
logick\'{e} funkce a proveden\'{\i}m nějak\'{e} Espresso operace nad touto
logickou funkc\'{\i} se mohl vyskytovat libovoln\'{y} počet
nač\'{\i}t\'{a}n\'{\i} a zpracov\'{a}n\'{\i} jin\'{y}ch logick\'{y}ch
funkc\'{\i}. Aby se tyto struktury vz\'{a}jemně nepřepisovaly, bylo potřeba
upravit st\'{a}vaj\'{\i}c\'{\i} k\'{o}d. Na v\'{y}běr bylo několik
mo\v{z}nost\'{\i}:

\begin{enumerate}
\item Neupravovat vnitřek původn\'{\i}ch Espresso funkc\'{\i} a jen z~nich udělat priv\'{a}tn\'{\i} metody tř\'{\i}dy PLA, přičem\v{z} bude tato tř\'{\i}da obsahovat zm\'{\i}něn\'{e} struktury pod stejn\'{y}m n\'{a}zvem, jak tomu bylo v~původn\'{\i}m Espressu.
Tato mo\v{z}nost se n\'{a}sledně zavrhla, proto\v{z}e Espresso
pou\v{z}\'{\i}v\'{a} spoustu struktur, kter\'{e} jsou hierarchicky
uspoř\'{a}d\'{a}ny a jejich společn\'{y}m znakem je pr\'{a}vě př\'{\i}stup
k~zm\'{\i}něn\'{y}m struktur\'{a}m. Touto \'{u}pravou by se v\v{s}echen
zdrojov\'{y} k\'{o}d znepřehlednil, co\v{z} by bylo jen na \v{s}kodu při
př\'{\i}padn\'{y}ch dal\v{s}\'{\i}ch \'{u}prav\'{a}ch.

\item Neupravovat vnitřek původn\'{\i}ch Espresso funkc\'{\i} a zajistit, aby se tyto struktury před ka\v{z}dou operac\'{\i} zkop\'{\i}rovaly z~priv\'{a}tn\'{\i} z\'{a}lohy pr\'{a}vě zpracov\'{a}van\'{e} logick\'{e} funkce a po skončen\'{\i} t\'{e}to operace se priv\'{a}tn\'{\i} z\'{a}loha zpětně aktualizovala z~glob\'{a}ln\'{\i}ch struktur původn\'{\i}ho Espressa.
Jak je jistě vidět, toto ře\v{s}en\'{\i} m\'{a} zcela zbytečně velikou
re\v{z}ii a nen\'{\i} zcela elegantn\'{\i}.

\item Odstraněn\'{\i} zbytečn\'{e} re\v{z}ie předchoz\'{\i}ho př\'{\i}kladu by se doc\'{\i}lilo, kdyby funkce Espressa pracovaly ne s~{\it glob\'{a}ln\'{\i}mi strukturami}, ale pouze s~{\it glob\'{a}ln\'{\i}mi ukazateli na struktury}. Neust\'{a}l\'{e} kop\'{\i}rov\'{a}n\'{\i} cel\'{y}ch struktur by bylo nahrazeno přirazen\'{\i}m adres do těchto ukazatelů. To by obn\'{a}\v{s}elo pozměněn\'{\i} zdrojov\'{y}ch k\'{o}dů původn\'{\i}ho Espressa -- zaměnit př\'{\i}m\'{y} př\'{\i}stup k~polo\v{z}k\'{a}m struktur za př\'{\i}stup nepř\'{\i}m\'{y} (pomoc\'{\i} dereference ukazatele a n\'{a}sledn\'{e}ho př\'{\i}m\'{e}ho př\'{\i}stupu). Zabezpečit inicializaci těchto ukazatelů bylo \'{u}kolem nadřazen\'{e} tř\'{\i}dy PLA, kter\'{a} jedin\'{a} spou\v{s}t\'{\i} funkce původn\'{\i}ho Espressa. Tato mo\v{z}nost byla nakonec vybr\'{a}na.
\end{enumerate}

{\bf Kontrola alokace paměti}\\
Testy proveden\'{e} po portaci zdrojov\'{y}ch k\'{o}dů do jazyka C odhalily
nezachycen\'{e} chyby při alokaci paměti. Jak ji\v{z} bylo zm\'{\i}něno,
k~chybě do\v{s}lo během prov\'{a}děn\'{\i} funkce, kter\'{a} představuje
č\'{a}st Espresso algoritmu maj\'{\i}c\'{\i}ho vysok\'{e} paměťov\'{e}
po\v{z}adavky.
Proto\v{z}e zasvěcen\'{\i} čitatele do konkr\'{e}tn\'{\i}ho př\'{\i}padu by
zabralo spoustu vysvětlov\'{a}n\'{\i}, bude zde uveden č\'{a}stečně
obecn\'{y} postup, jak v~takov\'{e}m př\'{\i}padě postupovat.
V~takov\'{e}to situaci se po\v{z}adavky na opravu daj\'{\i} shrnout do těchto bodů:
\begin{itemize}
\item Chyba mus\'{\i} b\'{y}t programem zachycena
\item Inici\'{a}tor akce (u\v{z}ivatel) se o chybě mus\'{\i} dozvědět, tj. informace o v\'{y}skytu chyby se mus\'{\i} distribuovat od m\'{\i}sta vzniku a\v{z} k u\v{z}ivateli
\item ka\v{z}d\'{a} funkce, přes kterou informace o v\'{y}skytu chyby proch\'{a}z\'{\i} mus\'{\i} prov\'{e}st dealokaci dat, kter\'{a} jsou chybou zasa\v{z}ena, př\'{\i}padně dat, kter\'{a} kvůli předčasn\'{e}mu ukončen\'{\i} funkce nebudou ji\v{z} upotřebena.
\end{itemize}
Tyto po\v{z}adavky byly aplikov\'{a}ny na v\v{s}echny zainteresovan\'{e}
funkce -- od těch nejspodněj\v{s}\'{\i}ch, kter\'{e} alokuj\'{\i} paměť,
a\v{z} po ty nejvy\v{s}\v{s}\'{\i}, kter\'{e} tvoř\'{\i} u\v{z}ivatelsk\'{e}
rozhran\'{\i}. Jeliko\v{z} vět\v{s}ina funkc\'{\i} měla n\'{a}vratov\'{y}
typ {\it ukazatel}, byla informace o v\'{y}skytu chyby před\'{a}na pomoc\'{\i} hodnoty
{\it NULL} (metody u\v{z}ivatelsk\'{e}ho rozhran\'{\i} vět\v{s}inou oznamuj\'{\i} tuto
ud\'{a}lost hodnotou $-1)$. Tato změna si vy\v{z}\'{a}dala pečlivě
promy\v{s}len\'{y} z\'{a}sah do řady funkc\'{\i}, přičem\v{z}
největ\v{s}\'{\i} obt\'{\i}\v{z} bylo určit zasa\v{z}en\'{a} a
neupotřebiteln\'{a} data.

Dal\v{s}\'{\i} změny proveden\'{e} v~původn\'{\i} zdrojov\'{e}m k\'{o}du
Espressa se t\'{y}kaly přizpůsoben\'{\i} nov\'{y}m po\v{z}adavkům (např.
pr\'{a}ce s~nov\'{y}mi druhy v\'{y}stupn\'{\i}ch proudů,{\ldots}) a nem\'{a}
smysl tady opisovat v\v{s}echny. Byly uvedeny jen ty
nejdůle\v{z}itěj\v{s}\'{\i}.


\subsection {Ře\v{s}en\'{\i} probl\'{e}mů v~interfacu}
N\'{a}sleduj\'{\i}c\'{\i} č\'{a}st popisuje ře\v{s}en\'{\i} probl\'{e}mů, se
kter\'{y}mi bylo potřeba se vypoř\'{a}dat při n\'{a}vrhu a implementaci
samotn\'{e}ho knihovn\'{\i}ho rozhran\'{\i}.

{\bf Pou\v{z}it\'{\i} tř\'{\i}dy EspressoOptions}\\
Tř\'{\i}da EspressoOptions vznikla kvůli po\v{z}adavku, aby bylo mo\v{z}no
spou\v{s}tět Espresso s~předpřipraven\'{y}mi nastaven\'{\i}mi a tyto
nastaven\'{\i} kdykoliv pohodlně měnit. Původně se zam\'{y}\v{s}lelo, \v{z}e
tato tř\'{\i}da bude parametrem ka\v{z}d\'{e} funkce Espressa. T\'{\i}m
p\'{a}dem doch\'{a}z\'{\i} ke kop\'{\i}rov\'{a}n\'{\i} nastaven\'{\i},
ani\v{z} je to zapotřeb\'{\i}. V~star\v{s}\'{\i}ch verz\'{\i}ch n\'{a}vrhu
byl konstruktor parametrizov\'{a}n a doch\'{a}zelo k~načten\'{\i}
logick\'{e} funkce u\v{z} při inicializaci objektu. EspressoOptions se měli
zad\'{a}vat jako parametr metody konkr\'{e}tn\'{\i}ho objektu. Konflikt
vznikal v~tom, \v{z}e někter\'{e} nastaven\'{\i} byla zapotřeb\'{\i} u\v{z}
při nač\'{\i}t\'{a}n\'{\i} logick\'{e} funkce. Tento i probl\'{e}m
zbytečn\'{e}ho přepisov\'{a}n\'{\i} nastaven\'{\i} se vyře\v{s}il
pou\v{z}it\'{\i}m {\it statick\'{e}} metody {\it setOptions()} tř\'{\i}dy {\it PLA.}

{\bf Konstruktor bez parametrů}\\
Původn\'{\i} idea byla, \v{z}e um\'{\i}stěn\'{\i} logick\'{e} funkce, kterou
chce u\v{z}ivatel nač\'{\i}st (ze souboru, proudu nebo řetězce) bude
parametrem konstruktoru tř\'{\i}dy PLA. Jen\v{z}e při
zpracov\'{a}v\'{a}n\'{\i} vstupu mů\v{z}e doj\'{\i}t k~mno\v{z}stv\'{\i}
z\'{a}va\v{z}n\'{y}ch chyb a inicializace objektu se nemus\'{\i} pov\'{e}st.
U\v{z}ivatel by se o vyskytnut\'{e} chybě neměl mo\v{z}nost dozvědět,
proto\v{z}e konstruktor nem\'{a} n\'{a}vratovou hodnotu. Mů\v{z}e jen hodit
v\'{y}jimku, co by nebylo zrovna nejlep\v{s}\'{\i} ře\v{s}en\'{\i}. Proto
bylo rozhodnuto, \v{z}e se vytvoř\'{\i} konstruktor bez parametrů a
u\v{z}ivatel bude muset pro načten\'{\i} logick\'{e} funkce za\v{z}\'{a}dat
metodami {\it loadFromFile()} a {\it loadFromString()}

{\bf Metody pro načten\'{\i} }\\
Po\v{z}adavkem na knihovnu bylo, aby se logick\'{a} funkce mohla nač\'{\i}st
jak ze souboru (zadan\'{e}ho jm\'{e}nem nebo deskriptorem), tak z~řetězce
jazyka C (typ {\it char*}). Jeliko\v{z} řetězec a jm\'{e}no souboru jsou stejn\'{e}ho
typu ({\it char*}), mohlo by b\'{y}t pro u\v{z}ivatele matouc\'{\i}, \v{z}e stejn\'{a}
metoda je schopna nač\'{\i}st logickou funkci jak ze souboru, tak z~řetězce.
Proto se přistoupilo k~mnemotechnick\'{e} změně a vytvořily se metody
{\it loadFromFile()} a {\it LoadFromString()}, u kter\'{y}ch si je u\v{z}ivatel jist jejich funkc\'{\i} a
vkl\'{a}dan\'{y}m parametrem.

{\bf Dopočet chyběj\'{\i}c\'{\i}ch dat}\\
Logick\'{a} funkce je \'{u}plně pops\'{a}na třemi mno\v{z}inami hodnot
\footnote{Čitatel znal\'{y} problematiky jistě v\'{\i}, \v{z}e řeč je o
ON-setu, OFF-setu a DC-setu. Pro tento v\'{y}klad je v\v{s}ak
zach\'{a}zen\'{\i} do detailů ne\v{z}\'{a}douc\'{\i} a neznal\'{y} čitatel
by se mohl nechat zm\'{a}st. }. Jej\'{\i} z\'{a}pis v~t\'{e}to \'{u}pln\'{e}
formě zbytečně zab\'{\i}r\'{a} mnoho m\'{\i}sta a proto\v{z}e jsou tyto
mno\v{z}iny disjunktn\'{\i} \footnote{jejich průnik je pr\'{a}zdn\'{a}
mno\v{z}ina}, daj\'{\i} se vz\'{a}jemně dopoč\'{\i}tat.
Potřeba jednotliv\'{y}ch mno\v{z}in z\'{a}vis\'{\i} na prov\'{a}děn\'{e}
operaci a v\'{y}stupn\'{\i}m form\'{a}tu logick\'{e} funkce. Původn\'{\i}
Espresso poznalo oba tyto parametry ji\v{z} při spu\v{s}těn\'{\i}. T\'{\i}m
p\'{a}dem nebyl probl\'{e}m dopoč\'{\i}tat potřebn\'{e} mno\v{z}iny hned po
\'{u}spě\v{s}n\'{e}m načten\'{\i} logick\'{e} funkce. V~na\v{s}em
př\'{\i}padě je tomu jinak -- znalost u\v{z}ivatelem po\v{z}adovan\'{e}
operace ji\v{z} při nač\'{\i}tan\'{\i} logick\'{e} funkce je vyloučena, a
proto mus\'{\i} knihovna reagovat na potřebu dopočtu konkr\'{e}tn\'{\i}
mno\v{z}iny a\v{z} v~okam\v{z}iku spu\v{s}těn\'{\i} po\v{z}adovan\'{e}
operace. Proto\v{z}e tuto kontrolu a př\'{\i}padn\'{y} dopočet mus\'{\i}
prov\'{a}dět v\v{s}echny metody pracuj\'{\i}c\'{\i} s~mno\v{z}inami, byla
vytvořen\'{a} priv\'{a}tn\'{\i} metoda {\it computeSets()}, kter\'{a} tuto činnost
obstar\'{a}vala.

{\bf Ře\v{s}en\'{\i} parametru --Dcheck}\\
V\'{y}stupem t\'{e}to funkce v původn\'{\i}m Espressu byli 4 ř\'{a}dky textu
informuj\'{\i}c\'{\i} o disjunktnosti mno\v{z}in tvoř\'{\i}c\'{\i} danou
logickou funkci. Jeliko\v{z} se ka\v{z}d\'{e} tvrzen\'{\i} dalo vyj\'{a}dřit
hodnotami {\it pravda}/{\it nepravda}, nab\'{\i}zelo se ře\v{s}en\'{\i} pomoc\'{\i} dekompozice tohoto
v\'{y}pisu na mno\v{z}inu metod vracej\'{\i}c\'{\i}ch {\it bool}.
Metoda {\it check(FILE* target)} vyp\'{\i}\v{s}e původn\'{\i} v\'{y}pis a současně vr\'{a}t\'{\i}
hodnotu true nebo false v~z\'{a}vislosti na tom, jestli se během
ověřov\'{a}n\'{\i}, kter\'{e} prov\'{a}d\'{\i}, vyskytla nějak\'{a} chyba.
Dekompozic\'{\i} byly vytvořeny metody {\it ONDCdisjoint()}, {\it ONOFFdisjoint()}, {\it DCOFFdisjoint()} a {\it universe()} vracej\'{\i}c\'{\i} {\it bool} a
informuj\'{\i}c\'{\i} o pravdivosti konkr\'{e}tn\'{\i}ho v\'{y}roku.

Bli\v{z}\v{s}\'{\i} popis jednotliv\'{y}ch metod naleznete v~př\'{\i}loze \ref{PLA}

{\bf Ře\v{s}en\'{\i} parametru --Dstats}\\
Obdobn\'{y} probl\'{e}m jako u {\it check()} se vyskytl i tady. Ře\v{s}en\'{\i} u\v{z}
nebylo tak jednoduch\'{e} a dekompozice na integr\'{a}ln\'{\i} typy se
nedala pou\v{z}\'{\i}t na v\v{s}echny poskytovan\'{e} informace, proto\v{z}e
v\'{y}stup byl v~někter\'{y}ch př\'{\i}padech proměnlivě dlouh\'{y}
v\'{y}pis č\'{\i}seln\'{y}ch hodnot. Tento v\'{y}pis z\'{a}visel na
velikosti zpracov\'{a}van\'{e} funkce a tak\'{e} na jej\'{\i}m ,,typu``.
Po\v{z}adavkem zadavatele bylo, aby byly pomoc\'{\i} rozhran\'{\i} knihovny
př\'{\i}stupn\'{e} v\v{s}echny informace -- nepostačovalo je pouze vypsat do
v\'{y}stupn\'{\i}ho proudu. Pro tento \'{u}čel se vytvořila struktura
{\it PLAStats}, kter\'{a} obsahuje integr\'{a}ln\'{\i} typy, vektory a struktury {\it SetCost }odpov\'{\i}daj\'{\i}c\'{\i}
v\v{s}em po\v{z}adovan\'{y}m polo\v{z}k\'{a}m. Nutno podotknout, \v{z}e tato
struktura se před\'{a}v\'{a} pomoc\'{\i} n\'{a}vratov\'{e} hodnoty
{\it ukazatel} a ne {\it referenc\'{\i}}. Pou\v{z}it\'{\i}m reference by se musela cel\'{a} struktura
zkop\'{\i}rovat, co\v{z} u tak slo\v{z}it\'{e} struktury stoj\'{\i} určitou
re\v{z}ii. Proto se dynamicky vytvoř\'{\i} nov\'{a} struktura na haldě a
ukazatel na n\'{\i} se před\'{a} u\v{z}ivateli. Plyne z~toho jedin\'{a}
nev\'{y}hoda -- u\v{z}ivatel mus\'{\i} tuto strukturu smazat s\'{a}m. (Popis
PLAStats se nach\'{a}z\'{\i} v~př\'{\i}loze \ref{PLAStats})

{\bf Zpracov\'{a}n\'{\i} dvou logick\'{y}ch funkc\'{\i}}\\
Espresso mělo několik funkc\'{\i}, kter\'{e} vykonaly nějakou operaci nad
dvěma vstupn\'{\i}mi logick\'{y}mi funkcemi (např. průnik,
sjednocen\'{\i},{\ldots}) a v\'{y}sledkem byla třet\'{\i}. Původně
v\'{y}sledek přepsal jednu ze vstupn\'{\i}ch funkc\'{\i} -- nebyl důvod
ponech\'{a}vat je nezměněny, proto\v{z}e program se po vyps\'{a}ni
v\'{y}sledku stejně ukončil. Po diskuzi se zadavatelem vznikl po\v{z}adavek,
aby vstupn\'{\i} funkce zůstaly nezměněny a v\'{y}sledn\'{a} třet\'{\i} byla
před\'{a}na pomoc\'{\i} n\'{a}vratov\'{e} hodnoty.

{\bf Přirazen\'{\i} v\'{y}stupů}\\
Espresso poskytovalo u\v{z}ivateli o sv\'{e}m běhu spoustu v\'{y}pisů. Ne
v\v{s}echny se daly potlačit a \v{z}\'{a}dn\'{e}mu se nedalo určit, kam
m\'{a} b\'{y}t posl\'{a}n. Knihovna m\'{a} naproti tomu poskytovat
\'{u}plnou kontrolu nad zobrazovan\'{y}mi daty. U\v{z}ivatel mů\v{z}e určit
{\it kam} a {\it jak\'{a} data} budou zaps\'{a}na. K~tomuto \'{u}čelu byly v\'{y}stupy Espressa
rozděleny do \v{s}esti skupin, přičem\v{z} ka\v{z}d\'{e} jedn\'{e} skupině
se d\'{a} explicitně určit, zda a kam se m\'{a} vypisovat. Toto
opatřen\'{\i} obn\'{a}\v{s}elo \'{u}pravu v\v{s}ech funkc\'{\i} pro
v\'{y}pis. Popis jednotliv\'{y}ch skupin a jim přislouchaj\'{\i}c\'{\i}m
metod\'{a}m lze nal\'{e}zt v~př\'{\i}loze \ref{EspressoOptions}

{\bf N\'{a}vratov\'{e} hodnoty funkc\'{\i}}\\
Jeliko\v{z} bylo potřeba u\v{z}ivatele informovat o spr\'{a}vnosti průběhu
volan\'{y}ch metod, byla vět\v{s}ině těchto metod určena n\'{a}vratov\'{a}
hodnota typu {\it int} (celoč\'{\i}seln\'{y} typ). V\'{y}jimku tvořily pouze metody
vracej\'{\i}c\'{\i} typ {\it ukazatel na strukturu} nebo typ {\it bool.}
V\'{y}skyt chyby při prov\'{a}děn\'{\i} dan\'{e} metody je indikov\'{a}n
n\'{a}vratovou hodnotou $-1$ u celoč\'{\i}seln\'{e}ho typu$, $u typu {\it bool} hodnotou
{\it false} a u typu {\it ukazatel na strukturu} hodnotou {\it NULL}. N\'{a}vratov\'{a} hodnota typu {\it void} byla pou\v{z}ita jen u
někter\'{y}ch metod tř\'{\i}dy {\it EspressoOptions}

{\bf Settry a gettry}\\
Metody pro nastaven\'{\i} parametrů původn\'{\i}ho Espressa jsou vět\v{s}nou
ve tvaru {\it nazev{\_}parametru()} pro z\'{\i}sk\'{a}n\'{\i} hodnoty dan\'{e}ho parametru a
{\it setnazev{\_}parametru()} pro jeho nastaven\'{\i}. {\it Nazev{\_}parametru} byl volen tak, aby byl stejn\'{y}, př\'{\i}padně
nejv\'{\i}c podobn\'{y} parametru v~původn\'{\i}m Espressu.


\subsection {V\'{y}sledek implementace}
Knihovn\'{\i} rozhran\'{\i} se \'{u}spě\v{s}ně propojilo s~původn\'{\i}mi
zdrojov\'{y}mi k\'{o}dy Espressa. V~podstatě se jednalo o ,,obalen\'{\i}``
Espressa navrhovan\'{y}m rozhran\'{\i}m, přičem\v{z} původn\'{\i}
zdrojov\'{e} k\'{o}dy se přizpůsobovaly tlaku rozhran\'{\i} a rozhran\'{\i}
samotn\'{e} bylo formov\'{a}no zadan\'{y}mi a nově vznikl\'{y}mi
po\v{z}adavky.

Kromě toho, \v{z}e přibyly dvě struktury pro před\'{a}v\'{a}n\'{\i} dat
u\v{z}ivateli, se konečn\'{a} verze knihovny od navrhovan\'{e} v\'{y}razně
neli\v{s}\'{\i}. Implementovaly se v\v{s}echny po\v{z}adavky zadavatele a
v~r\'{a}mci mo\v{z}nost\'{\i} byly odstraněny i chyby v původn\'{\i}m
Espressu.

Popis metod jednotliv\'{y}ch tř\'{\i}d a polo\v{z}ek struktur lze nal\'{e}zt
v~př\'{\i}loh\'{a}ch:
\begin{enumerate}
\item tř\'{\i}da PLA v~př\'{\i}loze č\'{\i}slo \ref{PLA}
\item tř\'{\i}da EspressoOptions v~př\'{\i}loze č\'{\i}slo \ref{EspressoOptions}
\item struktury PLAStats a SetCost v~př\'{\i}loze č\'{\i}slo \ref{PLAStats} a \ref{SetCost}
\end{enumerate}

\section{Kompilace knihoven}\label{Kompilace}
V\'{y}sledkem implementace jsou ji\v{z} kompletn\'{\i} zdrojov\'{e} k\'{o}dy
knihovny. Ty ček\'{a} je\v{s}tě posledn\'{\i} krok a t\'{\i}m je kompilace
za \'{u}čelem vytvořen\'{\i} knihovny. Jeliko\v{z} bylo původn\'{\i}
Espresso multiplatformn\'{\i} a během \'{u}prav se nepou\v{z}ily
\v{z}\'{a}dn\'{e} platformně z\'{a}visl\'{e} knihovny jsou zdrojov\'{e}
k\'{o}dy knihovny přenositeln\'{e} a tud\'{\i}\v{z} nen\'{\i} potřeba je
před kompilac\'{\i} na různ\'{y}ch operačn\'{\i}ch syst\'{e}mech upravovat.


\subsection {Statick\'{a} knihovna}
Vytvořen\'{\i} statick\'{e} knihovny pod Linuxem i MS Windows je stejn\'{e}.
Implementačn\'{\i} soubory je potřeba nejdř\'{\i}v zkompilovat pomoc\'{\i}
programu g++ s~parametrem --c. Vzniknou tak soubory s~koncovkou $.o$, kter\'{e} se
n\'{a}sledně spoj\'{\i} pomoc\'{\i} programu {\it ar} s~parametrem --r do jedin\'{e}ho
souboru s~koncovkou $.a$ -- v\'{y}sledn\'{e} statick\'{e} knihovny.
Pou\v{z}it\'{\i} knihovny je n\'{a}sleduj\'{\i}c\'{\i} -- do sv\'{e}ho
zdrojov\'{e}ho k\'{o}du u\v{z}ivatel vlo\v{z}\'{\i} hlavičkov\'{y} soubor
(EspressoLib.h) a při kompilaci přid\'{a} do z\'{a}znamu knihoven soubor
EspressoLib.a.


\subsection {Dynamick\'{a} knihovna}
Kompilace dynamick\'{e} knihovny pro MS Windows a Linux je
rozd\'{\i}ln\'{a}, společn\'{a} je jen konvence -- soubory s~koncovkou $.a$
maj\'{\i} prefix {\it lib}, samotn\'{a} dynamick\'{a} knihovna tento prefix nem\'{a}
a m\'{a} koncovku {\it .dll} (MS Windows) nebo {\it .so} (Linux).
N\'{a}sledně je uveden postup kompilace pro obě platformy.


\subsubsection{\'{U}prava pro MS Windows}
Pro dynamickou knihovnu vytv\'{a}řenou pod MS Windows je potřebn\'{e}
zdrojov\'{y} k\'{o}d knihovny m\'{\i}rně upravit. MS Windows na rozd\'{\i}l
od Linuxu vy\v{z}aduje, aby se funkce a tř\'{\i}dy určen\'{e} pro export
explicitně označily.
Na vytvořen\'{\i} dynamick\'{e} knihovny se pou\v{z}ilo programovac\'{\i}
prostřed\'{\i} {\it Dev-C++} a v~něm vytvořen\'{a} \v{s}ablona projektu pro dynamickou
knihovnu. V~n\'{\i} u\v{z} byly definov\'{a}ny potřebn\'{e} makra a tak\'{e}
byly n\'{a}zorně pou\v{z}ity. Makro {\it BUILD{\_}DLL} je definov\'{a}no pouze při kompilaci
knihovny, tak\v{z}e nen\'{\i} nutn\'{e} vytv\'{a}řet dvě verze
hlavičkov\'{e}ho souboru.
Pro zaj\'{\i}mavost jsou zde uvedeny změny, jak\'{e} je potřeba ve
zdrojov\'{e}m k\'{o}du prov\'{e}st:


\begin{verbatim}
#include <windows.h>

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

class DLL_EXPORT MyClass{
/* deklarace Vaší třídy */
};

void DLL_EXPORT funkce(); /* deklarace Vaší funkce */
\end{verbatim}


\subsubsection{\'{U}prava pro Linux}
Kompilace dynamick\'{e} knihovny pod Linux nevy\v{z}aduje \v{z}\'{a}dn\'{e}
dodatečn\'{e} \'{u}pravy k\'{o}du. Tento př\'{\i}stup je pohodln\'{y}, na
druhou stranu autor nem\'{a} mo\v{z}nost funkce nebo tř\'{\i}dy skr\'{y}t --
při vytv\'{a}řen\'{\i} knihovny jsou vyexportov\'{a}ny v\v{s}echny.
Kompilace knihovny byla ponech\'{a}na na programovac\'{\i}m prostřed\'{\i}
{\it Code::Blocks}, kter\'{e} mělo v~sobě připraveny \v{s}ablony pro kompilaci {\it dynamicky v\'{a}zan\'{e} knihovny} (Dynamic Link
Library) a tak\'{e} {\it sd\'{\i}len\'{e} knihovny} (Shared Library)

Zdrojov\'{e} k\'{o}dy k~jednotliv\'{y}m verz\'{\i}m jsou v~adres\'{a}ři
{\it src} na přilo\v{z}en\'{e}m optick\'{e}m m\'{e}diu. Zkompilovan\'{e} knihovny
s~uk\'{a}zkami pou\v{z}it\'{\i} jsou v~adres\'{a}ři {\it exe}.

