diff options
| author | Paul Eggert | 2013-10-15 09:38:36 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-10-15 09:38:36 -0700 |
| commit | 454e2fb9b928cb5d0f09db4e4334570419eb56b3 (patch) | |
| tree | d91d017bf293501e7b6afc7733f7c8f3674bdeb3 /src/data.c | |
| parent | c911772ee8de21bab0b5ba63fac19fc7dc377f45 (diff) | |
| download | emacs-454e2fb9b928cb5d0f09db4e4334570419eb56b3.tar.gz emacs-454e2fb9b928cb5d0f09db4e4334570419eb56b3.zip | |
Disallow bool vector operations on mixed-length operands.
The old behavior left garbage in the result vector sometimes,
and didn't seem to be useful.
* data.c (Qwrong_length_argument): New static var.
(wrong_length_argument): New function.
(bool_vector_binop_driver): Check that args agree in length.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/src/data.c b/src/data.c index dea70ca42d6..9314add11aa 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -41,6 +41,7 @@ Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound; | |||
| 41 | static Lisp_Object Qsubr; | 41 | static Lisp_Object Qsubr; |
| 42 | Lisp_Object Qerror_conditions, Qerror_message, Qtop_level; | 42 | Lisp_Object Qerror_conditions, Qerror_message, Qtop_level; |
| 43 | Lisp_Object Qerror, Quser_error, Qquit, Qargs_out_of_range; | 43 | Lisp_Object Qerror, Quser_error, Qquit, Qargs_out_of_range; |
| 44 | static Lisp_Object Qwrong_length_argument; | ||
| 44 | static Lisp_Object Qwrong_type_argument; | 45 | static Lisp_Object Qwrong_type_argument; |
| 45 | Lisp_Object Qvoid_variable, Qvoid_function; | 46 | Lisp_Object Qvoid_variable, Qvoid_function; |
| 46 | static Lisp_Object Qcyclic_function_indirection; | 47 | static Lisp_Object Qcyclic_function_indirection; |
| @@ -179,6 +180,18 @@ set_blv_valcell (struct Lisp_Buffer_Local_Value *blv, Lisp_Object val) | |||
| 179 | blv->valcell = val; | 180 | blv->valcell = val; |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 183 | static _Noreturn void | ||
| 184 | wrong_length_argument (Lisp_Object a1, Lisp_Object a2, Lisp_Object a3) | ||
| 185 | { | ||
| 186 | Lisp_Object size1 = make_number (bool_vector_size (a1)); | ||
| 187 | Lisp_Object size2 = make_number (bool_vector_size (a2)); | ||
| 188 | if (NILP (a3)) | ||
| 189 | xsignal2 (Qwrong_length_argument, size1, size2); | ||
| 190 | else | ||
| 191 | xsignal3 (Qwrong_length_argument, size1, size2, | ||
| 192 | make_number (bool_vector_size (a3))); | ||
| 193 | } | ||
| 194 | |||
| 182 | Lisp_Object | 195 | Lisp_Object |
| 183 | wrong_type_argument (register Lisp_Object predicate, register Lisp_Object value) | 196 | wrong_type_argument (register Lisp_Object predicate, register Lisp_Object value) |
| 184 | { | 197 | { |
| @@ -3004,7 +3017,9 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3004 | CHECK_BOOL_VECTOR (op1); | 3017 | CHECK_BOOL_VECTOR (op1); |
| 3005 | CHECK_BOOL_VECTOR (op2); | 3018 | CHECK_BOOL_VECTOR (op2); |
| 3006 | 3019 | ||
| 3007 | nr_bits = min (bool_vector_size (op1), bool_vector_size (op2)); | 3020 | nr_bits = bool_vector_size (op1); |
| 3021 | if (bool_vector_size (op2) != nr_bits) | ||
| 3022 | wrong_length_argument (op1, op2, dest); | ||
| 3008 | 3023 | ||
| 3009 | if (NILP (dest)) | 3024 | if (NILP (dest)) |
| 3010 | { | 3025 | { |
| @@ -3014,7 +3029,8 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3014 | else | 3029 | else |
| 3015 | { | 3030 | { |
| 3016 | CHECK_BOOL_VECTOR (dest); | 3031 | CHECK_BOOL_VECTOR (dest); |
| 3017 | nr_bits = min (nr_bits, bool_vector_size (dest)); | 3032 | if (bool_vector_size (dest) != nr_bits) |
| 3033 | wrong_length_argument (op1, op2, dest); | ||
| 3018 | } | 3034 | } |
| 3019 | 3035 | ||
| 3020 | nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD; | 3036 | nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD; |
| @@ -3103,11 +3119,10 @@ bits_word_to_host_endian (bits_word val) | |||
| 3103 | 3119 | ||
| 3104 | DEFUN ("bool-vector-exclusive-or", Fbool_vector_exclusive_or, | 3120 | DEFUN ("bool-vector-exclusive-or", Fbool_vector_exclusive_or, |
| 3105 | Sbool_vector_exclusive_or, 2, 3, 0, | 3121 | Sbool_vector_exclusive_or, 2, 3, 0, |
| 3106 | doc: /* Compute C = A ^ B, bitwise exclusive or. | 3122 | doc: /* Return A ^ B, bitwise exclusive or. |
| 3107 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | 3123 | If optional third argument C is given, store result into C. |
| 3108 | vector in which to store the result. Return the destination vector if | 3124 | A, B, and C must be bool vectors of the same length. |
| 3109 | it changed or nil otherwise. */ | 3125 | Return the destination vector if it changed or nil otherwise. */) |
| 3110 | ) | ||
| 3111 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | 3126 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) |
| 3112 | { | 3127 | { |
| 3113 | return bool_vector_binop_driver (a, b, c, bool_vector_exclusive_or); | 3128 | return bool_vector_binop_driver (a, b, c, bool_vector_exclusive_or); |
| @@ -3115,10 +3130,10 @@ it changed or nil otherwise. */ | |||
| 3115 | 3130 | ||
| 3116 | DEFUN ("bool-vector-union", Fbool_vector_union, | 3131 | DEFUN ("bool-vector-union", Fbool_vector_union, |
| 3117 | Sbool_vector_union, 2, 3, 0, | 3132 | Sbool_vector_union, 2, 3, 0, |
| 3118 | doc: /* Compute C = A | B, bitwise or. | 3133 | doc: /* Return A | B, bitwise or. |
| 3119 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | 3134 | If optional third argument C is given, store result into C. |
| 3120 | vector in which to store the result. Return the destination vector if | 3135 | A, B, and C must be bool vectors of the same length. |
| 3121 | it changed or nil otherwise. */) | 3136 | Return the destination vector if it changed or nil otherwise. */) |
| 3122 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | 3137 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) |
| 3123 | { | 3138 | { |
| 3124 | return bool_vector_binop_driver (a, b, c, bool_vector_union); | 3139 | return bool_vector_binop_driver (a, b, c, bool_vector_union); |
| @@ -3126,10 +3141,10 @@ it changed or nil otherwise. */) | |||
| 3126 | 3141 | ||
| 3127 | DEFUN ("bool-vector-intersection", Fbool_vector_intersection, | 3142 | DEFUN ("bool-vector-intersection", Fbool_vector_intersection, |
| 3128 | Sbool_vector_intersection, 2, 3, 0, | 3143 | Sbool_vector_intersection, 2, 3, 0, |
| 3129 | doc: /* Compute C = A & B, bitwise and. | 3144 | doc: /* Return A & B, bitwise and. |
| 3130 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | 3145 | If optional third argument C is given, store result into C. |
| 3131 | vector in which to store the result. Return the destination vector if | 3146 | A, B, and C must be bool vectors of the same length. |
| 3132 | it changed or nil otherwise. */) | 3147 | Return the destination vector if it changed or nil otherwise. */) |
| 3133 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | 3148 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) |
| 3134 | { | 3149 | { |
| 3135 | return bool_vector_binop_driver (a, b, c, bool_vector_intersection); | 3150 | return bool_vector_binop_driver (a, b, c, bool_vector_intersection); |
| @@ -3137,10 +3152,10 @@ it changed or nil otherwise. */) | |||
| 3137 | 3152 | ||
| 3138 | DEFUN ("bool-vector-set-difference", Fbool_vector_set_difference, | 3153 | DEFUN ("bool-vector-set-difference", Fbool_vector_set_difference, |
| 3139 | Sbool_vector_set_difference, 2, 3, 0, | 3154 | Sbool_vector_set_difference, 2, 3, 0, |
| 3140 | doc: /* Compute C = A &~ B, set difference. | 3155 | doc: /* Return A &~ B, set difference. |
| 3141 | A, B, and C must be bool vectors. If C is nil, allocate a new bool | 3156 | If optional third argument C is given, store result into C. |
| 3142 | vector in which to store the result. Return the destination vector if | 3157 | A, B, and C must be bool vectors of the same length. |
| 3143 | it changed or nil otherwise. */) | 3158 | Return the destination vector if it changed or nil otherwise. */) |
| 3144 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) | 3159 | (Lisp_Object a, Lisp_Object b, Lisp_Object c) |
| 3145 | { | 3160 | { |
| 3146 | return bool_vector_binop_driver (a, b, c, bool_vector_set_difference); | 3161 | return bool_vector_binop_driver (a, b, c, bool_vector_set_difference); |
| @@ -3157,9 +3172,9 @@ DEFUN ("bool-vector-subsetp", Fbool_vector_subsetp, | |||
| 3157 | 3172 | ||
| 3158 | DEFUN ("bool-vector-not", Fbool_vector_not, | 3173 | DEFUN ("bool-vector-not", Fbool_vector_not, |
| 3159 | Sbool_vector_not, 1, 2, 0, | 3174 | Sbool_vector_not, 1, 2, 0, |
| 3160 | doc: /* Compute B = ~A. | 3175 | doc: /* Compute ~A, set complement. |
| 3161 | B must be a bool vector. A must be a bool vector or nil. | 3176 | If optional second argument B is given, store result into B. |
| 3162 | If A is nil, allocate a new bool vector in which to store the result. | 3177 | A and B must be bool vectors of the same length. |
| 3163 | Return the destination vector. */) | 3178 | Return the destination vector. */) |
| 3164 | (Lisp_Object a, Lisp_Object b) | 3179 | (Lisp_Object a, Lisp_Object b) |
| 3165 | { | 3180 | { |
| @@ -3176,7 +3191,8 @@ Return the destination vector. */) | |||
| 3176 | else | 3191 | else |
| 3177 | { | 3192 | { |
| 3178 | CHECK_BOOL_VECTOR (b); | 3193 | CHECK_BOOL_VECTOR (b); |
| 3179 | nr_bits = min (nr_bits, bool_vector_size (b)); | 3194 | if (bool_vector_size (b) != nr_bits) |
| 3195 | wrong_length_argument (a, b, Qnil); | ||
| 3180 | } | 3196 | } |
| 3181 | 3197 | ||
| 3182 | bdata = (bits_word *) XBOOL_VECTOR (b)->data; | 3198 | bdata = (bits_word *) XBOOL_VECTOR (b)->data; |
| @@ -3323,6 +3339,7 @@ syms_of_data (void) | |||
| 3323 | DEFSYM (Qerror, "error"); | 3339 | DEFSYM (Qerror, "error"); |
| 3324 | DEFSYM (Quser_error, "user-error"); | 3340 | DEFSYM (Quser_error, "user-error"); |
| 3325 | DEFSYM (Qquit, "quit"); | 3341 | DEFSYM (Qquit, "quit"); |
| 3342 | DEFSYM (Qwrong_length_argument, "wrong-length-argument"); | ||
| 3326 | DEFSYM (Qwrong_type_argument, "wrong-type-argument"); | 3343 | DEFSYM (Qwrong_type_argument, "wrong-type-argument"); |
| 3327 | DEFSYM (Qargs_out_of_range, "args-out-of-range"); | 3344 | DEFSYM (Qargs_out_of_range, "args-out-of-range"); |
| 3328 | DEFSYM (Qvoid_function, "void-function"); | 3345 | DEFSYM (Qvoid_function, "void-function"); |
| @@ -3397,6 +3414,7 @@ syms_of_data (void) | |||
| 3397 | PUT_ERROR (Qquit, Qnil, "Quit"); | 3414 | PUT_ERROR (Qquit, Qnil, "Quit"); |
| 3398 | 3415 | ||
| 3399 | PUT_ERROR (Quser_error, error_tail, ""); | 3416 | PUT_ERROR (Quser_error, error_tail, ""); |
| 3417 | PUT_ERROR (Qwrong_length_argument, error_tail, "Wrong length argument"); | ||
| 3400 | PUT_ERROR (Qwrong_type_argument, error_tail, "Wrong type argument"); | 3418 | PUT_ERROR (Qwrong_type_argument, error_tail, "Wrong type argument"); |
| 3401 | PUT_ERROR (Qargs_out_of_range, error_tail, "Args out of range"); | 3419 | PUT_ERROR (Qargs_out_of_range, error_tail, "Args out of range"); |
| 3402 | PUT_ERROR (Qvoid_function, error_tail, | 3420 | PUT_ERROR (Qvoid_function, error_tail, |