diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2012-03-15 20:53:14 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2012-03-15 20:53:14 (GMT) |
commit | b337ae979dad938f1ef72df4f67b612a883040b1 (patch) | |
tree | 97bbd651a366c406bb7a22bde36f37f7448dc550 /src | |
parent | 207c05e2e9f1c2844416c19fe5b74b2d71610fd1 (diff) | |
download | hdf5-b337ae979dad938f1ef72df4f67b612a883040b1.zip hdf5-b337ae979dad938f1ef72df4f67b612a883040b1.tar.gz hdf5-b337ae979dad938f1ef72df4f67b612a883040b1.tar.bz2 |
[svn-r22076] #Issue 7922 - H5Pset_data_transform had seg fault with some operations like x*-100.
The parser mistaked "-" as substraction. I fixed it and also fixed another problem
with some special cases like 100-x and 2/x.
Tested on jam, koala, and ostrich.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5HF.c | 1 | ||||
-rw-r--r-- | src/H5Ztrans.c | 187 |
2 files changed, 159 insertions, 29 deletions
@@ -361,6 +361,7 @@ H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj, herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + #ifdef QAK HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); #endif /* QAK */ diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c index 5a707b5..2a2796d 100644 --- a/src/H5Ztrans.c +++ b/src/H5Ztrans.c @@ -94,6 +94,8 @@ static H5Z_node *H5Z_parse_term(H5Z_token *current, H5Z_datval_ptrs* dat_val_poi static H5Z_node *H5Z_parse_factor(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers); static H5Z_node *H5Z_new_node(H5Z_token_type type); static void H5Z_do_op(H5Z_node* tree); +static hbool_t H5Z_op_is_numbs(H5Z_node* _tree); +static hbool_t H5Z_op_is_numbs2(H5Z_node* _tree); static hid_t H5Z_xform_find_type(const H5T_t* type); static herr_t H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_type, H5Z_result* res); static void H5Z_xform_destroy_parse_tree(H5Z_node *tree); @@ -105,41 +107,46 @@ static void H5Z_XFORM_DEBUG(H5Z_node *tree); static void H5Z_print(H5Z_node *tree, FILE *stream); #endif /* H5Z_XFORM_DEBUG */ - #define H5Z_XFORM_DO_OP1(RESL,RESR,TYPE,OP,SIZE) \ { \ - if( (((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type != H5Z_XFORM_SYMBOL)) || (((RESR).type == H5Z_XFORM_SYMBOL) && ((RESL).type != H5Z_XFORM_SYMBOL))) \ + size_t u; \ + \ + if(((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type != H5Z_XFORM_SYMBOL)) \ + { \ + TYPE* p; \ + double tree_val; \ + \ + tree_val = ((RESR).type==H5Z_XFORM_INTEGER ? (double)(RESR).value.int_val : (RESR).value.float_val); \ + p = (TYPE*)(RESL).value.dat_val; \ + \ + for(u=0; u<(SIZE); u++) \ + *p++ = *p OP tree_val; \ + } \ + else if(((RESR).type == H5Z_XFORM_SYMBOL) && ((RESL).type != H5Z_XFORM_SYMBOL)) \ { \ - size_t u; \ TYPE* p; \ double tree_val; \ \ - if((RESL).type == H5Z_XFORM_SYMBOL) \ - { \ - tree_val = ((RESR).type==H5Z_XFORM_INTEGER ? (double)(RESR).value.int_val : (RESR).value.float_val); \ - p = (TYPE*)(RESL).value.dat_val; \ - } \ + /* The case that the left operand is nothing, like -x or +x */ \ + if((RESL).type == H5Z_XFORM_ERROR) \ + tree_val = 0; \ else \ - { \ tree_val = ((RESL).type==H5Z_XFORM_INTEGER ? (double)(RESL).value.int_val : (RESL).value.float_val); \ - p = (TYPE*)(RESR).value.dat_val; \ - } \ - \ + \ + p = (TYPE*)(RESR).value.dat_val; \ for(u=0; u<(SIZE); u++) \ - *p++ OP tree_val; \ - } \ + *p++ = tree_val OP *p; \ + } \ else if( ((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type==H5Z_XFORM_SYMBOL)) \ { \ - size_t u; \ TYPE* pl = (TYPE*)(RESL).value.dat_val; \ TYPE* pr = (TYPE*)(RESR).value.dat_val; \ \ for(u=0; u<(SIZE); u++) \ - *pl++ OP *pr++; \ + *pl++ = *pl OP *pr++; \ } \ else \ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unexpected type conversion operation") \ - \ } /* Due to the undefined nature of embedding macros/conditionals within macros, we employ @@ -235,6 +242,7 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); } #endif /*H5_SIZEOF_LONG_DOUBLE */ + #define H5Z_XFORM_DO_OP3(OP) \ { \ if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER)) \ @@ -259,6 +267,48 @@ static void H5Z_print(H5Z_node *tree, FILE *stream); } \ } +/* The difference of this macro from H5Z_XFORM_DO_OP3 is that it handles the operations when the left operand is empty, like -x or +x. + * The reason that it's seperated from H5Z_XFORM_DO_OP3 is because compilers don't accept operations like *x or /x. So in H5Z_do_op, + * these two macros are called in different ways. + */ +#define H5Z_XFORM_DO_OP6(OP) \ +{ \ + if(!tree->lchild && (tree->rchild->type==H5Z_XFORM_INTEGER)) \ + { \ + tree->type = H5Z_XFORM_INTEGER; \ + tree->value.int_val = OP tree->rchild->value.int_val; \ + H5MM_xfree(tree->rchild); \ + tree->rchild = NULL; \ + } \ + else if(!tree->lchild && (tree->rchild->type==H5Z_XFORM_FLOAT)) \ + { \ + tree->type = H5Z_XFORM_FLOAT; \ + tree->value.float_val = OP tree->rchild->value.float_val; \ + H5MM_xfree(tree->rchild); \ + tree->rchild = NULL; \ + } \ + else if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER)) \ + { \ + tree->type = H5Z_XFORM_INTEGER; \ + tree->value.int_val = tree->lchild->value.int_val OP tree->rchild->value.int_val; \ + H5MM_xfree(tree->lchild); \ + H5MM_xfree(tree->rchild); \ + tree->lchild = NULL; \ + tree->rchild = NULL; \ + } \ + else if( ( (tree->lchild->type == H5Z_XFORM_FLOAT) || (tree->lchild->type == H5Z_XFORM_INTEGER)) && \ + ( (tree->rchild->type == H5Z_XFORM_FLOAT) || (tree->rchild->type == H5Z_XFORM_INTEGER))) \ + { \ + tree->type = H5Z_XFORM_FLOAT; \ + tree->value.float_val = ((tree->lchild->type == H5Z_XFORM_FLOAT) ? tree->lchild->value.float_val : (double)tree->lchild->value.int_val) OP \ + ((tree->rchild->type == H5Z_XFORM_FLOAT) ? tree->rchild->value.float_val : (double)tree->rchild->value.int_val); \ + H5MM_xfree(tree->lchild); \ + H5MM_xfree(tree->rchild); \ + tree->lchild = NULL; \ + tree->rchild = NULL; \ + } \ +} + #define H5Z_XFORM_DO_OP4(TYPE) \ { \ if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL) \ @@ -1027,6 +1077,9 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_ /* check args */ HDassert(tree); + HDmemset(&resl, 0, sizeof(H5Z_result)); + HDmemset(&resr, 0, sizeof(H5Z_result)); + if (tree->type == H5Z_XFORM_INTEGER) { res->type = H5Z_XFORM_INTEGER; res->value.int_val = tree->value.int_val; @@ -1044,7 +1097,7 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_ res->value.dat_val = *((void**)(tree->value.dat_val)); } /* end if */ else { - if(H5Z_xform_eval_full(tree->lchild, array_size, array_type, &resl) < 0) + if(tree->lchild && H5Z_xform_eval_full(tree->lchild, array_size, array_type, &resl) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform") if(H5Z_xform_eval_full(tree->rchild, array_size, array_type, &resr) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform") @@ -1059,19 +1112,19 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_ switch (tree->type) { case H5Z_XFORM_PLUS: - H5Z_XFORM_TYPE_OP(resl, resr, array_type, +=, array_size) + H5Z_XFORM_TYPE_OP(resl, resr, array_type, +, array_size) break; case H5Z_XFORM_MINUS: - H5Z_XFORM_TYPE_OP(resl, resr, array_type, -=, array_size) + H5Z_XFORM_TYPE_OP(resl, resr, array_type, -, array_size) break; case H5Z_XFORM_MULT: - H5Z_XFORM_TYPE_OP(resl, resr, array_type, *=, array_size) + H5Z_XFORM_TYPE_OP(resl, resr, array_type, *, array_size) break; case H5Z_XFORM_DIVIDE: - H5Z_XFORM_TYPE_OP(resl, resr, array_type, /=, array_size) + H5Z_XFORM_TYPE_OP(resl, resr, array_type, /, array_size) break; default: @@ -1274,22 +1327,37 @@ H5Z_xform_reduce_tree(H5Z_node* tree) FUNC_ENTER_NOAPI_NOINIT_NOERR if(tree) { - if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_DIVIDE) ||(tree->type == H5Z_XFORM_MULT) ||(tree->type == H5Z_XFORM_MINUS)) + if((tree->type == H5Z_XFORM_DIVIDE) || (tree->type == H5Z_XFORM_MULT)) { - if(((tree->lchild->type == H5Z_XFORM_INTEGER) || (tree->lchild->type == H5Z_XFORM_FLOAT)) && ((tree->rchild->type == H5Z_XFORM_INTEGER) || (tree->rchild->type == H5Z_XFORM_FLOAT))) + if(H5Z_op_is_numbs(tree)) H5Z_do_op(tree); else { H5Z_xform_reduce_tree(tree->lchild); - if(((tree->lchild->type == H5Z_XFORM_INTEGER) || (tree->lchild->type == H5Z_XFORM_FLOAT)) && ((tree->rchild->type == H5Z_XFORM_INTEGER) || (tree->rchild->type == H5Z_XFORM_FLOAT))) + if(H5Z_op_is_numbs(tree)) H5Z_do_op(tree); else { H5Z_xform_reduce_tree(tree->rchild); - if(((tree->lchild->type == H5Z_XFORM_INTEGER) || (tree->lchild->type == H5Z_XFORM_FLOAT)) && ((tree->rchild->type == H5Z_XFORM_INTEGER) || (tree->rchild->type == H5Z_XFORM_FLOAT))) + if(H5Z_op_is_numbs(tree)) + H5Z_do_op(tree); + } + } + } else if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_MINUS)) { + if(H5Z_op_is_numbs2(tree)) + H5Z_do_op(tree); + else + { + H5Z_xform_reduce_tree(tree->lchild); + if(H5Z_op_is_numbs2(tree)) + H5Z_do_op(tree); + else { + H5Z_xform_reduce_tree(tree->rchild); + if(H5Z_op_is_numbs2(tree)) H5Z_do_op(tree); } } } + } FUNC_LEAVE_NOAPI_VOID; @@ -1297,6 +1365,63 @@ H5Z_xform_reduce_tree(H5Z_node* tree) /*------------------------------------------------------------------------- + * Function: H5Z_op_is_numbs + * Purpose: Internal function to facilitate the condition check in + * H5Z_xform_reduce_tree to reduce the bulkiness of the code. + * Return: TRUE or FALSE + * Programmer: Raymond Lu + * 15 March 2012 + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +H5Z_op_is_numbs(H5Z_node* _tree) +{ + hbool_t ret_value = FALSE; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + assert(_tree); + + if(((_tree->lchild->type == H5Z_XFORM_INTEGER) || (_tree->lchild->type == H5Z_XFORM_FLOAT)) && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT))) + ret_value = TRUE; + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5Z_op_is_numbs2 + * Purpose: Internal function to facilitate the condition check in + * H5Z_xform_reduce_tree to reduce the bulkiness of the code. + * The difference from H5Z_op_is_numbs is that the left child + * can be empty, like -x or +x. + * Return: TRUE or FALSE + * Programmer: Raymond Lu + * 15 March 2012 + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +H5Z_op_is_numbs2(H5Z_node* _tree) +{ + hbool_t ret_value = FALSE; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + assert(_tree); + + if((!_tree->lchild && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT))) || + ((_tree->lchild && ((_tree->lchild->type == H5Z_XFORM_INTEGER) || (_tree->lchild->type == H5Z_XFORM_FLOAT))) && (_tree->rchild && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT))))) + ret_value = TRUE; + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- * Function: H5Z_do_op * Purpose: If the root of the tree passed in points to a simple * arithmetic operation and the left and right subtrees are both @@ -1307,7 +1432,11 @@ H5Z_xform_reduce_tree(H5Z_node* tree) * Programmer: Leon Arber * April 1, 2004. * Modifications: -* + * Raymond Lu + * 15 March 2012 + * I added a new macro H5Z_XFORM_DO_OP6 to handle the special + * operations like -x or +x when the left operand is empty. + * *------------------------------------------------------------------------- */ static void @@ -1320,9 +1449,9 @@ H5Z_do_op(H5Z_node* tree) else if(tree->type == H5Z_XFORM_MULT) H5Z_XFORM_DO_OP3(*) else if(tree->type == H5Z_XFORM_PLUS) - H5Z_XFORM_DO_OP3(+) + H5Z_XFORM_DO_OP6(+) else if(tree->type == H5Z_XFORM_MINUS) - H5Z_XFORM_DO_OP3(-) + H5Z_XFORM_DO_OP6(-) FUNC_LEAVE_NOAPI_VOID; } |