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. */ 38 YASM_LIB_DECL 39 void yasm_intnum_initialize(void); 40 41 /** Clean up internal intnum allocations. */ 42 YASM_LIB_DECL 43 void 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 */ 49 YASM_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 */ 56 YASM_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 */ 63 YASM_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 */ 70 YASM_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 */ 79 YASM_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 */ 88 YASM_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 */ 95 YASM_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 */ 102 YASM_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 */ 112 YASM_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 */ 123 YASM_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 */ 131 YASM_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 */ 137 YASM_LIB_DECL 138 void 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 */ 148 YASM_LIB_DECL 149 int 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 */ 156 YASM_LIB_DECL 157 int yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2); 158 159 /** Zero an intnum. 160 * \param intn intnum 161 */ 162 YASM_LIB_DECL 163 void 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 */ 169 YASM_LIB_DECL 170 void 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 */ 176 YASM_LIB_DECL 177 void 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 */ 183 YASM_LIB_DECL 184 void 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 */ 190 YASM_LIB_DECL 191 int 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 */ 197 YASM_LIB_DECL 198 int 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 */ 204 YASM_LIB_DECL 205 int 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 */ 211 YASM_LIB_DECL 212 int 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 */ 221 YASM_LIB_DECL 222 unsigned 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 */ 231 YASM_LIB_DECL 232 long 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 */ 248 YASM_LIB_DECL 249 void 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 */ 263 YASM_LIB_DECL 264 int 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 */ 273 YASM_LIB_DECL 274 int 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 */ 282 YASM_LIB_DECL 283 unsigned 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 */ 291 YASM_LIB_DECL 292 unsigned 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 */ 299 YASM_LIB_DECL 300 unsigned 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 */ 306 YASM_LIB_DECL 307 unsigned 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 */ 314 YASM_LIB_DECL 315 unsigned 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 */ 321 YASM_LIB_DECL 322 unsigned 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 */ 330 YASM_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 */ 337 YASM_LIB_DECL 338 void yasm_intnum_print(const yasm_intnum *intn, FILE *f); 339 340 #endif 341