#include "xed-types.h"
#include "xed-util.h"
#include "xed-util-private.h"
#include "xed-portability.h"
#include "xed-portability-private.h"
#include "xed-common-defs.h"
#include "xed-common-hdrs.h"
#if defined(__linux__) && defined(__STDC_HOSTED__) && __STDC_HOSTED__ == 0
extern void abort (void) __attribute__ ((__noreturn__));
#else
# include <stdlib.h>
#endif
#include <ctype.h>
int xed_verbose = 2;
#include <stdio.h>
#if defined(XED_MESSAGES)
FILE* xed_log_file;
#endif
void xed_set_verbosity(int v) {
xed_verbose = v;
}
void xed_set_log_file(void* o) {
#if defined(XED_MESSAGES)
xed_log_file = (FILE*)o;
#else
(void)o;
#endif
}
#if !defined(XED_64B)
static XED_INLINE xed_uint64_t get_bit63(xed_uint64_t x) {
const xed_uint64_t s = 63;
return (x >> s) & 1;
}
static XED_INLINE xed_uint64_t xed_divide_by_10_64by32(xed_uint64_t numerator) {
int i=0;
const xed_uint32_t denominator = 10;
xed_uint64_t tn=numerator;
xed_uint64_t tqlo=0;
xed_uint32_t ir=0,b=0;
xed_uint32_t num=0;
xed_uint32_t qbit=0;
for(i=0;i<64;i++) {
b = get_bit63(tn); num = (ir << 1) | b; if (num >= denominator) {
ir = num - denominator;
qbit = 1;
}
else {
ir = num;
qbit = 0;
}
tqlo = (tqlo <<1) | qbit;
tn = tn << 1;
}
return tqlo;
}
#endif
int xed_itoa(char* buf, xed_uint64_t f, int buflen) {
char tbuf[100];
char* p = tbuf;
char* fp;
xed_uint64_t t = f;
xed_uint64_t x,v;
if (f == 0) {
*p++ = '0';
*p = 0;
return xed_strncpy(buf,tbuf,buflen);
}
while(t) {
#if defined(XED_64B)
x = t / 10;
#else
x = xed_divide_by_10_64by32(t);
#endif
v = t - (x*10);
*p++ = XED_STATIC_CAST(char, '0' + v);
t = x;
}
*p=0;
p--;
fp = tbuf;
while(fp < p) {
char ec = *p;
char fc = *fp;
*fp = ec;
*p = fc;
fp++;
p--;
}
return xed_strncpy(buf,tbuf,buflen);
}
static int add_leading_zeros(char* buf,
char* tbuf,
int buflen,
xed_uint_t bits_to_print)
{
char* p = buf;
xed_uint_t ilen = xed_strlen(tbuf);
if (ilen < bits_to_print) {
xed_uint_t i;
xed_uint_t zeros = bits_to_print - ilen;
for(i=0 ; i < zeros && buflen>0 ; i++) {
buflen--;
*p++ = '0';
}
}
return xed_strncpy(p,tbuf,buflen);
}
int xed_itoa_bin(char *buf,
xed_uint64_t f,
xed_uint_t bits_to_print,
xed_uint_t buflen)
{
char tbuf[65];
xed_int_t i;
char *p = tbuf;
xed_uint64_t base_letter = XED_STATIC_CAST(xed_uint64_t, '0');
xed_uint_t num_bits = (bits_to_print > 64) ? 64 : bits_to_print;
if (num_bits >= buflen) {
num_bits = buflen - 1;
}
for (i = num_bits - 1; i >= 0; i--) {
*p++ = XED_STATIC_CAST(char, base_letter + ((f >> i) & 1));
}
*p = 0;
return xed_strncpy(buf, tbuf, buflen);
}
int xed_itoa_hex_ul(char* buf,
xed_uint64_t f,
xed_uint_t bits_to_print,
xed_bool_t leading_zeros,
int buflen,
xed_bool_t lowercase)
{
const xed_uint64_t one = 1;
xed_uint_t nibbles_to_print = (bits_to_print+3)/4;
xed_uint64_t mul,rdiv;
xed_uint64_t n;
char tbuf[100];
char* p = tbuf;
xed_uint64_t ff,t;
xed_uint_t div = 0;
xed_uint64_t base_letter;
if (bits_to_print == 64) ff = f;
else
ff = f & ((one<<bits_to_print)-1);
if (ff == 0) {
*p++ = '0';
*p = 0;
if (leading_zeros)
return add_leading_zeros(buf,tbuf,buflen,bits_to_print);
else
return xed_strncpy(buf,tbuf,buflen);
}
t = ff;
while(t) {
t = t >> 4;
div++;
}
n = ff;
if (lowercase)
base_letter = XED_STATIC_CAST(xed_uint64_t,'a');
else
base_letter = XED_STATIC_CAST(xed_uint64_t,'A');
while(div > 0) {
div--;
rdiv = one<<(4*div);
mul = (n >> (4*div)) & 0xF;
if (div <= nibbles_to_print) {
if (mul<10)
*p++ = XED_STATIC_CAST(char,mul + '0');
else
*p++ = XED_STATIC_CAST(char,mul - 10 + base_letter);
}
n = n - (mul*rdiv);
}
*p = 0;
if (leading_zeros)
return add_leading_zeros(buf,tbuf,buflen,bits_to_print);
return xed_strncpy(buf,tbuf,buflen);
}
int xed_itoa_hex_zeros(char* buf,
xed_uint64_t f,
xed_uint_t bits_to_print,
xed_bool_t leading_zeros,
int buflen) {
const xed_bool_t lowercase=1;
return xed_itoa_hex_ul(buf,f,bits_to_print, leading_zeros, buflen, lowercase);
}
int xed_itoa_hex(char* buf,
xed_uint64_t f,
xed_uint_t bits_to_print,
int buflen)
{
const xed_bool_t lowercase = 1;
const xed_bool_t leading_zeros = 0;
return xed_itoa_hex_ul(buf, f, bits_to_print, leading_zeros, buflen, lowercase);
}
int xed_itoa_signed(char* buf, xed_int64_t f, int buflen) {
xed_uint64_t x;
int blen = buflen;
if (f<0) {
blen = xed_strncpy(buf,"-",blen);
x = XED_STATIC_CAST(xed_uint64_t,-f);
}
else
x = XED_STATIC_CAST(xed_uint64_t,f);
return xed_itoa(buf+xed_strlen(buf), x, blen);
}
int xed_sprintf_uint8_hex(char* buf, xed_uint8_t x, int buflen) {
return xed_itoa_hex(buf,x,8,buflen);
}
int xed_sprintf_uint16_hex(char* buf, xed_uint16_t x, int buflen) {
return xed_itoa_hex(buf,x,16,buflen);
}
int xed_sprintf_uint32_hex(char* buf, xed_uint32_t x, int buflen) {
return xed_itoa_hex(buf,x,32,buflen);
}
int xed_sprintf_uint64_hex(char* buf, xed_uint64_t x, int buflen) {
return xed_itoa_hex(buf,x,64,buflen);
}
int xed_sprintf_uint8(char* buf, xed_uint8_t x, int buflen) {
return xed_itoa(buf, x, buflen);
}
int xed_sprintf_uint16(char* buf, xed_uint16_t x, int buflen) {
return xed_itoa(buf, x, buflen);
}
int xed_sprintf_uint32(char* buf, xed_uint32_t x, int buflen) {
return xed_itoa(buf, x, buflen);
}
int xed_sprintf_uint64(char* buf, xed_uint64_t x, int buflen) {
return xed_itoa(buf, x, buflen);
}
int xed_sprintf_int8(char* buf, xed_int8_t x, int buflen) {
return xed_itoa_signed(buf,x,buflen);
}
int xed_sprintf_int16(char* buf, xed_int16_t x, int buflen) {
return xed_itoa_signed(buf,x,buflen);
}
int xed_sprintf_int32(char* buf, xed_int32_t x, int buflen) {
return xed_itoa_signed(buf,x,buflen);
}
int xed_sprintf_int64(char* buf, xed_int64_t x, int buflen) {
return xed_itoa_signed(buf,x,buflen);
}
char xed_to_ascii_hex_nibble(xed_uint_t x, xed_bool_t lowercase) {
if (x<=9)
return XED_STATIC_CAST(char,x+'0');
if (x<=15) {
if (lowercase)
return XED_STATIC_CAST(char,x-10+'a');
else
return XED_STATIC_CAST(char,x-10+'A');
}
return '?';
}
static char xed_tolower(char c) {
if (c >= 'A' && c <= 'Z')
return c-'A'+'a';
return c;
}
int xed_strncat_lower(char* dst, const char* src, int len) {
xed_uint_t dst_len = xed_strlen(dst) ;
xed_uint_t orig_max = dst_len + XED_STATIC_CAST(xed_uint_t,len);
xed_uint_t i;
xed_uint_t src_len = xed_strlen(src);
xed_uint_t copy_max = src_len;
xed_uint_t ulen = (xed_uint_t)len-1;
if (len <= 0)
return 0;
if (src_len > ulen)
copy_max = ulen;
for(i=0;i<copy_max;i++)
dst[dst_len+i]=xed_tolower(src[i]);
dst[dst_len+copy_max]=0;
return XED_STATIC_CAST(int,orig_max - xed_strlen(dst));
}
xed_int64_t xed_sign_extend_arbitrary_to_64(xed_uint64_t x, unsigned int bits) {
xed_uint64_t one = 1;
xed_int64_t mask = one<<(bits-1);
xed_int64_t vmask, o=0;
if (bits < 64) {
vmask = (one<<bits)-1;
o = ((x&vmask) ^ mask)- mask;
}
else if (bits == 64)
o=x;
else
xed_assert(0);
return o;
}
xed_int32_t xed_sign_extend_arbitrary_to_32(xed_uint32_t x, unsigned int bits) {
xed_int32_t mask = 1<<(bits-1);
xed_int32_t vmask, o=0;
if (bits < 32) {
vmask = (1<<bits)-1;
o = ((x&vmask) ^ mask)- mask;
}
else if (bits == 32)
o=x;
else
xed_assert(0);
return o;
}
xed_int64_t xed_sign_extend32_64(xed_int32_t x) {
return x;
}
xed_int64_t xed_sign_extend16_64(xed_int16_t x) {
return x;
}
xed_int64_t xed_sign_extend8_64(xed_int8_t x) {
return x;
}
xed_int32_t xed_sign_extend16_32(xed_int16_t x) {
return x;
}
xed_int32_t xed_sign_extend8_32(xed_int8_t x) {
return x;
}
xed_int16_t xed_sign_extend8_16(xed_int8_t x) {
return x;
}
xed_uint64_t xed_zero_extend32_64(xed_uint32_t x) {
return x;
}
xed_uint64_t xed_zero_extend16_64(xed_uint16_t x) {
return x;
}
xed_uint64_t xed_zero_extend8_64(xed_uint8_t x) {
return x;
}
xed_uint32_t xed_zero_extend16_32(xed_uint16_t x) {
return x;
}
xed_uint32_t xed_zero_extend8_32(xed_uint8_t x) {
return x;
}
xed_uint16_t xed_zero_extend8_16(xed_uint8_t x) {
return x;
}
#if defined(XED_LITTLE_ENDIAN_SWAPPING)
static XED_INLINE xed_int64_t xed_sign_extend4_64(xed_int8_t x) {
const xed_int64_t eight = 8;
xed_int64_t o = (x ^ eight)- eight;
return o;
}
static XED_INLINE xed_int32_t xed_sign_extend4_32(xed_int8_t x) {
xed_int32_t o = (x ^ 0x00000008)- 0x00000008;
return o;
}
xed_int64_t xed_little_endian_hilo_to_int64(xed_uint32_t hi_le, xed_uint32_t lo_le, unsigned int len) {
switch(len) {
case 4:
return xed_sign_extend4_64(XED_STATIC_CAST(xed_int8_t,lo_le&0xF));
case 8:
return xed_sign_extend8_64(XED_STATIC_CAST(xed_int8_t,lo_le));
case 16:
return xed_sign_extend16_64(xed_bswap16(XED_STATIC_CAST(xed_uint16_t,lo_le)));
case 32: {
xed_int32_t y = xed_bswap32(XED_STATIC_CAST(xed_uint32_t,lo_le));
xed_int64_t z;
z= xed_sign_extend32_64(y);
return z;
}
case 64: {
xed_uint64_t z = xed_make_uint64(xed_bswap32(hi_le),xed_bswap32(lo_le));
return XED_STATIC_CAST(xed_int64_t,z);
}
default:
xed_assert(0);
return 0;
}
}
xed_uint64_t xed_little_endian_hilo_to_uint64(xed_uint32_t hi_le, xed_uint32_t lo_le, unsigned int len) {
switch(len) {
case 4:
return XED_STATIC_CAST(xed_uint8_t,lo_le&0xF);
case 8:
return XED_STATIC_CAST(xed_uint8_t,lo_le);
case 16:
return xed_bswap16(XED_STATIC_CAST(xed_uint16_t,lo_le));
case 32:
return xed_bswap32(XED_STATIC_CAST(xed_uint32_t,lo_le));
case 64:
return xed_make_uint64(xed_bswap32(hi_le),xed_bswap32(lo_le));
default:
xed_assert(0);
return 0;
}
}
xed_uint64_t xed_little_endian_to_uint64(xed_uint64_t x, unsigned int len) {
switch(len) {
case 4:
return XED_STATIC_CAST(xed_uint8_t,x&0xF);
case 8:
return XED_STATIC_CAST(xed_uint8_t,x);
case 16:
return xed_bswap16(XED_STATIC_CAST(xed_uint16_t,x));
case 32:
return xed_bswap32(XED_STATIC_CAST(xed_uint32_t,x));
case 64:
return xed_bswap64(x);
default:
xed_assert(0);
return 0;
}
}
xed_int64_t xed_little_endian_to_int64(xed_uint64_t x, unsigned int len){
switch(len) {
case 4:
return xed_sign_extend4_64(XED_STATIC_CAST(xed_int8_t,x&0xF));
case 8:
return xed_sign_extend8_64(XED_STATIC_CAST(xed_int8_t,x));
case 16:
return xed_sign_extend16_64(xed_bswap16(XED_STATIC_CAST(xed_uint16_t,x)));
case 32: {
xed_int32_t y = xed_bswap32(XED_STATIC_CAST(xed_uint32_t,x));
xed_int64_t z;
z= xed_sign_extend32_64(y);
return z;
}
case 64:
return XED_STATIC_CAST(xed_int64_t,xed_bswap64(x));
default:
xed_assert(0);
return 0;
}
}
xed_int32_t xed_little_endian_to_int32(xed_uint64_t x, unsigned int len){
switch(len) {
case 4:
return xed_sign_extend4_32(XED_STATIC_CAST(xed_int8_t,x&0xF));
case 8:
return xed_sign_extend8_32(XED_STATIC_CAST(xed_int8_t,x));
case 16:
return xed_sign_extend16_32(xed_bswap16(XED_STATIC_CAST(xed_uint16_t,x)));
case 32: {
xed_int32_t y = xed_bswap32(XED_STATIC_CAST(xed_uint32_t,x));
return y;
}
default:
xed_assert(0);
return 0;
}
}
#endif
xed_uint8_t xed_get_byte(xed_uint64_t x, unsigned int i, unsigned int len) {
xed_assert (i < len);
(void)len; return XED_BYTE_CAST(x >> (i*8));
}
xed_uint_t
xed_shortest_width_signed(xed_int64_t x, xed_uint8_t legal_widths) {
static const xed_int64_t max1[] = { 0x7f, 0x7fff, 0x7fffffff };
static const xed_int64_t min1[] = {
-128,
-0x8000LL, -0x80000000LL };
unsigned int i,j;
for(i=0;i<3;i++)
{
j = 1 << i;
if ((j & legal_widths)==j)
if (x <= max1[i] && x >= min1[i])
break;
}
return 1<<i;
}
xed_uint_t
xed_shortest_width_unsigned(xed_uint64_t x, xed_uint8_t legal_widths) {
unsigned int i,j;
const xed_uint64_t one = 1;
for(i=0;i<3; i++)
{
j = 1 << i;
if ((j & legal_widths)==j)
if (x < (one<<(j*8)))
break;
}
return 1<<i;
}
void xed_derror(const char* s) {
XED2DIE((xed_log_file,"%s\n", s));
(void)s; }
static xed_user_abort_function_t xed_user_abort_function = 0;
static void* xed_user_abort_other = 0;
void xed_register_abort_function(xed_user_abort_function_t fn,
void* other) {
xed_user_abort_function = fn;
xed_user_abort_other = other;
}
void xed_internal_assert( const char* msg, const char* file, int line) {
if (xed_user_abort_function) {
(*xed_user_abort_function)(msg, file, line, xed_user_abort_other);
}
else {
fprintf(stderr,"ASSERTION FAILURE %s at %s:%d\n", msg, file, line);
}
abort();
}