get-started.tex - 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{va… | |
240 \end{alltt} |