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}