libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | LICENSE

get-started.tex (6604B)


      1 \chapter{Get started}
      2 \label{chap:Get started}
      3 
      4 In this chapter, you will learn the basics of libzahl.
      5 You should read the sections in order.
      6 
      7 \vspace{1cm}
      8 \minitoc
      9 
     10 
     11 % TODO add a section a linking and stuff here.
     12 
     13 
     14 \newpage
     15 \section{Initialisation}
     16 \label{sec:Initialisation}
     17 
     18 Before using libzahl, it must be initialised. When
     19 initialising, you must select a location whither libzahl
     20 long jumps on error.
     21 
     22 \begin{alltt}
     23    #include <zahl.h>
     24 
     25    int
     26    main(void)
     27    \{
     28        jmp_buf jmpenv;
     29        if (setjmp(jmpenv))
     30            return 1; \textcolor{c}{/* \textrm{Exit on error} */}
     31        zsetup(jmpenv);
     32        \textcolor{c}{/* \textrm{\ldots} */}
     33        return 0;
     34    \}
     35 \end{alltt}
     36 
     37 {\tt zsetup} also initialises temporary variables used
     38 by libzahl's functions, and constants used by libzahl's
     39 functions. Furthermore, it initialises the memory pool
     40 and a stack which libzahl uses to keep track of temporary
     41 allocations that need to be pooled for use if a function
     42 fails.
     43 
     44 It is recommended to also uninitialise libzahl when you
     45 are done using it, for example before the program exits.
     46 
     47 \begin{alltt}
     48    \textcolor{c}{int
     49    main(void)
     50    \{
     51        jmp_buf jmpenv;
     52        if (setjmp(jmpenv))
     53            return 1; /* \textrm{Exit on error} */
     54        zsetup(jmpenv);
     55        /* \textrm{\ldots} */}
     56        zunsetup();
     57        \textcolor{c}{return 0;
     58    \}}
     59 \end{alltt}
     60 
     61 {\tt zunsetup} frees all memory that has been reclaimed to
     62 the memory pool, and all memory allocated by {\tt zsetup}.
     63 Note that this does not free integers that are still
     64 in use. It is possible to simply call {\tt zunsetup}
     65 directly followed by {\tt zsetup} to free all pooled
     66 memory.
     67 
     68 
     69 \newpage
     70 \section{Exceptional conditions}
     71 \label{sec:Exceptional conditions}
     72 
     73 Exceptional conditions, casually called `errors',
     74 are treated in libzahl using long jumps.
     75 
     76 \begin{alltt}
     77    int
     78    main(int argc, char *argv[])
     79    \{
     80        jmp_buf jmpenv;
     81        if (setjmp(jmpenv))
     82            return 1; \textcolor{c}{/* \textrm{Exit on error} */}
     83        zsetup(jmpenv);
     84        return 0;
     85    \}
     86 \end{alltt}
     87 
     88 Just exiting on error is not a particularly good
     89 idea. Instead, you may want to print an error message.
     90 This is done with {\tt zperror}.
     91 
     92 \begin{alltt}
     93    if (setjmp(jmpenv)) \{
     94        zperror(\textcolor{c}{*argv});
     95        \textcolor{c}{return 1;}
     96    \}
     97 \end{alltt}
     98 
     99 \noindent
    100 {\tt zperror} works just like {\tt perror}. It
    101 outputs an error description to standard error.
    102 A line break is printed at the end of the message.
    103 If the argument passed to {\tt zperror} is neither
    104 {\tt NULL} nor an empty string, it is printed in
    105 front of the description, with a colon and a
    106 space separating the passed string and the description.
    107 For example, {\tt zperror("my-app")} may output
    108 
    109 \begin{verbatim}
    110    my-app: Cannot allocate memory
    111 \end{verbatim}
    112 
    113 libzahl also provides {\tt zerror}. Calling this
    114 function will provide you with an error code and
    115 a textual description.
    116 
    117 \begin{alltt}
    118    \textcolor{c}{if (setjmp(jmpenv)) \{}
    119        const char *description;
    120        zerror(&description);
    121        fprintf(stderr, "\%s: \%s\verb|\|n", *argv, description);
    122        \textcolor{c}{return 1;}
    123    \textcolor{c}{\}}
    124 \end{alltt}
    125 
    126 \noindent
    127 This code behaves like the example above that
    128 calls {\tt zperror}. If you are interested in the
    129 error code, you instead look at the return value.
    130 
    131 \begin{alltt}
    132    \textcolor{c}{if (setjmp(jmpenv)) \{}
    133        enum zerror e = zerror(NULL);
    134        switch (e) \{
    135        case ZERROR_ERRNO_SET:
    136            perror("");
    137            \textcolor{c}{return 1;}
    138        case ZERROR_0_POW_0:
    139            fprintf(stderr, "Indeterminate form: 0^0\verb|\|n");
    140            \textcolor{c}{return 1;}
    141        case ZERROR_0_DIV_0:
    142            fprintf(stderr, "Indeterminate form: 0/0\verb|\|n");
    143            \textcolor{c}{return 1;}
    144        case ZERROR_DIV_0:
    145            fprintf(stderr, "Do not divide by zero, dummy\verb|\|n");
    146            \textcolor{c}{return 1;}
    147        case ZERROR_NEGATIVE:
    148            fprintf(stderr, "Undefined (negative input)\verb|\|n");
    149            \textcolor{c}{return 1;}
    150        case ZERROR_INVALID_RADIX:
    151            fprintf(stderr, "Radix must be at least 2\verb|\|n");
    152            \textcolor{c}{return 1;}
    153        default:
    154            zperror("");
    155            \textcolor{c}{return 1;}
    156        \}
    157    \textcolor{c}{\}}
    158 \end{alltt}
    159 
    160 To change the point whither libzahl's functions
    161 jump, call {\tt setjmp} and {\tt zsetup} again.
    162 
    163 \begin{alltt}
    164    jmp_buf jmpenv;
    165    if (setjmp(jmpenv)) \{
    166        \textcolor{c}{/* \textrm{\ldots} */}
    167    \}
    168    zsetup(jmpenv);
    169    \textcolor{c}{/* \textrm{\ldots} */}
    170    if (setjmp(jmpenv)) \{
    171        \textcolor{c}{/* \textrm{\ldots} */}
    172    \}
    173    zsetup(jmpenv);
    174 \end{alltt}
    175 
    176 
    177 \newpage
    178 \section{Create an integer}
    179 \label{sec:Create an integer}
    180 
    181 To do any real work with libzahl, we need integers. The
    182 data type for a big integer in libzahl is {\tt z\_t}
    183 \psecref{sec:Integer structure}. Before a {\tt z\_t}
    184 can be assigned a value, it must be initialised.
    185 
    186 \begin{alltt}
    187    z_t a;
    188    \textcolor{c}{/* \textrm{\ldots} */
    189    zsetup(jmpenv);}
    190    zinit(a);
    191    \textcolor{c}{/* \textrm{\ldots} */
    192    zunsetup();}
    193 \end{alltt}
    194 
    195 \noindent
    196 {\tt zinit(a)} is actually a less cumbersome and optimised
    197 alternative to calling {\tt memset(a, 0, sizeof(z\_t))}.
    198 It sets the values of two members: {\tt .alloced} and
    199 {\tt .chars}, to 0 and {\tt NULL}. This is necessary,
    200 otherwise the memory allocated could be fooled to deallocate
    201 a false pointer, causing the program to abort.
    202 
    203 Once the reference has been initialised, you may assign it
    204 a value. The simplest way to do this is by calling
    205 
    206 \begin{alltt}
    207    void zseti(z_t a, int64_t value);
    208 \end{alltt}
    209 
    210 \noindent
    211 For example {\tt zseti(a, 1)}, assignes the value 1 to
    212 the {\tt z\_t} {\tt a}.
    213 
    214 When you are done using a big integer reference, you should
    215 call {\tt zfree} to let libzahl know that it should pool
    216 the allocation of the {\tt .chars} member.
    217 
    218 \begin{alltt}
    219    z_t a;
    220    zinit(a);
    221    \textcolor{c}{/* \textrm{\ldots} */}
    222    zfree(a); \textcolor{c}{/* \textrm{before \texttt{zunsetup}} */}
    223 \end{alltt}
    224 
    225 \noindent
    226 Instead of calling {\tt zfree(a)}, it is possible — but
    227 strongly discouraged — to call {\tt free(a->chars)}.
    228 Note however, by doing so, the allocation is not pooled
    229 for reuse.
    230 
    231 If you plan to reuse the variable later, you need to
    232 reinitialise it by calling {\tt zinit} again.
    233 
    234 Alternatives to {\tt zseti} include \psecref{sec:Assignment}:
    235 
    236 \begin{alltt}
    237    void zsetu(z_t a, uint64_t value);
    238    void zsets(z_t a, const char *value);
    239    void zset(z_t a, z_t value); \textcolor{c}{/* \textrm{copy \texttt{value} into \texttt{a}} */}
    240 \end{alltt}