aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorPaul Eggert2013-10-15 09:38:36 -0700
committerPaul Eggert2013-10-15 09:38:36 -0700
commit454e2fb9b928cb5d0f09db4e4334570419eb56b3 (patch)
treed91d017bf293501e7b6afc7733f7c8f3674bdeb3 /src/data.c
parentc911772ee8de21bab0b5ba63fac19fc7dc377f45 (diff)
downloademacs-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.c64
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;
41static Lisp_Object Qsubr; 41static Lisp_Object Qsubr;
42Lisp_Object Qerror_conditions, Qerror_message, Qtop_level; 42Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
43Lisp_Object Qerror, Quser_error, Qquit, Qargs_out_of_range; 43Lisp_Object Qerror, Quser_error, Qquit, Qargs_out_of_range;
44static Lisp_Object Qwrong_length_argument;
44static Lisp_Object Qwrong_type_argument; 45static Lisp_Object Qwrong_type_argument;
45Lisp_Object Qvoid_variable, Qvoid_function; 46Lisp_Object Qvoid_variable, Qvoid_function;
46static Lisp_Object Qcyclic_function_indirection; 47static 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
183static _Noreturn void
184wrong_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
182Lisp_Object 195Lisp_Object
183wrong_type_argument (register Lisp_Object predicate, register Lisp_Object value) 196wrong_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
3104DEFUN ("bool-vector-exclusive-or", Fbool_vector_exclusive_or, 3120DEFUN ("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.
3107A, B, and C must be bool vectors. If C is nil, allocate a new bool 3123If optional third argument C is given, store result into C.
3108vector in which to store the result. Return the destination vector if 3124A, B, and C must be bool vectors of the same length.
3109it changed or nil otherwise. */ 3125Return 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
3116DEFUN ("bool-vector-union", Fbool_vector_union, 3131DEFUN ("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.
3119A, B, and C must be bool vectors. If C is nil, allocate a new bool 3134If optional third argument C is given, store result into C.
3120vector in which to store the result. Return the destination vector if 3135A, B, and C must be bool vectors of the same length.
3121it changed or nil otherwise. */) 3136Return 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
3127DEFUN ("bool-vector-intersection", Fbool_vector_intersection, 3142DEFUN ("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.
3130A, B, and C must be bool vectors. If C is nil, allocate a new bool 3145If optional third argument C is given, store result into C.
3131vector in which to store the result. Return the destination vector if 3146A, B, and C must be bool vectors of the same length.
3132it changed or nil otherwise. */) 3147Return 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
3138DEFUN ("bool-vector-set-difference", Fbool_vector_set_difference, 3153DEFUN ("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.
3141A, B, and C must be bool vectors. If C is nil, allocate a new bool 3156If optional third argument C is given, store result into C.
3142vector in which to store the result. Return the destination vector if 3157A, B, and C must be bool vectors of the same length.
3143it changed or nil otherwise. */) 3158Return 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
3158DEFUN ("bool-vector-not", Fbool_vector_not, 3173DEFUN ("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.
3161B must be a bool vector. A must be a bool vector or nil. 3176If optional second argument B is given, store result into B.
3162If A is nil, allocate a new bool vector in which to store the result. 3177A and B must be bool vectors of the same length.
3163Return the destination vector. */) 3178Return 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,