… | |
… | |
46 | {psiconv_formula_op_mul,2,"*"}, |
46 | {psiconv_formula_op_mul,2,"*"}, |
47 | {psiconv_formula_op_div,2,"/"}, |
47 | {psiconv_formula_op_div,2,"/"}, |
48 | {psiconv_formula_op_pow,2,"^"}, |
48 | {psiconv_formula_op_pow,2,"^"}, |
49 | {psiconv_formula_op_pos,1,"+"}, |
49 | {psiconv_formula_op_pos,1,"+"}, |
50 | {psiconv_formula_op_neg,1,"-"}, |
50 | {psiconv_formula_op_neg,1,"-"}, |
|
|
51 | {psiconv_formula_op_not,1,"NOT"}, |
|
|
52 | {psiconv_formula_op_and,2,"AND"}, |
|
|
53 | {psiconv_formula_op_or,2,"OR"}, |
51 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
54 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
52 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
55 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
53 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, /* 10 */ |
56 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, /* 10 */ |
54 | {psiconv_formula_op_con,2,"&"}, |
57 | {psiconv_formula_op_con,2,"&"}, |
55 | {psiconv_formula_op_bra,1,"{}"}, |
58 | {psiconv_formula_op_bra,1,"()"}, |
56 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
59 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
57 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
60 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
58 | {psiconv_formula_mark_eof,0,"End of formula"}, |
61 | {psiconv_formula_mark_eof,0,"End of formula"}, |
59 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
62 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
60 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
63 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
… | |
… | |
284 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
287 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
285 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
288 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
286 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
289 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
287 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
290 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
288 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
291 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
289 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
|
|
290 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
|
|
291 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
|
|
292 | {psiconv_formula_unknown,0,"*UNKNOWN*"}}; |
292 | {psiconv_formula_unknown,0,"*UNKNOWN*"}}; |
293 | |
293 | |
294 | static psiconv_string_t psiconv_read_sheet_string(const psiconv_buffer buf, |
294 | static psiconv_string_t psiconv_read_sheet_string(const psiconv_buffer buf, |
295 | int lev, |
295 | int lev, |
296 | psiconv_u32 off,int *length, int *status) |
296 | psiconv_u32 off,int *length, int *status) |
… | |
… | |
438 | if (length) |
438 | if (length) |
439 | *length = 0; |
439 | *length = 0; |
440 | return res; |
440 | return res; |
441 | } |
441 | } |
442 | |
442 | |
443 | int psiconv_parse_formula(const psiconv_buffer buf, int lev, |
443 | static int psiconv_parse_formula_element_list(const psiconv_buffer buf, int lev, |
444 | psiconv_u32 off, int *length, |
444 | psiconv_u32 off, int *length, |
445 | psiconv_formula *result) |
445 | psiconv_formula *result, |
|
|
446 | psiconv_u32 maxlen) |
446 | { |
447 | { |
447 | int res=0; |
448 | int res=0; |
448 | int len=0; |
449 | int len=0; |
449 | int leng; |
450 | int leng; |
450 | int eof = 0; |
451 | int eof = 0; |
451 | psiconv_u8 marker; |
452 | psiconv_u8 marker,submarker; |
452 | psiconv_u32 bytelen; |
|
|
453 | psiconv_formula_list formula_stack; |
453 | psiconv_formula_list formula_stack; |
454 | psiconv_formula formula,subformula1,subformula2,subformula3,subformula4; |
454 | psiconv_formula formula,subformula,subformula1,subformula2, |
|
|
455 | subformula3,subformula4; |
|
|
456 | psiconv_u16 temp,nr_of_subs; |
455 | |
457 | |
456 | psiconv_progress(lev+1,off,"Going to read a formula"); |
458 | psiconv_progress(lev+1,off,"Going to read a formula element list"); |
457 | if (!(*result = malloc(sizeof(**result)))) |
459 | if (!(*result = malloc(sizeof(**result)))) |
458 | goto ERROR1; |
460 | goto ERROR1; |
459 | if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) |
461 | if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) |
460 | goto ERROR2; |
462 | goto ERROR2; |
461 | if (!(formula = malloc(sizeof(*formula)))) |
463 | if (!(formula = malloc(sizeof(*formula)))) |
… | |
… | |
473 | subformula3->type = psiconv_formula_unknown; |
475 | subformula3->type = psiconv_formula_unknown; |
474 | if (!(subformula4 = malloc(sizeof(*subformula4)))) |
476 | if (!(subformula4 = malloc(sizeof(*subformula4)))) |
475 | goto ERROR7; |
477 | goto ERROR7; |
476 | subformula4->type = psiconv_formula_unknown; |
478 | subformula4->type = psiconv_formula_unknown; |
477 | |
479 | |
478 | psiconv_progress(lev+2,off+len, |
|
|
479 | "Going to read the formula byte length"); |
|
|
480 | bytelen = psiconv_read_S(buf,lev+2,off+len,&leng,&res); |
|
|
481 | if (res) |
|
|
482 | goto ERROR8; |
|
|
483 | psiconv_debug(lev+2,off+len,"Formula byte length: %d",bytelen); |
|
|
484 | len += leng; |
|
|
485 | bytelen += len; |
|
|
486 | |
|
|
487 | psiconv_progress(lev+2,off+len,"Going to read the formula items"); |
|
|
488 | while (!eof && len < bytelen) { |
480 | while (!eof && len+off < maxlen) { |
489 | psiconv_progress(lev+3,off+len,"Going to read a formula item marker"); |
481 | psiconv_progress(lev+3,off+len,"Going to read a formula item marker"); |
490 | marker = psiconv_read_u8(buf,lev+2,off+len,&res); |
482 | marker = psiconv_read_u8(buf,lev+2,off+len,&res); |
491 | if (res) |
483 | if (res) |
492 | goto ERROR8; |
484 | goto ERROR8; |
493 | psiconv_debug(lev+3,off+len,"Marker: %02x (%s)",marker, |
485 | psiconv_debug(lev+3,off+len,"Marker: %02x (%s)",marker, |
… | |
… | |
495 | len ++; |
487 | len ++; |
496 | |
488 | |
497 | if (formula_elements[marker].formula_type == psiconv_formula_unknown) { |
489 | if (formula_elements[marker].formula_type == psiconv_formula_unknown) { |
498 | psiconv_warn(lev+3,off+len,"Unknown formula marker found!"); |
490 | psiconv_warn(lev+3,off+len,"Unknown formula marker found!"); |
499 | goto ERROR8; |
491 | goto ERROR8; |
500 | } else if (formula_elements[marker].formula_type == |
492 | } else if ((formula_elements[marker].formula_type == |
501 | psiconv_formula_mark_eof) { |
493 | psiconv_formula_mark_eof) || |
|
|
494 | (formula_elements[marker].formula_type == |
|
|
495 | psiconv_formula_mark_opend) || |
|
|
496 | (formula_elements[marker].formula_type == |
|
|
497 | psiconv_formula_mark_opsep)) { |
|
|
498 | len--; |
502 | psiconv_progress(lev+3,off+len,"End of formula"); |
499 | psiconv_progress(lev+3,off+len,"End of this formula list"); |
503 | eof = 1; |
500 | eof = 1; |
504 | } else if (formula_elements[marker].formula_type == |
501 | } else if (formula_elements[marker].formula_type == |
505 | psiconv_formula_dat_int) { |
502 | psiconv_formula_dat_int) { |
506 | psiconv_progress(lev+3,off+len,"Next item: an integer"); |
503 | psiconv_progress(lev+3,off+len,"Next item: an integer"); |
507 | formula->data.dat_int = psiconv_read_u32(buf,lev+2,off+len,&res); |
504 | formula->data.dat_int = psiconv_read_u32(buf,lev+2,off+len,&res); |
… | |
… | |
535 | formula->type = formula_elements[marker].formula_type; |
532 | formula->type = formula_elements[marker].formula_type; |
536 | len += leng; |
533 | len += leng; |
537 | if ((res = psiconv_list_add(formula_stack,formula))) |
534 | if ((res = psiconv_list_add(formula_stack,formula))) |
538 | goto ERROR8; |
535 | goto ERROR8; |
539 | formula->type = psiconv_formula_unknown; |
536 | formula->type = psiconv_formula_unknown; |
540 | } else if (formula_elements[marker].formula_type == |
537 | } else if ((formula_elements[marker].formula_type == |
|
|
538 | psiconv_formula_dat_cellblock) || |
|
|
539 | (formula_elements[marker].formula_type == |
541 | psiconv_formula_dat_cellblock) { |
540 | psiconv_formula_dat_vcellblock)) { |
542 | psiconv_progress(lev+3,off+len,"Next item: a cell block"); |
541 | psiconv_progress(lev+3,off+len,"Next item: a cell block"); |
543 | if ((res = psiconv_parse_sheet_cell_block(buf,lev+2,off+len,&leng, |
542 | if ((res = psiconv_parse_sheet_cell_block(buf,lev+2,off+len,&leng, |
544 | &formula->data.dat_cellblock))) |
543 | &formula->data.dat_cellblock))) |
545 | goto ERROR8; |
544 | goto ERROR8; |
546 | formula->type = formula_elements[marker].formula_type; |
545 | formula->type = formula_elements[marker].formula_type; |
… | |
… | |
561 | goto ERROR8; |
560 | goto ERROR8; |
562 | formula->type = psiconv_formula_unknown; |
561 | formula->type = psiconv_formula_unknown; |
563 | } else if ((formula_elements[marker].formula_type == |
562 | } else if ((formula_elements[marker].formula_type == |
564 | psiconv_formula_dat_var) || |
563 | psiconv_formula_dat_var) || |
565 | (formula_elements[marker].formula_type == |
564 | (formula_elements[marker].formula_type == |
566 | psiconv_formula_dat_string) || |
|
|
567 | (formula_elements[marker].formula_type == |
|
|
568 | psiconv_formula_dat_vcellblock) || |
565 | psiconv_formula_dat_vcellblock)) { |
569 | (formula_elements[marker].formula_type == |
|
|
570 | psiconv_formula_mark_opsep) || |
|
|
571 | (formula_elements[marker].formula_type == |
|
|
572 | psiconv_formula_mark_opend)) { |
|
|
573 | psiconv_warn(lev+3,off+len,"Not yet supported formula mark!"); |
566 | psiconv_warn(lev+3,off+len,"Not yet supported formula mark!"); |
574 | goto ERROR8; |
567 | goto ERROR8; |
575 | } else if (formula_elements[marker].number_of_args == -1) { |
568 | } else if (formula_elements[marker].number_of_args == -1) { |
576 | psiconv_warn(lev+3,off+len,"Vararg functions not yet supported!"); |
569 | psiconv_progress(lev+3,off+len,"Going to parse a vararg function"); |
|
|
570 | if (!(formula->data.fun_operands = |
|
|
571 | psiconv_list_new(sizeof(*formula)))) |
|
|
572 | goto ERROR8; |
|
|
573 | formula->type = formula_elements[marker].formula_type; |
|
|
574 | nr_of_subs = 0; |
|
|
575 | do { |
|
|
576 | nr_of_subs ++; |
|
|
577 | psiconv_progress(lev+4,off+len,"Going to read vararg argument %d", |
|
|
578 | nr_of_subs); |
|
|
579 | if ((res = psiconv_parse_formula_element_list(buf,lev+4,off+len,&leng, |
|
|
580 | &subformula,maxlen))) |
|
|
581 | goto ERROR8; |
|
|
582 | len += leng; |
|
|
583 | if ((res = psiconv_list_add(formula->data.fun_operands,subformula))) { |
|
|
584 | psiconv_free_formula(subformula); |
|
|
585 | goto ERROR8; |
|
|
586 | } |
|
|
587 | free(subformula); |
|
|
588 | psiconv_progress(lev+4,off+len,"Going to read the next marker"); |
|
|
589 | submarker = psiconv_read_u8(buf,lev+4,off+len,&res); |
|
|
590 | len ++; |
|
|
591 | if (res) |
|
|
592 | goto ERROR8; |
|
|
593 | } while (formula_elements[submarker].formula_type |
|
|
594 | == psiconv_formula_mark_opsep); |
|
|
595 | if (formula_elements[submarker].formula_type |
|
|
596 | != psiconv_formula_mark_opend) { |
|
|
597 | psiconv_warn(lev+3,off+len,"Formula corrupted!"); |
|
|
598 | psiconv_debug(lev+3,off+len,"Found unexpected marker %02x",submarker); |
577 | goto ERROR8; |
599 | goto ERROR8; |
|
|
600 | } |
|
|
601 | psiconv_progress(lev+3,off+len,"Going to read the repeated marker %02x", |
|
|
602 | marker); |
|
|
603 | submarker = psiconv_read_u8(buf,lev+3,off+len,&res); |
|
|
604 | if (res) |
|
|
605 | goto ERROR8; |
|
|
606 | if (submarker != marker) { |
|
|
607 | psiconv_warn(lev+3,off+len,"Formula corrupted!"); |
|
|
608 | psiconv_debug(lev+3,off+len,"Expected marker %02x, found %02x", |
|
|
609 | marker,submarker); |
|
|
610 | goto ERROR8; |
|
|
611 | } |
|
|
612 | len++; |
|
|
613 | psiconv_progress(lev+3,off+len, |
|
|
614 | "Going to read the number of arguments (%d expected)", |
|
|
615 | nr_of_subs); |
|
|
616 | temp = psiconv_read_u16(buf,lev+3,off+len,&res); |
|
|
617 | if (res) |
|
|
618 | goto ERROR8; |
|
|
619 | if (temp != nr_of_subs) { |
|
|
620 | psiconv_warn(lev+3,off+len,"Formula corrupted!"); |
|
|
621 | psiconv_debug(lev+3,off+len, |
|
|
622 | "Read %d arguments, but formula says there are %d", |
|
|
623 | nr_of_subs,temp); |
|
|
624 | goto ERROR8; |
|
|
625 | } |
|
|
626 | len += 2; |
|
|
627 | if ((res = psiconv_list_add(formula_stack,formula))) |
|
|
628 | goto ERROR8; |
|
|
629 | formula->type = psiconv_formula_unknown; |
578 | } else { |
630 | } else { |
579 | if (formula_elements[marker].number_of_args > 0) |
631 | if (formula_elements[marker].number_of_args > 0) |
580 | if ((res = psiconv_list_pop(formula_stack,subformula1))) |
632 | if ((res = psiconv_list_pop(formula_stack,subformula1))) |
581 | goto ERROR8; |
633 | goto ERROR8; |
582 | if (formula_elements[marker].number_of_args > 1) |
634 | if (formula_elements[marker].number_of_args > 1) |
… | |
… | |
608 | goto ERROR8; |
660 | goto ERROR8; |
609 | subformula4->type = subformula3->type = subformula2->type = |
661 | subformula4->type = subformula3->type = subformula2->type = |
610 | subformula1->type = formula->type = psiconv_formula_unknown; |
662 | subformula1->type = formula->type = psiconv_formula_unknown; |
611 | } |
663 | } |
612 | } |
664 | } |
613 | if ((len != bytelen) || !eof) { |
665 | if ((len+off > maxlen) || !eof) { |
614 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
666 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
615 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
667 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
616 | bytelen,len); |
668 | maxlen,len+off); |
617 | goto ERROR8; |
669 | goto ERROR8; |
618 | } |
670 | } |
619 | if ((psiconv_list_length(formula_stack)) != 1) { |
671 | if ((psiconv_list_length(formula_stack)) != 1) { |
620 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
672 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
621 | psiconv_debug(lev+2,off+len,"More than one item left on the stack (%d)", |
673 | psiconv_debug(lev+2,off+len,"More than one item left on the stack (%d)", |
… | |
… | |
629 | |
681 | |
630 | if (length) |
682 | if (length) |
631 | *length = len; |
683 | *length = len; |
632 | |
684 | |
633 | psiconv_progress(lev,off+len-1, |
685 | psiconv_progress(lev,off+len-1, |
634 | "End of formula (total length: %08x)", len); |
686 | "End of formula element list (total length: %08x)", len); |
635 | return 0; |
687 | return 0; |
636 | |
688 | |
637 | ERROR8: |
689 | ERROR8: |
638 | psiconv_free_formula(subformula4); |
690 | psiconv_free_formula(subformula4); |
639 | ERROR7: |
691 | ERROR7: |
… | |
… | |
647 | ERROR3: |
699 | ERROR3: |
648 | psiconv_free_formula_list(formula_stack); |
700 | psiconv_free_formula_list(formula_stack); |
649 | ERROR2: |
701 | ERROR2: |
650 | free (*result); |
702 | free (*result); |
651 | ERROR1: |
703 | ERROR1: |
652 | psiconv_warn(lev+1,off,"Reading of formula failed"); |
704 | psiconv_warn(lev+1,off,"Reading of formula element list failed"); |
653 | if (length) |
705 | if (length) |
654 | *length = 0; |
706 | *length = 0; |
655 | if (!res) |
707 | if (!res) |
656 | return -PSICONV_E_NOMEM; |
708 | return -PSICONV_E_NOMEM; |
657 | else |
709 | else |
658 | return res; |
710 | return res; |
659 | } |
711 | } |
660 | |
712 | |
|
|
713 | |
|
|
714 | |
|
|
715 | |
|
|
716 | int psiconv_parse_formula(const psiconv_buffer buf, int lev, |
|
|
717 | psiconv_u32 off, int *length, |
|
|
718 | psiconv_formula *result) |
|
|
719 | { |
|
|
720 | int res=0; |
|
|
721 | int len=0; |
|
|
722 | int leng; |
|
|
723 | psiconv_u32 bytelen,formula_end; |
|
|
724 | psiconv_u8 temp; |
|
|
725 | |
|
|
726 | psiconv_progress(lev+1,off,"Going to read a formula"); |
|
|
727 | |
|
|
728 | psiconv_progress(lev+2,off+len, |
|
|
729 | "Going to read the formula byte length"); |
|
|
730 | bytelen = psiconv_read_S(buf,lev+2,off+len,&leng,&res); |
|
|
731 | if (res) |
|
|
732 | goto ERROR1; |
|
|
733 | psiconv_debug(lev+2,off+len,"Formula byte length: %d",bytelen); |
|
|
734 | len += leng; |
|
|
735 | bytelen += len; |
|
|
736 | formula_end = off + bytelen; |
|
|
737 | |
|
|
738 | psiconv_progress(lev+2,off+len,"Going to read the formula elements list"); |
|
|
739 | if ((res = psiconv_parse_formula_element_list(buf,lev+2,off+len,&leng, |
|
|
740 | result,formula_end))) |
|
|
741 | goto ERROR1; |
|
|
742 | len += leng; |
|
|
743 | |
|
|
744 | psiconv_progress(lev+2,off+len,"Going to read the eof marker"); |
|
|
745 | temp = psiconv_read_u8(buf,lev+2,off+len,&res); |
|
|
746 | if (res) |
|
|
747 | goto ERROR2; |
|
|
748 | if (formula_elements[temp].formula_type != psiconv_formula_mark_eof) { |
|
|
749 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
|
|
750 | psiconv_debug(lev+2,off+len,"Expected marker: %02x, found byte: %02x", |
|
|
751 | 0x15,temp); |
|
|
752 | goto ERROR2; |
|
|
753 | } |
|
|
754 | len ++; |
|
|
755 | |
|
|
756 | if (off+len != formula_end) { |
|
|
757 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
|
|
758 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
|
|
759 | formula_end,len+off); |
|
|
760 | goto ERROR2; |
|
|
761 | } |
|
|
762 | |
|
|
763 | if (length) |
|
|
764 | *length = len; |
|
|
765 | |
|
|
766 | psiconv_progress(lev,off+len-1, |
|
|
767 | "End of formula (total length: %08x)", len); |
|
|
768 | return 0; |
|
|
769 | |
|
|
770 | ERROR2: |
|
|
771 | psiconv_free_formula(*result); |
|
|
772 | ERROR1: |
|
|
773 | psiconv_warn(lev+1,off,"Reading of formula failed"); |
|
|
774 | if (length) |
|
|
775 | *length = 0; |
|
|
776 | if (!res) |
|
|
777 | return -PSICONV_E_NOMEM; |
|
|
778 | else |
|
|
779 | return res; |
|
|
780 | } |
|
|
781 | |
|
|
782 | |