--- psiconv/trunk/lib/psiconv/parse_formula.c 2001/01/31 00:57:17 104 +++ psiconv/trunk/lib/psiconv/parse_formula.c 2003/11/25 17:57:05 168 @@ -25,6 +25,11 @@ #include "parse_routines.h" #include "error.h" +#ifdef DMALLOC +#include +#endif + + struct formula_element { psiconv_formula_type_t formula_type; @@ -48,11 +53,11 @@ {psiconv_formula_op_pow,2,"^"}, {psiconv_formula_op_pos,1,"+"}, {psiconv_formula_op_neg,1,"-"}, - {psiconv_formula_unknown,0,"*UNKNOWN*"}, - {psiconv_formula_unknown,0,"*UNKNOWN*"}, - {psiconv_formula_unknown,0,"*UNKNOWN*"}, /* 10 */ + {psiconv_formula_op_not,1,"NOT"}, + {psiconv_formula_op_and,2,"AND"}, + {psiconv_formula_op_or,2,"OR"}, /* 10 */ {psiconv_formula_op_con,2,"&"}, - {psiconv_formula_op_bra,1,"{}"}, + {psiconv_formula_op_bra,1,"()"}, {psiconv_formula_unknown,0,"*UNKNOWN*"}, {psiconv_formula_unknown,0,"*UNKNOWN*"}, {psiconv_formula_mark_eof,0,"End of formula"}, @@ -286,93 +291,36 @@ {psiconv_formula_unknown,0,"*UNKNOWN*"}, {psiconv_formula_unknown,0,"*UNKNOWN*"}, {psiconv_formula_unknown,0,"*UNKNOWN*"}, - {psiconv_formula_unknown,0,"*UNKNOWN*"}, - {psiconv_formula_unknown,0,"*UNKNOWN*"}, - {psiconv_formula_unknown,0,"*UNKNOWN*"}, {psiconv_formula_unknown,0,"*UNKNOWN*"}}; -static psiconv_string_t psiconv_read_sheet_string(const psiconv_buffer buf, - int lev, - psiconv_u32 off,int *length, int *status) -{ - int stringlen,i,len,localstatus; - psiconv_string_t result; - char *res_copy; - - psiconv_progress(lev+1,off,"Going to read a sheet string"); - - stringlen = psiconv_read_u8(buf,lev+2,off,&localstatus); - if (localstatus) - goto ERROR1; - psiconv_debug(lev+2,off,"Length: %i",stringlen); - len = 1; - - result = malloc(stringlen + 1); - if (!result) - goto ERROR1; - for (i = 0; (i < stringlen) && !localstatus; i++) - result[i] = psiconv_read_u8(buf,lev,off+i+len,&localstatus); - if (localstatus) - goto ERROR2; - result[stringlen] = 0; - len += stringlen; - - res_copy = psiconv_make_printable(result); - if (!res_copy) - goto ERROR2; - psiconv_debug(lev+2,off,"Contents: `%s'",res_copy); - free(res_copy); - - if (length) - *length = len; - - if (status) - *status = 0; - - psiconv_progress(lev+1,off+len-1,"End of sheet string (total length: %08x)", - len); - - return result; - - -ERROR2: - free(result); -ERROR1: - psiconv_warn(lev+1,off,"Reading of sheet string failed"); - if (status) - *status = localstatus; - if (length) - *length = 0; - return NULL; -} - - -static int psiconv_parse_sheet_ref(const psiconv_buffer buf,int lev, +static int psiconv_parse_sheet_ref(const psiconv_config config, + const psiconv_buffer buf,int lev, psiconv_u32 off, int *length, psiconv_sheet_ref_t *result) { int res; psiconv_u16 temp; - psiconv_progress(lev+1,off,"Going to read a sheet ref"); - psiconv_progress(lev+2,off,"Going to read the offset encoding"); - temp = psiconv_read_u16(buf,lev+2,off,&res); + psiconv_progress(config,lev+1,off,"Going to read a sheet ref"); + psiconv_progress(config,lev+2,off,"Going to read the offset encoding"); + temp = psiconv_read_u16(config,buf,lev+2,off,&res); if (res) { if (length) *length = 0; return res; } - psiconv_debug(lev+2,off,"Encoded word: %04x",temp); + psiconv_debug(config,lev+2,off,"Encoded word: %04x",temp); result->absolute = (temp & 0x4000)?psiconv_bool_true:psiconv_bool_false; result->offset = (temp & 0x3fff) * ((temp & 0x8000)?-1:1); - psiconv_debug(lev+2,off,"Reference: %s offset %d", + psiconv_debug(config,lev+2,off,"Reference: %s offset %d", result->absolute?"absolute":"relative",result->offset); if (length) *length = 2; return 0; } -static int psiconv_parse_sheet_cell_reference(const psiconv_buffer buf,int lev, +static int psiconv_parse_sheet_cell_reference(const psiconv_config config, + const psiconv_buffer buf,int lev, psiconv_u32 off, int *length, psiconv_sheet_cell_reference_t *result) { @@ -380,27 +328,27 @@ int leng,res; psiconv_u8 temp; - psiconv_progress(lev+1,off+len,"Going to read a sheet cell reference"); - psiconv_progress(lev+2,off+len,"Going to read the row reference"); - if ((res = psiconv_parse_sheet_ref(buf,lev+2,off+len,&leng,&result->row))) + psiconv_progress(config,lev+1,off+len,"Going to read a sheet cell reference"); + psiconv_progress(config,lev+2,off+len,"Going to read the row reference"); + if ((res = psiconv_parse_sheet_ref(config,buf,lev+2,off+len,&leng,&result->row))) goto ERROR; len += leng; - psiconv_progress(lev+2,off+len,"Going to read the column reference"); - if ((res = psiconv_parse_sheet_ref(buf,lev+2,off+len,&leng,&result->column))) + psiconv_progress(config,lev+2,off+len,"Going to read the column reference"); + if ((res = psiconv_parse_sheet_ref(config,buf,lev+2,off+len,&leng,&result->column))) goto ERROR; len += leng; - psiconv_progress(lev+2,off+len, + psiconv_progress(config,lev+2,off+len, "Going to read the trailing byte (%02x expected)",0); - temp = psiconv_read_u8(buf,lev+2,off+len,&res); + temp = psiconv_read_u8(config,buf,lev+2,off+len,&res); if (res) goto ERROR; if (temp != 0) { - psiconv_warn(lev+2,off+len,"Unknown byte in cell reference (ignored"); - psiconv_debug(lev+2,off+len,"Trailing byte: %02x",temp); + psiconv_warn(config,lev+2,off+len,"Unknown byte in cell reference (ignored"); + psiconv_debug(config,lev+2,off+len,"Trailing byte: %02x",temp); } len ++; - psiconv_progress(lev,off+len-1, + psiconv_progress(config,lev,off+len-1, "End of cell reference (total length: %08x)", len); if (length) *length = len; @@ -411,25 +359,26 @@ return res; } -static int psiconv_parse_sheet_cell_block(const psiconv_buffer buf,int lev, +static int psiconv_parse_sheet_cell_block(const psiconv_config config, + const psiconv_buffer buf,int lev, psiconv_u32 off, int *length, psiconv_sheet_cell_block_t *result) { int len = 0; int leng,res; - psiconv_progress(lev+1,off+len,"Going to read a sheet cell block"); - psiconv_progress(lev+2,off+len,"Going to read the first cell"); - if ((res = psiconv_parse_sheet_cell_reference(buf,lev+2,off+len,&leng, + psiconv_progress(config,lev+1,off+len,"Going to read a sheet cell block"); + psiconv_progress(config,lev+2,off+len,"Going to read the first cell"); + if ((res = psiconv_parse_sheet_cell_reference(config,buf,lev+2,off+len,&leng, &result->first))) goto ERROR; len += leng; - psiconv_progress(lev+2,off+len,"Going to read the last cell"); - if ((res = psiconv_parse_sheet_cell_reference(buf,lev+2,off+len,&leng, + psiconv_progress(config,lev+2,off+len,"Going to read the last cell"); + if ((res = psiconv_parse_sheet_cell_reference(config,buf,lev+2,off+len,&leng, &result->last))) goto ERROR; len += leng; - psiconv_progress(lev,off+len-1, + psiconv_progress(config,lev,off+len-1, "End of cell block (total length: %08x)", len); if (length) *length = len; @@ -440,20 +389,23 @@ return res; } -int psiconv_parse_formula(const psiconv_buffer buf, int lev, - psiconv_u32 off, int *length, - psiconv_formula *result) +static int psiconv_parse_formula_element_list(const psiconv_config config, + const psiconv_buffer buf, int lev, + psiconv_u32 off, int *length, + psiconv_formula *result, + psiconv_u32 maxlen) { int res=0; int len=0; int leng; int eof = 0; - psiconv_u8 marker; - psiconv_u32 bytelen; + psiconv_u8 marker,submarker,submarker2; psiconv_formula_list formula_stack; - psiconv_formula formula,subformula1,subformula2,subformula3,subformula4; + psiconv_formula formula,subformula,subformula1,subformula2, + subformula3,subformula4; + psiconv_u16 temp,nr_of_subs; - psiconv_progress(lev+1,off,"Going to read a formula"); + psiconv_progress(config,lev+1,off,"Going to read a formula element list"); if (!(*result = malloc(sizeof(**result)))) goto ERROR1; if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) @@ -475,61 +427,56 @@ goto ERROR7; subformula4->type = psiconv_formula_unknown; - psiconv_progress(lev+2,off+len, - "Going to read the formula byte length"); - bytelen = psiconv_read_S(buf,lev+2,off+len,&leng,&res); - if (res) - goto ERROR8; - psiconv_debug(lev+2,off+len,"Formula byte length: %d",bytelen); - len += leng; - bytelen += len; - - psiconv_progress(lev+2,off+len,"Going to read the formula items"); - while (!eof && len < bytelen) { - psiconv_progress(lev+3,off+len,"Going to read a formula item marker"); - marker = psiconv_read_u8(buf,lev+2,off+len,&res); + while (!eof && len+off < maxlen) { + psiconv_progress(config,lev+3,off+len,"Going to read a formula item marker"); + marker = psiconv_read_u8(config,buf,lev+2,off+len,&res); if (res) goto ERROR8; - psiconv_debug(lev+3,off+len,"Marker: %02x (%s)",marker, + psiconv_debug(config,lev+3,off+len,"Marker: %02x (%s)",marker, formula_elements[marker].name); len ++; if (formula_elements[marker].formula_type == psiconv_formula_unknown) { - psiconv_warn(lev+3,off+len,"Unknown formula marker found!"); + psiconv_warn(config,lev+3,off+len,"Unknown formula marker found!"); goto ERROR8; - } else if (formula_elements[marker].formula_type == - psiconv_formula_mark_eof) { - psiconv_progress(lev+3,off+len,"End of formula"); + } else if ((formula_elements[marker].formula_type == + psiconv_formula_mark_eof) || + (formula_elements[marker].formula_type == + psiconv_formula_mark_opend) || + (formula_elements[marker].formula_type == + psiconv_formula_mark_opsep)) { + len--; + psiconv_progress(config,lev+3,off+len,"End of this formula list"); eof = 1; } else if (formula_elements[marker].formula_type == psiconv_formula_dat_int) { - psiconv_progress(lev+3,off+len,"Next item: an integer"); - formula->data.dat_int = psiconv_read_u32(buf,lev+2,off+len,&res); + psiconv_progress(config,lev+3,off+len,"Next item: an integer"); + formula->data.dat_int = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) goto ERROR8; formula->type = formula_elements[marker].formula_type; - psiconv_debug(lev+3,off+len,"Value: %08x",formula->data.dat_int); + psiconv_debug(config,lev+3,off+len,"Value: %08x",formula->data.dat_int); len += 4; if ((res = psiconv_list_add(formula_stack,formula))) goto ERROR8; formula->type = psiconv_formula_unknown; } else if (formula_elements[marker].formula_type == psiconv_formula_dat_float) { - psiconv_progress(lev+3,off+len,"Next item: a float"); - formula->data.dat_float = psiconv_read_float(buf,lev+2,off+len,&leng, + psiconv_progress(config,lev+3,off+len,"Next item: a float"); + formula->data.dat_float = psiconv_read_float(config,buf,lev+2,off+len,&leng, &res); if (res) goto ERROR8; formula->type = formula_elements[marker].formula_type; - psiconv_debug(lev+3,off+len,"Value: %f",formula->data.dat_float); + psiconv_debug(config,lev+3,off+len,"Value: %f",formula->data.dat_float); len += leng; if ((res = psiconv_list_add(formula_stack,formula))) goto ERROR8; formula->type = psiconv_formula_unknown; } else if (formula_elements[marker].formula_type == psiconv_formula_dat_cellref) { - psiconv_progress(lev+3,off+len,"Next item: a cell reference"); - if ((res = psiconv_parse_sheet_cell_reference(buf,lev+2,off+len,&leng, + psiconv_progress(config,lev+3,off+len,"Next item: a cell reference"); + if ((res = psiconv_parse_sheet_cell_reference(config,buf,lev+2,off+len,&leng, &formula->data.dat_cellref))) goto ERROR8; formula->type = formula_elements[marker].formula_type; @@ -537,10 +484,12 @@ if ((res = psiconv_list_add(formula_stack,formula))) goto ERROR8; formula->type = psiconv_formula_unknown; - } else if (formula_elements[marker].formula_type == - psiconv_formula_dat_cellblock) { - psiconv_progress(lev+3,off+len,"Next item: a cell block"); - if ((res = psiconv_parse_sheet_cell_block(buf,lev+2,off+len,&leng, + } else if ((formula_elements[marker].formula_type == + psiconv_formula_dat_cellblock) || + (formula_elements[marker].formula_type == + psiconv_formula_dat_vcellblock)) { + psiconv_progress(config,lev+3,off+len,"Next item: a cell block"); + if ((res = psiconv_parse_sheet_cell_block(config,buf,lev+2,off+len,&leng, &formula->data.dat_cellblock))) goto ERROR8; formula->type = formula_elements[marker].formula_type; @@ -550,9 +499,9 @@ formula->type = psiconv_formula_unknown; } else if (formula_elements[marker].formula_type == psiconv_formula_dat_string) { - psiconv_progress(lev+3,off+len,"Next item: a string"); + psiconv_progress(config,lev+3,off+len,"Next item: a string"); formula->data.dat_string = - psiconv_read_sheet_string(buf,lev+2,off+len,&leng,&res); + psiconv_read_short_string(config,buf,lev+2,off+len,&leng,&res); if (res) goto ERROR8; formula->type = formula_elements[marker].formula_type; @@ -561,18 +510,90 @@ goto ERROR8; formula->type = psiconv_formula_unknown; } else if ((formula_elements[marker].formula_type == - psiconv_formula_dat_var) || - (formula_elements[marker].formula_type == - psiconv_formula_dat_vcellblock) || - (formula_elements[marker].formula_type == - psiconv_formula_mark_opsep) || - (formula_elements[marker].formula_type == - psiconv_formula_mark_opend)) { - psiconv_warn(lev+3,off+len,"Not yet supported formula mark!"); - goto ERROR8; + psiconv_formula_dat_var)) { + psiconv_progress(config,lev+3,off+len,"Next item: a variable reference"); + formula->data.dat_variable = psiconv_read_u32(config,buf,lev+2,off+len,&res); + if (res) + goto ERROR8; + formula->type = formula_elements[marker].formula_type; + len += 4; + if ((res = psiconv_list_add(formula_stack,formula))) + goto ERROR8; + formula->type = psiconv_formula_unknown; } else if (formula_elements[marker].number_of_args == -1) { - psiconv_warn(lev+3,off+len,"Vararg functions not yet supported!"); - goto ERROR8; + psiconv_progress(config,lev+3,off+len,"Going to parse a vararg function"); + if (!(formula->data.fun_operands = + psiconv_list_new(sizeof(*formula)))) + goto ERROR8; + formula->type = formula_elements[marker].formula_type; + nr_of_subs = 0; + do { + nr_of_subs ++; + psiconv_progress(config,lev+4,off+len,"Going to read vararg argument %d", + nr_of_subs); + if ((res = psiconv_parse_formula_element_list(config,buf,lev+4,off+len,&leng, + &subformula,maxlen))) + goto ERROR8; + len += leng; + if ((res = psiconv_list_add(formula->data.fun_operands,subformula))) { + psiconv_free_formula(subformula); + goto ERROR8; + } + free(subformula); + psiconv_progress(config,lev+4,off+len,"Going to read the next marker"); + submarker = psiconv_read_u8(config,buf,lev+4,off+len,&res); + len ++; + if (res) + goto ERROR8; + submarker2 = psiconv_read_u8(config,buf,lev+4,off+len,&res); + if (res) + goto ERROR8; + } while ((formula_elements[submarker].formula_type + == psiconv_formula_mark_opsep) && + (formula_elements[submarker2].formula_type + != psiconv_formula_mark_opend)); + if ((formula_elements[submarker].formula_type == + psiconv_formula_mark_opsep) && + (formula_elements[submarker2].formula_type == + psiconv_formula_mark_opend)) { + submarker=submarker2; + len++; + } + if (formula_elements[submarker].formula_type + != psiconv_formula_mark_opend) { + psiconv_warn(config,lev+3,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+3,off+len,"Found unexpected marker %02x",submarker); + goto ERROR8; + } + psiconv_progress(config,lev+3,off+len,"Going to read the repeated marker %02x", + marker); + submarker = psiconv_read_u8(config,buf,lev+3,off+len,&res); + if (res) + goto ERROR8; + if (submarker != marker) { + psiconv_warn(config,lev+3,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+3,off+len,"Expected marker %02x, found %02x", + marker,submarker); + goto ERROR8; + } + len++; + psiconv_progress(config,lev+3,off+len, + "Going to read the number of arguments (%d expected)", + nr_of_subs); + temp = psiconv_read_u16(config,buf,lev+3,off+len,&res); + if (res) + goto ERROR8; + if (temp != nr_of_subs) { + psiconv_warn(config,lev+3,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+3,off+len, + "Read %d arguments, but formula says there are %d", + nr_of_subs,temp); + goto ERROR8; + } + len += 2; + if ((res = psiconv_list_add(formula_stack,formula))) + goto ERROR8; + formula->type = psiconv_formula_unknown; } else { if (formula_elements[marker].number_of_args > 0) if ((res = psiconv_list_pop(formula_stack,subformula1))) @@ -608,15 +629,15 @@ subformula1->type = formula->type = psiconv_formula_unknown; } } - if ((len != bytelen) || !eof) { - psiconv_warn(lev+2,off+len,"Formula corrupted!"); - psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", - bytelen,len); + if ((len+off > maxlen) || !eof) { + psiconv_warn(config,lev+2,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+2,off+len,"Expected end: %04x, found end: %04x", + maxlen,len+off); goto ERROR8; } if ((psiconv_list_length(formula_stack)) != 1) { - psiconv_warn(lev+2,off+len,"Formula corrupted!"); - psiconv_debug(lev+2,off+len,"More than one item left on the stack (%d)", + psiconv_warn(config,lev+2,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+2,off+len,"More than one item left on the stack (%d)", psiconv_list_length(formula_stack)); goto ERROR8; } @@ -628,8 +649,8 @@ if (length) *length = len; - psiconv_progress(lev,off+len-1, - "End of formula (total length: %08x)", len); + psiconv_progress(config,lev,off+len-1, + "End of formula element list (total length: %08x)", len); return 0; ERROR8: @@ -647,7 +668,77 @@ ERROR2: free (*result); ERROR1: - psiconv_warn(lev+1,off,"Reading of formula failed"); + psiconv_warn(config,lev+1,off,"Reading of formula element list failed"); + if (length) + *length = 0; + if (!res) + return -PSICONV_E_NOMEM; + else + return res; +} + + + + +int psiconv_parse_formula(const psiconv_config config, + const psiconv_buffer buf, int lev, + psiconv_u32 off, int *length, + psiconv_formula *result) +{ + int res=0; + int len=0; + int leng; + psiconv_u32 bytelen,formula_end; + psiconv_u8 temp; + + psiconv_progress(config,lev+1,off,"Going to read a formula"); + + psiconv_progress(config,lev+2,off+len, + "Going to read the formula byte length"); + bytelen = psiconv_read_S(config,buf,lev+2,off+len,&leng,&res); + if (res) + goto ERROR1; + psiconv_debug(config,lev+2,off+len,"Formula byte length: %d",bytelen); + len += leng; + bytelen += len; + formula_end = off + bytelen; + + psiconv_progress(config,lev+2,off+len,"Going to read the formula elements list"); + if ((res = psiconv_parse_formula_element_list(config,buf,lev+2,off+len,&leng, + result,formula_end))) + goto ERROR1; + len += leng; + + psiconv_progress(config,lev+2,off+len,"Going to read the eof marker"); + temp = psiconv_read_u8(config,buf,lev+2,off+len,&res); + if (res) + goto ERROR2; + if (formula_elements[temp].formula_type != psiconv_formula_mark_eof) { + psiconv_warn(config,lev+2,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+2,off+len,"Expected marker: %02x, found byte: %02x", + 0x15,temp); + goto ERROR2; + } + len ++; + + if (off+len != formula_end) { + psiconv_warn(config,lev+2,off+len,"Formula corrupted!"); + psiconv_debug(config,lev+2,off+len,"Expected end: %04x, found end: %04x", + formula_end,len+off); + goto ERROR2; + } + + if (length) + *length = len; + + psiconv_progress(config,lev,off+len-1, + "End of formula (total length: %08x)", len); + return 0; + +ERROR2: + psiconv_free_formula(*result); +ERROR1: + psiconv_warn(config,lev+1,off,"Reading of formula failed"); if (length) *length = 0; if (!res) @@ -656,3 +747,4 @@ return res; } +