#include <stdio.h> /* output for error messages */
#include <stdlib.h>
-/*****************************************************************************
+/*
* local definitions and macros
- *****************************************************************************/
+ */
#define BIT_PATTERN_SIZE (8 * BIGGEST_INTEGER_SIZE_IN_BYTES)
#define CALC_BUFFER_SIZE (4 * BIGGEST_INTEGER_SIZE_IN_BYTES)
#define MAX_VALUE_SIZE (2 * BIGGEST_INTEGER_SIZE_IN_BYTES)
#define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__)
+/* shortcut output for debugging only, gices always full precisition */
+#define sc_print_hex(a) sc_print((a), 0, SC_HEX)
+#define sc_print_dec(a) sc_print((a), 0, SC_DEC)
+#define sc_print_oct(a) sc_print((a), 0, SC_OCT)
+#define sc_print_bin(a) sc_print((a), 0, SC_BIN)
+
+
#if 0
# define DEBUGPRINTF(x) printf x
#else
# define DEBUGPRINTF(x) ((void)0)
#endif
-/*****************************************************************************
+/*
* private variables
- *****************************************************************************/
+ */
static char calc_buffer[CALC_BUFFER_SIZE]; /* buffer holding all results */
{ {SC_E, SC_0}, {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C} },
{ {SC_F, SC_0}, {SC_7, SC_8}, {SC_3, SC_C}, {SC_1, SC_E} }
};
+
+/* for converting to binary string */
+static const char *binary_table[16] = {
+ "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
+ "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
+};
+
/*****************************************************************************
* private functions
*****************************************************************************/
memset(rem, SC_0, CALC_BUFFER_SIZE);
/* if the dividend is zero result is zero (quot is zero)*/
- if (sc_comp(dividend, quot) == 0) return;
+ if (sc_comp(dividend, quot) == 0)
+ return;
/* if the divisor is zero this won't work (quot is zero) */
if (sc_comp(divisor, quot) == 0) assert(0 && "quotision by zero!");
return res;
}
-const char *sc_print(const void *value, unsigned base)
+/*
+ * convert to a string
+ */
+const char *sc_print(const void *value, unsigned bits, enum base_t base)
{
- int counter;
+ char base_val[CALC_BUFFER_SIZE];
+ char div1_res[CALC_BUFFER_SIZE];
+ char div2_res[CALC_BUFFER_SIZE];
+ char rem_res[CALC_BUFFER_SIZE];
+ int counter, nibbles, i;
+ char x;
const char *val = (const char *)value;
+ const char *p;
+ char *m, *n, *t;
char *pos;
static char *buf = NULL;
- if (buf != NULL) free(buf);
- buf = malloc(BIT_PATTERN_SIZE);
+ if (! buf) {
+ /* TODO: this buffer could be allocated in the initialising phase too */
+ buf = malloc(BIT_PATTERN_SIZE + 1);
+ if (! buf)
+ return NULL;
+ }
- pos = buf + BIT_PATTERN_SIZE - 1;
+ pos = buf + BIT_PATTERN_SIZE;
*pos = '\0';
- switch (base)
- {
- case SC_HEX:
- for (counter = 0; counter < MAX_VALUE_SIZE; counter++)
- {
- if (val[counter] < SC_A)
- *(--pos) = val[counter] + '0';
- else
- *(--pos) = val[counter] + 'a' - 10;
- }
- break;
+ /* special case */
+ if (bits == 0)
+ bits = BIT_PATTERN_SIZE;
- default:
- assert(0);
- }
+ nibbles = bits >> 2;
+ switch (base) {
+
+ case SC_HEX:
+ for (counter = 0; counter < nibbles; ++counter)
+ *(--pos) = "0123456789abcdef"[_val(val[counter])];
+
+ /* last nibble must be masked */
+ if (bits & 3) {
+ x = and_table[_val(val[++counter])][bits & 3];
+ *(--pos) = "0123456789abcdef"[_val(x)];
+ }
+
+ /* now kill zeros */
+ for (; counter > 1; --counter, ++pos)
+ if (pos[0] != '0')
+ break;
+ break;
+
+ case SC_BIN:
+ for (counter = 0; counter < nibbles; ++counter) {
+ pos -= 4;
+ p = binary_table[_val(val[counter])];
+ pos[0] = p[0];
+ pos[1] = p[1];
+ pos[2] = p[2];
+ pos[3] = p[3];
+ }
+
+ /* last nibble must be masked */
+ if (bits & 3) {
+ x = and_table[_val(val[++counter])][bits & 3];
+
+ pos -= 4;
+ p = binary_table[_val(x)];
+ pos[0] = p[0];
+ pos[1] = p[1];
+ pos[2] = p[2];
+ pos[3] = p[3];
+ }
+
+ /* now kill zeros */
+ for (counter <<= 2; counter > 1; --counter, ++pos)
+ if (pos[0] != '0')
+ break;
+ break;
+
+ case SC_DEC:
+ case SC_OCT:
+ memset(base_val, SC_0, CALC_BUFFER_SIZE);
+ base_val[0] = base == SC_DEC ? SC_A : SC_8;
+
+ /* transfer data into oscilating buffers */
+ memset(div1_res, SC_0, CALC_BUFFER_SIZE);
+ for (counter = 0; counter < nibbles; ++counter)
+ div1_res[counter] = val[counter];
+
+ /* last nibble must be masked */
+ if (bits & 3) {
+ ++counter;
+
+ div1_res[counter] = and_table[_val(val[counter])][bits & 3];
+ }
+
+ m = div1_res;
+ n = div2_res;
+ for (;;) {
+ _divmod(m, base_val, n, rem_res);
+ t = m;
+ m = n;
+ n = t;
+ *(--pos) = "0123456789abcdef"[_val(rem_res[0])];
+
+ x = 0;
+ for (i = 0; i < sizeof(div1_res); ++i)
+ x |= _val(m[i]);
+
+ if (x == 0)
+ break;
+ }
+ break;
+
+ default:
+ assert(0);
+ return NULL;
+}
return pos;
}
SC_F,
};
+/**
+ * Possible operations on integer values.
+ */
enum {
- SC_ADD = 0,
- SC_SUB,
- SC_NEG,
- SC_MUL,
- SC_DIV,
- SC_MOD,
- SC_SHL,
- SC_SHR,
- SC_SHRS,
- SC_ROT,
- SC_AND,
- SC_OR,
- SC_NOT,
- SC_XOR,
+ SC_ADD = 0, /**< Addition */
+ SC_SUB, /**< Substraction */
+ SC_NEG, /**< Unary Minus */
+ SC_MUL, /**< Multiplication */
+ SC_DIV, /**< Integer Division (with rounding toward zero ?) */
+ SC_MOD, /**< Devision Remainder */
+ SC_SHL, /**< Left Shift */
+ SC_SHR, /**< Logical (unsigned) Right Shift */
+ SC_SHRS, /**< Arithmetic (signed) Right Shift */
+ SC_ROT, /**< Rotation (both directions) */
+ SC_AND, /**< Bitwise And */
+ SC_OR, /**< Bitwise Or */
+ SC_NOT, /**< Bitwise Not */
+ SC_XOR, /**< Bitwise Exclusive Or */
};
-enum {
- SC_HEX,
- SC_DEC,
- SC_OKT,
- SC_BIN,
+/**
+ * The output mode for ntger values.
+ */
+enum base_t {
+ SC_HEX, /**< hexadecimal output */
+ SC_DEC, /**< decimal output */
+ SC_OCT, /**< octal output */
+ SC_BIN, /**< binary output */
};
-/*****************************************************************************
+/*
* definitions and macros
- *****************************************************************************/
+ */
#define sc_add(a, b) sc_calc((a), (b), SC_ADD)
#define sc_sub(a, b) sc_calc((a), (b), SC_SUB)
#define sc_neg(a) sc_calc((a), NULL, SC_NEG)
#define sc_shrs(a, b, c, d) sc_bitcalc((a), (b), (c), (d), SC_SHRS)
#define sc_rot(a, b, c, d) sc_bitcalc((a), (b), (c), (d), SC_ROT)
-#define sc_print_hex(a) sc_print((a), SC_HEX)
-#define sc_print_dec(a) sc_print((a), SC_DEC)
-#define sc_print_okt(a) sc_print((a), SC_OKT)
-#define sc_print_bin(a) sc_print((a), SC_BIN)
-/*****************************************************************************
+/*
* function declarations
- *****************************************************************************/
+ */
const void *sc_get_buffer(void);
const int sc_get_buffer_length(void);
unsigned char sc_sub_bits(const void *val, int len, unsigned byte_ofs);
-const char *sc_print(const void *val1, unsigned base);
+/**
+ * Converts a tarval into a string.
+ *
+ * @param val1 the value pointer
+ * @param bits number of valid bits in this value
+ * @param base output base
+ */
+const char *sc_print(const void *val1, unsigned bits, enum base_t base);
#endif /* _STRCALC_H_ */