@@ -209,14 +209,6 @@ static bool gmp_zend_parse_arg_into_mpz(zval *arg, mpz_ptr *destination_mpz_ptr,
209209#define INIT_GMP_RETVAL (gmpnumber ) \
210210 gmp_create(return_value, &gmpnumber)
211211
212- /*
213- * The gmp_*_op functions provide an implementation for several common types
214- * of GMP functions. The gmp_zval_(unary|binary)_*_op functions have to be manually
215- * passed zvals to work on, whereas the gmp_(unary|binary)_*_op macros already
216- * include parameter parsing.
217- */
218- typedef void (* gmp_unary_op_t )(mpz_ptr , mpz_srcptr );
219-
220212#define GMP_FN_NAME (name ) gmp_##name
221213#define GMP_MPZ_FN_NAME (name ) mpz_##name
222214
@@ -243,23 +235,6 @@ typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
243235
244236#define GMP_BINARY_OP_FUNCTION (name ) GMP_BINARY_OP_FUNCTION_EX(GMP_FN_NAME(name), GMP_MPZ_FN_NAME(name))
245237
246- typedef void (* gmp_unary_ui_op_t )(mpz_ptr , gmp_ulong );
247-
248- typedef void (* gmp_binary_op_t )(mpz_ptr , mpz_srcptr , mpz_srcptr );
249-
250- typedef void (* gmp_binary_ui_op_t )(mpz_ptr , mpz_srcptr , gmp_ulong );
251- typedef void (* gmp_binary_op2_t )(mpz_ptr , mpz_ptr , mpz_srcptr , mpz_srcptr );
252- typedef gmp_ulong (* gmp_binary_ui_op2_t )(mpz_ptr , mpz_ptr , mpz_srcptr , gmp_ulong );
253-
254- static inline void gmp_zval_binary_ui_op (zval * return_value , zval * a_arg , zval * b_arg , gmp_binary_op_t gmp_op , gmp_binary_ui_op_t gmp_ui_op , bool check_b_zero , bool is_operator );
255-
256- static void gmp_mpz_tdiv_q_ui (mpz_ptr a , mpz_srcptr b , gmp_ulong c ) {
257- mpz_tdiv_q_ui (a , b , c );
258- }
259- static void gmp_mpz_mod_ui (mpz_ptr a , mpz_srcptr b , gmp_ulong c ) {
260- mpz_mod_ui (a , b , c );
261- }
262-
263238static void gmp_free_object_storage (zend_object * obj ) /* {{{ */
264239{
265240 gmp_object * intern = GET_GMP_OBJECT_FROM_OBJ (obj );
@@ -359,6 +334,39 @@ static zend_object *gmp_clone_obj(zend_object *obj) /* {{{ */
359334}
360335/* }}} */
361336
337+ typedef void (* gmp_binary_op_t )(mpz_ptr , mpz_srcptr , mpz_srcptr );
338+
339+ static zend_result binop_operator_helper (gmp_binary_op_t gmp_op , zval * return_value , zval * op1 , zval * op2 ) {
340+ mpz_ptr gmp_op1 , gmp_op2 , gmp_result ;
341+ if (!gmp_zend_parse_arg_into_mpz_ex (op1 , & gmp_op1 , 1 , true)) {
342+ if (!EG (exception )) {
343+ zend_type_error ("Number must be of type GMP|string|int, %s given" , zend_zval_value_name (op1 ));
344+ }
345+ return FAILURE ;
346+ }
347+ if (!gmp_zend_parse_arg_into_mpz_ex (op2 , & gmp_op2 , 2 , true)) {
348+ if (!EG (exception )) {
349+ zend_type_error ("Number must be of type GMP|string|int, %s given" , zend_zval_value_name (op2 ));
350+ }
351+ return FAILURE ;
352+ }
353+ /* Check special requirements for op2 */
354+ if (gmp_op == mpz_tdiv_q && mpz_cmp_ui (gmp_op2 , 0 ) == 0 ) {
355+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
356+ return FAILURE ;
357+ }
358+ if (gmp_op == mpz_mod && mpz_cmp_ui (gmp_op2 , 0 ) == 0 ) {
359+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
360+ return FAILURE ;
361+ }
362+
363+ gmp_create (return_value , & gmp_result );
364+ gmp_op (gmp_result , gmp_op1 , gmp_op2 );
365+ return SUCCESS ;
366+ }
367+
368+ typedef void (* gmp_binary_ui_op_t )(mpz_ptr , mpz_srcptr , gmp_ulong );
369+
362370static zend_result shift_operator_helper (gmp_binary_ui_op_t op , zval * return_value , zval * op1 , zval * op2 , uint8_t opcode ) {
363371 zend_long shift = 0 ;
364372
@@ -444,41 +452,32 @@ typeof_op_failure: ;
444452 return FAILURE ;
445453}
446454
447- #define DO_BINARY_UI_OP_EX (op , uop , check_b_zero ) \
448- gmp_zval_binary_ui_op( \
449- result, op1, op2, op, uop, check_b_zero, /* is_operator */ true ); \
450- if (UNEXPECTED(EG(exception))) { return FAILURE; } \
451- return SUCCESS;
452-
453- #define DO_BINARY_UI_OP (op ) DO_BINARY_UI_OP_EX(op, op ## _ui, 0)
454- #define DO_BINARY_OP (op ) DO_BINARY_UI_OP_EX(op, NULL, 0)
455-
456455static zend_result gmp_do_operation_ex (uint8_t opcode , zval * result , zval * op1 , zval * op2 ) /* {{{ */
457456{
458457 mpz_ptr gmp_op1 , gmp_result ;
459458 switch (opcode ) {
460459 case ZEND_ADD :
461- DO_BINARY_UI_OP (mpz_add );
460+ return binop_operator_helper (mpz_add , result , op1 , op2 );
462461 case ZEND_SUB :
463- DO_BINARY_UI_OP (mpz_sub );
462+ return binop_operator_helper (mpz_sub , result , op1 , op2 );
464463 case ZEND_MUL :
465- DO_BINARY_UI_OP (mpz_mul );
464+ return binop_operator_helper (mpz_mul , result , op1 , op2 );
466465 case ZEND_POW :
467466 return shift_operator_helper (mpz_pow_ui , result , op1 , op2 , opcode );
468467 case ZEND_DIV :
469- DO_BINARY_UI_OP_EX (mpz_tdiv_q , gmp_mpz_tdiv_q_ui , 1 );
468+ return binop_operator_helper (mpz_tdiv_q , result , op1 , op2 );
470469 case ZEND_MOD :
471- DO_BINARY_UI_OP_EX (mpz_mod , gmp_mpz_mod_ui , 1 );
470+ return binop_operator_helper (mpz_mod , result , op1 , op2 );
472471 case ZEND_SL :
473472 return shift_operator_helper (mpz_mul_2exp , result , op1 , op2 , opcode );
474473 case ZEND_SR :
475474 return shift_operator_helper (mpz_fdiv_q_2exp , result , op1 , op2 , opcode );
476475 case ZEND_BW_OR :
477- DO_BINARY_OP (mpz_ior );
476+ return binop_operator_helper (mpz_ior , result , op1 , op2 );
478477 case ZEND_BW_AND :
479- DO_BINARY_OP (mpz_and );
478+ return binop_operator_helper (mpz_and , result , op1 , op2 );
480479 case ZEND_BW_XOR :
481- DO_BINARY_OP (mpz_xor );
480+ return binop_operator_helper (mpz_xor , result , op1 , op2 );
482481 case ZEND_BW_NOT : {
483482 if (!gmp_zend_parse_arg_into_mpz_ex (op1 , & gmp_op1 , 1 , false)) {
484483 return FAILURE ;
@@ -808,56 +807,6 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operat
808807}
809808/* }}} */
810809
811- /* {{{ gmp_zval_binary_ui_op
812- Execute GMP binary operation.
813- */
814- static inline void gmp_zval_binary_ui_op (zval * return_value , zval * a_arg , zval * b_arg , gmp_binary_op_t gmp_op , gmp_binary_ui_op_t gmp_ui_op , bool check_b_zero , bool is_operator )
815- {
816- mpz_ptr gmpnum_a , gmpnum_b , gmpnum_result ;
817- gmp_temp_t temp_a , temp_b ;
818-
819- FETCH_GMP_ZVAL (gmpnum_a , a_arg , temp_a , is_operator ? 0 : 1 );
820-
821- if (gmp_ui_op && Z_TYPE_P (b_arg ) == IS_LONG && Z_LVAL_P (b_arg ) >= 0 ) {
822- gmpnum_b = NULL ;
823- temp_b .is_used = 0 ;
824- } else {
825- FETCH_GMP_ZVAL_DEP (gmpnum_b , b_arg , temp_b , temp_a , is_operator ? 0 : 2 );
826- }
827-
828- if (check_b_zero ) {
829- int b_is_zero = 0 ;
830- if (!gmpnum_b ) {
831- b_is_zero = (Z_LVAL_P (b_arg ) == 0 );
832- } else {
833- b_is_zero = !mpz_cmp_ui (gmpnum_b , 0 );
834- }
835-
836- if (b_is_zero ) {
837- if ((gmp_binary_op_t ) mpz_mod == gmp_op ) {
838- zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
839- } else {
840- zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
841- }
842- FREE_GMP_TEMP (temp_a );
843- FREE_GMP_TEMP (temp_b );
844- RETURN_THROWS ();
845- }
846- }
847-
848- INIT_GMP_RETVAL (gmpnum_result );
849-
850- if (!gmpnum_b ) {
851- gmp_ui_op (gmpnum_result , gmpnum_a , (gmp_ulong ) Z_LVAL_P (b_arg ));
852- } else {
853- gmp_op (gmpnum_result , gmpnum_a , gmpnum_b );
854- }
855-
856- FREE_GMP_TEMP (temp_a );
857- FREE_GMP_TEMP (temp_b );
858- }
859- /* }}} */
860-
861810static bool gmp_verify_base (zend_long base , uint32_t arg_num )
862811{
863812 if (base && (base < 2 || base > GMP_MAX_BASE )) {
0 commit comments