/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
+ * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
#define _digit(a) ((a)+SC_0)
#define _bitisset(digit, pos) (((digit) & SHIFT(pos)) != SC_0)
-#define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__)
-
/* shortcut output for debugging */
# define sc_print_hex(a) sc_print((a), 0, SC_HEX, 0)
# define sc_print_dec(a) sc_print((a), 0, SC_DEC, 1)
/*****************************************************************************
* private functions
*****************************************************************************/
-static void _fail_char(const char *str, size_t len, const char fchar, int pos,
- const char *file, int line) {
- printf("ERROR:\n");
- printf("Unexpected character '%c' in %s:%d\n", fchar, file, line);
- while (len-- && *str) printf("%c", *str++); printf("\n");
- while (--pos) printf(" "); printf("^\n");
- exit(-1);
-}
/**
* implements the bitwise NOT operation
*/
static void do_sub(const char *val1, const char *val2, char *buffer)
{
- char *temp_buffer = alloca(calc_buffer_size); /* intermediate buffer to hold -val2 */
+ char *temp_buffer = (char*) alloca(calc_buffer_size); /* intermediate buffer to hold -val2 */
do_negate(val2, temp_buffer);
do_add(val1, temp_buffer, buffer);
char sign = 0; /* marks result sign */
int c_inner, c_outer; /* loop counters */
- temp_buffer = alloca(calc_buffer_size);
- neg_val1 = alloca(calc_buffer_size);
- neg_val2 = alloca(calc_buffer_size);
+ temp_buffer = (char*) alloca(calc_buffer_size);
+ neg_val1 = (char*) alloca(calc_buffer_size);
+ neg_val2 = (char*) alloca(calc_buffer_size);
/* init result buffer to zeros */
memset(temp_buffer, SC_0, calc_buffer_size);
int c_dividend; /* loop counters */
- neg_val1 = alloca(calc_buffer_size);
- neg_val2 = alloca(calc_buffer_size);
+ neg_val1 = (char*) alloca(calc_buffer_size);
+ neg_val2 = (char*) alloca(calc_buffer_size);
/* clear result buffer */
memset(quot, SC_0, calc_buffer_size);
static void do_rotl(const char *val1, char *buffer, long offset, int radius, unsigned is_signed)
{
char *temp1, *temp2;
- temp1 = alloca(calc_buffer_size);
- temp2 = alloca(calc_buffer_size);
+ temp1 = (char*) alloca(calc_buffer_size);
+ temp2 = (char*) alloca(calc_buffer_size);
offset = offset % radius;
*/
void sign_extend(void *buffer, ir_mode *mode)
{
- char *calc_buffer = buffer;
+ char *calc_buffer = (char*) buffer;
int bits = get_mode_size_bits(mode) - 1;
int nibble = bits >> 2;
int max = max_digit[bits & 3];
}
}
-/* FIXME doesn't check for overflows */
-void sc_val_from_str(const char *str, unsigned int len, void *buffer, ir_mode *mode)
+/* we assume that '0'-'9', 'a'-'z' and 'A'-'Z' are a range.
+ * The C-standard does theoretically allow otherwise. */
+static inline void check_ascii(void)
{
- const char *orig_str = str;
- unsigned int orig_len = len;
+ /* C standard guarantees that '0'-'9' is a range */
+ assert('b'-'a' == 1
+ && 'c'-'a' == 2
+ && 'd'-'a' == 3
+ && 'e'-'a' == 4
+ && 'f'-'a' == 5);
+ assert('B'-'A' == 1
+ && 'C'-'A' == 2
+ && 'D'-'A' == 3
+ && 'E'-'A' == 4
+ && 'F'-'A' == 5);
+}
- char sign = 0;
- char *base, *val;
+int sc_val_from_str(char sign, unsigned base, const char *str,
+ size_t len, void *buffer)
+{
+ char *sc_base, *val;
- base = alloca(calc_buffer_size);
- val = alloca(calc_buffer_size);
+ assert(sign == -1 || sign == 1);
+ assert(str != NULL);
+ assert(len > 0);
+ check_ascii();
- /* verify valid pointers (not null) */
- assert(str);
- /* a string no characters long is an error */
- assert(len);
+ assert(base > 1 && base <= 16);
+ sc_base = (char*) alloca(calc_buffer_size);
+ sc_val_from_ulong(base, sc_base);
- if (buffer == NULL) buffer = calc_buffer;
+ val = (char*) alloca(calc_buffer_size);
+ if (buffer == NULL)
+ buffer = calc_buffer;
CLEAR_BUFFER(buffer);
- CLEAR_BUFFER(base);
CLEAR_BUFFER(val);
- /* strip leading spaces */
- while ((len > 0) && (*str == ' ')) { len--; str++; }
-
- /* if the first two characters are 0x or 0X -> hex
- * if the first is a 0 -> oct
- * else dec, strip leading -/+ and remember sign
- *
- * only a + or - sign is no number resulting in an error */
- if (len >= 2) {
- switch (str[0]) {
- case '0':
- if (str[1] == 'x' || str[1] == 'X') { /* hex */
- str += 2;
- len -= 2;
- base[1] = SC_1; base[0] = SC_0;
- } else { /* oct */
- str += 1;
- len -= 1;
- base[1] = SC_0; base[0] = SC_8;
- }
- break;
-
- case '+':
- str += 1;
- len -= 1;
- base[1] = SC_0; base[0] = SC_A;
- break;
-
- case '-':
- str += 1;
- len -= 1;
- sign = 1;
- base[1] = SC_0; base[0] = SC_A;
- break;
-
- default: /* dec, else would have begun with 0x or 0 */
- base[1] = SC_0; base[0] = SC_A;
- }
- } else { /* dec, else would have begun with 0x or 0 */
- base[1] = SC_0; base[0] = SC_A;
- }
-
/* BEGIN string evaluation, from left to right */
while (len > 0) {
- switch (*str) {
- case 'f':
- case 'e':
- case 'd':
- case 'c':
- case 'b':
- case 'a':
- if (base[0] > SC_A || base[1] > SC_0) { /* (base > 10) */
- val[0] = _digit((*str)-'a'+10);
- }
- else
- fail_char(orig_str, orig_len, *str, str-orig_str+1);
- break;
-
- case 'F':
- case 'E':
- case 'D':
- case 'C':
- case 'B':
- case 'A':
- if (base[0] > SC_A || base[1] > SC_0) { /* (base > 10) */
- val[0] = _digit((*str)-'A'+10);
- }
- else
- fail_char(orig_str, orig_len, *str, str-orig_str+1);
- break;
-
- case '9':
- case '8':
- if (base[0] > SC_8 || base[1] > SC_0) { /* (base > 8) */
- val[0] = _digit((*str)-'0');
- }
- else
- fail_char(orig_str, orig_len, *str, str-orig_str+1);
- break;
-
- case '7':
- case '6':
- case '5':
- case '4':
- case '3':
- case '2':
- case '1':
- case '0':
- val[0] = _digit((*str)-'0');
- break;
+ char c = *str;
+ unsigned v;
+ if (c >= '0' && c <= '9')
+ v = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ v = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ v = c - 'a' + 10;
+ else
+ return 0;
- default:
- fail_char(orig_str, orig_len, *str, str-orig_str+1);
- } /* switch (*str) */
+ if (v >= base)
+ return 0;
+ val[0] = v;
/* Radix conversion from base b to base B:
* (UnUn-1...U1U0)b == ((((Un*b + Un-1)*b + ...)*b + U1)*b + U0)B */
- do_mul(base, calc_buffer, calc_buffer); /* multiply current value with base */
- do_add(val, calc_buffer, calc_buffer); /* add next digit to current value */
+ /* multiply current value with base */
+ do_mul(sc_base, (const char*) buffer, (char*) buffer);
+ /* add next digit to current value */
+ do_add(val, (const char*) buffer, (char*) buffer);
/* get ready for the next letter */
str++;
len--;
} /* while (len > 0 ) */
- if (sign)
- do_negate(calc_buffer, calc_buffer);
+ if (sign < 0)
+ do_negate((const char*) buffer, (char*) buffer);
- /* beware: even if hex numbers have no sign, we need sign extension here */
- sign_extend(calc_buffer, mode);
+ return 1;
}
void sc_val_from_long(long value, void *buffer)
char sign, is_minlong;
if (buffer == NULL) buffer = calc_buffer;
- pos = buffer;
+ pos = (char*) buffer;
sign = (value < 0);
is_minlong = value == LONG_MIN;
if (sign) {
if (is_minlong)
- do_inc(buffer, buffer);
+ do_inc((const char*) buffer, (char*) buffer);
- do_negate(buffer, buffer);
+ do_negate((const char*) buffer, (char*) buffer);
}
}
unsigned char *pos;
if (buffer == NULL) buffer = calc_buffer;
- pos = buffer;
+ pos = (unsigned char*) buffer;
while (pos < (unsigned char *)buffer + calc_buffer_size) {
*pos++ = (unsigned char)_digit(value & 0xf);
if (!sign) return; /* unsigned means minimum is 0(zero) */
- pos = buffer;
+ pos = (char*) buffer;
bits = num_bits - 1;
for (i = 0; i < bits/4; i++)
if (buffer == NULL) buffer = calc_buffer;
CLEAR_BUFFER(buffer);
- pos = buffer;
+ pos = (char*) buffer;
bits = num_bits - sign;
for (i = 0; i < bits/4; i++)
void sc_truncate(unsigned int num_bits, void *buffer)
{
- char *cbuffer = buffer;
+ char *cbuffer = (char*) buffer;
char *pos = cbuffer + (num_bits / 4);
char *end = cbuffer + calc_buffer_size;
int sc_get_bit_at(const void *value, unsigned pos)
{
- const char *val = value;
+ const char *val = (const char*) value;
unsigned nibble = pos >> 2;
return (val[nibble] & SHIFT(pos & 3)) != SC_0;
void sc_set_bit_at(void *value, unsigned pos)
{
- char *val = value;
+ char *val = (char*) value;
unsigned nibble = pos >> 2;
val[nibble] |= SHIFT(pos & 3);
int sc_is_negative(const void *value)
{
- return do_sign(value) == -1;
+ return do_sign((const char*) value) == -1;
}
int sc_had_carry(void)
char *pos;
const char *digits = small_digits;
- base_val = alloca(calc_buffer_size);
- div1_res = alloca(calc_buffer_size);
- div2_res = alloca(calc_buffer_size);
- rem_res = alloca(calc_buffer_size);
+ base_val = (char*) alloca(calc_buffer_size);
+ div1_res = (char*) alloca(calc_buffer_size);
+ div2_res = (char*) alloca(calc_buffer_size);
+ rem_res = (char*) alloca(calc_buffer_size);
pos = output_buffer + bit_pattern_size;
*(--pos) = '\0';
DEBUGPRINTF_COMPUTATION(("%s + ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_add(value1, value2, calc_buffer);
+ do_add((const char*) value1, (const char*) value2, (char*) calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s - ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_sub(value1, value2, calc_buffer);
+ do_sub((const char*) value1, (const char*) value2, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("- %s ->", sc_print_hex(value1)));
- do_negate(value1, calc_buffer);
+ do_negate((const char*) value1, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s & ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_bitand(value1, value2, calc_buffer);
+ do_bitand((const char*) value1, (const char*) value2, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s & ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("~%s -> ", sc_print_hex(value2)));
- do_bitandnot(value1, value2, calc_buffer);
+ do_bitandnot((const char*) value1, (const char*) value2, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s | ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_bitor(value1, value2, calc_buffer);
+ do_bitor((const char*) value1, (const char*) value2, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s ^ ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_bitxor(value1, value2, calc_buffer);
+ do_bitxor((const char*) value1, (const char*) value2, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("~ %s ->", sc_print_hex(value1)));
- do_bitnot(value1, calc_buffer);
+ do_bitnot((const char*) value1, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s * ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_mul(value1, value2, calc_buffer);
+ do_mul((const char*) value1, (const char*) value2, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
void sc_div(const void *value1, const void *value2, void *buffer)
{
/* temp buffer holding unused result of divmod */
- char *unused_res = alloca(calc_buffer_size);
+ char *unused_res = (char*) alloca(calc_buffer_size);
CLEAR_BUFFER(calc_buffer);
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s / ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_divmod(value1, value2, calc_buffer, unused_res);
+ do_divmod((const char*) value1, (const char*) value2, calc_buffer, unused_res);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
void sc_mod(const void *value1, const void *value2, void *buffer)
{
/* temp buffer holding unused result of divmod */
- char *unused_res = alloca(calc_buffer_size);
+ char *unused_res = (char*) alloca(calc_buffer_size);
CLEAR_BUFFER(calc_buffer);
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s %% ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_divmod(value1, value2, unused_res, calc_buffer);
+ do_divmod((const char*) value1, (const char*) value2, unused_res, calc_buffer);
DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
DEBUGPRINTF_COMPUTATION(("%s %% ", sc_print_hex(value1)));
DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
- do_divmod(value1, value2, div_buffer, mod_buffer);
+ do_divmod((const char*) value1, (const char*) value2, (char*) div_buffer, (char*) mod_buffer);
DEBUGPRINTF_COMPUTATION(("%s:%s\n", sc_print_hex(div_buffer), sc_print_hex(mod_buffer)));
}
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s << %ld ", sc_print_hex(value1), shift_cnt));
- do_shl(val1, calc_buffer, shift_cnt, bitsize, sign);
+ do_shl((const char*) val1, calc_buffer, shift_cnt, bitsize, sign);
DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s >>u %ld ", sc_print_hex(value1), shift_cnt));
- do_shr(val1, calc_buffer, shift_cnt, bitsize, sign, 0);
+ do_shr((const char*) val1, calc_buffer, shift_cnt, bitsize, sign, 0);
DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s >>s %ld ", sc_print_hex(value1), offset));
- do_shr(val1, calc_buffer, offset, bitsize, sign, 1);
+ do_shr((const char*) val1, calc_buffer, offset, bitsize, sign, 1);
DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s <<>> %ld ", sc_print_hex(value1), offset));
- do_rotl(val1, calc_buffer, offset, bitsize, sign);
+ do_rotl((const char*) val1, calc_buffer, offset, bitsize, sign);
DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));