X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Fstrcalc.c;h=50aaf56896fe0a58115b19d22fc6cb4843b15d41;hb=0d61f4e9a295d71deca66e1580273e484e7f0f9f;hp=338ad01de9848e4c67047a01dacdebf94fd52bc2;hpb=32ea6ea0320f551448bb66e534e3351977464d42;p=libfirm diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index 338ad01de..50aaf5689 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -45,8 +45,6 @@ #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) @@ -277,14 +275,6 @@ static const char *binary_table[16] = { /***************************************************************************** * 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 @@ -823,139 +813,77 @@ void sign_extend(void *buffer, ir_mode *mode) } } -/* 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, + unsigned int 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 = alloca(calc_buffer_size); + sc_val_from_ulong(base, sc_base); - if (buffer == NULL) buffer = calc_buffer; + val = 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, buffer, buffer); + /* add next digit to current value */ + do_add(val, buffer, 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(buffer, 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) @@ -1065,14 +993,14 @@ void sc_truncate(unsigned int num_bits, void *buffer) assert(pos < end); - switch(num_bits % 4) { + switch (num_bits % 4) { case 0: /* nothing to do */ break; case 1: *pos++ &= SC_1; break; case 2: *pos++ &= SC_3; break; case 3: *pos++ &= SC_7; break; } - for( ; pos < end; ++pos) + for ( ; pos < end; ++pos) *pos = SC_0; }