| author | |
| committer | |
| log | ee9d1d0414ac6cc877e86055dcb08543db9b57ad |
| tree | ce3b8d86127d634179ea4c78fa9a19fdc730ad6e |
| parent | 848504117f17a5fa8ead8c168e0e430e22be6e43 |
7 files changed, 1987 insertions(+), 28 deletions(-)
src/all_types.hpp-2| ... | ... | @@ -833,7 +833,6 @@ struct AstNode { |
| 833 | 833 | enum NodeType type; |
| 834 | 834 | size_t line; |
| 835 | 835 | size_t column; |
| 836 | uint32_t create_index; // for determinism purposes | |
| 837 | 836 | ImportTableEntry *owner; |
| 838 | 837 | union { |
| 839 | 838 | AstNodeRoot root; |
| ... | ... | @@ -1523,7 +1522,6 @@ struct CodeGen { |
| 1523 | 1522 | LLVMValueRef return_address_fn_val; |
| 1524 | 1523 | LLVMValueRef frame_address_fn_val; |
| 1525 | 1524 | bool error_during_imports; |
| 1526 | uint32_t next_node_index; | |
| 1527 | 1525 | TypeTableEntry *err_tag_type; |
| 1528 | 1526 | |
| 1529 | 1527 | const char **clang_argv; |
src/analyze.cpp+1-2| ... | ... | @@ -3163,8 +3163,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a |
| 3163 | 3163 | import_entry->line_offsets = tokenization.line_offsets; |
| 3164 | 3164 | import_entry->path = abs_full_path; |
| 3165 | 3165 | |
| 3166 | import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color, | |
| 3167 | &g->next_node_index); | |
| 3166 | import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color); | |
| 3168 | 3167 | assert(import_entry->root); |
| 3169 | 3168 | if (g->verbose) { |
| 3170 | 3169 | ast_print(stderr, import_entry->root, 0); |
src/parseh.cpp+493-17| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 | |
| 18 | 18 | #include <clang/Frontend/ASTUnit.h> |
| 19 | 19 | #include <clang/Frontend/CompilerInstance.h> |
| 20 | #include <clang/AST/Expr.h> | |
| 20 | 21 | |
| 21 | 22 | #include <string.h> |
| 22 | 23 | |
| ... | ... | @@ -54,6 +55,7 @@ struct Context { |
| 54 | 55 | uint32_t next_anon_index; |
| 55 | 56 | |
| 56 | 57 | CodeGen *codegen; |
| 58 | ASTContext *ctx; | |
| 57 | 59 | }; |
| 58 | 60 | |
| 59 | 61 | static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl, |
| ... | ... | @@ -602,9 +604,477 @@ static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *de |
| 602 | 604 | return resolve_qual_type_with_table(c, qt, decl, &c->global_type_table); |
| 603 | 605 | } |
| 604 | 606 | |
| 607 | #include "ast_render.hpp" | |
| 608 | ||
| 609 | static AstNode * ast_trans_stmt(Context *c, Stmt *stmt); | |
| 610 | ||
| 611 | static AstNode * ast_trans_expr(Context *c, Expr *expr) { | |
| 612 | return ast_trans_stmt(c, expr); | |
| 613 | } | |
| 614 | ||
| 615 | static AstNode * ast_create_node(Context *c, const SourceRange &range, NodeType id) { | |
| 616 | AstNode *node = allocate<AstNode>(1); | |
| 617 | node->type = id; | |
| 618 | node->owner = c->import; | |
| 619 | // TODO line/column. mapping to C file?? | |
| 620 | return node; | |
| 621 | } | |
| 622 | ||
| 623 | static AstNode * ast_trans_compound_stmt(Context *c, CompoundStmt *stmt) { | |
| 624 | AstNode *block_node = ast_create_node(c, stmt->getSourceRange(), NodeTypeBlock); | |
| 625 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | |
| 626 | AstNode *child_node = ast_trans_stmt(c, *it); | |
| 627 | block_node->data.block.statements.append(child_node); | |
| 628 | } | |
| 629 | return block_node; | |
| 630 | } | |
| 631 | ||
| 632 | static AstNode *ast_trans_return_stmt(Context *c, ReturnStmt *stmt) { | |
| 633 | Expr *value_expr = stmt->getRetValue(); | |
| 634 | if (value_expr == nullptr) { | |
| 635 | zig_panic("TODO handle C return void"); | |
| 636 | } else { | |
| 637 | AstNode *return_node = ast_create_node(c, stmt->getSourceRange(), NodeTypeReturnExpr); | |
| 638 | return_node->data.return_expr.expr = ast_trans_expr(c, value_expr); | |
| 639 | return return_node; | |
| 640 | } | |
| 641 | } | |
| 642 | ||
| 643 | static void aps_int_to_bigint(Context *c, const llvm::APSInt &aps_int, BigInt *bigint) { | |
| 644 | // TODO respect actually big integers | |
| 645 | if (aps_int.isSigned()) { | |
| 646 | if (aps_int > INT64_MAX || aps_int < INT64_MIN) { | |
| 647 | zig_panic("TODO actually bigint in C"); | |
| 648 | } else { | |
| 649 | bigint_init_signed(bigint, aps_int.getExtValue()); | |
| 650 | } | |
| 651 | } else { | |
| 652 | if (aps_int > INT64_MAX) { | |
| 653 | zig_panic("TODO actually bigint in C"); | |
| 654 | } else { | |
| 655 | bigint_init_unsigned(bigint, aps_int.getExtValue()); | |
| 656 | } | |
| 657 | } | |
| 658 | } | |
| 659 | static AstNode * ast_trans_integer_literal(Context *c, IntegerLiteral *stmt) { | |
| 660 | AstNode *node = ast_create_node(c, stmt->getSourceRange(), NodeTypeIntLiteral); | |
| 661 | llvm::APSInt result; | |
| 662 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { | |
| 663 | fprintf(stderr, "TODO unable to convert integer literal to zig\n"); | |
| 664 | } | |
| 665 | node->data.int_literal.bigint = allocate<BigInt>(1); | |
| 666 | aps_int_to_bigint(c, result, node->data.int_literal.bigint); | |
| 667 | return node; | |
| 668 | } | |
| 669 | ||
| 670 | static AstNode *ast_trans_stmt(Context *c, Stmt *stmt) { | |
| 671 | Stmt::StmtClass sc = stmt->getStmtClass(); | |
| 672 | switch (sc) { | |
| 673 | case Stmt::ReturnStmtClass: | |
| 674 | return ast_trans_return_stmt(c, (ReturnStmt *)stmt); | |
| 675 | case Stmt::CompoundStmtClass: | |
| 676 | return ast_trans_compound_stmt(c, (CompoundStmt *)stmt); | |
| 677 | case Stmt::IntegerLiteralClass: | |
| 678 | return ast_trans_integer_literal(c, (IntegerLiteral *)stmt); | |
| 679 | case Stmt::CaseStmtClass: | |
| 680 | zig_panic("TODO handle C CaseStmtClass"); | |
| 681 | case Stmt::DefaultStmtClass: | |
| 682 | zig_panic("TODO handle C DefaultStmtClass"); | |
| 683 | case Stmt::SwitchStmtClass: | |
| 684 | zig_panic("TODO handle C SwitchStmtClass"); | |
| 685 | case Stmt::WhileStmtClass: | |
| 686 | zig_panic("TODO handle C WhileStmtClass"); | |
| 687 | case Stmt::NoStmtClass: | |
| 688 | zig_panic("TODO handle C NoStmtClass"); | |
| 689 | case Stmt::GCCAsmStmtClass: | |
| 690 | zig_panic("TODO handle C GCCAsmStmtClass"); | |
| 691 | case Stmt::MSAsmStmtClass: | |
| 692 | zig_panic("TODO handle C MSAsmStmtClass"); | |
| 693 | case Stmt::AttributedStmtClass: | |
| 694 | zig_panic("TODO handle C AttributedStmtClass"); | |
| 695 | case Stmt::BreakStmtClass: | |
| 696 | zig_panic("TODO handle C BreakStmtClass"); | |
| 697 | case Stmt::CXXCatchStmtClass: | |
| 698 | zig_panic("TODO handle C CXXCatchStmtClass"); | |
| 699 | case Stmt::CXXForRangeStmtClass: | |
| 700 | zig_panic("TODO handle C CXXForRangeStmtClass"); | |
| 701 | case Stmt::CXXTryStmtClass: | |
| 702 | zig_panic("TODO handle C CXXTryStmtClass"); | |
| 703 | case Stmt::CapturedStmtClass: | |
| 704 | zig_panic("TODO handle C CapturedStmtClass"); | |
| 705 | case Stmt::ContinueStmtClass: | |
| 706 | zig_panic("TODO handle C ContinueStmtClass"); | |
| 707 | case Stmt::CoreturnStmtClass: | |
| 708 | zig_panic("TODO handle C CoreturnStmtClass"); | |
| 709 | case Stmt::CoroutineBodyStmtClass: | |
| 710 | zig_panic("TODO handle C CoroutineBodyStmtClass"); | |
| 711 | case Stmt::DeclStmtClass: | |
| 712 | zig_panic("TODO handle C DeclStmtClass"); | |
| 713 | case Stmt::DoStmtClass: | |
| 714 | zig_panic("TODO handle C DoStmtClass"); | |
| 715 | case Stmt::BinaryConditionalOperatorClass: | |
| 716 | zig_panic("TODO handle C BinaryConditionalOperatorClass"); | |
| 717 | case Stmt::ConditionalOperatorClass: | |
| 718 | zig_panic("TODO handle C ConditionalOperatorClass"); | |
| 719 | case Stmt::AddrLabelExprClass: | |
| 720 | zig_panic("TODO handle C AddrLabelExprClass"); | |
| 721 | case Stmt::ArrayInitIndexExprClass: | |
| 722 | zig_panic("TODO handle C ArrayInitIndexExprClass"); | |
| 723 | case Stmt::ArrayInitLoopExprClass: | |
| 724 | zig_panic("TODO handle C ArrayInitLoopExprClass"); | |
| 725 | case Stmt::ArraySubscriptExprClass: | |
| 726 | zig_panic("TODO handle C ArraySubscriptExprClass"); | |
| 727 | case Stmt::ArrayTypeTraitExprClass: | |
| 728 | zig_panic("TODO handle C ArrayTypeTraitExprClass"); | |
| 729 | case Stmt::AsTypeExprClass: | |
| 730 | zig_panic("TODO handle C AsTypeExprClass"); | |
| 731 | case Stmt::AtomicExprClass: | |
| 732 | zig_panic("TODO handle C AtomicExprClass"); | |
| 733 | case Stmt::BinaryOperatorClass: | |
| 734 | zig_panic("TODO handle C BinaryOperatorClass"); | |
| 735 | case Stmt::CompoundAssignOperatorClass: | |
| 736 | zig_panic("TODO handle C CompoundAssignOperatorClass"); | |
| 737 | case Stmt::BlockExprClass: | |
| 738 | zig_panic("TODO handle C BlockExprClass"); | |
| 739 | case Stmt::CXXBindTemporaryExprClass: | |
| 740 | zig_panic("TODO handle C CXXBindTemporaryExprClass"); | |
| 741 | case Stmt::CXXBoolLiteralExprClass: | |
| 742 | zig_panic("TODO handle C CXXBoolLiteralExprClass"); | |
| 743 | case Stmt::CXXConstructExprClass: | |
| 744 | zig_panic("TODO handle C CXXConstructExprClass"); | |
| 745 | case Stmt::CXXTemporaryObjectExprClass: | |
| 746 | zig_panic("TODO handle C CXXTemporaryObjectExprClass"); | |
| 747 | case Stmt::CXXDefaultArgExprClass: | |
| 748 | zig_panic("TODO handle C CXXDefaultArgExprClass"); | |
| 749 | case Stmt::CXXDefaultInitExprClass: | |
| 750 | zig_panic("TODO handle C CXXDefaultInitExprClass"); | |
| 751 | case Stmt::CXXDeleteExprClass: | |
| 752 | zig_panic("TODO handle C CXXDeleteExprClass"); | |
| 753 | case Stmt::CXXDependentScopeMemberExprClass: | |
| 754 | zig_panic("TODO handle C CXXDependentScopeMemberExprClass"); | |
| 755 | case Stmt::CXXFoldExprClass: | |
| 756 | zig_panic("TODO handle C CXXFoldExprClass"); | |
| 757 | case Stmt::CXXInheritedCtorInitExprClass: | |
| 758 | zig_panic("TODO handle C CXXInheritedCtorInitExprClass"); | |
| 759 | case Stmt::CXXNewExprClass: | |
| 760 | zig_panic("TODO handle C CXXNewExprClass"); | |
| 761 | case Stmt::CXXNoexceptExprClass: | |
| 762 | zig_panic("TODO handle C CXXNoexceptExprClass"); | |
| 763 | case Stmt::CXXNullPtrLiteralExprClass: | |
| 764 | zig_panic("TODO handle C CXXNullPtrLiteralExprClass"); | |
| 765 | case Stmt::CXXPseudoDestructorExprClass: | |
| 766 | zig_panic("TODO handle C CXXPseudoDestructorExprClass"); | |
| 767 | case Stmt::CXXScalarValueInitExprClass: | |
| 768 | zig_panic("TODO handle C CXXScalarValueInitExprClass"); | |
| 769 | case Stmt::CXXStdInitializerListExprClass: | |
| 770 | zig_panic("TODO handle C CXXStdInitializerListExprClass"); | |
| 771 | case Stmt::CXXThisExprClass: | |
| 772 | zig_panic("TODO handle C CXXThisExprClass"); | |
| 773 | case Stmt::CXXThrowExprClass: | |
| 774 | zig_panic("TODO handle C CXXThrowExprClass"); | |
| 775 | case Stmt::CXXTypeidExprClass: | |
| 776 | zig_panic("TODO handle C CXXTypeidExprClass"); | |
| 777 | case Stmt::CXXUnresolvedConstructExprClass: | |
| 778 | zig_panic("TODO handle C CXXUnresolvedConstructExprClass"); | |
| 779 | case Stmt::CXXUuidofExprClass: | |
| 780 | zig_panic("TODO handle C CXXUuidofExprClass"); | |
| 781 | case Stmt::CallExprClass: | |
| 782 | zig_panic("TODO handle C CallExprClass"); | |
| 783 | case Stmt::CUDAKernelCallExprClass: | |
| 784 | zig_panic("TODO handle C CUDAKernelCallExprClass"); | |
| 785 | case Stmt::CXXMemberCallExprClass: | |
| 786 | zig_panic("TODO handle C CXXMemberCallExprClass"); | |
| 787 | case Stmt::CXXOperatorCallExprClass: | |
| 788 | zig_panic("TODO handle C CXXOperatorCallExprClass"); | |
| 789 | case Stmt::UserDefinedLiteralClass: | |
| 790 | zig_panic("TODO handle C UserDefinedLiteralClass"); | |
| 791 | case Stmt::CStyleCastExprClass: | |
| 792 | zig_panic("TODO handle C CStyleCastExprClass"); | |
| 793 | case Stmt::CXXFunctionalCastExprClass: | |
| 794 | zig_panic("TODO handle C CXXFunctionalCastExprClass"); | |
| 795 | case Stmt::CXXConstCastExprClass: | |
| 796 | zig_panic("TODO handle C CXXConstCastExprClass"); | |
| 797 | case Stmt::CXXDynamicCastExprClass: | |
| 798 | zig_panic("TODO handle C CXXDynamicCastExprClass"); | |
| 799 | case Stmt::CXXReinterpretCastExprClass: | |
| 800 | zig_panic("TODO handle C CXXReinterpretCastExprClass"); | |
| 801 | case Stmt::CXXStaticCastExprClass: | |
| 802 | zig_panic("TODO handle C CXXStaticCastExprClass"); | |
| 803 | case Stmt::ObjCBridgedCastExprClass: | |
| 804 | zig_panic("TODO handle C ObjCBridgedCastExprClass"); | |
| 805 | case Stmt::ImplicitCastExprClass: | |
| 806 | zig_panic("TODO handle C ImplicitCastExprClass"); | |
| 807 | case Stmt::CharacterLiteralClass: | |
| 808 | zig_panic("TODO handle C CharacterLiteralClass"); | |
| 809 | case Stmt::ChooseExprClass: | |
| 810 | zig_panic("TODO handle C ChooseExprClass"); | |
| 811 | case Stmt::CompoundLiteralExprClass: | |
| 812 | zig_panic("TODO handle C CompoundLiteralExprClass"); | |
| 813 | case Stmt::ConvertVectorExprClass: | |
| 814 | zig_panic("TODO handle C ConvertVectorExprClass"); | |
| 815 | case Stmt::CoawaitExprClass: | |
| 816 | zig_panic("TODO handle C CoawaitExprClass"); | |
| 817 | case Stmt::CoyieldExprClass: | |
| 818 | zig_panic("TODO handle C CoyieldExprClass"); | |
| 819 | case Stmt::DeclRefExprClass: | |
| 820 | zig_panic("TODO handle C DeclRefExprClass"); | |
| 821 | case Stmt::DependentCoawaitExprClass: | |
| 822 | zig_panic("TODO handle C DependentCoawaitExprClass"); | |
| 823 | case Stmt::DependentScopeDeclRefExprClass: | |
| 824 | zig_panic("TODO handle C DependentScopeDeclRefExprClass"); | |
| 825 | case Stmt::DesignatedInitExprClass: | |
| 826 | zig_panic("TODO handle C DesignatedInitExprClass"); | |
| 827 | case Stmt::DesignatedInitUpdateExprClass: | |
| 828 | zig_panic("TODO handle C DesignatedInitUpdateExprClass"); | |
| 829 | case Stmt::ExprWithCleanupsClass: | |
| 830 | zig_panic("TODO handle C ExprWithCleanupsClass"); | |
| 831 | case Stmt::ExpressionTraitExprClass: | |
| 832 | zig_panic("TODO handle C ExpressionTraitExprClass"); | |
| 833 | case Stmt::ExtVectorElementExprClass: | |
| 834 | zig_panic("TODO handle C ExtVectorElementExprClass"); | |
| 835 | case Stmt::FloatingLiteralClass: | |
| 836 | zig_panic("TODO handle C FloatingLiteralClass"); | |
| 837 | case Stmt::FunctionParmPackExprClass: | |
| 838 | zig_panic("TODO handle C FunctionParmPackExprClass"); | |
| 839 | case Stmt::GNUNullExprClass: | |
| 840 | zig_panic("TODO handle C GNUNullExprClass"); | |
| 841 | case Stmt::GenericSelectionExprClass: | |
| 842 | zig_panic("TODO handle C GenericSelectionExprClass"); | |
| 843 | case Stmt::ImaginaryLiteralClass: | |
| 844 | zig_panic("TODO handle C ImaginaryLiteralClass"); | |
| 845 | case Stmt::ImplicitValueInitExprClass: | |
| 846 | zig_panic("TODO handle C ImplicitValueInitExprClass"); | |
| 847 | case Stmt::InitListExprClass: | |
| 848 | zig_panic("TODO handle C InitListExprClass"); | |
| 849 | case Stmt::LambdaExprClass: | |
| 850 | zig_panic("TODO handle C LambdaExprClass"); | |
| 851 | case Stmt::MSPropertyRefExprClass: | |
| 852 | zig_panic("TODO handle C MSPropertyRefExprClass"); | |
| 853 | case Stmt::MSPropertySubscriptExprClass: | |
| 854 | zig_panic("TODO handle C MSPropertySubscriptExprClass"); | |
| 855 | case Stmt::MaterializeTemporaryExprClass: | |
| 856 | zig_panic("TODO handle C MaterializeTemporaryExprClass"); | |
| 857 | case Stmt::MemberExprClass: | |
| 858 | zig_panic("TODO handle C MemberExprClass"); | |
| 859 | case Stmt::NoInitExprClass: | |
| 860 | zig_panic("TODO handle C NoInitExprClass"); | |
| 861 | case Stmt::OMPArraySectionExprClass: | |
| 862 | zig_panic("TODO handle C OMPArraySectionExprClass"); | |
| 863 | case Stmt::ObjCArrayLiteralClass: | |
| 864 | zig_panic("TODO handle C ObjCArrayLiteralClass"); | |
| 865 | case Stmt::ObjCAvailabilityCheckExprClass: | |
| 866 | zig_panic("TODO handle C ObjCAvailabilityCheckExprClass"); | |
| 867 | case Stmt::ObjCBoolLiteralExprClass: | |
| 868 | zig_panic("TODO handle C ObjCBoolLiteralExprClass"); | |
| 869 | case Stmt::ObjCBoxedExprClass: | |
| 870 | zig_panic("TODO handle C ObjCBoxedExprClass"); | |
| 871 | case Stmt::ObjCDictionaryLiteralClass: | |
| 872 | zig_panic("TODO handle C ObjCDictionaryLiteralClass"); | |
| 873 | case Stmt::ObjCEncodeExprClass: | |
| 874 | zig_panic("TODO handle C ObjCEncodeExprClass"); | |
| 875 | case Stmt::ObjCIndirectCopyRestoreExprClass: | |
| 876 | zig_panic("TODO handle C ObjCIndirectCopyRestoreExprClass"); | |
| 877 | case Stmt::ObjCIsaExprClass: | |
| 878 | zig_panic("TODO handle C ObjCIsaExprClass"); | |
| 879 | case Stmt::ObjCIvarRefExprClass: | |
| 880 | zig_panic("TODO handle C ObjCIvarRefExprClass"); | |
| 881 | case Stmt::ObjCMessageExprClass: | |
| 882 | zig_panic("TODO handle C ObjCMessageExprClass"); | |
| 883 | case Stmt::ObjCPropertyRefExprClass: | |
| 884 | zig_panic("TODO handle C ObjCPropertyRefExprClass"); | |
| 885 | case Stmt::ObjCProtocolExprClass: | |
| 886 | zig_panic("TODO handle C ObjCProtocolExprClass"); | |
| 887 | case Stmt::ObjCSelectorExprClass: | |
| 888 | zig_panic("TODO handle C ObjCSelectorExprClass"); | |
| 889 | case Stmt::ObjCStringLiteralClass: | |
| 890 | zig_panic("TODO handle C ObjCStringLiteralClass"); | |
| 891 | case Stmt::ObjCSubscriptRefExprClass: | |
| 892 | zig_panic("TODO handle C ObjCSubscriptRefExprClass"); | |
| 893 | case Stmt::OffsetOfExprClass: | |
| 894 | zig_panic("TODO handle C OffsetOfExprClass"); | |
| 895 | case Stmt::OpaqueValueExprClass: | |
| 896 | zig_panic("TODO handle C OpaqueValueExprClass"); | |
| 897 | case Stmt::UnresolvedLookupExprClass: | |
| 898 | zig_panic("TODO handle C UnresolvedLookupExprClass"); | |
| 899 | case Stmt::UnresolvedMemberExprClass: | |
| 900 | zig_panic("TODO handle C UnresolvedMemberExprClass"); | |
| 901 | case Stmt::PackExpansionExprClass: | |
| 902 | zig_panic("TODO handle C PackExpansionExprClass"); | |
| 903 | case Stmt::ParenExprClass: | |
| 904 | zig_panic("TODO handle C ParenExprClass"); | |
| 905 | case Stmt::ParenListExprClass: | |
| 906 | zig_panic("TODO handle C ParenListExprClass"); | |
| 907 | case Stmt::PredefinedExprClass: | |
| 908 | zig_panic("TODO handle C PredefinedExprClass"); | |
| 909 | case Stmt::PseudoObjectExprClass: | |
| 910 | zig_panic("TODO handle C PseudoObjectExprClass"); | |
| 911 | case Stmt::ShuffleVectorExprClass: | |
| 912 | zig_panic("TODO handle C ShuffleVectorExprClass"); | |
| 913 | case Stmt::SizeOfPackExprClass: | |
| 914 | zig_panic("TODO handle C SizeOfPackExprClass"); | |
| 915 | case Stmt::StmtExprClass: | |
| 916 | zig_panic("TODO handle C StmtExprClass"); | |
| 917 | case Stmt::StringLiteralClass: | |
| 918 | zig_panic("TODO handle C StringLiteralClass"); | |
| 919 | case Stmt::SubstNonTypeTemplateParmExprClass: | |
| 920 | zig_panic("TODO handle C SubstNonTypeTemplateParmExprClass"); | |
| 921 | case Stmt::SubstNonTypeTemplateParmPackExprClass: | |
| 922 | zig_panic("TODO handle C SubstNonTypeTemplateParmPackExprClass"); | |
| 923 | case Stmt::TypeTraitExprClass: | |
| 924 | zig_panic("TODO handle C TypeTraitExprClass"); | |
| 925 | case Stmt::TypoExprClass: | |
| 926 | zig_panic("TODO handle C TypoExprClass"); | |
| 927 | case Stmt::UnaryExprOrTypeTraitExprClass: | |
| 928 | zig_panic("TODO handle C UnaryExprOrTypeTraitExprClass"); | |
| 929 | case Stmt::UnaryOperatorClass: | |
| 930 | zig_panic("TODO handle C UnaryOperatorClass"); | |
| 931 | case Stmt::VAArgExprClass: | |
| 932 | zig_panic("TODO handle C VAArgExprClass"); | |
| 933 | case Stmt::ForStmtClass: | |
| 934 | zig_panic("TODO handle C ForStmtClass"); | |
| 935 | case Stmt::GotoStmtClass: | |
| 936 | zig_panic("TODO handle C GotoStmtClass"); | |
| 937 | case Stmt::IfStmtClass: | |
| 938 | zig_panic("TODO handle C IfStmtClass"); | |
| 939 | case Stmt::IndirectGotoStmtClass: | |
| 940 | zig_panic("TODO handle C IndirectGotoStmtClass"); | |
| 941 | case Stmt::LabelStmtClass: | |
| 942 | zig_panic("TODO handle C LabelStmtClass"); | |
| 943 | case Stmt::MSDependentExistsStmtClass: | |
| 944 | zig_panic("TODO handle C MSDependentExistsStmtClass"); | |
| 945 | case Stmt::NullStmtClass: | |
| 946 | zig_panic("TODO handle C NullStmtClass"); | |
| 947 | case Stmt::OMPAtomicDirectiveClass: | |
| 948 | zig_panic("TODO handle C OMPAtomicDirectiveClass"); | |
| 949 | case Stmt::OMPBarrierDirectiveClass: | |
| 950 | zig_panic("TODO handle C OMPBarrierDirectiveClass"); | |
| 951 | case Stmt::OMPCancelDirectiveClass: | |
| 952 | zig_panic("TODO handle C OMPCancelDirectiveClass"); | |
| 953 | case Stmt::OMPCancellationPointDirectiveClass: | |
| 954 | zig_panic("TODO handle C OMPCancellationPointDirectiveClass"); | |
| 955 | case Stmt::OMPCriticalDirectiveClass: | |
| 956 | zig_panic("TODO handle C OMPCriticalDirectiveClass"); | |
| 957 | case Stmt::OMPFlushDirectiveClass: | |
| 958 | zig_panic("TODO handle C OMPFlushDirectiveClass"); | |
| 959 | case Stmt::OMPDistributeDirectiveClass: | |
| 960 | zig_panic("TODO handle C OMPDistributeDirectiveClass"); | |
| 961 | case Stmt::OMPDistributeParallelForDirectiveClass: | |
| 962 | zig_panic("TODO handle C OMPDistributeParallelForDirectiveClass"); | |
| 963 | case Stmt::OMPDistributeParallelForSimdDirectiveClass: | |
| 964 | zig_panic("TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | |
| 965 | case Stmt::OMPDistributeSimdDirectiveClass: | |
| 966 | zig_panic("TODO handle C OMPDistributeSimdDirectiveClass"); | |
| 967 | case Stmt::OMPForDirectiveClass: | |
| 968 | zig_panic("TODO handle C OMPForDirectiveClass"); | |
| 969 | case Stmt::OMPForSimdDirectiveClass: | |
| 970 | zig_panic("TODO handle C OMPForSimdDirectiveClass"); | |
| 971 | case Stmt::OMPParallelForDirectiveClass: | |
| 972 | zig_panic("TODO handle C OMPParallelForDirectiveClass"); | |
| 973 | case Stmt::OMPParallelForSimdDirectiveClass: | |
| 974 | zig_panic("TODO handle C OMPParallelForSimdDirectiveClass"); | |
| 975 | case Stmt::OMPSimdDirectiveClass: | |
| 976 | zig_panic("TODO handle C OMPSimdDirectiveClass"); | |
| 977 | case Stmt::OMPTargetParallelForSimdDirectiveClass: | |
| 978 | zig_panic("TODO handle C OMPTargetParallelForSimdDirectiveClass"); | |
| 979 | case Stmt::OMPTargetSimdDirectiveClass: | |
| 980 | zig_panic("TODO handle C OMPTargetSimdDirectiveClass"); | |
| 981 | case Stmt::OMPTargetTeamsDistributeDirectiveClass: | |
| 982 | zig_panic("TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | |
| 983 | case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: | |
| 984 | zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | |
| 985 | case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | |
| 986 | zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | |
| 987 | case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: | |
| 988 | zig_panic("TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | |
| 989 | case Stmt::OMPTaskLoopDirectiveClass: | |
| 990 | zig_panic("TODO handle C OMPTaskLoopDirectiveClass"); | |
| 991 | case Stmt::OMPTaskLoopSimdDirectiveClass: | |
| 992 | zig_panic("TODO handle C OMPTaskLoopSimdDirectiveClass"); | |
| 993 | case Stmt::OMPTeamsDistributeDirectiveClass: | |
| 994 | zig_panic("TODO handle C OMPTeamsDistributeDirectiveClass"); | |
| 995 | case Stmt::OMPTeamsDistributeParallelForDirectiveClass: | |
| 996 | zig_panic("TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | |
| 997 | case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: | |
| 998 | zig_panic("TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | |
| 999 | case Stmt::OMPTeamsDistributeSimdDirectiveClass: | |
| 1000 | zig_panic("TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | |
| 1001 | case Stmt::OMPMasterDirectiveClass: | |
| 1002 | zig_panic("TODO handle C OMPMasterDirectiveClass"); | |
| 1003 | case Stmt::OMPOrderedDirectiveClass: | |
| 1004 | zig_panic("TODO handle C OMPOrderedDirectiveClass"); | |
| 1005 | case Stmt::OMPParallelDirectiveClass: | |
| 1006 | zig_panic("TODO handle C OMPParallelDirectiveClass"); | |
| 1007 | case Stmt::OMPParallelSectionsDirectiveClass: | |
| 1008 | zig_panic("TODO handle C OMPParallelSectionsDirectiveClass"); | |
| 1009 | case Stmt::OMPSectionDirectiveClass: | |
| 1010 | zig_panic("TODO handle C OMPSectionDirectiveClass"); | |
| 1011 | case Stmt::OMPSectionsDirectiveClass: | |
| 1012 | zig_panic("TODO handle C OMPSectionsDirectiveClass"); | |
| 1013 | case Stmt::OMPSingleDirectiveClass: | |
| 1014 | zig_panic("TODO handle C OMPSingleDirectiveClass"); | |
| 1015 | case Stmt::OMPTargetDataDirectiveClass: | |
| 1016 | zig_panic("TODO handle C OMPTargetDataDirectiveClass"); | |
| 1017 | case Stmt::OMPTargetDirectiveClass: | |
| 1018 | zig_panic("TODO handle C OMPTargetDirectiveClass"); | |
| 1019 | case Stmt::OMPTargetEnterDataDirectiveClass: | |
| 1020 | zig_panic("TODO handle C OMPTargetEnterDataDirectiveClass"); | |
| 1021 | case Stmt::OMPTargetExitDataDirectiveClass: | |
| 1022 | zig_panic("TODO handle C OMPTargetExitDataDirectiveClass"); | |
| 1023 | case Stmt::OMPTargetParallelDirectiveClass: | |
| 1024 | zig_panic("TODO handle C OMPTargetParallelDirectiveClass"); | |
| 1025 | case Stmt::OMPTargetParallelForDirectiveClass: | |
| 1026 | zig_panic("TODO handle C OMPTargetParallelForDirectiveClass"); | |
| 1027 | case Stmt::OMPTargetTeamsDirectiveClass: | |
| 1028 | zig_panic("TODO handle C OMPTargetTeamsDirectiveClass"); | |
| 1029 | case Stmt::OMPTargetUpdateDirectiveClass: | |
| 1030 | zig_panic("TODO handle C OMPTargetUpdateDirectiveClass"); | |
| 1031 | case Stmt::OMPTaskDirectiveClass: | |
| 1032 | zig_panic("TODO handle C OMPTaskDirectiveClass"); | |
| 1033 | case Stmt::OMPTaskgroupDirectiveClass: | |
| 1034 | zig_panic("TODO handle C OMPTaskgroupDirectiveClass"); | |
| 1035 | case Stmt::OMPTaskwaitDirectiveClass: | |
| 1036 | zig_panic("TODO handle C OMPTaskwaitDirectiveClass"); | |
| 1037 | case Stmt::OMPTaskyieldDirectiveClass: | |
| 1038 | zig_panic("TODO handle C OMPTaskyieldDirectiveClass"); | |
| 1039 | case Stmt::OMPTeamsDirectiveClass: | |
| 1040 | zig_panic("TODO handle C OMPTeamsDirectiveClass"); | |
| 1041 | case Stmt::ObjCAtCatchStmtClass: | |
| 1042 | zig_panic("TODO handle C ObjCAtCatchStmtClass"); | |
| 1043 | case Stmt::ObjCAtFinallyStmtClass: | |
| 1044 | zig_panic("TODO handle C ObjCAtFinallyStmtClass"); | |
| 1045 | case Stmt::ObjCAtSynchronizedStmtClass: | |
| 1046 | zig_panic("TODO handle C ObjCAtSynchronizedStmtClass"); | |
| 1047 | case Stmt::ObjCAtThrowStmtClass: | |
| 1048 | zig_panic("TODO handle C ObjCAtThrowStmtClass"); | |
| 1049 | case Stmt::ObjCAtTryStmtClass: | |
| 1050 | zig_panic("TODO handle C ObjCAtTryStmtClass"); | |
| 1051 | case Stmt::ObjCAutoreleasePoolStmtClass: | |
| 1052 | zig_panic("TODO handle C ObjCAutoreleasePoolStmtClass"); | |
| 1053 | case Stmt::ObjCForCollectionStmtClass: | |
| 1054 | zig_panic("TODO handle C ObjCForCollectionStmtClass"); | |
| 1055 | case Stmt::SEHExceptStmtClass: | |
| 1056 | zig_panic("TODO handle C SEHExceptStmtClass"); | |
| 1057 | case Stmt::SEHFinallyStmtClass: | |
| 1058 | zig_panic("TODO handle C SEHFinallyStmtClass"); | |
| 1059 | case Stmt::SEHLeaveStmtClass: | |
| 1060 | zig_panic("TODO handle C SEHLeaveStmtClass"); | |
| 1061 | case Stmt::SEHTryStmtClass: | |
| 1062 | zig_panic("TODO handle C SEHTryStmtClass"); | |
| 1063 | } | |
| 1064 | zig_unreachable(); | |
| 1065 | } | |
| 1066 | ||
| 605 | 1067 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 606 | 1068 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); |
| 607 | 1069 | |
| 1070 | if (fn_decl->hasBody()) { | |
| 1071 | fprintf(stderr, "fn %s\n", buf_ptr(fn_name)); | |
| 1072 | Stmt *body = fn_decl->getBody(); | |
| 1073 | AstNode *body_node = ast_trans_stmt(c, body); | |
| 1074 | ast_render(c->codegen, stderr, body_node, 4); | |
| 1075 | fprintf(stderr, "\n"); | |
| 1076 | } | |
| 1077 | ||
| 608 | 1078 | if (get_global(c, fn_name)) { |
| 609 | 1079 | // we already saw this function |
| 610 | 1080 | return; |
| ... | ... | @@ -1373,7 +1843,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1373 | 1843 | |
| 1374 | 1844 | std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>(); |
| 1375 | 1845 | |
| 1376 | bool skip_function_bodies = true; | |
| 1846 | bool skip_function_bodies = false; | |
| 1377 | 1847 | bool only_local_decls = true; |
| 1378 | 1848 | bool capture_diagnostics = true; |
| 1379 | 1849 | bool user_files_are_volatile = true; |
| ... | ... | @@ -1390,7 +1860,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1390 | 1860 | single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit, |
| 1391 | 1861 | nullptr)); |
| 1392 | 1862 | |
| 1393 | ||
| 1394 | 1863 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. |
| 1395 | 1864 | if (!ast_unit && !err_unit) { |
| 1396 | 1865 | return ErrorFileSystem; |
| ... | ... | @@ -1416,29 +1885,36 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1416 | 1885 | break; |
| 1417 | 1886 | } |
| 1418 | 1887 | StringRef msg_str_ref = it->getMessage(); |
| 1419 | FullSourceLoc fsl = it->getLocation(); | |
| 1420 | FileID file_id = fsl.getFileID(); | |
| 1421 | StringRef filename = fsl.getManager().getFilename(fsl); | |
| 1422 | unsigned line = fsl.getSpellingLineNumber() - 1; | |
| 1423 | unsigned column = fsl.getSpellingColumnNumber() - 1; | |
| 1424 | unsigned offset = fsl.getManager().getFileOffset(fsl); | |
| 1425 | const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); | |
| 1426 | 1888 | Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin()); |
| 1427 | Buf *path; | |
| 1428 | if (filename.empty()) { | |
| 1429 | path = buf_alloc(); | |
| 1430 | } else { | |
| 1431 | path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size()); | |
| 1432 | } | |
| 1889 | FullSourceLoc fsl = it->getLocation(); | |
| 1890 | if (fsl.hasManager()) { | |
| 1891 | FileID file_id = fsl.getFileID(); | |
| 1892 | StringRef filename = fsl.getManager().getFilename(fsl); | |
| 1893 | unsigned line = fsl.getSpellingLineNumber() - 1; | |
| 1894 | unsigned column = fsl.getSpellingColumnNumber() - 1; | |
| 1895 | unsigned offset = fsl.getManager().getFileOffset(fsl); | |
| 1896 | const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); | |
| 1897 | Buf *path; | |
| 1898 | if (filename.empty()) { | |
| 1899 | path = buf_alloc(); | |
| 1900 | } else { | |
| 1901 | path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size()); | |
| 1902 | } | |
| 1433 | 1903 | |
| 1434 | ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); | |
| 1904 | ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); | |
| 1435 | 1905 | |
| 1436 | c->errors->append(err_msg); | |
| 1906 | c->errors->append(err_msg); | |
| 1907 | } else { | |
| 1908 | // NOTE the only known way this gets triggered right now is if you have a lot of errors | |
| 1909 | // clang emits "too many errors emitted, stopping now" | |
| 1910 | fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg)); | |
| 1911 | } | |
| 1437 | 1912 | } |
| 1438 | 1913 | |
| 1439 | 1914 | return 0; |
| 1440 | 1915 | } |
| 1441 | 1916 | |
| 1917 | c->ctx = &ast_unit->getASTContext(); | |
| 1442 | 1918 | c->source_manager = &ast_unit->getSourceManager(); |
| 1443 | 1919 | |
| 1444 | 1920 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); |
src/parser.cpp+1-5| ... | ... | @@ -20,7 +20,6 @@ struct ParseContext { |
| 20 | 20 | ZigList<Token> *tokens; |
| 21 | 21 | ImportTableEntry *owner; |
| 22 | 22 | ErrColor err_color; |
| 23 | uint32_t *next_node_index; | |
| 24 | 23 | // These buffers are used freqently so we preallocate them once here. |
| 25 | 24 | Buf *void_buf; |
| 26 | 25 | Buf *empty_buf; |
| ... | ... | @@ -70,8 +69,6 @@ static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { |
| 70 | 69 | AstNode *node = allocate<AstNode>(1); |
| 71 | 70 | node->type = type; |
| 72 | 71 | node->owner = pc->owner; |
| 73 | node->create_index = *pc->next_node_index; | |
| 74 | *pc->next_node_index += 1; | |
| 75 | 72 | return node; |
| 76 | 73 | } |
| 77 | 74 | |
| ... | ... | @@ -2611,7 +2608,7 @@ static AstNode *ast_parse_root(ParseContext *pc, size_t *token_index) { |
| 2611 | 2608 | } |
| 2612 | 2609 | |
| 2613 | 2610 | AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, |
| 2614 | ErrColor err_color, uint32_t *next_node_index) | |
| 2611 | ErrColor err_color) | |
| 2615 | 2612 | { |
| 2616 | 2613 | ParseContext pc = {0}; |
| 2617 | 2614 | pc.void_buf = buf_create_from_str("void"); |
| ... | ... | @@ -2620,7 +2617,6 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, |
| 2620 | 2617 | pc.owner = owner; |
| 2621 | 2618 | pc.buf = buf; |
| 2622 | 2619 | pc.tokens = tokens; |
| 2623 | pc.next_node_index = next_node_index; | |
| 2624 | 2620 | size_t token_index = 0; |
| 2625 | 2621 | pc.root = ast_parse_root(&pc, &token_index); |
| 2626 | 2622 | return pc.root; |
src/parser.hpp+1-2| ... | ... | @@ -17,8 +17,7 @@ void ast_token_error(Token *token, const char *format, ...); |
| 17 | 17 | |
| 18 | 18 | |
| 19 | 19 | // This function is provided by generated code, generated by parsergen.cpp |
| 20 | AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, ErrColor err_color, | |
| 21 | uint32_t *next_node_index); | |
| 20 | AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, ErrColor err_color); | |
| 22 | 21 | |
| 23 | 22 | void ast_print(AstNode *node, int indent); |
| 24 | 23 |
std/zlib/deflate.zig created+522| ... | ... | @@ -0,0 +1,522 @@ |
| 1 | const z_stream = struct { | |
| 2 | /// next input byte */ | |
| 3 | next_in: &const u8, | |
| 4 | ||
| 5 | /// number of bytes available at next_in | |
| 6 | avail_in: u16, | |
| 7 | /// total number of input bytes read so far | |
| 8 | total_in: u32, | |
| 9 | ||
| 10 | /// next output byte will go here | |
| 11 | next_out: u8, | |
| 12 | /// remaining free space at next_out | |
| 13 | avail_out: u16, | |
| 14 | /// total number of bytes output so far | |
| 15 | total_out: u32, | |
| 16 | ||
| 17 | /// last error message, NULL if no error | |
| 18 | msg: ?&const u8, | |
| 19 | /// not visible by applications | |
| 20 | state: | |
| 21 | struct internal_state FAR *state; // not visible by applications */ | |
| 22 | ||
| 23 | alloc_func zalloc; // used to allocate the internal state */ | |
| 24 | free_func zfree; // used to free the internal state */ | |
| 25 | voidpf opaque; // private data object passed to zalloc and zfree */ | |
| 26 | ||
| 27 | int data_type; // best guess about the data type: binary or text | |
| 28 | // for deflate, or the decoding state for inflate */ | |
| 29 | uint32_t adler; // Adler-32 or CRC-32 value of the uncompressed data */ | |
| 30 | uint32_t reserved; // reserved for future use */ | |
| 31 | }; | |
| 32 | ||
| 33 | typedef struct internal_state { | |
| 34 | z_stream * strm; /* pointer back to this zlib stream */ | |
| 35 | int status; /* as the name implies */ | |
| 36 | uint8_t *pending_buf; /* output still pending */ | |
| 37 | ulg pending_buf_size; /* size of pending_buf */ | |
| 38 | uint8_t *pending_out; /* next pending byte to output to the stream */ | |
| 39 | ulg pending; /* nb of bytes in the pending buffer */ | |
| 40 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | |
| 41 | gz_headerp gzhead; /* gzip header information to write */ | |
| 42 | ulg gzindex; /* where in extra, name, or comment */ | |
| 43 | uint8_t method; /* can only be DEFLATED */ | |
| 44 | int last_flush; /* value of flush param for previous deflate call */ | |
| 45 | ||
| 46 | /* used by deflate.c: */ | |
| 47 | ||
| 48 | uint16_t w_size; /* LZ77 window size (32K by default) */ | |
| 49 | uint16_t w_bits; /* log2(w_size) (8..16) */ | |
| 50 | uint16_t w_mask; /* w_size - 1 */ | |
| 51 | ||
| 52 | uint8_t *window; | |
| 53 | /* Sliding window. Input bytes are read into the second half of the window, | |
| 54 | * and move to the first half later to keep a dictionary of at least wSize | |
| 55 | * bytes. With this organization, matches are limited to a distance of | |
| 56 | * wSize-MAX_MATCH bytes, but this ensures that IO is always | |
| 57 | * performed with a length multiple of the block size. Also, it limits | |
| 58 | * the window size to 64K, which is quite useful on MSDOS. | |
| 59 | * To do: use the user input buffer as sliding window. | |
| 60 | */ | |
| 61 | ||
| 62 | ulg window_size; | |
| 63 | /* Actual size of window: 2*wSize, except when the user input buffer | |
| 64 | * is directly used as sliding window. | |
| 65 | */ | |
| 66 | ||
| 67 | Posf *prev; | |
| 68 | /* Link to older string with same hash index. To limit the size of this | |
| 69 | * array to 64K, this link is maintained only for the last 32K strings. | |
| 70 | * An index in this array is thus a window index modulo 32K. | |
| 71 | */ | |
| 72 | ||
| 73 | Posf *head; /* Heads of the hash chains or NIL. */ | |
| 74 | ||
| 75 | uint16_t ins_h; /* hash index of string to be inserted */ | |
| 76 | uint16_t hash_size; /* number of elements in hash table */ | |
| 77 | uint16_t hash_bits; /* log2(hash_size) */ | |
| 78 | uint16_t hash_mask; /* hash_size-1 */ | |
| 79 | ||
| 80 | uint16_t hash_shift; | |
| 81 | /* Number of bits by which ins_h must be shifted at each input | |
| 82 | * step. It must be such that after MIN_MATCH steps, the oldest | |
| 83 | * byte no longer takes part in the hash key, that is: | |
| 84 | * hash_shift * MIN_MATCH >= hash_bits | |
| 85 | */ | |
| 86 | ||
| 87 | long block_start; | |
| 88 | /* Window position at the beginning of the current output block. Gets | |
| 89 | * negative when the window is moved backwards. | |
| 90 | */ | |
| 91 | ||
| 92 | uint16_t match_length; /* length of best match */ | |
| 93 | IPos prev_match; /* previous match */ | |
| 94 | int match_available; /* set if previous match exists */ | |
| 95 | uint16_t strstart; /* start of string to insert */ | |
| 96 | uint16_t match_start; /* start of matching string */ | |
| 97 | uint16_t lookahead; /* number of valid bytes ahead in window */ | |
| 98 | ||
| 99 | uint16_t prev_length; | |
| 100 | /* Length of the best match at previous step. Matches not greater than this | |
| 101 | * are discarded. This is used in the lazy match evaluation. | |
| 102 | */ | |
| 103 | ||
| 104 | uint16_t max_chain_length; | |
| 105 | /* To speed up deflation, hash chains are never searched beyond this | |
| 106 | * length. A higher limit improves compression ratio but degrades the | |
| 107 | * speed. | |
| 108 | */ | |
| 109 | ||
| 110 | uint16_t max_lazy_match; | |
| 111 | /* Attempt to find a better match only when the current match is strictly | |
| 112 | * smaller than this value. This mechanism is used only for compression | |
| 113 | * levels >= 4. | |
| 114 | */ | |
| 115 | # define max_insert_length max_lazy_match | |
| 116 | /* Insert new strings in the hash table only if the match length is not | |
| 117 | * greater than this length. This saves time but degrades compression. | |
| 118 | * max_insert_length is used only for compression levels <= 3. | |
| 119 | */ | |
| 120 | ||
| 121 | int level; /* compression level (1..9) */ | |
| 122 | int strategy; /* favor or force Huffman coding*/ | |
| 123 | ||
| 124 | uint16_t good_match; | |
| 125 | /* Use a faster search when the previous match is longer than this */ | |
| 126 | ||
| 127 | int nice_match; /* Stop searching when current match exceeds this */ | |
| 128 | ||
| 129 | /* used by trees.c: */ | |
| 130 | /* Didn't use ct_data typedef below to suppress compiler warning */ | |
| 131 | struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ | |
| 132 | struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ | |
| 133 | struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ | |
| 134 | ||
| 135 | struct tree_desc_s l_desc; /* desc. for literal tree */ | |
| 136 | struct tree_desc_s d_desc; /* desc. for distance tree */ | |
| 137 | struct tree_desc_s bl_desc; /* desc. for bit length tree */ | |
| 138 | ||
| 139 | ush bl_count[MAX_BITS+1]; | |
| 140 | /* number of codes at each bit length for an optimal tree */ | |
| 141 | ||
| 142 | int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ | |
| 143 | int heap_len; /* number of elements in the heap */ | |
| 144 | int heap_max; /* element of largest frequency */ | |
| 145 | /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. | |
| 146 | * The same heap array is used to build all trees. | |
| 147 | */ | |
| 148 | ||
| 149 | uch depth[2*L_CODES+1]; | |
| 150 | /* Depth of each subtree used as tie breaker for trees of equal frequency | |
| 151 | */ | |
| 152 | ||
| 153 | uchf *l_buf; /* buffer for literals or lengths */ | |
| 154 | ||
| 155 | uint16_t lit_bufsize; | |
| 156 | /* Size of match buffer for literals/lengths. There are 4 reasons for | |
| 157 | * limiting lit_bufsize to 64K: | |
| 158 | * - frequencies can be kept in 16 bit counters | |
| 159 | * - if compression is not successful for the first block, all input | |
| 160 | * data is still in the window so we can still emit a stored block even | |
| 161 | * when input comes from standard input. (This can also be done for | |
| 162 | * all blocks if lit_bufsize is not greater than 32K.) | |
| 163 | * - if compression is not successful for a file smaller than 64K, we can | |
| 164 | * even emit a stored file instead of a stored block (saving 5 bytes). | |
| 165 | * This is applicable only for zip (not gzip or zlib). | |
| 166 | * - creating new Huffman trees less frequently may not provide fast | |
| 167 | * adaptation to changes in the input data statistics. (Take for | |
| 168 | * example a binary file with poorly compressible code followed by | |
| 169 | * a highly compressible string table.) Smaller buffer sizes give | |
| 170 | * fast adaptation but have of course the overhead of transmitting | |
| 171 | * trees more frequently. | |
| 172 | * - I can't count above 4 | |
| 173 | */ | |
| 174 | ||
| 175 | uint16_t last_lit; /* running index in l_buf */ | |
| 176 | ||
| 177 | ushf *d_buf; | |
| 178 | /* Buffer for distances. To simplify the code, d_buf and l_buf have | |
| 179 | * the same number of elements. To use different lengths, an extra flag | |
| 180 | * array would be necessary. | |
| 181 | */ | |
| 182 | ||
| 183 | ulg opt_len; /* bit length of current block with optimal trees */ | |
| 184 | ulg static_len; /* bit length of current block with static trees */ | |
| 185 | uint16_t matches; /* number of string matches in current block */ | |
| 186 | uint16_t insert; /* bytes at end of window left to insert */ | |
| 187 | ||
| 188 | #ifdef ZLIB_DEBUG | |
| 189 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ | |
| 190 | ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ | |
| 191 | #endif | |
| 192 | ||
| 193 | ush bi_buf; | |
| 194 | /* Output buffer. bits are inserted starting at the bottom (least | |
| 195 | * significant bits). | |
| 196 | */ | |
| 197 | int bi_valid; | |
| 198 | /* Number of valid bits in bi_buf. All bits above the last valid bit | |
| 199 | * are always zero. | |
| 200 | */ | |
| 201 | ||
| 202 | ulg high_water; | |
| 203 | /* High water mark offset in window for initialized bytes -- bytes above | |
| 204 | * this are set to zero in order to avoid memory check warnings when | |
| 205 | * longest match routines access bytes past the input. This is then | |
| 206 | * updated to the new high water mark. | |
| 207 | */ | |
| 208 | ||
| 209 | } FAR deflate_state; | |
| 210 | ||
| 211 | fn deflate(strm: &z_stream, flush: int) -> %void { | |
| 212 | ||
| 213 | } | |
| 214 | ||
| 215 | int deflate (z_stream * strm, int flush) { | |
| 216 | int old_flush; /* value of flush param for previous deflate call */ | |
| 217 | deflate_state *s; | |
| 218 | ||
| 219 | if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { | |
| 220 | return Z_STREAM_ERROR; | |
| 221 | } | |
| 222 | s = strm->state; | |
| 223 | ||
| 224 | if (strm->next_out == Z_NULL || | |
| 225 | (strm->avail_in != 0 && strm->next_in == Z_NULL) || | |
| 226 | (s->status == FINISH_STATE && flush != Z_FINISH)) { | |
| 227 | ERR_RETURN(strm, Z_STREAM_ERROR); | |
| 228 | } | |
| 229 | if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); | |
| 230 | ||
| 231 | old_flush = s->last_flush; | |
| 232 | s->last_flush = flush; | |
| 233 | ||
| 234 | /* Flush as much pending output as possible */ | |
| 235 | if (s->pending != 0) { | |
| 236 | flush_pending(strm); | |
| 237 | if (strm->avail_out == 0) { | |
| 238 | /* Since avail_out is 0, deflate will be called again with | |
| 239 | * more output space, but possibly with both pending and | |
| 240 | * avail_in equal to zero. There won't be anything to do, | |
| 241 | * but this is not an error situation so make sure we | |
| 242 | * return OK instead of BUF_ERROR at next call of deflate: | |
| 243 | */ | |
| 244 | s->last_flush = -1; | |
| 245 | return Z_OK; | |
| 246 | } | |
| 247 | ||
| 248 | /* Make sure there is something to do and avoid duplicate consecutive | |
| 249 | * flushes. For repeated and useless calls with Z_FINISH, we keep | |
| 250 | * returning Z_STREAM_END instead of Z_BUF_ERROR. | |
| 251 | */ | |
| 252 | } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && | |
| 253 | flush != Z_FINISH) { | |
| 254 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 255 | } | |
| 256 | ||
| 257 | /* User must not provide more input after the first FINISH: */ | |
| 258 | if (s->status == FINISH_STATE && strm->avail_in != 0) { | |
| 259 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 260 | } | |
| 261 | ||
| 262 | /* Write the header */ | |
| 263 | if (s->status == INIT_STATE) { | |
| 264 | /* zlib header */ | |
| 265 | uint16_t header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; | |
| 266 | uint16_t level_flags; | |
| 267 | ||
| 268 | if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) | |
| 269 | level_flags = 0; | |
| 270 | else if (s->level < 6) | |
| 271 | level_flags = 1; | |
| 272 | else if (s->level == 6) | |
| 273 | level_flags = 2; | |
| 274 | else | |
| 275 | level_flags = 3; | |
| 276 | header |= (level_flags << 6); | |
| 277 | if (s->strstart != 0) header |= PRESET_DICT; | |
| 278 | header += 31 - (header % 31); | |
| 279 | ||
| 280 | putShortMSB(s, header); | |
| 281 | ||
| 282 | /* Save the adler32 of the preset dictionary: */ | |
| 283 | if (s->strstart != 0) { | |
| 284 | putShortMSB(s, (uint16_t)(strm->adler >> 16)); | |
| 285 | putShortMSB(s, (uint16_t)(strm->adler & 0xffff)); | |
| 286 | } | |
| 287 | strm->adler = adler32(0L, Z_NULL, 0); | |
| 288 | s->status = BUSY_STATE; | |
| 289 | ||
| 290 | /* Compression must start with an empty pending buffer */ | |
| 291 | flush_pending(strm); | |
| 292 | if (s->pending != 0) { | |
| 293 | s->last_flush = -1; | |
| 294 | return Z_OK; | |
| 295 | } | |
| 296 | } | |
| 297 | #ifdef GZIP | |
| 298 | if (s->status == GZIP_STATE) { | |
| 299 | /* gzip header */ | |
| 300 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 301 | put_byte(s, 31); | |
| 302 | put_byte(s, 139); | |
| 303 | put_byte(s, 8); | |
| 304 | if (s->gzhead == Z_NULL) { | |
| 305 | put_byte(s, 0); | |
| 306 | put_byte(s, 0); | |
| 307 | put_byte(s, 0); | |
| 308 | put_byte(s, 0); | |
| 309 | put_byte(s, 0); | |
| 310 | put_byte(s, s->level == 9 ? 2 : | |
| 311 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 312 | 4 : 0)); | |
| 313 | put_byte(s, OS_CODE); | |
| 314 | s->status = BUSY_STATE; | |
| 315 | ||
| 316 | /* Compression must start with an empty pending buffer */ | |
| 317 | flush_pending(strm); | |
| 318 | if (s->pending != 0) { | |
| 319 | s->last_flush = -1; | |
| 320 | return Z_OK; | |
| 321 | } | |
| 322 | } | |
| 323 | else { | |
| 324 | put_byte(s, (s->gzhead->text ? 1 : 0) + | |
| 325 | (s->gzhead->hcrc ? 2 : 0) + | |
| 326 | (s->gzhead->extra == Z_NULL ? 0 : 4) + | |
| 327 | (s->gzhead->name == Z_NULL ? 0 : 8) + | |
| 328 | (s->gzhead->comment == Z_NULL ? 0 : 16) | |
| 329 | ); | |
| 330 | put_byte(s, (uint8_t)(s->gzhead->time & 0xff)); | |
| 331 | put_byte(s, (uint8_t)((s->gzhead->time >> 8) & 0xff)); | |
| 332 | put_byte(s, (uint8_t)((s->gzhead->time >> 16) & 0xff)); | |
| 333 | put_byte(s, (uint8_t)((s->gzhead->time >> 24) & 0xff)); | |
| 334 | put_byte(s, s->level == 9 ? 2 : | |
| 335 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 336 | 4 : 0)); | |
| 337 | put_byte(s, s->gzhead->os & 0xff); | |
| 338 | if (s->gzhead->extra != Z_NULL) { | |
| 339 | put_byte(s, s->gzhead->extra_len & 0xff); | |
| 340 | put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); | |
| 341 | } | |
| 342 | if (s->gzhead->hcrc) | |
| 343 | strm->adler = crc32(strm->adler, s->pending_buf, | |
| 344 | s->pending); | |
| 345 | s->gzindex = 0; | |
| 346 | s->status = EXTRA_STATE; | |
| 347 | } | |
| 348 | } | |
| 349 | if (s->status == EXTRA_STATE) { | |
| 350 | if (s->gzhead->extra != Z_NULL) { | |
| 351 | ulg beg = s->pending; /* start of bytes to update crc */ | |
| 352 | uint16_t left = (s->gzhead->extra_len & 0xffff) - s->gzindex; | |
| 353 | while (s->pending + left > s->pending_buf_size) { | |
| 354 | uint16_t copy = s->pending_buf_size - s->pending; | |
| 355 | zmemcpy(s->pending_buf + s->pending, | |
| 356 | s->gzhead->extra + s->gzindex, copy); | |
| 357 | s->pending = s->pending_buf_size; | |
| 358 | HCRC_UPDATE(beg); | |
| 359 | s->gzindex += copy; | |
| 360 | flush_pending(strm); | |
| 361 | if (s->pending != 0) { | |
| 362 | s->last_flush = -1; | |
| 363 | return Z_OK; | |
| 364 | } | |
| 365 | beg = 0; | |
| 366 | left -= copy; | |
| 367 | } | |
| 368 | zmemcpy(s->pending_buf + s->pending, | |
| 369 | s->gzhead->extra + s->gzindex, left); | |
| 370 | s->pending += left; | |
| 371 | HCRC_UPDATE(beg); | |
| 372 | s->gzindex = 0; | |
| 373 | } | |
| 374 | s->status = NAME_STATE; | |
| 375 | } | |
| 376 | if (s->status == NAME_STATE) { | |
| 377 | if (s->gzhead->name != Z_NULL) { | |
| 378 | ulg beg = s->pending; /* start of bytes to update crc */ | |
| 379 | int val; | |
| 380 | do { | |
| 381 | if (s->pending == s->pending_buf_size) { | |
| 382 | HCRC_UPDATE(beg); | |
| 383 | flush_pending(strm); | |
| 384 | if (s->pending != 0) { | |
| 385 | s->last_flush = -1; | |
| 386 | return Z_OK; | |
| 387 | } | |
| 388 | beg = 0; | |
| 389 | } | |
| 390 | val = s->gzhead->name[s->gzindex++]; | |
| 391 | put_byte(s, val); | |
| 392 | } while (val != 0); | |
| 393 | HCRC_UPDATE(beg); | |
| 394 | s->gzindex = 0; | |
| 395 | } | |
| 396 | s->status = COMMENT_STATE; | |
| 397 | } | |
| 398 | if (s->status == COMMENT_STATE) { | |
| 399 | if (s->gzhead->comment != Z_NULL) { | |
| 400 | ulg beg = s->pending; /* start of bytes to update crc */ | |
| 401 | int val; | |
| 402 | do { | |
| 403 | if (s->pending == s->pending_buf_size) { | |
| 404 | HCRC_UPDATE(beg); | |
| 405 | flush_pending(strm); | |
| 406 | if (s->pending != 0) { | |
| 407 | s->last_flush = -1; | |
| 408 | return Z_OK; | |
| 409 | } | |
| 410 | beg = 0; | |
| 411 | } | |
| 412 | val = s->gzhead->comment[s->gzindex++]; | |
| 413 | put_byte(s, val); | |
| 414 | } while (val != 0); | |
| 415 | HCRC_UPDATE(beg); | |
| 416 | } | |
| 417 | s->status = HCRC_STATE; | |
| 418 | } | |
| 419 | if (s->status == HCRC_STATE) { | |
| 420 | if (s->gzhead->hcrc) { | |
| 421 | if (s->pending + 2 > s->pending_buf_size) { | |
| 422 | flush_pending(strm); | |
| 423 | if (s->pending != 0) { | |
| 424 | s->last_flush = -1; | |
| 425 | return Z_OK; | |
| 426 | } | |
| 427 | } | |
| 428 | put_byte(s, (uint8_t)(strm->adler & 0xff)); | |
| 429 | put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff)); | |
| 430 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 431 | } | |
| 432 | s->status = BUSY_STATE; | |
| 433 | ||
| 434 | /* Compression must start with an empty pending buffer */ | |
| 435 | flush_pending(strm); | |
| 436 | if (s->pending != 0) { | |
| 437 | s->last_flush = -1; | |
| 438 | return Z_OK; | |
| 439 | } | |
| 440 | } | |
| 441 | #endif | |
| 442 | ||
| 443 | /* Start a new block or continue the current one. | |
| 444 | */ | |
| 445 | if (strm->avail_in != 0 || s->lookahead != 0 || | |
| 446 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | |
| 447 | block_state bstate; | |
| 448 | ||
| 449 | bstate = s->level == 0 ? deflate_stored(s, flush) : | |
| 450 | s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : | |
| 451 | s->strategy == Z_RLE ? deflate_rle(s, flush) : | |
| 452 | (*(configuration_table[s->level].func))(s, flush); | |
| 453 | ||
| 454 | if (bstate == finish_started || bstate == finish_done) { | |
| 455 | s->status = FINISH_STATE; | |
| 456 | } | |
| 457 | if (bstate == need_more || bstate == finish_started) { | |
| 458 | if (strm->avail_out == 0) { | |
| 459 | s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ | |
| 460 | } | |
| 461 | return Z_OK; | |
| 462 | /* If flush != Z_NO_FLUSH && avail_out == 0, the next call | |
| 463 | * of deflate should use the same flush parameter to make sure | |
| 464 | * that the flush is complete. So we don't have to output an | |
| 465 | * empty block here, this will be done at next call. This also | |
| 466 | * ensures that for a very small output buffer, we emit at most | |
| 467 | * one empty block. | |
| 468 | */ | |
| 469 | } | |
| 470 | if (bstate == block_done) { | |
| 471 | if (flush == Z_PARTIAL_FLUSH) { | |
| 472 | _tr_align(s); | |
| 473 | } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ | |
| 474 | _tr_stored_block(s, (char*)0, 0L, 0); | |
| 475 | /* For a full flush, this empty block will be recognized | |
| 476 | * as a special marker by inflate_sync(). | |
| 477 | */ | |
| 478 | if (flush == Z_FULL_FLUSH) { | |
| 479 | CLEAR_HASH(s); /* forget history */ | |
| 480 | if (s->lookahead == 0) { | |
| 481 | s->strstart = 0; | |
| 482 | s->block_start = 0L; | |
| 483 | s->insert = 0; | |
| 484 | } | |
| 485 | } | |
| 486 | } | |
| 487 | flush_pending(strm); | |
| 488 | if (strm->avail_out == 0) { | |
| 489 | s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ | |
| 490 | return Z_OK; | |
| 491 | } | |
| 492 | } | |
| 493 | } | |
| 494 | ||
| 495 | if (flush != Z_FINISH) return Z_OK; | |
| 496 | if (s->wrap <= 0) return Z_STREAM_END; | |
| 497 | ||
| 498 | /* Write the trailer */ | |
| 499 | #ifdef GZIP | |
| 500 | if (s->wrap == 2) { | |
| 501 | put_byte(s, (uint8_t)(strm->adler & 0xff)); | |
| 502 | put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff)); | |
| 503 | put_byte(s, (uint8_t)((strm->adler >> 16) & 0xff)); | |
| 504 | put_byte(s, (uint8_t)((strm->adler >> 24) & 0xff)); | |
| 505 | put_byte(s, (uint8_t)(strm->total_in & 0xff)); | |
| 506 | put_byte(s, (uint8_t)((strm->total_in >> 8) & 0xff)); | |
| 507 | put_byte(s, (uint8_t)((strm->total_in >> 16) & 0xff)); | |
| 508 | put_byte(s, (uint8_t)((strm->total_in >> 24) & 0xff)); | |
| 509 | } | |
| 510 | else | |
| 511 | #endif | |
| 512 | { | |
| 513 | putShortMSB(s, (uint16_t)(strm->adler >> 16)); | |
| 514 | putShortMSB(s, (uint16_t)(strm->adler & 0xffff)); | |
| 515 | } | |
| 516 | flush_pending(strm); | |
| 517 | /* If avail_out is zero, the application will call deflate again | |
| 518 | * to flush the rest. | |
| 519 | */ | |
| 520 | if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ | |
| 521 | return s->pending != 0 ? Z_OK : Z_STREAM_END; | |
| 522 | } |
std/zlib/inflate.zig created+969| ... | ... | @@ -0,0 +1,969 @@ |
| 1 | ||
| 2 | error Z_STREAM_ERROR; | |
| 3 | error Z_STREAM_END; | |
| 4 | error Z_NEED_DICT; | |
| 5 | error Z_ERRNO; | |
| 6 | error Z_STREAM_ERROR; | |
| 7 | error Z_DATA_ERROR; | |
| 8 | error Z_MEM_ERROR; | |
| 9 | error Z_BUF_ERROR; | |
| 10 | error Z_VERSION_ERROR; | |
| 11 | ||
| 12 | pub Flush = enum { | |
| 13 | NO_FLUSH, | |
| 14 | PARTIAL_FLUSH, | |
| 15 | SYNC_FLUSH, | |
| 16 | FULL_FLUSH, | |
| 17 | FINISH, | |
| 18 | BLOCK, | |
| 19 | TREES, | |
| 20 | }; | |
| 21 | ||
| 22 | const code = struct { | |
| 23 | /// operation, extra bits, table bits | |
| 24 | op: u8, | |
| 25 | /// bits in this part of the code | |
| 26 | bits: u8, | |
| 27 | /// offset in table or code value | |
| 28 | val: u16, | |
| 29 | }; | |
| 30 | ||
| 31 | /// State maintained between inflate() calls -- approximately 7K bytes, not | |
| 32 | /// including the allocated sliding window, which is up to 32K bytes. | |
| 33 | const inflate_state = struct { | |
| 34 | z_stream * strm; /* pointer back to this zlib stream */ | |
| 35 | inflate_mode mode; /* current inflate mode */ | |
| 36 | int last; /* true if processing last block */ | |
| 37 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip, | |
| 38 | bit 2 true to validate check value */ | |
| 39 | int havedict; /* true if dictionary provided */ | |
| 40 | int flags; /* gzip header method and flags (0 if zlib) */ | |
| 41 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ | |
| 42 | unsigned long check; /* protected copy of check value */ | |
| 43 | unsigned long total; /* protected copy of output count */ | |
| 44 | gz_headerp head; /* where to save gzip header information */ | |
| 45 | /* sliding window */ | |
| 46 | unsigned wbits; /* log base 2 of requested window size */ | |
| 47 | unsigned wsize; /* window size or zero if not using window */ | |
| 48 | unsigned whave; /* valid bytes in the window */ | |
| 49 | unsigned wnext; /* window write index */ | |
| 50 | u8 FAR *window; /* allocated sliding window, if needed */ | |
| 51 | /* bit accumulator */ | |
| 52 | unsigned long hold; /* input bit accumulator */ | |
| 53 | unsigned bits; /* number of bits in "in" */ | |
| 54 | /* for string and stored block copying */ | |
| 55 | unsigned length; /* literal or length of data to copy */ | |
| 56 | unsigned offset; /* distance back to copy string from */ | |
| 57 | /* for table and code decoding */ | |
| 58 | unsigned extra; /* extra bits needed */ | |
| 59 | /* fixed and dynamic code tables */ | |
| 60 | code const FAR *lencode; /* starting table for length/literal codes */ | |
| 61 | code const FAR *distcode; /* starting table for distance codes */ | |
| 62 | unsigned lenbits; /* index bits for lencode */ | |
| 63 | unsigned distbits; /* index bits for distcode */ | |
| 64 | /* dynamic table building */ | |
| 65 | unsigned ncode; /* number of code length code lengths */ | |
| 66 | unsigned nlen; /* number of length code lengths */ | |
| 67 | unsigned ndist; /* number of distance code lengths */ | |
| 68 | unsigned have; /* number of code lengths in lens[] */ | |
| 69 | code FAR *next; /* next available space in codes[] */ | |
| 70 | unsigned short lens[320]; /* temporary storage for code lengths */ | |
| 71 | unsigned short work[288]; /* work area for code table building */ | |
| 72 | code codes[ENOUGH]; /* space for code tables */ | |
| 73 | int sane; /* if false, allow invalid distance too far */ | |
| 74 | int back; /* bits back of last unprocessed length/lit */ | |
| 75 | unsigned was; /* initial length of match */ | |
| 76 | }; | |
| 77 | ||
| 78 | const alloc_func = fn(opaque: &c_void, items: u16, size: u16); | |
| 79 | const free_func = fn(opaque: &c_void, address: &c_void); | |
| 80 | ||
| 81 | const z_stream = struct { | |
| 82 | /// next input byte | |
| 83 | next_in: &u8, | |
| 84 | /// number of bytes available at next_in | |
| 85 | avail_in: u16, | |
| 86 | /// total number of input bytes read so far | |
| 87 | total_in: u32, | |
| 88 | ||
| 89 | /// next output byte will go here | |
| 90 | next_out: &u8, | |
| 91 | /// remaining free space at next_out | |
| 92 | avail_out: u16, | |
| 93 | /// total number of bytes output so far */ | |
| 94 | total_out: u32, | |
| 95 | ||
| 96 | /// last error message, NULL if no error | |
| 97 | msg: &const u8, | |
| 98 | /// not visible by applications | |
| 99 | state: &inflate_state, | |
| 100 | ||
| 101 | /// used to allocate the internal state | |
| 102 | zalloc: alloc_func, | |
| 103 | /// used to free the internal state | |
| 104 | zfree: free_func, | |
| 105 | /// private data object passed to zalloc and zfree | |
| 106 | opaque: &c_void, | |
| 107 | ||
| 108 | /// best guess about the data type: binary or text | |
| 109 | /// for deflate, or the decoding state for inflate | |
| 110 | data_type: i32, | |
| 111 | ||
| 112 | /// Adler-32 or CRC-32 value of the uncompressed data | |
| 113 | adler: u32, | |
| 114 | }; | |
| 115 | ||
| 116 | // Possible inflate modes between inflate() calls | |
| 117 | /// i: waiting for magic header | |
| 118 | pub const HEAD = 16180; | |
| 119 | /// i: waiting for method and flags (gzip) | |
| 120 | pub const FLAGS = 16181; | |
| 121 | /// i: waiting for modification time (gzip) | |
| 122 | pub const TIME = 16182; | |
| 123 | /// i: waiting for extra flags and operating system (gzip) | |
| 124 | pub const OS = 16183; | |
| 125 | /// i: waiting for extra length (gzip) | |
| 126 | pub const EXLEN = 16184; | |
| 127 | /// i: waiting for extra bytes (gzip) | |
| 128 | pub const EXTRA = 16185; | |
| 129 | /// i: waiting for end of file name (gzip) | |
| 130 | pub const NAME = 16186; | |
| 131 | /// i: waiting for end of comment (gzip) | |
| 132 | pub const COMMENT = 16187; | |
| 133 | /// i: waiting for header crc (gzip) | |
| 134 | pub const HCRC = 16188; | |
| 135 | /// i: waiting for dictionary check value | |
| 136 | pub const DICTID = 16189; | |
| 137 | /// waiting for inflateSetDictionary() call | |
| 138 | pub const DICT = 16190; | |
| 139 | /// i: waiting for type bits, including last-flag bit | |
| 140 | pub const TYPE = 16191; | |
| 141 | /// i: same, but skip check to exit inflate on new block | |
| 142 | pub const TYPEDO = 16192; | |
| 143 | /// i: waiting for stored size (length and complement) | |
| 144 | pub const STORED = 16193; | |
| 145 | /// i/o: same as COPY below, but only first time in | |
| 146 | pub const COPY_ = 16194; | |
| 147 | /// i/o: waiting for input or output to copy stored block | |
| 148 | pub const COPY = 16195; | |
| 149 | /// i: waiting for dynamic block table lengths | |
| 150 | pub const TABLE = 16196; | |
| 151 | /// i: waiting for code length code lengths | |
| 152 | pub const LENLENS = 16197; | |
| 153 | /// i: waiting for length/lit and distance code lengths | |
| 154 | pub const CODELENS = 16198; | |
| 155 | /// i: same as LEN below, but only first time in | |
| 156 | pub const LEN_ = 16199; | |
| 157 | /// i: waiting for length/lit/eob code | |
| 158 | pub const LEN = 16200; | |
| 159 | /// i: waiting for length extra bits | |
| 160 | pub const LENEXT = 16201; | |
| 161 | /// i: waiting for distance code | |
| 162 | pub const DIST = 16202; | |
| 163 | /// i: waiting for distance extra bits | |
| 164 | pub const DISTEXT = 16203; | |
| 165 | /// o: waiting for output space to copy string | |
| 166 | pub const MATCH = 16204; | |
| 167 | /// o: waiting for output space to write literal | |
| 168 | pub const LIT = 16205; | |
| 169 | /// i: waiting for 32-bit check value | |
| 170 | pub const CHECK = 16206; | |
| 171 | /// i: waiting for 32-bit length (gzip) | |
| 172 | pub const LENGTH = 16207; | |
| 173 | /// finished check, done -- remain here until reset | |
| 174 | pub const DONE = 16208; | |
| 175 | /// got a data error -- remain here until reset | |
| 176 | pub const BAD = 16209; | |
| 177 | /// got an inflate() memory error -- remain here until reset | |
| 178 | pub const MEM = 16210; | |
| 179 | /// looking for synchronization bytes to restart inflate() */ | |
| 180 | pub const SYNC = 16211; | |
| 181 | ||
| 182 | /// inflate() uses a state machine to process as much input data and generate as | |
| 183 | /// much output data as possible before returning. The state machine is | |
| 184 | /// structured roughly as follows: | |
| 185 | /// | |
| 186 | /// for (;;) switch (state) { | |
| 187 | /// ... | |
| 188 | /// case STATEn: | |
| 189 | /// if (not enough input data or output space to make progress) | |
| 190 | /// return; | |
| 191 | /// ... make progress ... | |
| 192 | /// state = STATEm; | |
| 193 | /// break; | |
| 194 | /// ... | |
| 195 | /// } | |
| 196 | /// | |
| 197 | /// so when inflate() is called again, the same case is attempted again, and | |
| 198 | /// if the appropriate resources are provided, the machine proceeds to the | |
| 199 | /// next state. The NEEDBITS() macro is usually the way the state evaluates | |
| 200 | /// whether it can proceed or should return. NEEDBITS() does the return if | |
| 201 | /// the requested bits are not available. The typical use of the BITS macros | |
| 202 | /// is: | |
| 203 | /// | |
| 204 | /// NEEDBITS(n); | |
| 205 | /// ... do something with BITS(n) ... | |
| 206 | /// DROPBITS(n); | |
| 207 | /// | |
| 208 | /// where NEEDBITS(n) either returns from inflate() if there isn't enough | |
| 209 | /// input left to load n bits into the accumulator, or it continues. BITS(n) | |
| 210 | /// gives the low n bits in the accumulator. When done, DROPBITS(n) drops | |
| 211 | /// the low n bits off the accumulator. INITBITS() clears the accumulator | |
| 212 | /// and sets the number of available bits to zero. BYTEBITS() discards just | |
| 213 | /// enough bits to put the accumulator on a byte boundary. After BYTEBITS() | |
| 214 | /// and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. | |
| 215 | /// | |
| 216 | /// NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return | |
| 217 | /// if there is no input available. The decoding of variable length codes uses | |
| 218 | /// PULLBYTE() directly in order to pull just enough bytes to decode the next | |
| 219 | /// code, and no more. | |
| 220 | /// | |
| 221 | /// Some states loop until they get enough input, making sure that enough | |
| 222 | /// state information is maintained to continue the loop where it left off | |
| 223 | /// if NEEDBITS() returns in the loop. For example, want, need, and keep | |
| 224 | /// would all have to actually be part of the saved state in case NEEDBITS() | |
| 225 | /// returns: | |
| 226 | /// | |
| 227 | /// case STATEw: | |
| 228 | /// while (want < need) { | |
| 229 | /// NEEDBITS(n); | |
| 230 | /// keep[want++] = BITS(n); | |
| 231 | /// DROPBITS(n); | |
| 232 | /// } | |
| 233 | /// state = STATEx; | |
| 234 | /// case STATEx: | |
| 235 | /// | |
| 236 | /// As shown above, if the next state is also the next case, then the break | |
| 237 | /// is omitted. | |
| 238 | /// | |
| 239 | /// A state may also return if there is not enough output space available to | |
| 240 | /// complete that state. Those states are copying stored data, writing a | |
| 241 | /// literal byte, and copying a matching string. | |
| 242 | /// | |
| 243 | /// When returning, a "goto inf_leave" is used to update the total counters, | |
| 244 | /// update the check value, and determine whether any progress has been made | |
| 245 | /// during that inflate() call in order to return the proper return code. | |
| 246 | /// Progress is defined as a change in either strm->avail_in or strm->avail_out. | |
| 247 | /// When there is a window, goto inf_leave will update the window with the last | |
| 248 | /// output written. If a goto inf_leave occurs in the middle of decompression | |
| 249 | /// and there is no window currently, goto inf_leave will create one and copy | |
| 250 | /// output to the window for the next call of inflate(). | |
| 251 | /// | |
| 252 | /// In this implementation, the flush parameter of inflate() only affects the | |
| 253 | /// return code (per zlib.h). inflate() always writes as much as possible to | |
| 254 | /// strm->next_out, given the space available and the provided input--the effect | |
| 255 | /// documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers | |
| 256 | /// the allocation of and copying into a sliding window until necessary, which | |
| 257 | /// provides the effect documented in zlib.h for Z_FINISH when the entire input | |
| 258 | /// stream available. So the only thing the flush parameter actually does is: | |
| 259 | /// when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it | |
| 260 | /// will return Z_BUF_ERROR if it has not reached the end of the stream. | |
| 261 | pub fn inflate(strm: &z_stream, flush: Flush, gunzip: bool) -> %void { | |
| 262 | // next input | |
| 263 | var next: &const u8 = undefined; | |
| 264 | // next output | |
| 265 | var put: &u8 = undefined; | |
| 266 | ||
| 267 | // available input and output | |
| 268 | var have: u16 = undefined; | |
| 269 | var left: u16 = undefined; | |
| 270 | ||
| 271 | // bit buffer | |
| 272 | var hold: u32 = undefined; | |
| 273 | // bits in bit buffer | |
| 274 | var bits: u16 = undefined; | |
| 275 | // save starting available input and output | |
| 276 | var in: u16 = undefined; | |
| 277 | var out: u16 = undefined; | |
| 278 | // number of stored or match bytes to copy | |
| 279 | var copy: u16 = undefined; | |
| 280 | // where to copy match bytes from | |
| 281 | var from: &u8 = undefined; | |
| 282 | // current decoding table entry | |
| 283 | var here: code = undefined; | |
| 284 | // parent table entry | |
| 285 | var last: code = undefined; | |
| 286 | // length to copy for repeats, bits to drop | |
| 287 | var len: u16 = undefined; | |
| 288 | ||
| 289 | // return code | |
| 290 | var ret: error = undefined; | |
| 291 | ||
| 292 | // buffer for gzip header crc calculation | |
| 293 | var hbuf: [4]u8 = undefined; | |
| 294 | ||
| 295 | // permutation of code lengths | |
| 296 | const short_order = []u16 = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | |
| 297 | ||
| 298 | if (inflateStateCheck(strm) or strm.next_out == Z_NULL or (strm.next_in == Z_NULL and strm.avail_in != 0)) { | |
| 299 | return error.Z_STREAM_ERROR; | |
| 300 | } | |
| 301 | ||
| 302 | var state: &inflate_state = strm.state; | |
| 303 | if (state.mode == TYPE) { | |
| 304 | state.mode = TYPEDO; // skip check | |
| 305 | } | |
| 306 | put = strm.next_out; \ | |
| 307 | left = strm.avail_out; \ | |
| 308 | next = strm.next_in; \ | |
| 309 | have = strm.avail_in; \ | |
| 310 | hold = state.hold; \ | |
| 311 | bits = state.bits; \ | |
| 312 | in = have; | |
| 313 | out = left; | |
| 314 | ret = Z_OK; | |
| 315 | for (;;) | |
| 316 | switch (state.mode) { | |
| 317 | case HEAD: | |
| 318 | if (state.wrap == 0) { | |
| 319 | state.mode = TYPEDO; | |
| 320 | break; | |
| 321 | } | |
| 322 | NEEDBITS(16); | |
| 323 | #ifdef GUNZIP | |
| 324 | if ((state.wrap & 2) && hold == 0x8b1f) { /* gzip header */ | |
| 325 | if (state.wbits == 0) | |
| 326 | state.wbits = 15; | |
| 327 | state.check = crc32(0L, Z_NULL, 0); | |
| 328 | CRC2(state.check, hold); | |
| 329 | INITBITS(); | |
| 330 | state.mode = FLAGS; | |
| 331 | break; | |
| 332 | } | |
| 333 | state.flags = 0; /* expect zlib header */ | |
| 334 | if (state.head != Z_NULL) | |
| 335 | state.head.done = -1; | |
| 336 | if (!(state.wrap & 1) || /* check if zlib header allowed */ | |
| 337 | #else | |
| 338 | if ( | |
| 339 | #endif | |
| 340 | ((BITS(8) << 8) + (hold >> 8)) % 31) { | |
| 341 | strm.msg = (char *)"incorrect header check"; | |
| 342 | state.mode = BAD; | |
| 343 | break; | |
| 344 | } | |
| 345 | if (BITS(4) != Z_DEFLATED) { | |
| 346 | strm.msg = (char *)"unknown compression method"; | |
| 347 | state.mode = BAD; | |
| 348 | break; | |
| 349 | } | |
| 350 | DROPBITS(4); | |
| 351 | len = BITS(4) + 8; | |
| 352 | if (state.wbits == 0) | |
| 353 | state.wbits = len; | |
| 354 | if (len > 15 || len > state.wbits) { | |
| 355 | strm.msg = (char *)"invalid window size"; | |
| 356 | state.mode = BAD; | |
| 357 | break; | |
| 358 | } | |
| 359 | state.dmax = 1U << len; | |
| 360 | Tracev((stderr, "inflate: zlib header ok\n")); | |
| 361 | strm.adler = state.check = adler32(0L, Z_NULL, 0); | |
| 362 | state.mode = hold & 0x200 ? DICTID : TYPE; | |
| 363 | INITBITS(); | |
| 364 | break; | |
| 365 | #ifdef GUNZIP | |
| 366 | case FLAGS: | |
| 367 | NEEDBITS(16); | |
| 368 | state.flags = (int)(hold); | |
| 369 | if ((state.flags & 0xff) != Z_DEFLATED) { | |
| 370 | strm.msg = (char *)"unknown compression method"; | |
| 371 | state.mode = BAD; | |
| 372 | break; | |
| 373 | } | |
| 374 | if (state.flags & 0xe000) { | |
| 375 | strm.msg = (char *)"unknown header flags set"; | |
| 376 | state.mode = BAD; | |
| 377 | break; | |
| 378 | } | |
| 379 | if (state.head != Z_NULL) | |
| 380 | state.head.text = (int)((hold >> 8) & 1); | |
| 381 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 382 | CRC2(state.check, hold); | |
| 383 | INITBITS(); | |
| 384 | state.mode = TIME; | |
| 385 | case TIME: | |
| 386 | NEEDBITS(32); | |
| 387 | if (state.head != Z_NULL) | |
| 388 | state.head.time = hold; | |
| 389 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 390 | CRC4(state.check, hold); | |
| 391 | INITBITS(); | |
| 392 | state.mode = OS; | |
| 393 | case OS: | |
| 394 | NEEDBITS(16); | |
| 395 | if (state.head != Z_NULL) { | |
| 396 | state.head.xflags = (int)(hold & 0xff); | |
| 397 | state.head.os = (int)(hold >> 8); | |
| 398 | } | |
| 399 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 400 | CRC2(state.check, hold); | |
| 401 | INITBITS(); | |
| 402 | state.mode = EXLEN; | |
| 403 | case EXLEN: | |
| 404 | if (state.flags & 0x0400) { | |
| 405 | NEEDBITS(16); | |
| 406 | state.length = (unsigned)(hold); | |
| 407 | if (state.head != Z_NULL) | |
| 408 | state.head.extra_len = (unsigned)hold; | |
| 409 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 410 | CRC2(state.check, hold); | |
| 411 | INITBITS(); | |
| 412 | } | |
| 413 | else if (state.head != Z_NULL) | |
| 414 | state.head.extra = Z_NULL; | |
| 415 | state.mode = EXTRA; | |
| 416 | case EXTRA: | |
| 417 | if (state.flags & 0x0400) { | |
| 418 | copy = state.length; | |
| 419 | if (copy > have) copy = have; | |
| 420 | if (copy) { | |
| 421 | if (state.head != Z_NULL && | |
| 422 | state.head.extra != Z_NULL) { | |
| 423 | len = state.head.extra_len - state.length; | |
| 424 | zmemcpy(state.head.extra + len, next, | |
| 425 | len + copy > state.head.extra_max ? | |
| 426 | state.head.extra_max - len : copy); | |
| 427 | } | |
| 428 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 429 | state.check = crc32(state.check, next, copy); | |
| 430 | have -= copy; | |
| 431 | next += copy; | |
| 432 | state.length -= copy; | |
| 433 | } | |
| 434 | if (state.length) goto inf_leave; | |
| 435 | } | |
| 436 | state.length = 0; | |
| 437 | state.mode = NAME; | |
| 438 | case NAME: | |
| 439 | if (state.flags & 0x0800) { | |
| 440 | if (have == 0) goto inf_leave; | |
| 441 | copy = 0; | |
| 442 | do { | |
| 443 | len = (unsigned)(next[copy++]); | |
| 444 | if (state.head != Z_NULL && | |
| 445 | state.head.name != Z_NULL && | |
| 446 | state.length < state.head.name_max) | |
| 447 | state.head.name[state.length++] = (Bytef)len; | |
| 448 | } while (len && copy < have); | |
| 449 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 450 | state.check = crc32(state.check, next, copy); | |
| 451 | have -= copy; | |
| 452 | next += copy; | |
| 453 | if (len) goto inf_leave; | |
| 454 | } | |
| 455 | else if (state.head != Z_NULL) | |
| 456 | state.head.name = Z_NULL; | |
| 457 | state.length = 0; | |
| 458 | state.mode = COMMENT; | |
| 459 | case COMMENT: | |
| 460 | if (state.flags & 0x1000) { | |
| 461 | if (have == 0) goto inf_leave; | |
| 462 | copy = 0; | |
| 463 | do { | |
| 464 | len = (unsigned)(next[copy++]); | |
| 465 | if (state.head != Z_NULL && | |
| 466 | state.head.comment != Z_NULL && | |
| 467 | state.length < state.head.comm_max) | |
| 468 | state.head.comment[state.length++] = (Bytef)len; | |
| 469 | } while (len && copy < have); | |
| 470 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 471 | state.check = crc32(state.check, next, copy); | |
| 472 | have -= copy; | |
| 473 | next += copy; | |
| 474 | if (len) goto inf_leave; | |
| 475 | } | |
| 476 | else if (state.head != Z_NULL) | |
| 477 | state.head.comment = Z_NULL; | |
| 478 | state.mode = HCRC; | |
| 479 | case HCRC: | |
| 480 | if (state.flags & 0x0200) { | |
| 481 | NEEDBITS(16); | |
| 482 | if ((state.wrap & 4) && hold != (state.check & 0xffff)) { | |
| 483 | strm.msg = (char *)"header crc mismatch"; | |
| 484 | state.mode = BAD; | |
| 485 | break; | |
| 486 | } | |
| 487 | INITBITS(); | |
| 488 | } | |
| 489 | if (state.head != Z_NULL) { | |
| 490 | state.head.hcrc = (int)((state.flags >> 9) & 1); | |
| 491 | state.head.done = 1; | |
| 492 | } | |
| 493 | strm.adler = state.check = crc32(0L, Z_NULL, 0); | |
| 494 | state.mode = TYPE; | |
| 495 | break; | |
| 496 | #endif | |
| 497 | case DICTID: | |
| 498 | NEEDBITS(32); | |
| 499 | strm.adler = state.check = ZSWAP32(hold); | |
| 500 | INITBITS(); | |
| 501 | state.mode = DICT; | |
| 502 | case DICT: | |
| 503 | if (state.havedict == 0) { | |
| 504 | strm.next_out = put; \ | |
| 505 | strm.avail_out = left; \ | |
| 506 | strm.next_in = next; \ | |
| 507 | strm.avail_in = have; \ | |
| 508 | state.hold = hold; \ | |
| 509 | state.bits = bits; \ | |
| 510 | return Z_NEED_DICT; | |
| 511 | } | |
| 512 | strm.adler = state.check = adler32(0L, Z_NULL, 0); | |
| 513 | state.mode = TYPE; | |
| 514 | case TYPE: | |
| 515 | if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; | |
| 516 | case TYPEDO: | |
| 517 | if (state.last) { | |
| 518 | BYTEBITS(); | |
| 519 | state.mode = CHECK; | |
| 520 | break; | |
| 521 | } | |
| 522 | NEEDBITS(3); | |
| 523 | state.last = BITS(1); | |
| 524 | DROPBITS(1); | |
| 525 | switch (BITS(2)) { | |
| 526 | case 0: /* stored block */ | |
| 527 | Tracev((stderr, "inflate: stored block%s\n", | |
| 528 | state.last ? " (last)" : "")); | |
| 529 | state.mode = STORED; | |
| 530 | break; | |
| 531 | case 1: /* fixed block */ | |
| 532 | fixedtables(state); | |
| 533 | Tracev((stderr, "inflate: fixed codes block%s\n", | |
| 534 | state.last ? " (last)" : "")); | |
| 535 | state.mode = LEN_; /* decode codes */ | |
| 536 | if (flush == Z_TREES) { | |
| 537 | DROPBITS(2); | |
| 538 | goto inf_leave; | |
| 539 | } | |
| 540 | break; | |
| 541 | case 2: /* dynamic block */ | |
| 542 | Tracev((stderr, "inflate: dynamic codes block%s\n", | |
| 543 | state.last ? " (last)" : "")); | |
| 544 | state.mode = TABLE; | |
| 545 | break; | |
| 546 | case 3: | |
| 547 | strm.msg = (char *)"invalid block type"; | |
| 548 | state.mode = BAD; | |
| 549 | } | |
| 550 | DROPBITS(2); | |
| 551 | break; | |
| 552 | case STORED: | |
| 553 | BYTEBITS(); /* go to byte boundary */ | |
| 554 | NEEDBITS(32); | |
| 555 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | |
| 556 | strm.msg = (char *)"invalid stored block lengths"; | |
| 557 | state.mode = BAD; | |
| 558 | break; | |
| 559 | } | |
| 560 | state.length = (unsigned)hold & 0xffff; | |
| 561 | Tracev((stderr, "inflate: stored length %u\n", | |
| 562 | state.length)); | |
| 563 | INITBITS(); | |
| 564 | state.mode = COPY_; | |
| 565 | if (flush == Z_TREES) goto inf_leave; | |
| 566 | case COPY_: | |
| 567 | state.mode = COPY; | |
| 568 | case COPY: | |
| 569 | copy = state.length; | |
| 570 | if (copy) { | |
| 571 | if (copy > have) copy = have; | |
| 572 | if (copy > left) copy = left; | |
| 573 | if (copy == 0) goto inf_leave; | |
| 574 | zmemcpy(put, next, copy); | |
| 575 | have -= copy; | |
| 576 | next += copy; | |
| 577 | left -= copy; | |
| 578 | put += copy; | |
| 579 | state.length -= copy; | |
| 580 | break; | |
| 581 | } | |
| 582 | Tracev((stderr, "inflate: stored end\n")); | |
| 583 | state.mode = TYPE; | |
| 584 | break; | |
| 585 | case TABLE: | |
| 586 | NEEDBITS(14); | |
| 587 | state.nlen = BITS(5) + 257; | |
| 588 | DROPBITS(5); | |
| 589 | state.ndist = BITS(5) + 1; | |
| 590 | DROPBITS(5); | |
| 591 | state.ncode = BITS(4) + 4; | |
| 592 | DROPBITS(4); | |
| 593 | #ifndef PKZIP_BUG_WORKAROUND | |
| 594 | if (state.nlen > 286 || state.ndist > 30) { | |
| 595 | strm.msg = (char *)"too many length or distance symbols"; | |
| 596 | state.mode = BAD; | |
| 597 | break; | |
| 598 | } | |
| 599 | #endif | |
| 600 | Tracev((stderr, "inflate: table sizes ok\n")); | |
| 601 | state.have = 0; | |
| 602 | state.mode = LENLENS; | |
| 603 | case LENLENS: | |
| 604 | while (state.have < state.ncode) { | |
| 605 | NEEDBITS(3); | |
| 606 | state.lens[order[state.have++]] = (unsigned short)BITS(3); | |
| 607 | DROPBITS(3); | |
| 608 | } | |
| 609 | while (state.have < 19) | |
| 610 | state.lens[order[state.have++]] = 0; | |
| 611 | state.next = state.codes; | |
| 612 | state.lencode = (const code FAR *)(state.next); | |
| 613 | state.lenbits = 7; | |
| 614 | ret = inflate_table(CODES, state.lens, 19, &(state.next), | |
| 615 | &(state.lenbits), state.work); | |
| 616 | if (ret) { | |
| 617 | strm.msg = (char *)"invalid code lengths set"; | |
| 618 | state.mode = BAD; | |
| 619 | break; | |
| 620 | } | |
| 621 | Tracev((stderr, "inflate: code lengths ok\n")); | |
| 622 | state.have = 0; | |
| 623 | state.mode = CODELENS; | |
| 624 | case CODELENS: | |
| 625 | while (state.have < state.nlen + state.ndist) { | |
| 626 | for (;;) { | |
| 627 | here = state.lencode[BITS(state.lenbits)]; | |
| 628 | if ((unsigned)(here.bits) <= bits) break; | |
| 629 | PULLBYTE(); | |
| 630 | } | |
| 631 | if (here.val < 16) { | |
| 632 | DROPBITS(here.bits); | |
| 633 | state.lens[state.have++] = here.val; | |
| 634 | } | |
| 635 | else { | |
| 636 | if (here.val == 16) { | |
| 637 | NEEDBITS(here.bits + 2); | |
| 638 | DROPBITS(here.bits); | |
| 639 | if (state.have == 0) { | |
| 640 | strm.msg = (char *)"invalid bit length repeat"; | |
| 641 | state.mode = BAD; | |
| 642 | break; | |
| 643 | } | |
| 644 | len = state.lens[state.have - 1]; | |
| 645 | copy = 3 + BITS(2); | |
| 646 | DROPBITS(2); | |
| 647 | } | |
| 648 | else if (here.val == 17) { | |
| 649 | NEEDBITS(here.bits + 3); | |
| 650 | DROPBITS(here.bits); | |
| 651 | len = 0; | |
| 652 | copy = 3 + BITS(3); | |
| 653 | DROPBITS(3); | |
| 654 | } | |
| 655 | else { | |
| 656 | NEEDBITS(here.bits + 7); | |
| 657 | DROPBITS(here.bits); | |
| 658 | len = 0; | |
| 659 | copy = 11 + BITS(7); | |
| 660 | DROPBITS(7); | |
| 661 | } | |
| 662 | if (state.have + copy > state.nlen + state.ndist) { | |
| 663 | strm.msg = (char *)"invalid bit length repeat"; | |
| 664 | state.mode = BAD; | |
| 665 | break; | |
| 666 | } | |
| 667 | while (copy--) | |
| 668 | state.lens[state.have++] = (unsigned short)len; | |
| 669 | } | |
| 670 | } | |
| 671 | ||
| 672 | /* handle error breaks in while */ | |
| 673 | if (state.mode == BAD) break; | |
| 674 | ||
| 675 | /* check for end-of-block code (better have one) */ | |
| 676 | if (state.lens[256] == 0) { | |
| 677 | strm.msg = (char *)"invalid code -- missing end-of-block"; | |
| 678 | state.mode = BAD; | |
| 679 | break; | |
| 680 | } | |
| 681 | ||
| 682 | /* build code tables -- note: do not change the lenbits or distbits | |
| 683 | values here (9 and 6) without reading the comments in inftrees.h | |
| 684 | concerning the ENOUGH constants, which depend on those values */ | |
| 685 | state.next = state.codes; | |
| 686 | state.lencode = (const code FAR *)(state.next); | |
| 687 | state.lenbits = 9; | |
| 688 | ret = inflate_table(LENS, state.lens, state.nlen, &(state.next), | |
| 689 | &(state.lenbits), state.work); | |
| 690 | if (ret) { | |
| 691 | strm.msg = (char *)"invalid literal/lengths set"; | |
| 692 | state.mode = BAD; | |
| 693 | break; | |
| 694 | } | |
| 695 | state.distcode = (const code FAR *)(state.next); | |
| 696 | state.distbits = 6; | |
| 697 | ret = inflate_table(DISTS, state.lens + state.nlen, state.ndist, | |
| 698 | &(state.next), &(state.distbits), state.work); | |
| 699 | if (ret) { | |
| 700 | strm.msg = (char *)"invalid distances set"; | |
| 701 | state.mode = BAD; | |
| 702 | break; | |
| 703 | } | |
| 704 | Tracev((stderr, "inflate: codes ok\n")); | |
| 705 | state.mode = LEN_; | |
| 706 | if (flush == Z_TREES) goto inf_leave; | |
| 707 | case LEN_: | |
| 708 | state.mode = LEN; | |
| 709 | case LEN: | |
| 710 | if (have >= 6 && left >= 258) { | |
| 711 | strm.next_out = put; \ | |
| 712 | strm.avail_out = left; \ | |
| 713 | strm.next_in = next; \ | |
| 714 | strm.avail_in = have; \ | |
| 715 | state.hold = hold; \ | |
| 716 | state.bits = bits; \ | |
| 717 | ||
| 718 | inflate_fast(strm, out); | |
| 719 | ||
| 720 | put = strm.next_out; \ | |
| 721 | left = strm.avail_out; \ | |
| 722 | next = strm.next_in; \ | |
| 723 | have = strm.avail_in; \ | |
| 724 | hold = state.hold; \ | |
| 725 | bits = state.bits; \ | |
| 726 | if (state.mode == TYPE) | |
| 727 | state.back = -1; | |
| 728 | break; | |
| 729 | } | |
| 730 | state.back = 0; | |
| 731 | for (;;) { | |
| 732 | here = state.lencode[BITS(state.lenbits)]; | |
| 733 | if ((unsigned)(here.bits) <= bits) break; | |
| 734 | PULLBYTE(); | |
| 735 | } | |
| 736 | if (here.op && (here.op & 0xf0) == 0) { | |
| 737 | last = here; | |
| 738 | for (;;) { | |
| 739 | here = state.lencode[last.val + | |
| 740 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 741 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 742 | PULLBYTE(); | |
| 743 | } | |
| 744 | DROPBITS(last.bits); | |
| 745 | state.back += last.bits; | |
| 746 | } | |
| 747 | DROPBITS(here.bits); | |
| 748 | state.back += here.bits; | |
| 749 | state.length = (unsigned)here.val; | |
| 750 | if ((int)(here.op) == 0) { | |
| 751 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 752 | "inflate: literal '%c'\n" : | |
| 753 | "inflate: literal 0x%02x\n", here.val)); | |
| 754 | state.mode = LIT; | |
| 755 | break; | |
| 756 | } | |
| 757 | if (here.op & 32) { | |
| 758 | Tracevv((stderr, "inflate: end of block\n")); | |
| 759 | state.back = -1; | |
| 760 | state.mode = TYPE; | |
| 761 | break; | |
| 762 | } | |
| 763 | if (here.op & 64) { | |
| 764 | strm.msg = (char *)"invalid literal/length code"; | |
| 765 | state.mode = BAD; | |
| 766 | break; | |
| 767 | } | |
| 768 | state.extra = (unsigned)(here.op) & 15; | |
| 769 | state.mode = LENEXT; | |
| 770 | case LENEXT: | |
| 771 | if (state.extra) { | |
| 772 | NEEDBITS(state.extra); | |
| 773 | state.length += BITS(state.extra); | |
| 774 | DROPBITS(state.extra); | |
| 775 | state.back += state.extra; | |
| 776 | } | |
| 777 | Tracevv((stderr, "inflate: length %u\n", state.length)); | |
| 778 | state.was = state.length; | |
| 779 | state.mode = DIST; | |
| 780 | case DIST: | |
| 781 | for (;;) { | |
| 782 | here = state.distcode[BITS(state.distbits)]; | |
| 783 | if ((unsigned)(here.bits) <= bits) break; | |
| 784 | PULLBYTE(); | |
| 785 | } | |
| 786 | if ((here.op & 0xf0) == 0) { | |
| 787 | last = here; | |
| 788 | for (;;) { | |
| 789 | here = state.distcode[last.val + | |
| 790 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 791 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 792 | PULLBYTE(); | |
| 793 | } | |
| 794 | DROPBITS(last.bits); | |
| 795 | state.back += last.bits; | |
| 796 | } | |
| 797 | DROPBITS(here.bits); | |
| 798 | state.back += here.bits; | |
| 799 | if (here.op & 64) { | |
| 800 | strm.msg = (char *)"invalid distance code"; | |
| 801 | state.mode = BAD; | |
| 802 | break; | |
| 803 | } | |
| 804 | state.offset = (unsigned)here.val; | |
| 805 | state.extra = (unsigned)(here.op) & 15; | |
| 806 | state.mode = DISTEXT; | |
| 807 | case DISTEXT: | |
| 808 | if (state.extra) { | |
| 809 | NEEDBITS(state.extra); | |
| 810 | state.offset += BITS(state.extra); | |
| 811 | DROPBITS(state.extra); | |
| 812 | state.back += state.extra; | |
| 813 | } | |
| 814 | #ifdef INFLATE_STRICT | |
| 815 | if (state.offset > state.dmax) { | |
| 816 | strm.msg = (char *)"invalid distance too far back"; | |
| 817 | state.mode = BAD; | |
| 818 | break; | |
| 819 | } | |
| 820 | #endif | |
| 821 | Tracevv((stderr, "inflate: distance %u\n", state.offset)); | |
| 822 | state.mode = MATCH; | |
| 823 | case MATCH: | |
| 824 | if (left == 0) goto inf_leave; | |
| 825 | copy = out - left; | |
| 826 | if (state.offset > copy) { /* copy from window */ | |
| 827 | copy = state.offset - copy; | |
| 828 | if (copy > state.whave) { | |
| 829 | if (state.sane) { | |
| 830 | strm.msg = (char *)"invalid distance too far back"; | |
| 831 | state.mode = BAD; | |
| 832 | break; | |
| 833 | } | |
| 834 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | |
| 835 | Trace((stderr, "inflate.c too far\n")); | |
| 836 | copy -= state.whave; | |
| 837 | if (copy > state.length) copy = state.length; | |
| 838 | if (copy > left) copy = left; | |
| 839 | left -= copy; | |
| 840 | state.length -= copy; | |
| 841 | do { | |
| 842 | *put++ = 0; | |
| 843 | } while (--copy); | |
| 844 | if (state.length == 0) state.mode = LEN; | |
| 845 | break; | |
| 846 | #endif | |
| 847 | } | |
| 848 | if (copy > state.wnext) { | |
| 849 | copy -= state.wnext; | |
| 850 | from = state.window + (state.wsize - copy); | |
| 851 | } | |
| 852 | else | |
| 853 | from = state.window + (state.wnext - copy); | |
| 854 | if (copy > state.length) copy = state.length; | |
| 855 | } | |
| 856 | else { /* copy from output */ | |
| 857 | from = put - state.offset; | |
| 858 | copy = state.length; | |
| 859 | } | |
| 860 | if (copy > left) copy = left; | |
| 861 | left -= copy; | |
| 862 | state.length -= copy; | |
| 863 | do { | |
| 864 | *put++ = *from++; | |
| 865 | } while (--copy); | |
| 866 | if (state.length == 0) state.mode = LEN; | |
| 867 | break; | |
| 868 | case LIT: | |
| 869 | if (left == 0) goto inf_leave; | |
| 870 | *put++ = (u8)(state.length); | |
| 871 | left--; | |
| 872 | state.mode = LEN; | |
| 873 | break; | |
| 874 | case CHECK: | |
| 875 | if (state.wrap) { | |
| 876 | NEEDBITS(32); | |
| 877 | out -= left; | |
| 878 | strm.total_out += out; | |
| 879 | state.total += out; | |
| 880 | if ((state.wrap & 4) && out) | |
| 881 | strm.adler = state.check = | |
| 882 | UPDATE(state.check, put - out, out); | |
| 883 | out = left; | |
| 884 | if ((state.wrap & 4) && ( | |
| 885 | #ifdef GUNZIP | |
| 886 | state.flags ? hold : | |
| 887 | #endif | |
| 888 | ZSWAP32(hold)) != state.check) { | |
| 889 | strm.msg = (char *)"incorrect data check"; | |
| 890 | state.mode = BAD; | |
| 891 | break; | |
| 892 | } | |
| 893 | INITBITS(); | |
| 894 | Tracev((stderr, "inflate: check matches trailer\n")); | |
| 895 | } | |
| 896 | #ifdef GUNZIP | |
| 897 | state.mode = LENGTH; | |
| 898 | case LENGTH: | |
| 899 | if (state.wrap && state.flags) { | |
| 900 | NEEDBITS(32); | |
| 901 | if (hold != (state.total & 0xffffffffUL)) { | |
| 902 | strm.msg = (char *)"incorrect length check"; | |
| 903 | state.mode = BAD; | |
| 904 | break; | |
| 905 | } | |
| 906 | INITBITS(); | |
| 907 | Tracev((stderr, "inflate: length matches trailer\n")); | |
| 908 | } | |
| 909 | #endif | |
| 910 | state.mode = DONE; | |
| 911 | case DONE: | |
| 912 | ret = Z_STREAM_END; | |
| 913 | goto inf_leave; | |
| 914 | case BAD: | |
| 915 | ret = Z_DATA_ERROR; | |
| 916 | goto inf_leave; | |
| 917 | case MEM: | |
| 918 | return Z_MEM_ERROR; | |
| 919 | case SYNC: | |
| 920 | default: | |
| 921 | return Z_STREAM_ERROR; | |
| 922 | } | |
| 923 | ||
| 924 | /* | |
| 925 | Return from inflate(), updating the total counts and the check value. | |
| 926 | If there was no progress during the inflate() call, return a buffer | |
| 927 | error. Call updatewindow() to create and/or update the window state. | |
| 928 | Note: a memory error from inflate() is non-recoverable. | |
| 929 | */ | |
| 930 | inf_leave: | |
| 931 | strm.next_out = put; \ | |
| 932 | strm.avail_out = left; \ | |
| 933 | strm.next_in = next; \ | |
| 934 | strm.avail_in = have; \ | |
| 935 | state.hold = hold; \ | |
| 936 | state.bits = bits; \ | |
| 937 | if (state.wsize || (out != strm.avail_out && state.mode < BAD && | |
| 938 | (state.mode < CHECK || flush != Z_FINISH))) | |
| 939 | if (updatewindow(strm, strm.next_out, out - strm.avail_out)) { | |
| 940 | state.mode = MEM; | |
| 941 | return Z_MEM_ERROR; | |
| 942 | } | |
| 943 | in -= strm.avail_in; | |
| 944 | out -= strm.avail_out; | |
| 945 | strm.total_in += in; | |
| 946 | strm.total_out += out; | |
| 947 | state.total += out; | |
| 948 | if ((state.wrap & 4) && out) | |
| 949 | strm.adler = state.check = | |
| 950 | UPDATE(state.check, strm.next_out - out, out); | |
| 951 | strm.data_type = (int)state.bits + (state.last ? 64 : 0) + | |
| 952 | (state.mode == TYPE ? 128 : 0) + | |
| 953 | (state.mode == LEN_ || state.mode == COPY_ ? 256 : 0); | |
| 954 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) | |
| 955 | ret = Z_BUF_ERROR; | |
| 956 | return ret; | |
| 957 | } | |
| 958 | ||
| 959 | local int inflateStateCheck(z_stream * strm) { | |
| 960 | struct inflate_state FAR *state; | |
| 961 | if (strm == Z_NULL || | |
| 962 | strm.zalloc == (alloc_func)0 || strm.zfree == (free_func)0) | |
| 963 | return 1; | |
| 964 | state = (struct inflate_state FAR *)strm.state; | |
| 965 | if (state == Z_NULL || state.strm != strm || | |
| 966 | state.mode < HEAD || state.mode > SYNC) | |
| 967 | return 1; | |
| 968 | return 0; | |
| 969 | } |