1/**
2 * \file libyasm/intnum.h
3 * \brief YASM integer number interface.
4 *
5 * \license
6 *  Copyright (C) 2001-2007  Peter Johnson
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *  - Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *  - Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 * \endlicense
29 */
30#ifndef YASM_INTNUM_H
31#define YASM_INTNUM_H
32
33#ifndef YASM_LIB_DECL
34#define YASM_LIB_DECL
35#endif
36
37/** Initialize intnum internal data structures. */
38YASM_LIB_DECL
39void yasm_intnum_initialize(void);
40
41/** Clean up internal intnum allocations. */
42YASM_LIB_DECL
43void yasm_intnum_cleanup(void);
44
45/** Create a new intnum from a decimal string.
46 * \param str       decimal string
47 * \return Newly allocated intnum.
48 */
49YASM_LIB_DECL
50/*@only@*/ yasm_intnum *yasm_intnum_create_dec(char *str);
51
52/** Create a new intnum from a binary string.
53 * \param str       binary string
54 * \return Newly allocated intnum.
55 */
56YASM_LIB_DECL
57/*@only@*/ yasm_intnum *yasm_intnum_create_bin(char *str);
58
59/** Create a new intnum from an octal string.
60 * \param str       octal string
61 * \return Newly allocated intnum.
62 */
63YASM_LIB_DECL
64/*@only@*/ yasm_intnum *yasm_intnum_create_oct(char *str);
65
66/** Create a new intnum from a hexidecimal string.
67 * \param str       hexidecimal string
68 * \return Newly allocated intnum.
69 */
70YASM_LIB_DECL
71/*@only@*/ yasm_intnum *yasm_intnum_create_hex(char *str);
72
73/** Convert character constant to integer value, using NASM rules.  NASM syntax
74 * supports automatic conversion from strings such as 'abcd' to a 32-bit
75 * integer value (little endian order).  This function performs those conversions.
76 * \param str       character constant string
77 * \return Newly allocated intnum.
78 */
79YASM_LIB_DECL
80/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_nasm(const char *str);
81
82/** Convert character constant to integer value, using TASM rules.  TASM syntax
83 * supports automatic conversion from strings such as 'abcd' to a 32-bit
84 * integer value (big endian order).  This function performs those conversions.
85 * \param str       character constant string
86 * \return Newly allocated intnum.
87 */
88YASM_LIB_DECL
89/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_tasm(const char *str);
90
91/** Create a new intnum from an unsigned integer value.
92 * \param i         unsigned integer value
93 * \return Newly allocated intnum.
94 */
95YASM_LIB_DECL
96/*@only@*/ yasm_intnum *yasm_intnum_create_uint(unsigned long i);
97
98/** Create a new intnum from an signed integer value.
99 * \param i         signed integer value
100 * \return Newly allocated intnum.
101 */
102YASM_LIB_DECL
103/*@only@*/ yasm_intnum *yasm_intnum_create_int(long i);
104
105/** Create a new intnum from LEB128-encoded form.
106 * \param ptr   pointer to start of LEB128 encoded form
107 * \param sign  signed (1) or unsigned (0) LEB128 format
108 * \param size  number of bytes read from ptr (output)
109 * \return Newly allocated intnum.  Number of bytes read returned into
110 *         bytes_read parameter.
111 */
112YASM_LIB_DECL
113/*@only@*/ yasm_intnum *yasm_intnum_create_leb128
114    (const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size);
115
116/** Create a new intnum from a little-endian or big-endian buffer.
117 * In little endian, the LSB is in ptr[0].
118 * \param ptr       pointer to start of buffer
119 * \param sign      signed (1) or unsigned (0) source
120 * \param srcsize   source buffer size (in bytes)
121 * \param bigendian endianness (nonzero=big, zero=little)
122 */
123YASM_LIB_DECL
124/*@only@*/ yasm_intnum *yasm_intnum_create_sized
125    (unsigned char *ptr, int sign, size_t srcsize, int bigendian);
126
127/** Duplicate an intnum.
128 * \param intn  intnum
129 * \return Newly allocated intnum with the same value as intn.
130 */
131YASM_LIB_DECL
132/*@only@*/ yasm_intnum *yasm_intnum_copy(const yasm_intnum *intn);
133
134/** Destroy (free allocated memory for) an intnum.
135 * \param intn  intnum
136 */
137YASM_LIB_DECL
138void yasm_intnum_destroy(/*@only@*/ yasm_intnum *intn);
139
140/** Floating point calculation function: acc = acc op operand.
141 * \note Not all operations in yasm_expr_op may be supported; unsupported
142 *       operations will result in an error.
143 * \param acc       intnum accumulator
144 * \param op        operation
145 * \param operand   intnum operand
146 * \return Nonzero if error occurred.
147 */
148YASM_LIB_DECL
149int yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand);
150
151/** Compare two intnums.
152 * \param intn1     first intnum
153 * \param intn2     second intnum
154 * \return -1 if intn1 < intn2, 0 if intn1 == intn2, 1 if intn1 > intn2.
155 */
156YASM_LIB_DECL
157int yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2);
158
159/** Zero an intnum.
160 * \param intn      intnum
161 */
162YASM_LIB_DECL
163void yasm_intnum_zero(yasm_intnum *intn);
164
165/** Set an intnum to the value of another intnum.
166 * \param intn      intnum
167 * \param val       intnum to get value from
168 */
169YASM_LIB_DECL
170void yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val);
171
172/** Set an intnum to an unsigned integer.
173 * \param intn      intnum
174 * \param val       integer value
175 */
176YASM_LIB_DECL
177void yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val);
178
179/** Set an intnum to an signed integer.
180 * \param intn      intnum
181 * \param val       integer value
182 */
183YASM_LIB_DECL
184void yasm_intnum_set_int(yasm_intnum *intn, long val);
185
186/** Simple value check for 0.
187 * \param acc       intnum
188 * \return Nonzero if acc==0.
189 */
190YASM_LIB_DECL
191int yasm_intnum_is_zero(const yasm_intnum *acc);
192
193/** Simple value check for 1.
194 * \param acc       intnum
195 * \return Nonzero if acc==1.
196 */
197YASM_LIB_DECL
198int yasm_intnum_is_pos1(const yasm_intnum *acc);
199
200/** Simple value check for -1.
201 * \param acc       intnum
202 * \return Nonzero if acc==-1.
203 */
204YASM_LIB_DECL
205int yasm_intnum_is_neg1(const yasm_intnum *acc);
206
207/** Simple sign check.
208 * \param acc       intnum
209 * \return -1 if negative, 0 if zero, +1 if positive
210 */
211YASM_LIB_DECL
212int yasm_intnum_sign(const yasm_intnum *acc);
213
214/** Convert an intnum to an unsigned 32-bit value.  The value is in "standard"
215 * C format (eg, of unknown endian).
216 * \note Parameter intnum is truncated to fit into 32 bits.  Use
217 *       intnum_check_size() to check for overflow.
218 * \param intn  intnum
219 * \return Unsigned 32-bit value of intn.
220 */
221YASM_LIB_DECL
222unsigned long yasm_intnum_get_uint(const yasm_intnum *intn);
223
224/** Convert an intnum to a signed 32-bit value.  The value is in "standard" C
225 * format (eg, of unknown endian).
226 * \note Parameter intnum is truncated to fit into 32 bits.  Use
227 *       intnum_check_size() to check for overflow.
228 * \param intn  intnum
229 * \return Signed 32-bit value of intn.
230 */
231YASM_LIB_DECL
232long yasm_intnum_get_int(const yasm_intnum *intn);
233
234/** Output #yasm_intnum to buffer in little-endian or big-endian.  Puts the
235 * value into the least significant bits of the destination, or may be shifted
236 * into more significant bits by the shift parameter.  The destination bits are
237 * cleared before being set.  [0] should be the first byte output to the file.
238 * \param intn      intnum
239 * \param ptr       pointer to storage for size bytes of output
240 * \param destsize  destination size (in bytes)
241 * \param valsize   size (in bits)
242 * \param shift     left shift (in bits); may be negative to specify right
243 *                  shift (standard warnings include truncation to boundary)
244 * \param bigendian endianness (nonzero=big, zero=little)
245 * \param warn      enables standard warnings (value doesn't fit into valsize
246 *                  bits): <0=signed warnings, >0=unsigned warnings, 0=no warn
247 */
248YASM_LIB_DECL
249void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
250                           size_t destsize, size_t valsize, int shift,
251                           int bigendian, int warn);
252
253/** Check to see if intnum will fit without overflow into size bits.
254 * \param intn      intnum
255 * \param size      number of bits of output space
256 * \param rshift    right shift
257 * \param rangetype signed/unsigned range selection:
258 *                  0 => (0, unsigned max);
259 *                  1 => (signed min, signed max);
260 *                  2 => (signed min, unsigned max)
261 * \return Nonzero if intnum will fit.
262 */
263YASM_LIB_DECL
264int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
265                           size_t rshift, int rangetype);
266
267/** Check to see if intnum will fit into a particular numeric range.
268 * \param intn      intnum
269 * \param low       low end of range (inclusive)
270 * \param high      high end of range (inclusive)
271 * \return Nonzero if intnum is within range.
272 */
273YASM_LIB_DECL
274int yasm_intnum_in_range(const yasm_intnum *intn, long low, long high);
275
276/** Output #yasm_intnum to buffer in LEB128-encoded form.
277 * \param intn      intnum
278 * \param ptr       pointer to storage for output bytes
279 * \param sign      signedness of LEB128 encoding (0=unsigned, 1=signed)
280 * \return Number of bytes generated.
281 */
282YASM_LIB_DECL
283unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn,
284                                     unsigned char *ptr, int sign);
285
286/** Calculate number of bytes LEB128-encoded form of #yasm_intnum will take.
287 * \param intn      intnum
288 * \param sign      signedness of LEB128 encoding (0=unsigned, 1=signed)
289 * \return Number of bytes.
290 */
291YASM_LIB_DECL
292unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign);
293
294/** Output integer to buffer in signed LEB128-encoded form.
295 * \param v         integer
296 * \param ptr       pointer to storage for output bytes
297 * \return Number of bytes generated.
298 */
299YASM_LIB_DECL
300unsigned long yasm_get_sleb128(long v, unsigned char *ptr);
301
302/** Calculate number of bytes signed LEB128-encoded form of integer will take.
303 * \param v         integer
304 * \return Number of bytes.
305 */
306YASM_LIB_DECL
307unsigned long yasm_size_sleb128(long v);
308
309/** Output integer to buffer in unsigned LEB128-encoded form.
310 * \param v         integer
311 * \param ptr       pointer to storage for output bytes
312 * \return Number of bytes generated.
313 */
314YASM_LIB_DECL
315unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr);
316
317/** Calculate number of bytes unsigned LEB128-encoded form of integer will take.
318 * \param v         integer
319 * \return Number of bytes.
320 */
321YASM_LIB_DECL
322unsigned long yasm_size_uleb128(unsigned long v);
323
324/** Get an intnum as a signed decimal string.  The returned string will
325 * contain a leading '-' if the intnum is negative.
326 * \param intn  intnum
327 * \return Newly allocated string containing the decimal representation of
328 *         the intnum.
329 */
330YASM_LIB_DECL
331/*@only@*/ char *yasm_intnum_get_str(const yasm_intnum *intn);
332
333/** Print an intnum.  For debugging purposes.
334 * \param f     file
335 * \param intn  intnum
336 */
337YASM_LIB_DECL
338void yasm_intnum_print(const yasm_intnum *intn, FILE *f);
339
340#endif
341