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