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