@@ -213,14 +213,6 @@ static bool gmp_zend_parse_arg_into_mpz(zval *arg, mpz_ptr *destination_mpz_ptr,
213213#define INIT_GMP_RETVAL (gmpnumber ) \
214214 gmp_create(return_value, &gmpnumber)
215215
216- /*
217- * The gmp_*_op functions provide an implementation for several common types
218- * of GMP functions. The gmp_zval_(unary|binary)_*_op functions have to be manually
219- * passed zvals to work on, whereas the gmp_(unary|binary)_*_op macros already
220- * include parameter parsing.
221- */
222- typedef void (* gmp_unary_op_t )(mpz_ptr , mpz_srcptr );
223-
224216#define GMP_FN_NAME (name ) gmp_##name
225217#define GMP_MPZ_FN_NAME (name ) mpz_##name
226218
@@ -247,23 +239,6 @@ typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
247239
248240#define GMP_BINARY_OP_FUNCTION (name ) GMP_BINARY_OP_FUNCTION_EX(GMP_FN_NAME(name), GMP_MPZ_FN_NAME(name))
249241
250- typedef void (* gmp_unary_ui_op_t )(mpz_ptr , gmp_ulong );
251-
252- typedef void (* gmp_binary_op_t )(mpz_ptr , mpz_srcptr , mpz_srcptr );
253-
254- typedef void (* gmp_binary_ui_op_t )(mpz_ptr , mpz_srcptr , gmp_ulong );
255- typedef void (* gmp_binary_op2_t )(mpz_ptr , mpz_ptr , mpz_srcptr , mpz_srcptr );
256- typedef gmp_ulong (* gmp_binary_ui_op2_t )(mpz_ptr , mpz_ptr , mpz_srcptr , gmp_ulong );
257-
258- 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 );
259-
260- static void gmp_mpz_tdiv_q_ui (mpz_ptr a , mpz_srcptr b , gmp_ulong c ) {
261- mpz_tdiv_q_ui (a , b , c );
262- }
263- static void gmp_mpz_mod_ui (mpz_ptr a , mpz_srcptr b , gmp_ulong c ) {
264- mpz_mod_ui (a , b , c );
265- }
266-
267242static void gmp_free_object_storage (zend_object * obj ) /* {{{ */
268243{
269244 gmp_object * intern = GET_GMP_OBJECT_FROM_OBJ (obj );
@@ -363,6 +338,39 @@ static zend_object *gmp_clone_obj(zend_object *obj) /* {{{ */
363338}
364339/* }}} */
365340
341+ typedef void (* gmp_binary_op_t )(mpz_ptr , mpz_srcptr , mpz_srcptr );
342+
343+ static zend_result binop_operator_helper (gmp_binary_op_t gmp_op , zval * return_value , zval * op1 , zval * op2 ) {
344+ mpz_ptr gmp_op1 , gmp_op2 , gmp_result ;
345+ if (!gmp_zend_parse_arg_into_mpz_ex (op1 , & gmp_op1 , 1 , true)) {
346+ if (!EG (exception )) {
347+ zend_type_error ("Number must be of type GMP|string|int, %s given" , zend_zval_value_name (op1 ));
348+ }
349+ return FAILURE ;
350+ }
351+ if (!gmp_zend_parse_arg_into_mpz_ex (op2 , & gmp_op2 , 2 , true)) {
352+ if (!EG (exception )) {
353+ zend_type_error ("Number must be of type GMP|string|int, %s given" , zend_zval_value_name (op2 ));
354+ }
355+ return FAILURE ;
356+ }
357+ /* Check special requirements for op2 */
358+ if (gmp_op == mpz_tdiv_q && mpz_cmp_ui (gmp_op2 , 0 ) == 0 ) {
359+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
360+ return FAILURE ;
361+ }
362+ if (gmp_op == mpz_mod && mpz_cmp_ui (gmp_op2 , 0 ) == 0 ) {
363+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
364+ return FAILURE ;
365+ }
366+
367+ gmp_create (return_value , & gmp_result );
368+ gmp_op (gmp_result , gmp_op1 , gmp_op2 );
369+ return SUCCESS ;
370+ }
371+
372+ typedef void (* gmp_binary_ui_op_t )(mpz_ptr , mpz_srcptr , gmp_ulong );
373+
366374static zend_result shift_operator_helper (gmp_binary_ui_op_t op , zval * return_value , zval * op1 , zval * op2 , uint8_t opcode ) {
367375 zend_long shift = 0 ;
368376
@@ -448,41 +456,32 @@ typeof_op_failure: ;
448456 return FAILURE ;
449457}
450458
451- #define DO_BINARY_UI_OP_EX (op , uop , check_b_zero ) \
452- gmp_zval_binary_ui_op( \
453- result, op1, op2, op, uop, check_b_zero, /* is_operator */ true ); \
454- if (UNEXPECTED(EG(exception))) { return FAILURE; } \
455- return SUCCESS;
456-
457- #define DO_BINARY_UI_OP (op ) DO_BINARY_UI_OP_EX(op, op ## _ui, 0)
458- #define DO_BINARY_OP (op ) DO_BINARY_UI_OP_EX(op, NULL, 0)
459-
460459static zend_result gmp_do_operation_ex (uint8_t opcode , zval * result , zval * op1 , zval * op2 ) /* {{{ */
461460{
462461 mpz_ptr gmp_op1 , gmp_result ;
463462 switch (opcode ) {
464463 case ZEND_ADD :
465- DO_BINARY_UI_OP (mpz_add );
464+ return binop_operator_helper (mpz_add , result , op1 , op2 );
466465 case ZEND_SUB :
467- DO_BINARY_UI_OP (mpz_sub );
466+ return binop_operator_helper (mpz_sub , result , op1 , op2 );
468467 case ZEND_MUL :
469- DO_BINARY_UI_OP (mpz_mul );
468+ return binop_operator_helper (mpz_mul , result , op1 , op2 );
470469 case ZEND_POW :
471470 return shift_operator_helper (mpz_pow_ui , result , op1 , op2 , opcode );
472471 case ZEND_DIV :
473- DO_BINARY_UI_OP_EX (mpz_tdiv_q , gmp_mpz_tdiv_q_ui , 1 );
472+ return binop_operator_helper (mpz_tdiv_q , result , op1 , op2 );
474473 case ZEND_MOD :
475- DO_BINARY_UI_OP_EX (mpz_mod , gmp_mpz_mod_ui , 1 );
474+ return binop_operator_helper (mpz_mod , result , op1 , op2 );
476475 case ZEND_SL :
477476 return shift_operator_helper (mpz_mul_2exp , result , op1 , op2 , opcode );
478477 case ZEND_SR :
479478 return shift_operator_helper (mpz_fdiv_q_2exp , result , op1 , op2 , opcode );
480479 case ZEND_BW_OR :
481- DO_BINARY_OP (mpz_ior );
480+ return binop_operator_helper (mpz_ior , result , op1 , op2 );
482481 case ZEND_BW_AND :
483- DO_BINARY_OP (mpz_and );
482+ return binop_operator_helper (mpz_and , result , op1 , op2 );
484483 case ZEND_BW_XOR :
485- DO_BINARY_OP (mpz_xor );
484+ return binop_operator_helper (mpz_xor , result , op1 , op2 );
486485 case ZEND_BW_NOT : {
487486 if (!gmp_zend_parse_arg_into_mpz_ex (op1 , & gmp_op1 , 1 , false)) {
488487 return FAILURE ;
@@ -812,56 +811,6 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operat
812811}
813812/* }}} */
814813
815- /* {{{ gmp_zval_binary_ui_op
816- Execute GMP binary operation.
817- */
818- 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 )
819- {
820- mpz_ptr gmpnum_a , gmpnum_b , gmpnum_result ;
821- gmp_temp_t temp_a , temp_b ;
822-
823- FETCH_GMP_ZVAL (gmpnum_a , a_arg , temp_a , is_operator ? 0 : 1 );
824-
825- if (gmp_ui_op && Z_TYPE_P (b_arg ) == IS_LONG && Z_LVAL_P (b_arg ) >= 0 ) {
826- gmpnum_b = NULL ;
827- temp_b .is_used = 0 ;
828- } else {
829- FETCH_GMP_ZVAL_DEP (gmpnum_b , b_arg , temp_b , temp_a , is_operator ? 0 : 2 );
830- }
831-
832- if (check_b_zero ) {
833- int b_is_zero = 0 ;
834- if (!gmpnum_b ) {
835- b_is_zero = (Z_LVAL_P (b_arg ) == 0 );
836- } else {
837- b_is_zero = !mpz_cmp_ui (gmpnum_b , 0 );
838- }
839-
840- if (b_is_zero ) {
841- if ((gmp_binary_op_t ) mpz_mod == gmp_op ) {
842- zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
843- } else {
844- zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
845- }
846- FREE_GMP_TEMP (temp_a );
847- FREE_GMP_TEMP (temp_b );
848- RETURN_THROWS ();
849- }
850- }
851-
852- INIT_GMP_RETVAL (gmpnum_result );
853-
854- if (!gmpnum_b ) {
855- gmp_ui_op (gmpnum_result , gmpnum_a , (gmp_ulong ) Z_LVAL_P (b_arg ));
856- } else {
857- gmp_op (gmpnum_result , gmpnum_a , gmpnum_b );
858- }
859-
860- FREE_GMP_TEMP (temp_a );
861- FREE_GMP_TEMP (temp_b );
862- }
863- /* }}} */
864-
865814static bool gmp_verify_base (zend_long base , uint32_t arg_num )
866815{
867816 if (base && (base < 2 || base > GMP_MAX_BASE )) {
0 commit comments