yasm_intnum_get_sized().
* intnum.h (yasm_intnum_create_sized): Prototype.
* yasm.pyx: Bring in _PyLong_From/AsByteArray functions.
* intnum.pyx: Use yasm_intnum_create_sized(), etc to implement full 128-bit
number handling.
* intnum.c (yasm_intnum_get_str): Return strings in hex rather than in
decimal.
svn path=/trunk/yasm/; revision=1488
return intn;
}
+yasm_intnum *
+yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize,
+ int bigendian, unsigned long line)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ unsigned long i = 0;
+
+ intn->origsize = 0;
+
+ if (srcsize*8 > BITVECT_NATIVE_SIZE)
+ yasm__warning(YASM_WARN_GENERAL, line,
+ N_("Numeric constant too large for internal format"));
+
+ /* Read the buffer into a bitvect */
+ BitVector_Empty(conv_bv);
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else {
+ for (i = 0; i < srcsize; i++)
+ BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]);
+ }
+
+ /* Sign extend if needed */
+ if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i] & 0x80) == 0x80)
+ BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1);
+
+ if (Set_Max(conv_bv) < 32) {
+ intn->type = INTNUM_UL;
+ intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
+ } else {
+ intn->type = INTNUM_BV;
+ intn->val.bv = BitVector_Clone(conv_bv);
+ }
+
+ return intn;
+}
+
yasm_intnum *
yasm_intnum_copy(const yasm_intnum *intn)
{
char *
yasm_intnum_get_str(const yasm_intnum *intn)
{
- unsigned char *s;
+ char *s, *s2;
switch (intn->type) {
case INTNUM_UL:
- s = yasm_xmalloc(16);
- sprintf((char *)s, "%lu", intn->val.ul);
- return (char *)s;
- break;
+ s = yasm_xmalloc(20);
+ sprintf(s, "0x%lx", intn->val.ul);
+ return s;
case INTNUM_BV:
- return (char *)BitVector_to_Dec(intn->val.bv);
- break;
+ if (BitVector_msb_(intn->val.bv)) {
+ /* it's negative: negate the bitvector to get positive */
+ BitVector_Negate(conv_bv, intn->val.bv);
+ s2 = (char *)BitVector_to_Hex(conv_bv);
+ s = yasm_xmalloc(strlen(s2)+4);
+ strcpy(s, "-0x");
+ strcat(s, s2);
+ yasm_xfree(s2);
+ } else {
+ s2 = (char *)BitVector_to_Hex(intn->val.bv);
+ s = yasm_xmalloc(strlen(s2)+3);
+ strcpy(s, "0x");
+ strcat(s, s2);
+ yasm_xfree(s2);
+ }
+ return s;
}
/*@notreached@*/
return NULL;
/** Create a new intnum from LEB128-encoded form.
* \param ptr pointer to start of LEB128 encoded form
- * \param sign signed (1) or unsiged (0) LEB128 format
+ * \param sign signed (1) or unsigned (0) LEB128 format
* \param size number of bytes read from ptr (output)
* \param line virtual line (where the number came from)
* \return Newly allocated intnum. Number of bytes read returned into
(const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size,
unsigned long line);
+/** Create a new intnum from a little-endian or big-endian buffer.
+ * In little endian, the LSB is in ptr[0].
+ * \param ptr pointer to start of buffer
+ * \param sign signed (1) or unsigned (0) source
+ * \param srcsize source buffer size (in bytes)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param line virtual line; may be 0 if warn is 0
+ */
+/*@only@*/ yasm_intnum *yasm_intnum_create_sized
+ (unsigned char *ptr, int sign, size_t srcsize, int bigendian,
+ unsigned long line);
+
/** Duplicate an intnum.
* \param intn intnum
* \return Newly allocated intnum with the same value as intn.
cdef yasm_intnum *yasm_intnum_create_int(long i)
cdef yasm_intnum *yasm_intnum_create_leb128(unsigned char *ptr,
int sign, unsigned long *size, unsigned long line)
+ cdef yasm_intnum *yasm_intnum_create_sized(unsigned char *ptr, int sign,
+ size_t srcsize, int bigendian, unsigned long line)
cdef yasm_intnum *yasm_intnum_copy(yasm_intnum *intn)
cdef void yasm_intnum_destroy(yasm_intnum *intn)
cdef void yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op,
cdef unsigned long yasm_size_uleb128(unsigned long v)
cdef void yasm_intnum_print(yasm_intnum *intn, FILE *f)
-# TODO: rework __new__ / __int__ / __long__ to support > int values
cdef class IntNum:
cdef yasm_intnum *intn
def __new__(self, value, base=None):
+ cdef unsigned char buf[16]
+
self.intn = NULL
if isinstance(value, IntNum):
val = None
if isinstance(value, str):
- val = int(value, base)
+ val = long(value, base)
elif isinstance(value, (int, long)):
- val = value
+ val = long(value)
if val is None:
raise ValueError
- if val < 0:
- self.intn = yasm_intnum_create_int(val)
- else:
- self.intn = yasm_intnum_create_uint(val)
+ _PyLong_AsByteArray(val, buf, 16, 1, 1)
+ self.intn = yasm_intnum_create_sized(buf, 1, 16, 0, 0)
def __dealloc__(self):
if self.intn != NULL: yasm_intnum_destroy(self.intn)
+ def __long__(self):
+ cdef unsigned char buf[16]
+ yasm_intnum_get_sized(self.intn, buf, 16, 128, 0, 0, 0, 0)
+ return _PyLong_FromByteArray(buf, 16, 1, 1)
+
def __int__(self):
- if yasm_intnum_sign(self.intn) < 0:
- return yasm_intnum_get_int(self.intn)
- else:
- return yasm_intnum_get_uint(self.intn)
+ return int(self.__long__())
def __repr__(self):
- return str(int(self))
+ return "IntNum(%s)" % str(int(self))
def __op(self, op, o=None):
lhs = IntNum(self)
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
+"""Interface to the Yasm library.
+
+The Yasm library (aka libyasm) provides the core functionality of the Yasm
+assembler. Classes in this library provide for manipulation of machine
+instructions and object file constructs such as symbol tables and sections.
+
+Expression objects encapsulate complex expressions containing registers,
+symbols, and operations such as SEG.
+
+Bytecode objects encapsulate data or code objects such as data, reserve,
+align, or instructions.
+
+Section objects encapsulate an object file section, including the section
+name, any Bytecode objects contained within that section, and other
+information.
+
+"""
cdef extern from "Python.h":
cdef object PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
cdef void *PyCObject_AsVoidPtr(object)
cdef void *PyCObject_GetDesc(object)
+ cdef object _PyLong_FromByteArray(unsigned char *bytes, unsigned int n,
+ int little_endian, int is_signed)
+ cdef int _PyLong_AsByteArray(object v, unsigned char *bytes, unsigned int n,
+ int little_endian, int is_signed) except -1
+
cdef extern from "libyasm/compat-queue.h":
pass