… | |
… | |
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; |
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,subformula1,subformula2,subformula3,subformula4; |
455 | |
455 | |
456 | psiconv_progress(lev+1,off,"Going to read a formula"); |
456 | psiconv_progress(lev+1,off,"Going to read a formula element list"); |
457 | if (!(*result = malloc(sizeof(**result)))) |
457 | if (!(*result = malloc(sizeof(**result)))) |
458 | goto ERROR1; |
458 | goto ERROR1; |
459 | if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) |
459 | if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) |
460 | goto ERROR2; |
460 | goto ERROR2; |
461 | if (!(formula = malloc(sizeof(*formula)))) |
461 | if (!(formula = malloc(sizeof(*formula)))) |
… | |
… | |
473 | subformula3->type = psiconv_formula_unknown; |
473 | subformula3->type = psiconv_formula_unknown; |
474 | if (!(subformula4 = malloc(sizeof(*subformula4)))) |
474 | if (!(subformula4 = malloc(sizeof(*subformula4)))) |
475 | goto ERROR7; |
475 | goto ERROR7; |
476 | subformula4->type = psiconv_formula_unknown; |
476 | subformula4->type = psiconv_formula_unknown; |
477 | |
477 | |
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) { |
478 | while (!eof && len+off < maxlen) { |
489 | psiconv_progress(lev+3,off+len,"Going to read a formula item marker"); |
479 | psiconv_progress(lev+3,off+len,"Going to read a formula item marker"); |
490 | marker = psiconv_read_u8(buf,lev+2,off+len,&res); |
480 | marker = psiconv_read_u8(buf,lev+2,off+len,&res); |
491 | if (res) |
481 | if (res) |
492 | goto ERROR8; |
482 | goto ERROR8; |
493 | psiconv_debug(lev+3,off+len,"Marker: %02x (%s)",marker, |
483 | psiconv_debug(lev+3,off+len,"Marker: %02x (%s)",marker, |
… | |
… | |
495 | len ++; |
485 | len ++; |
496 | |
486 | |
497 | if (formula_elements[marker].formula_type == psiconv_formula_unknown) { |
487 | if (formula_elements[marker].formula_type == psiconv_formula_unknown) { |
498 | psiconv_warn(lev+3,off+len,"Unknown formula marker found!"); |
488 | psiconv_warn(lev+3,off+len,"Unknown formula marker found!"); |
499 | goto ERROR8; |
489 | goto ERROR8; |
500 | } else if (formula_elements[marker].formula_type == |
490 | } else if ((formula_elements[marker].formula_type == |
501 | psiconv_formula_mark_eof) { |
491 | psiconv_formula_mark_eof) || |
|
|
492 | (formula_elements[marker].formula_type == |
|
|
493 | psiconv_formula_mark_opend) || |
|
|
494 | (formula_elements[marker].formula_type == |
|
|
495 | psiconv_formula_mark_opsep)) { |
|
|
496 | len--; |
502 | psiconv_progress(lev+3,off+len,"End of formula"); |
497 | psiconv_progress(lev+3,off+len,"End of this formula list"); |
503 | eof = 1; |
498 | eof = 1; |
504 | } else if (formula_elements[marker].formula_type == |
499 | } else if (formula_elements[marker].formula_type == |
505 | psiconv_formula_dat_int) { |
500 | psiconv_formula_dat_int) { |
506 | psiconv_progress(lev+3,off+len,"Next item: an integer"); |
501 | psiconv_progress(lev+3,off+len,"Next item: an integer"); |
507 | formula->data.dat_int = psiconv_read_u32(buf,lev+2,off+len,&res); |
502 | formula->data.dat_int = psiconv_read_u32(buf,lev+2,off+len,&res); |
… | |
… | |
561 | goto ERROR8; |
556 | goto ERROR8; |
562 | formula->type = psiconv_formula_unknown; |
557 | formula->type = psiconv_formula_unknown; |
563 | } else if ((formula_elements[marker].formula_type == |
558 | } else if ((formula_elements[marker].formula_type == |
564 | psiconv_formula_dat_var) || |
559 | psiconv_formula_dat_var) || |
565 | (formula_elements[marker].formula_type == |
560 | (formula_elements[marker].formula_type == |
566 | psiconv_formula_dat_vcellblock) || |
561 | psiconv_formula_dat_vcellblock)) { |
567 | (formula_elements[marker].formula_type == |
|
|
568 | psiconv_formula_mark_opsep) || |
|
|
569 | (formula_elements[marker].formula_type == |
|
|
570 | psiconv_formula_mark_opend)) { |
|
|
571 | psiconv_warn(lev+3,off+len,"Not yet supported formula mark!"); |
562 | psiconv_warn(lev+3,off+len,"Not yet supported formula mark!"); |
572 | goto ERROR8; |
563 | goto ERROR8; |
573 | } else if (formula_elements[marker].number_of_args == -1) { |
564 | } else if (formula_elements[marker].number_of_args == -1) { |
574 | psiconv_warn(lev+3,off+len,"Vararg functions not yet supported!"); |
565 | psiconv_warn(lev+3,off+len,"Vararg functions not yet supported!"); |
575 | goto ERROR8; |
566 | goto ERROR8; |
… | |
… | |
606 | goto ERROR8; |
597 | goto ERROR8; |
607 | subformula4->type = subformula3->type = subformula2->type = |
598 | subformula4->type = subformula3->type = subformula2->type = |
608 | subformula1->type = formula->type = psiconv_formula_unknown; |
599 | subformula1->type = formula->type = psiconv_formula_unknown; |
609 | } |
600 | } |
610 | } |
601 | } |
611 | if ((len != bytelen) || !eof) { |
602 | if ((len+off > maxlen) || !eof) { |
612 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
603 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
613 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
604 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
614 | bytelen,len); |
605 | maxlen,len+off); |
615 | goto ERROR8; |
606 | goto ERROR8; |
616 | } |
607 | } |
617 | if ((psiconv_list_length(formula_stack)) != 1) { |
608 | if ((psiconv_list_length(formula_stack)) != 1) { |
618 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
609 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
619 | psiconv_debug(lev+2,off+len,"More than one item left on the stack (%d)", |
610 | psiconv_debug(lev+2,off+len,"More than one item left on the stack (%d)", |
… | |
… | |
627 | |
618 | |
628 | if (length) |
619 | if (length) |
629 | *length = len; |
620 | *length = len; |
630 | |
621 | |
631 | psiconv_progress(lev,off+len-1, |
622 | psiconv_progress(lev,off+len-1, |
632 | "End of formula (total length: %08x)", len); |
623 | "End of formula element list (total length: %08x)", len); |
633 | return 0; |
624 | return 0; |
634 | |
625 | |
635 | ERROR8: |
626 | ERROR8: |
636 | psiconv_free_formula(subformula4); |
627 | psiconv_free_formula(subformula4); |
637 | ERROR7: |
628 | ERROR7: |
… | |
… | |
645 | ERROR3: |
636 | ERROR3: |
646 | psiconv_free_formula_list(formula_stack); |
637 | psiconv_free_formula_list(formula_stack); |
647 | ERROR2: |
638 | ERROR2: |
648 | free (*result); |
639 | free (*result); |
649 | ERROR1: |
640 | ERROR1: |
650 | psiconv_warn(lev+1,off,"Reading of formula failed"); |
641 | psiconv_warn(lev+1,off,"Reading of formula element list failed"); |
651 | if (length) |
642 | if (length) |
652 | *length = 0; |
643 | *length = 0; |
653 | if (!res) |
644 | if (!res) |
654 | return -PSICONV_E_NOMEM; |
645 | return -PSICONV_E_NOMEM; |
655 | else |
646 | else |
656 | return res; |
647 | return res; |
657 | } |
648 | } |
658 | |
649 | |
|
|
650 | |
|
|
651 | |
|
|
652 | |
|
|
653 | int psiconv_parse_formula(const psiconv_buffer buf, int lev, |
|
|
654 | psiconv_u32 off, int *length, |
|
|
655 | psiconv_formula *result) |
|
|
656 | { |
|
|
657 | int res=0; |
|
|
658 | int len=0; |
|
|
659 | int leng; |
|
|
660 | psiconv_u32 bytelen,formula_end; |
|
|
661 | psiconv_u8 temp; |
|
|
662 | |
|
|
663 | psiconv_progress(lev+1,off,"Going to read a formula"); |
|
|
664 | |
|
|
665 | psiconv_progress(lev+2,off+len, |
|
|
666 | "Going to read the formula byte length"); |
|
|
667 | bytelen = psiconv_read_S(buf,lev+2,off+len,&leng,&res); |
|
|
668 | if (res) |
|
|
669 | goto ERROR1; |
|
|
670 | psiconv_debug(lev+2,off+len,"Formula byte length: %d",bytelen); |
|
|
671 | len += leng; |
|
|
672 | bytelen += len; |
|
|
673 | formula_end = off + bytelen; |
|
|
674 | |
|
|
675 | psiconv_progress(lev+2,off+len,"Going to read the formula elements list"); |
|
|
676 | if ((res = psiconv_parse_formula_element_list(buf,lev+2,off+len,&leng, |
|
|
677 | result,formula_end))) |
|
|
678 | goto ERROR1; |
|
|
679 | len += leng; |
|
|
680 | |
|
|
681 | psiconv_progress(lev+2,off+len,"Going to read the eof marker"); |
|
|
682 | temp = psiconv_read_u8(buf,lev+2,off+len,&res); |
|
|
683 | if (res) |
|
|
684 | goto ERROR2; |
|
|
685 | if (formula_elements[temp].formula_type != psiconv_formula_mark_eof) { |
|
|
686 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
|
|
687 | psiconv_debug(lev+2,off+len,"Expected marker: %02x, found byte: %02x", |
|
|
688 | 0x15,temp); |
|
|
689 | goto ERROR2; |
|
|
690 | } |
|
|
691 | len ++; |
|
|
692 | |
|
|
693 | if (off+len != formula_end) { |
|
|
694 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
|
|
695 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
|
|
696 | formula_end,len+off); |
|
|
697 | goto ERROR2; |
|
|
698 | } |
|
|
699 | |
|
|
700 | if (length) |
|
|
701 | *length = len; |
|
|
702 | |
|
|
703 | psiconv_progress(lev,off+len-1, |
|
|
704 | "End of formula (total length: %08x)", len); |
|
|
705 | return 0; |
|
|
706 | |
|
|
707 | ERROR2: |
|
|
708 | psiconv_free_formula(*result); |
|
|
709 | ERROR1: |
|
|
710 | psiconv_warn(lev+1,off,"Reading of formula failed"); |
|
|
711 | if (length) |
|
|
712 | *length = 0; |
|
|
713 | if (!res) |
|
|
714 | return -PSICONV_E_NOMEM; |
|
|
715 | else |
|
|
716 | return res; |
|
|
717 | } |
|
|
718 | |
|
|
719 | |