@@ -213,14 +213,6 @@ static bool gmp_zend_parse_arg_into_mpz(zval *arg, mpz_ptr *destination_mpz_ptr,
213
213
#define INIT_GMP_RETVAL (gmpnumber ) \
214
214
gmp_create(return_value, &gmpnumber)
215
215
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
-
224
216
#define GMP_FN_NAME (name ) gmp_##name
225
217
#define GMP_MPZ_FN_NAME (name ) mpz_##name
226
218
@@ -247,23 +239,6 @@ typedef void (*gmp_unary_op_t)(mpz_ptr, mpz_srcptr);
247
239
248
240
#define GMP_BINARY_OP_FUNCTION (name ) GMP_BINARY_OP_FUNCTION_EX(GMP_FN_NAME(name), GMP_MPZ_FN_NAME(name))
249
241
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
-
267
242
static void gmp_free_object_storage (zend_object * obj ) /* {{{ */
268
243
{
269
244
gmp_object * intern = GET_GMP_OBJECT_FROM_OBJ (obj );
@@ -363,6 +338,39 @@ static zend_object *gmp_clone_obj(zend_object *obj) /* {{{ */
363
338
}
364
339
/* }}} */
365
340
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
+
366
374
static zend_result shift_operator_helper (gmp_binary_ui_op_t op , zval * return_value , zval * op1 , zval * op2 , uint8_t opcode ) {
367
375
zend_long shift = 0 ;
368
376
@@ -448,41 +456,32 @@ typeof_op_failure: ;
448
456
return FAILURE ;
449
457
}
450
458
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
-
460
459
static zend_result gmp_do_operation_ex (uint8_t opcode , zval * result , zval * op1 , zval * op2 ) /* {{{ */
461
460
{
462
461
mpz_ptr gmp_op1 , gmp_result ;
463
462
switch (opcode ) {
464
463
case ZEND_ADD :
465
- DO_BINARY_UI_OP (mpz_add );
464
+ return binop_operator_helper (mpz_add , result , op1 , op2 );
466
465
case ZEND_SUB :
467
- DO_BINARY_UI_OP (mpz_sub );
466
+ return binop_operator_helper (mpz_sub , result , op1 , op2 );
468
467
case ZEND_MUL :
469
- DO_BINARY_UI_OP (mpz_mul );
468
+ return binop_operator_helper (mpz_mul , result , op1 , op2 );
470
469
case ZEND_POW :
471
470
return shift_operator_helper (mpz_pow_ui , result , op1 , op2 , opcode );
472
471
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 );
474
473
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 );
476
475
case ZEND_SL :
477
476
return shift_operator_helper (mpz_mul_2exp , result , op1 , op2 , opcode );
478
477
case ZEND_SR :
479
478
return shift_operator_helper (mpz_fdiv_q_2exp , result , op1 , op2 , opcode );
480
479
case ZEND_BW_OR :
481
- DO_BINARY_OP (mpz_ior );
480
+ return binop_operator_helper (mpz_ior , result , op1 , op2 );
482
481
case ZEND_BW_AND :
483
- DO_BINARY_OP (mpz_and );
482
+ return binop_operator_helper (mpz_and , result , op1 , op2 );
484
483
case ZEND_BW_XOR :
485
- DO_BINARY_OP (mpz_xor );
484
+ return binop_operator_helper (mpz_xor , result , op1 , op2 );
486
485
case ZEND_BW_NOT : {
487
486
if (!gmp_zend_parse_arg_into_mpz_ex (op1 , & gmp_op1 , 1 , false)) {
488
487
return FAILURE ;
@@ -812,56 +811,6 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operat
812
811
}
813
812
/* }}} */
814
813
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
-
865
814
static bool gmp_verify_base (zend_long base , uint32_t arg_num )
866
815
{
867
816
if (base && (base < 2 || base > GMP_MAX_BASE )) {
0 commit comments