From: Nikita Popov Date: Tue, 6 May 2014 16:44:28 +0000 (+0200) Subject: Port ext/gmp (one failure) X-Git-Tag: POST_PHPNG_MERGE~397 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c5b5d7201134afd624d7aec19cedb669c9cf077;p=php Port ext/gmp (one failure) --- diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index cd50896cc7..df7c912938 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -191,8 +191,8 @@ zend_class_entry *gmp_ce; static zend_object_handlers gmp_object_handlers; typedef struct _gmp_object { - zend_object std; mpz_t num; + zend_object std; } gmp_object; typedef struct _gmp_temp { @@ -218,8 +218,13 @@ typedef struct _gmp_temp { #define IS_GMP(zval) \ (Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), gmp_ce TSRMLS_CC)) +#define GET_GMP_OBJECT_FROM_OBJ(obj) \ + ((gmp_object *) ((char *) (obj) - XtOffsetOf(gmp_object, std))) +#define GET_GMP_OBJECT_FROM_ZVAL(zv) \ + GET_GMP_OBJECT_FROM_OBJ(Z_OBJ_P(zv)) + #define GET_GMP_FROM_ZVAL(zval) \ - (((gmp_object *) zend_object_store_get_object((zval) TSRMLS_CC))->num) + GET_GMP_OBJECT_FROM_OBJ(Z_OBJ_P(zval))->num /* The FETCH_GMP_ZVAL_* family of macros is used to fetch a gmp number * (mpz_ptr) from a zval. If the zval is not a GMP instance, then we @@ -291,7 +296,7 @@ if (IS_GMP(zval)) { \ } #define INIT_GMP_RETVAL(gmpnumber) \ - gmp_create_ex(return_value, &gmpnumber TSRMLS_CC) + gmp_create(return_value, &gmpnumber TSRMLS_CC) static void gmp_strval(zval *result, mpz_t gmpnum, long base); static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC); @@ -356,70 +361,41 @@ static void gmp_efree(void *ptr, size_t size) } /* }}} */ -static inline long gmp_get_long(zval *zv) /* {{{ */ +static void gmp_free_object_storage(zend_object *obj TSRMLS_DC) /* {{{ */ { - if (Z_TYPE_P(zv) == IS_LONG) { - return Z_LVAL_P(zv); - } else { - zval tmp_zv; - MAKE_COPY_ZVAL(&zv, &tmp_zv); - convert_to_long(&tmp_zv); - return Z_LVAL(tmp_zv); - } -} -/* }}} */ + gmp_object *intern = GET_GMP_OBJECT_FROM_OBJ(obj); -static void gmp_free_object_storage(gmp_object *intern TSRMLS_DC) /* {{{ */ -{ mpz_clear(intern->num); - zend_object_std_dtor(&intern->std TSRMLS_CC); - efree(intern); } /* }}} */ -static inline zend_object_value gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ +static inline zend_object *gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ { - zend_object_value retval; - gmp_object *intern = emalloc(sizeof(gmp_object)); + gmp_object *intern = emalloc(sizeof(gmp_object) + + sizeof(zval) * (ce->default_properties_count - 1)); zend_object_std_init(&intern->std, ce TSRMLS_CC); object_properties_init(&intern->std, ce); mpz_init(intern->num); *gmpnum_target = intern->num; + intern->std.handlers = &gmp_object_handlers; - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, - (zend_objects_free_object_storage_t) gmp_free_object_storage, - NULL TSRMLS_CC - ); - retval.handlers = &gmp_object_handlers; - - return retval; + return &intern->std; } /* }}} */ -static zend_object_value gmp_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */ +static zend_object *gmp_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */ { mpz_ptr gmpnum_dummy; return gmp_create_object_ex(ce, &gmpnum_dummy TSRMLS_CC); } /* }}} */ -static inline void gmp_create_ex(zval *target, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ +static inline void gmp_create(zval *target, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ { - Z_TYPE_P(target) = IS_OBJECT; - Z_OBJVAL_P(target) = gmp_create_object_ex(gmp_ce, gmpnum_target TSRMLS_CC); -} -/* }}} */ - -static zval *gmp_create(mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */ -{ - zval *obj; - MAKE_STD_ZVAL(obj); - gmp_create_ex(obj, gmpnum_target TSRMLS_CC); - return obj; + ZVAL_OBJ(target, gmp_create_object_ex(gmp_ce, gmpnum_target TSRMLS_CC)); } /* }}} */ @@ -429,17 +405,14 @@ static int gmp_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* switch (type) { case IS_STRING: gmpnum = GET_GMP_FROM_ZVAL(readobj); - INIT_PZVAL(writeobj); gmp_strval(writeobj, gmpnum, 10); return SUCCESS; case IS_LONG: gmpnum = GET_GMP_FROM_ZVAL(readobj); - INIT_PZVAL(writeobj); ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); return SUCCESS; case IS_DOUBLE: gmpnum = GET_GMP_FROM_ZVAL(readobj); - INIT_PZVAL(writeobj); ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum)); return SUCCESS; default: @@ -452,50 +425,37 @@ static HashTable *gmp_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ * { HashTable *ht, *props = zend_std_get_properties(obj TSRMLS_CC); mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(obj); - zval *zv; + zval zv; *is_temp = 1; ALLOC_HASHTABLE(ht); ZEND_INIT_SYMTABLE_EX(ht, zend_hash_num_elements(props) + 1, 0); - zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref); - MAKE_STD_ZVAL(zv); - gmp_strval(zv, gmpnum, 10); - zend_hash_update(ht, "num", sizeof("num"), &zv, sizeof(zval *), NULL); + gmp_strval(&zv, gmpnum, 10); + zend_hash_str_update(ht, "num", sizeof("num")-1, &zv); return ht; } /* }}} */ -static zend_object_value gmp_clone_obj(zval *obj TSRMLS_DC) /* {{{ */ +static zend_object *gmp_clone_obj(zval *obj TSRMLS_DC) /* {{{ */ { - gmp_object *old_object = zend_object_store_get_object(obj TSRMLS_CC); - zend_object_value new_object_val = gmp_create_object(Z_OBJCE_P(obj) TSRMLS_CC); - gmp_object *new_object = zend_object_store_get_object_by_handle( - new_object_val.handle TSRMLS_CC - ); + gmp_object *old_object = GET_GMP_OBJECT_FROM_ZVAL(obj); + gmp_object *new_object = GET_GMP_OBJECT_FROM_OBJ(gmp_create_object(Z_OBJCE_P(obj) TSRMLS_CC)); - zend_objects_clone_members( - &new_object->std, new_object_val, - &old_object->std, Z_OBJ_HANDLE_P(obj) TSRMLS_CC - ); + zend_objects_clone_members( &new_object->std, &old_object->std TSRMLS_CC); mpz_set(new_object->num, old_object->num); - return new_object_val; + return &new_object->std; } /* }}} */ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2 TSRMLS_DC) { - zval op2_copy; - if (Z_TYPE_P(op2) != IS_LONG) { - op2_copy = *op2; - zval_copy_ctor(&op2_copy); - convert_to_long(&op2_copy); - op2 = &op2_copy; - } + long shift = zval_get_long(op2); - if (Z_LVAL_P(op2) < 0) { + if (shift < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Shift cannot be negative"); RETVAL_FALSE; } else { @@ -504,7 +464,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva FETCH_GMP_ZVAL(gmpnum_op, op1, temp); INIT_GMP_RETVAL(gmpnum_result); - op(gmpnum_result, gmpnum_op, (unsigned long) Z_LVAL_P(op2)); + op(gmpnum_result, gmpnum_op, (unsigned long) shift); FREE_GMP_TEMP(temp); } } @@ -563,7 +523,7 @@ static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op static int gmp_compare(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { gmp_cmp(result, op1, op2 TSRMLS_CC); - if (Z_TYPE_P(result) == IS_BOOL) { + if (Z_TYPE_P(result) == IS_FALSE) { ZVAL_LONG(result, 1); } return SUCCESS; @@ -574,64 +534,63 @@ static int gmp_serialize(zval *object, unsigned char **buffer, zend_uint *buf_le { mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(object); smart_str buf = {0}; - zval zv, *zv_ptr = &zv; + zval zv; php_serialize_data_t serialize_data = (php_serialize_data_t) data; + zend_array tmp_arr; PHP_VAR_SERIALIZE_INIT(serialize_data); - INIT_PZVAL(zv_ptr); - gmp_strval(zv_ptr, gmpnum, 10); - php_var_serialize(&buf, &zv_ptr, &serialize_data TSRMLS_CC); - zval_dtor(zv_ptr); + gmp_strval(&zv, gmpnum, 10); + php_var_serialize(&buf, &zv, &serialize_data TSRMLS_CC); + zval_dtor(&zv); - Z_ARRVAL_P(zv_ptr) = zend_std_get_properties(object TSRMLS_CC); - Z_TYPE_P(zv_ptr) = IS_ARRAY; - php_var_serialize(&buf, &zv_ptr, &serialize_data TSRMLS_CC); + ZVAL_ARR(&zv, &tmp_arr); + tmp_arr.ht = *zend_std_get_properties(object TSRMLS_CC); + php_var_serialize(&buf, &zv, &serialize_data TSRMLS_CC); PHP_VAR_SERIALIZE_DESTROY(serialize_data); - *buffer = (unsigned char *) buf.c; - *buf_len = buf.len; + *buffer = (unsigned char *) estrndup(buf.s->val, buf.s->len); + *buf_len = buf.s->len; + STR_RELEASE(buf.s); return SUCCESS; } /* }}} */ -static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */ +static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */ { mpz_ptr gmpnum; const unsigned char *p, *max; - zval zv, *zv_ptr = &zv; + zval zv; int retval = FAILURE; php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); - gmp_create_ex(*object, &gmpnum TSRMLS_CC); + gmp_create(object, &gmpnum TSRMLS_CC); p = buf; max = buf + buf_len; - INIT_ZVAL(zv); - if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) - || Z_TYPE_P(zv_ptr) != IS_STRING - || convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE + if (!php_var_unserialize(&zv, &p, max, &unserialize_data TSRMLS_CC) + || Z_TYPE(zv) != IS_STRING + || convert_to_gmp(gmpnum, &zv, 10 TSRMLS_CC) == FAILURE ) { zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC); goto exit; } zval_dtor(&zv); - INIT_ZVAL(zv); - if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) - || Z_TYPE_P(zv_ptr) != IS_ARRAY + if (!php_var_unserialize(&zv, &p, max, &unserialize_data TSRMLS_CC) + || Z_TYPE(zv) != IS_ARRAY ) { zend_throw_exception(NULL, "Could not unserialize properties", 0 TSRMLS_CC); goto exit; } - if (zend_hash_num_elements(Z_ARRVAL_P(zv_ptr)) != 0) { + if (zend_hash_num_elements(Z_ARRVAL(zv)) != 0) { zend_hash_copy( - zend_std_get_properties(*object TSRMLS_CC), Z_ARRVAL_P(zv_ptr), - (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *) + zend_std_get_properties(object TSRMLS_CC), Z_ARRVAL(zv), + (copy_ctor_func_t) zval_add_ref ); } @@ -663,6 +622,8 @@ ZEND_MINIT_FUNCTION(gmp) gmp_ce->unserialize = gmp_unserialize; memcpy(&gmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + gmp_object_handlers.offset = XtOffsetOf(gmp_object, std); + gmp_object_handlers.free_obj = gmp_free_object_storage; gmp_object_handlers.cast_object = gmp_cast_object; gmp_object_handlers.get_debug_info = gmp_get_debug_info; gmp_object_handlers.clone_obj = gmp_clone_obj; @@ -718,8 +679,9 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC) { switch (Z_TYPE_P(val)) { case IS_LONG: - case IS_BOOL: { - mpz_set_si(gmpnumber, gmp_get_long(val)); + case IS_FALSE: + case IS_TRUE: { + mpz_set_si(gmpnumber, zval_get_long(val)); return SUCCESS; } case IS_STRING: { @@ -759,15 +721,15 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC) static void gmp_strval(zval *result, mpz_t gmpnum, long base) /* {{{ */ { int num_len; - char *out_string; + zend_string *str; num_len = mpz_sizeinbase(gmpnum, abs(base)); if (mpz_sgn(gmpnum) < 0) { num_len++; } - out_string = emalloc(num_len + 1); - mpz_get_str(out_string, base, gmpnum); + str = STR_ALLOC(num_len, 0); + mpz_get_str(str->val, base, gmpnum); /* * From GMP documentation for mpz_sizeinbase(): @@ -777,13 +739,13 @@ static void gmp_strval(zval *result, mpz_t gmpnum, long base) /* {{{ */ * So let's check to see if we already have a \0 byte... */ - if (out_string[num_len - 1] == '\0') { - num_len--; + if (str->val[str->len - 1] == '\0') { + str->len--; } else { - out_string[num_len] = '\0'; + str->val[str->len] = '\0'; } - ZVAL_STRINGL(result, out_string, num_len, 0); + ZVAL_STR(result, str); } /* }}} */ @@ -871,6 +833,7 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result1, gmpnum_result2; int use_ui = 0; gmp_temp_t temp_a, temp_b; + zval result1, result2; FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); @@ -898,9 +861,12 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval } } + gmp_create(&result1, &gmpnum_result1 TSRMLS_CC); + gmp_create(&result2, &gmpnum_result2 TSRMLS_CC); + array_init(return_value); - add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC)); - add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC)); + add_next_index_zval(return_value, &result1); + add_next_index_zval(return_value, &result2); if (use_ui) { gmp_ui_op(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) Z_LVAL_P(b_arg)); @@ -952,7 +918,7 @@ static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_una mpz_ptr gmpnum_result; INIT_GMP_RETVAL(gmpnum_result); - gmp_op(gmpnum_result, gmp_get_long(a_arg)); + gmp_op(gmpnum_result, zval_get_long(a_arg)); } /* }}} */ @@ -1063,7 +1029,7 @@ ZEND_FUNCTION(gmp_intval) if (IS_GMP(gmpnumber_arg)) { RETVAL_LONG(mpz_get_si(GET_GMP_FROM_ZVAL(gmpnumber_arg))); } else { - RETVAL_LONG(gmp_get_long(gmpnumber_arg)); + RETVAL_LONG(zval_get_long(gmpnumber_arg)); } } /* }}} */ @@ -1259,7 +1225,7 @@ ZEND_FUNCTION(gmp_fact) RETURN_FALSE; } } else { - if (gmp_get_long(a_arg) < 0) { + if (zval_get_long(a_arg) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0"); RETURN_FALSE; } @@ -1382,6 +1348,7 @@ ZEND_FUNCTION(gmp_sqrtrem) zval *a_arg; mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2; gmp_temp_t temp_a; + zval result1, result2; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){ return; @@ -1395,9 +1362,12 @@ ZEND_FUNCTION(gmp_sqrtrem) RETURN_FALSE; } + gmp_create(&result1, &gmpnum_result1 TSRMLS_CC); + gmp_create(&result2, &gmpnum_result2 TSRMLS_CC); + array_init(return_value); - add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC)); - add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC)); + add_next_index_zval(return_value, &result1); + add_next_index_zval(return_value, &result2); mpz_sqrtrem(gmpnum_result1, gmpnum_result2, gmpnum_a); FREE_GMP_TEMP(temp_a); @@ -1444,6 +1414,7 @@ ZEND_FUNCTION(gmp_rootrem) long nth; mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2; gmp_temp_t temp_a; + zval result1, result2; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &nth) == FAILURE) { return; @@ -1462,9 +1433,12 @@ ZEND_FUNCTION(gmp_rootrem) RETURN_FALSE; } + gmp_create(&result1, &gmpnum_result1 TSRMLS_CC); + gmp_create(&result2, &gmpnum_result2 TSRMLS_CC); + array_init(return_value); - add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC)); - add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC)); + add_next_index_zval(return_value, &result1); + add_next_index_zval(return_value, &result2); #if GMP_42_OR_NEWER mpz_rootrem(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) nth); @@ -1533,6 +1507,7 @@ ZEND_FUNCTION(gmp_gcdext) zval *a_arg, *b_arg; mpz_ptr gmpnum_a, gmpnum_b, gmpnum_t, gmpnum_s, gmpnum_g; gmp_temp_t temp_a, temp_b; + zval result_g, result_s, result_t; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){ return; @@ -1541,10 +1516,14 @@ ZEND_FUNCTION(gmp_gcdext) FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a); FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a); + gmp_create(&result_g, &gmpnum_g TSRMLS_CC); + gmp_create(&result_s, &gmpnum_s TSRMLS_CC); + gmp_create(&result_t, &gmpnum_t TSRMLS_CC); + array_init(return_value); - add_assoc_zval(return_value, "g", gmp_create(&gmpnum_g TSRMLS_CC)); - add_assoc_zval(return_value, "s", gmp_create(&gmpnum_s TSRMLS_CC)); - add_assoc_zval(return_value, "t", gmp_create(&gmpnum_t TSRMLS_CC)); + add_assoc_zval(return_value, "g", &result_g); + add_assoc_zval(return_value, "s", &result_s); + add_assoc_zval(return_value, "t", &result_t); mpz_gcdext(gmpnum_g, gmpnum_s, gmpnum_t, gmpnum_a, gmpnum_b); FREE_GMP_TEMP(temp_a);