diff options
Diffstat (limited to 'src/ccl.c')
-rw-r--r-- | src/ccl.c | 115 |
1 files changed, 87 insertions, 28 deletions
diff --git a/src/ccl.c b/src/ccl.c index ef059ffff25..86debeef0e5 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -1142,19 +1142,52 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size ccl_expr_self: switch (op) { - case CCL_PLUS: reg[rrr] += i; break; - case CCL_MINUS: reg[rrr] -= i; break; - case CCL_MUL: reg[rrr] *= i; break; - case CCL_DIV: reg[rrr] /= i; break; + case CCL_PLUS: INT_ADD_WRAPV (reg[rrr], i, ®[rrr]); break; + case CCL_MINUS: INT_SUBTRACT_WRAPV (reg[rrr], i, ®[rrr]); break; + case CCL_MUL: INT_MULTIPLY_WRAPV (reg[rrr], i, ®[rrr]); break; + case CCL_DIV: + if (!i) + CCL_INVALID_CMD; + if (!INT_DIVIDE_OVERFLOW (reg[rrr], i)) + reg[rrr] /= i; + break; case CCL_MOD: reg[rrr] %= i; break; + if (!i) + CCL_INVALID_CMD; + reg[rrr] = i == -1 ? 0 : reg[rrr] % i; + break; case CCL_AND: reg[rrr] &= i; break; case CCL_OR: reg[rrr] |= i; break; case CCL_XOR: reg[rrr] ^= i; break; - case CCL_LSH: reg[rrr] <<= i; break; - case CCL_RSH: reg[rrr] >>= i; break; - case CCL_LSH8: reg[rrr] <<= 8; reg[rrr] |= i; break; + case CCL_LSH: + if (i < 0) + CCL_INVALID_CMD; + reg[rrr] = i < UINT_WIDTH ? (unsigned) reg[rrr] << i : 0; + break; + case CCL_RSH: + if (i < 0) + CCL_INVALID_CMD; + reg[rrr] = reg[rrr] >> min (i, INT_WIDTH - 1); + break; + case CCL_LSH8: + reg[rrr] = (unsigned) reg[rrr] << 8; + reg[rrr] |= i; + break; case CCL_RSH8: reg[7] = reg[rrr] & 0xFF; reg[rrr] >>= 8; break; - case CCL_DIVMOD: reg[7] = reg[rrr] % i; reg[rrr] /= i; break; + case CCL_DIVMOD: + if (!i) + CCL_INVALID_CMD; + if (i == -1) + { + reg[7] = 0; + INT_SUBTRACT_WRAPV (0, reg[rrr], ®[rrr]); + } + else + { + reg[7] = reg[rrr] % i; + reg[rrr] /= i; + } + break; case CCL_LS: reg[rrr] = reg[rrr] < i; break; case CCL_GT: reg[rrr] = reg[rrr] > i; break; case CCL_EQ: reg[rrr] = reg[rrr] == i; break; @@ -1204,19 +1237,52 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size ccl_set_expr: switch (op) { - case CCL_PLUS: reg[rrr] = i + j; break; - case CCL_MINUS: reg[rrr] = i - j; break; - case CCL_MUL: reg[rrr] = i * j; break; - case CCL_DIV: reg[rrr] = i / j; break; - case CCL_MOD: reg[rrr] = i % j; break; + case CCL_PLUS: INT_ADD_WRAPV (i, j, ®[rrr]); break; + case CCL_MINUS: INT_SUBTRACT_WRAPV (i, j, ®[rrr]); break; + case CCL_MUL: INT_MULTIPLY_WRAPV (i, j, ®[rrr]); break; + case CCL_DIV: + if (!j) + CCL_INVALID_CMD; + if (!INT_DIVIDE_OVERFLOW (i, j)) + i /= j; + reg[rrr] = i; + break; + case CCL_MOD: + if (!j) + CCL_INVALID_CMD; + reg[rrr] = j == -1 ? 0 : i % j; + break; case CCL_AND: reg[rrr] = i & j; break; case CCL_OR: reg[rrr] = i | j; break; case CCL_XOR: reg[rrr] = i ^ j; break; - case CCL_LSH: reg[rrr] = i << j; break; - case CCL_RSH: reg[rrr] = i >> j; break; - case CCL_LSH8: reg[rrr] = (i << 8) | j; break; + case CCL_LSH: + if (j < 0) + CCL_INVALID_CMD; + reg[rrr] = j < UINT_WIDTH ? (unsigned) i << j : 0; + break; + case CCL_RSH: + if (j < 0) + CCL_INVALID_CMD; + reg[rrr] = i >> min (j, INT_WIDTH - 1); + break; + case CCL_LSH8: + reg[rrr] = ((unsigned) i << 8) | j; + break; case CCL_RSH8: reg[rrr] = i >> 8; reg[7] = i & 0xFF; break; - case CCL_DIVMOD: reg[rrr] = i / j; reg[7] = i % j; break; + case CCL_DIVMOD: + if (!j) + CCL_INVALID_CMD; + if (j == -1) + { + INT_SUBTRACT_WRAPV (0, reg[rrr], ®[rrr]); + reg[7] = 0; + } + else + { + reg[rrr] = i / j; + reg[7] = i % j; + } + break; case CCL_LS: reg[rrr] = i < j; break; case CCL_GT: reg[rrr] = i > j; break; case CCL_EQ: reg[rrr] = i == j; break; @@ -1225,7 +1291,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size case CCL_NE: reg[rrr] = i != j; break; case CCL_DECODE_SJIS: { - i = (i << 8) | j; + i = ((unsigned) i << 8) | j; SJIS_TO_JIS (i); reg[rrr] = i >> 8; reg[7] = i & 0xFF; @@ -1233,7 +1299,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size } case CCL_ENCODE_SJIS: { - i = (i << 8) | j; + i = ((unsigned) i << 8) | j; JIS_TO_SJIS (i); reg[rrr] = i >> 8; reg[7] = i & 0xFF; @@ -2219,15 +2285,8 @@ Return index number of the registered CCL program. */) /* Extend the table. */ Vccl_program_table = larger_vector (Vccl_program_table, 1, -1); - { - Lisp_Object elt = make_uninit_vector (4); - - ASET (elt, 0, name); - ASET (elt, 1, ccl_prog); - ASET (elt, 2, resolved); - ASET (elt, 3, Qt); - ASET (Vccl_program_table, idx, elt); - } + ASET (Vccl_program_table, idx, + CALLN (Fvector, name, ccl_prog, resolved, Qt)); Fput (name, Qccl_program_idx, make_fixnum (idx)); return make_fixnum (idx); |