\chapter{Get started}
\label{chap:Get started}

In this chapter, you will learn the basics of libzahl.
You should read the sections in order.

\vspace{1cm}
\minitoc


% TODO add a section a linking and stuff here.


\newpage
\section{Initialisation}
\label{sec:Initialisation}

Before using libzahl, it must be initialised. When
initialising, you must select a location whither libzahl
long jumps on error.

\begin{alltt}
   #include <zahl.h>

   int
   main(void)
   \{
       jmp_buf jmpenv;
       if (setjmp(jmpenv))
           return 1; \textcolor{c}{/* \textrm{Exit on error} */}
       zsetup(jmpenv);
       \textcolor{c}{/* \textrm{\ldots} */}
       return 0;
   \}
\end{alltt}

{\tt zsetup} also initialises temporary variables used
by libzahl's functions, and constants used by libzahl's
functions. Furthermore, it initialises the memory pool
and a stack which libzahl uses to keep track of temporary
allocations that need to be pooled for use if a function
fails.

It is recommended to also uninitialise libzahl when you
are done using it, for example before the program exits.

\begin{alltt}
   \textcolor{c}{int
   main(void)
   \{
       jmp_buf jmpenv;
       if (setjmp(jmpenv))
           return 1; /* \textrm{Exit on error} */
       zsetup(jmpenv);
       /* \textrm{\ldots} */}
       zunsetup();
       \textcolor{c}{return 0;
   \}}
\end{alltt}

{\tt zunsetup} all memory that has been reclaimed to
the memory pool, and all memory allocated by {\tt zsetup}.
Note that this does not free integers that are still
in use. It is possible to simply call {\tt zunsetup}
directly followed by {\tt zsetup} to free all pooled
memory.


\newpage
\section{Exceptional conditions}
\label{sec:Exceptional conditions}

Exceptional conditions, casually called `errors',
are treated in libzahl using long jumps.

\begin{alltt}
   int
   main(int argc, char *argv[])
   \{
       jmp_buf jmpenv;
       if (setjmp(jmpenv))
           return 1; \textcolor{c}{/* \textrm{Exit on error} */}
       zsetup(jmpenv);
       return 0;
   \}
\end{alltt}

Just exiting on error is not a particularly good
idea. Instead, you may want to print an error message.
This is done with {\tt zperror}.

\begin{alltt}
   if (setjmp(jmpenv)) \{
       zperror(\textcolor{c}{*argv});
       \textcolor{c}{return 1;}
   \}
\end{alltt}

\noindent
{\tt zperror} works just like {\tt perror}. It
outputs an error description to standard error.
A line break is printed at the end of the message.
If the argument passed to {\tt zperror} is neither
{\tt NULL} nor an empty string, it is printed in
front of the description, with a colon and a
space separating the passed string and the description.
For example, {\tt zperror("my-app")} may output

\begin{verbatim}
   my-app: Cannot allocate memory
\end{verbatim}

libzahl also provides {\tt zerror}. Calling this
function will provide you with an error code and
a textual description.

\begin{alltt}
   \textcolor{c}{if (setjmp(jmpenv)) \{}
       const char *description;
       zerror(&description);
       fprintf(stderr, "\%s: \%s\verb|\|n", *argv, description);
       \textcolor{c}{return 1;}
   \textcolor{c}{\}}
\end{alltt}

\noindent
This code behaves like the example above that
calls {\tt zperror}. If you are interested in the
error code, you instead look at the return value.

\begin{alltt}
   \textcolor{c}{if (setjmp(jmpenv)) \{}
       enum zerror e = zerror(NULL);
       switch (e) \{
       case ZERROR_ERRNO_SET:
           perror("");
           \textcolor{c}{return 1;}
       case ZERROR_0_POW_0:
           fprintf(stderr, "Indeterminate form: 0^0\verb|\|n");
           \textcolor{c}{return 1;}
       case ZERROR_0_DIV_0:
           fprintf(stderr, "Indeterminate form: 0/0\verb|\|n");
           \textcolor{c}{return 1;}
       case ZERROR_DIV_0:
           fprintf(stderr, "Do not divide by zero, dummy\verb|\|n");
           \textcolor{c}{return 1;}
       case ZERROR_NEGATIVE:
           fprintf(stderr, "Undefined (negative input)\verb|\|n");
           \textcolor{c}{return 1;}
       default:
           zperror("");
           \textcolor{c}{return 1;}
       \}
   \textcolor{c}{\}}
\end{alltt}

To change the point whither libzahl's functions
jump, call {\tt setjmp} and {\tt zsetup} again.

\begin{alltt}
   jmp_buf jmpenv;
   if (setjmp(jmpenv)) \{
       \textcolor{c}{/* \textrm{\ldots} */}
   \}
   zsetup(jmpenv);
   \textcolor{c}{/* \textrm{\ldots} */}
   if (setjmp(jmpenv)) \{
       \textcolor{c}{/* \textrm{\ldots} */}
   \}
   zsetup(jmpenv);
\end{alltt}


\newpage
\section{Create an integer}
\label{sec:Create an integer}

To do any real work with libzahl, we need integers. The
data type for a big integer in libzahl is {\tt z\_t}
\psecref{sec:Integer structure}. Before a {\tt z\_t}
can be assign a value, it must be initialised.

\begin{alltt}
   z_t a;
   \textcolor{c}{/* \textrm{\ldots} */
   zsetup(jmpenv);}
   zinit(a);
   \textcolor{c}{/* \textrm{\ldots} */
   zunsetup();}
\end{alltt}

\noindent
{\tt zinit(a)} is actually a less cumbersome and optimised
alternative to calling {\tt memset(a, 0, sizeof(z\_t))}.
It sets the values of two members: {\tt .alloced} and
{\tt .chars}, to 0 and {\tt NULL}. This is necessary,
otherwise the memory allocated could be fooled to deallocate
a false pointer, causing the program to abort.

Once the reference has been initialised, you may assign it
a value. The simplest way to do this is by calling

\begin{alltt}
   void zseti(z_t a, int64_t value);
\end{alltt}

\noindent
For example {\tt zseti(a, 1)}, assignes the value 1 to
the {\tt z\_t} {\tt a}.

When you are done using a big integer reference, you should
call {\tt zfree} to let libzahl know that it should pool
the allocation of the {\tt .chars} member.

\begin{alltt}
   z_t a;
   zinit(a);
   \textcolor{c}{/* \textrm{\ldots} */}
   zfree(a); \textcolor{c}{/* \textrm{before \texttt{zunsetup}} */}
\end{alltt}

\noindent
Instead of calling {\tt zfree(a)}, it is possible — but
strongly discouraged — to call {\tt free(a->chars)}.
Note however, by doing so, the allocation is not pooled
for reuse.

If you plan to reuse the variable later, you need to
reinitialise it by calling {\tt zinit} again.

Alternatives to {\tt zseti} include:

\begin{alltt}
   void zsetu(z_t a, uint64_t value);
   void zsets(z_t a, const char *value);
   void zset(z_t a, z_t value); \textcolor{c}{/* \textrm{copy \texttt{value} into \texttt{a}} */}
\end{alltt}
