Commit ee9d1d0414
Changed files (7)
src/all_types.hpp
@@ -833,7 +833,6 @@ struct AstNode {
enum NodeType type;
size_t line;
size_t column;
- uint32_t create_index; // for determinism purposes
ImportTableEntry *owner;
union {
AstNodeRoot root;
@@ -1523,7 +1522,6 @@ struct CodeGen {
LLVMValueRef return_address_fn_val;
LLVMValueRef frame_address_fn_val;
bool error_during_imports;
- uint32_t next_node_index;
TypeTableEntry *err_tag_type;
const char **clang_argv;
src/analyze.cpp
@@ -3163,8 +3163,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a
import_entry->line_offsets = tokenization.line_offsets;
import_entry->path = abs_full_path;
- import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
- &g->next_node_index);
+ import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color);
assert(import_entry->root);
if (g->verbose) {
ast_print(stderr, import_entry->root, 0);
src/parseh.cpp
@@ -17,6 +17,7 @@
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
+#include <clang/AST/Expr.h>
#include <string.h>
@@ -54,6 +55,7 @@ struct Context {
uint32_t next_anon_index;
CodeGen *codegen;
+ ASTContext *ctx;
};
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
return resolve_qual_type_with_table(c, qt, decl, &c->global_type_table);
}
+#include "ast_render.hpp"
+
+static AstNode * ast_trans_stmt(Context *c, Stmt *stmt);
+
+static AstNode * ast_trans_expr(Context *c, Expr *expr) {
+ return ast_trans_stmt(c, expr);
+}
+
+static AstNode * ast_create_node(Context *c, const SourceRange &range, NodeType id) {
+ AstNode *node = allocate<AstNode>(1);
+ node->type = id;
+ node->owner = c->import;
+ // TODO line/column. mapping to C file??
+ return node;
+}
+
+static AstNode * ast_trans_compound_stmt(Context *c, CompoundStmt *stmt) {
+ AstNode *block_node = ast_create_node(c, stmt->getSourceRange(), NodeTypeBlock);
+ for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
+ AstNode *child_node = ast_trans_stmt(c, *it);
+ block_node->data.block.statements.append(child_node);
+ }
+ return block_node;
+}
+
+static AstNode *ast_trans_return_stmt(Context *c, ReturnStmt *stmt) {
+ Expr *value_expr = stmt->getRetValue();
+ if (value_expr == nullptr) {
+ zig_panic("TODO handle C return void");
+ } else {
+ AstNode *return_node = ast_create_node(c, stmt->getSourceRange(), NodeTypeReturnExpr);
+ return_node->data.return_expr.expr = ast_trans_expr(c, value_expr);
+ return return_node;
+ }
+}
+
+static void aps_int_to_bigint(Context *c, const llvm::APSInt &aps_int, BigInt *bigint) {
+ // TODO respect actually big integers
+ if (aps_int.isSigned()) {
+ if (aps_int > INT64_MAX || aps_int < INT64_MIN) {
+ zig_panic("TODO actually bigint in C");
+ } else {
+ bigint_init_signed(bigint, aps_int.getExtValue());
+ }
+ } else {
+ if (aps_int > INT64_MAX) {
+ zig_panic("TODO actually bigint in C");
+ } else {
+ bigint_init_unsigned(bigint, aps_int.getExtValue());
+ }
+ }
+}
+static AstNode * ast_trans_integer_literal(Context *c, IntegerLiteral *stmt) {
+ AstNode *node = ast_create_node(c, stmt->getSourceRange(), NodeTypeIntLiteral);
+ llvm::APSInt result;
+ if (!stmt->EvaluateAsInt(result, *c->ctx)) {
+ fprintf(stderr, "TODO unable to convert integer literal to zig\n");
+ }
+ node->data.int_literal.bigint = allocate<BigInt>(1);
+ aps_int_to_bigint(c, result, node->data.int_literal.bigint);
+ return node;
+}
+
+static AstNode *ast_trans_stmt(Context *c, Stmt *stmt) {
+ Stmt::StmtClass sc = stmt->getStmtClass();
+ switch (sc) {
+ case Stmt::ReturnStmtClass:
+ return ast_trans_return_stmt(c, (ReturnStmt *)stmt);
+ case Stmt::CompoundStmtClass:
+ return ast_trans_compound_stmt(c, (CompoundStmt *)stmt);
+ case Stmt::IntegerLiteralClass:
+ return ast_trans_integer_literal(c, (IntegerLiteral *)stmt);
+ case Stmt::CaseStmtClass:
+ zig_panic("TODO handle C CaseStmtClass");
+ case Stmt::DefaultStmtClass:
+ zig_panic("TODO handle C DefaultStmtClass");
+ case Stmt::SwitchStmtClass:
+ zig_panic("TODO handle C SwitchStmtClass");
+ case Stmt::WhileStmtClass:
+ zig_panic("TODO handle C WhileStmtClass");
+ case Stmt::NoStmtClass:
+ zig_panic("TODO handle C NoStmtClass");
+ case Stmt::GCCAsmStmtClass:
+ zig_panic("TODO handle C GCCAsmStmtClass");
+ case Stmt::MSAsmStmtClass:
+ zig_panic("TODO handle C MSAsmStmtClass");
+ case Stmt::AttributedStmtClass:
+ zig_panic("TODO handle C AttributedStmtClass");
+ case Stmt::BreakStmtClass:
+ zig_panic("TODO handle C BreakStmtClass");
+ case Stmt::CXXCatchStmtClass:
+ zig_panic("TODO handle C CXXCatchStmtClass");
+ case Stmt::CXXForRangeStmtClass:
+ zig_panic("TODO handle C CXXForRangeStmtClass");
+ case Stmt::CXXTryStmtClass:
+ zig_panic("TODO handle C CXXTryStmtClass");
+ case Stmt::CapturedStmtClass:
+ zig_panic("TODO handle C CapturedStmtClass");
+ case Stmt::ContinueStmtClass:
+ zig_panic("TODO handle C ContinueStmtClass");
+ case Stmt::CoreturnStmtClass:
+ zig_panic("TODO handle C CoreturnStmtClass");
+ case Stmt::CoroutineBodyStmtClass:
+ zig_panic("TODO handle C CoroutineBodyStmtClass");
+ case Stmt::DeclStmtClass:
+ zig_panic("TODO handle C DeclStmtClass");
+ case Stmt::DoStmtClass:
+ zig_panic("TODO handle C DoStmtClass");
+ case Stmt::BinaryConditionalOperatorClass:
+ zig_panic("TODO handle C BinaryConditionalOperatorClass");
+ case Stmt::ConditionalOperatorClass:
+ zig_panic("TODO handle C ConditionalOperatorClass");
+ case Stmt::AddrLabelExprClass:
+ zig_panic("TODO handle C AddrLabelExprClass");
+ case Stmt::ArrayInitIndexExprClass:
+ zig_panic("TODO handle C ArrayInitIndexExprClass");
+ case Stmt::ArrayInitLoopExprClass:
+ zig_panic("TODO handle C ArrayInitLoopExprClass");
+ case Stmt::ArraySubscriptExprClass:
+ zig_panic("TODO handle C ArraySubscriptExprClass");
+ case Stmt::ArrayTypeTraitExprClass:
+ zig_panic("TODO handle C ArrayTypeTraitExprClass");
+ case Stmt::AsTypeExprClass:
+ zig_panic("TODO handle C AsTypeExprClass");
+ case Stmt::AtomicExprClass:
+ zig_panic("TODO handle C AtomicExprClass");
+ case Stmt::BinaryOperatorClass:
+ zig_panic("TODO handle C BinaryOperatorClass");
+ case Stmt::CompoundAssignOperatorClass:
+ zig_panic("TODO handle C CompoundAssignOperatorClass");
+ case Stmt::BlockExprClass:
+ zig_panic("TODO handle C BlockExprClass");
+ case Stmt::CXXBindTemporaryExprClass:
+ zig_panic("TODO handle C CXXBindTemporaryExprClass");
+ case Stmt::CXXBoolLiteralExprClass:
+ zig_panic("TODO handle C CXXBoolLiteralExprClass");
+ case Stmt::CXXConstructExprClass:
+ zig_panic("TODO handle C CXXConstructExprClass");
+ case Stmt::CXXTemporaryObjectExprClass:
+ zig_panic("TODO handle C CXXTemporaryObjectExprClass");
+ case Stmt::CXXDefaultArgExprClass:
+ zig_panic("TODO handle C CXXDefaultArgExprClass");
+ case Stmt::CXXDefaultInitExprClass:
+ zig_panic("TODO handle C CXXDefaultInitExprClass");
+ case Stmt::CXXDeleteExprClass:
+ zig_panic("TODO handle C CXXDeleteExprClass");
+ case Stmt::CXXDependentScopeMemberExprClass:
+ zig_panic("TODO handle C CXXDependentScopeMemberExprClass");
+ case Stmt::CXXFoldExprClass:
+ zig_panic("TODO handle C CXXFoldExprClass");
+ case Stmt::CXXInheritedCtorInitExprClass:
+ zig_panic("TODO handle C CXXInheritedCtorInitExprClass");
+ case Stmt::CXXNewExprClass:
+ zig_panic("TODO handle C CXXNewExprClass");
+ case Stmt::CXXNoexceptExprClass:
+ zig_panic("TODO handle C CXXNoexceptExprClass");
+ case Stmt::CXXNullPtrLiteralExprClass:
+ zig_panic("TODO handle C CXXNullPtrLiteralExprClass");
+ case Stmt::CXXPseudoDestructorExprClass:
+ zig_panic("TODO handle C CXXPseudoDestructorExprClass");
+ case Stmt::CXXScalarValueInitExprClass:
+ zig_panic("TODO handle C CXXScalarValueInitExprClass");
+ case Stmt::CXXStdInitializerListExprClass:
+ zig_panic("TODO handle C CXXStdInitializerListExprClass");
+ case Stmt::CXXThisExprClass:
+ zig_panic("TODO handle C CXXThisExprClass");
+ case Stmt::CXXThrowExprClass:
+ zig_panic("TODO handle C CXXThrowExprClass");
+ case Stmt::CXXTypeidExprClass:
+ zig_panic("TODO handle C CXXTypeidExprClass");
+ case Stmt::CXXUnresolvedConstructExprClass:
+ zig_panic("TODO handle C CXXUnresolvedConstructExprClass");
+ case Stmt::CXXUuidofExprClass:
+ zig_panic("TODO handle C CXXUuidofExprClass");
+ case Stmt::CallExprClass:
+ zig_panic("TODO handle C CallExprClass");
+ case Stmt::CUDAKernelCallExprClass:
+ zig_panic("TODO handle C CUDAKernelCallExprClass");
+ case Stmt::CXXMemberCallExprClass:
+ zig_panic("TODO handle C CXXMemberCallExprClass");
+ case Stmt::CXXOperatorCallExprClass:
+ zig_panic("TODO handle C CXXOperatorCallExprClass");
+ case Stmt::UserDefinedLiteralClass:
+ zig_panic("TODO handle C UserDefinedLiteralClass");
+ case Stmt::CStyleCastExprClass:
+ zig_panic("TODO handle C CStyleCastExprClass");
+ case Stmt::CXXFunctionalCastExprClass:
+ zig_panic("TODO handle C CXXFunctionalCastExprClass");
+ case Stmt::CXXConstCastExprClass:
+ zig_panic("TODO handle C CXXConstCastExprClass");
+ case Stmt::CXXDynamicCastExprClass:
+ zig_panic("TODO handle C CXXDynamicCastExprClass");
+ case Stmt::CXXReinterpretCastExprClass:
+ zig_panic("TODO handle C CXXReinterpretCastExprClass");
+ case Stmt::CXXStaticCastExprClass:
+ zig_panic("TODO handle C CXXStaticCastExprClass");
+ case Stmt::ObjCBridgedCastExprClass:
+ zig_panic("TODO handle C ObjCBridgedCastExprClass");
+ case Stmt::ImplicitCastExprClass:
+ zig_panic("TODO handle C ImplicitCastExprClass");
+ case Stmt::CharacterLiteralClass:
+ zig_panic("TODO handle C CharacterLiteralClass");
+ case Stmt::ChooseExprClass:
+ zig_panic("TODO handle C ChooseExprClass");
+ case Stmt::CompoundLiteralExprClass:
+ zig_panic("TODO handle C CompoundLiteralExprClass");
+ case Stmt::ConvertVectorExprClass:
+ zig_panic("TODO handle C ConvertVectorExprClass");
+ case Stmt::CoawaitExprClass:
+ zig_panic("TODO handle C CoawaitExprClass");
+ case Stmt::CoyieldExprClass:
+ zig_panic("TODO handle C CoyieldExprClass");
+ case Stmt::DeclRefExprClass:
+ zig_panic("TODO handle C DeclRefExprClass");
+ case Stmt::DependentCoawaitExprClass:
+ zig_panic("TODO handle C DependentCoawaitExprClass");
+ case Stmt::DependentScopeDeclRefExprClass:
+ zig_panic("TODO handle C DependentScopeDeclRefExprClass");
+ case Stmt::DesignatedInitExprClass:
+ zig_panic("TODO handle C DesignatedInitExprClass");
+ case Stmt::DesignatedInitUpdateExprClass:
+ zig_panic("TODO handle C DesignatedInitUpdateExprClass");
+ case Stmt::ExprWithCleanupsClass:
+ zig_panic("TODO handle C ExprWithCleanupsClass");
+ case Stmt::ExpressionTraitExprClass:
+ zig_panic("TODO handle C ExpressionTraitExprClass");
+ case Stmt::ExtVectorElementExprClass:
+ zig_panic("TODO handle C ExtVectorElementExprClass");
+ case Stmt::FloatingLiteralClass:
+ zig_panic("TODO handle C FloatingLiteralClass");
+ case Stmt::FunctionParmPackExprClass:
+ zig_panic("TODO handle C FunctionParmPackExprClass");
+ case Stmt::GNUNullExprClass:
+ zig_panic("TODO handle C GNUNullExprClass");
+ case Stmt::GenericSelectionExprClass:
+ zig_panic("TODO handle C GenericSelectionExprClass");
+ case Stmt::ImaginaryLiteralClass:
+ zig_panic("TODO handle C ImaginaryLiteralClass");
+ case Stmt::ImplicitValueInitExprClass:
+ zig_panic("TODO handle C ImplicitValueInitExprClass");
+ case Stmt::InitListExprClass:
+ zig_panic("TODO handle C InitListExprClass");
+ case Stmt::LambdaExprClass:
+ zig_panic("TODO handle C LambdaExprClass");
+ case Stmt::MSPropertyRefExprClass:
+ zig_panic("TODO handle C MSPropertyRefExprClass");
+ case Stmt::MSPropertySubscriptExprClass:
+ zig_panic("TODO handle C MSPropertySubscriptExprClass");
+ case Stmt::MaterializeTemporaryExprClass:
+ zig_panic("TODO handle C MaterializeTemporaryExprClass");
+ case Stmt::MemberExprClass:
+ zig_panic("TODO handle C MemberExprClass");
+ case Stmt::NoInitExprClass:
+ zig_panic("TODO handle C NoInitExprClass");
+ case Stmt::OMPArraySectionExprClass:
+ zig_panic("TODO handle C OMPArraySectionExprClass");
+ case Stmt::ObjCArrayLiteralClass:
+ zig_panic("TODO handle C ObjCArrayLiteralClass");
+ case Stmt::ObjCAvailabilityCheckExprClass:
+ zig_panic("TODO handle C ObjCAvailabilityCheckExprClass");
+ case Stmt::ObjCBoolLiteralExprClass:
+ zig_panic("TODO handle C ObjCBoolLiteralExprClass");
+ case Stmt::ObjCBoxedExprClass:
+ zig_panic("TODO handle C ObjCBoxedExprClass");
+ case Stmt::ObjCDictionaryLiteralClass:
+ zig_panic("TODO handle C ObjCDictionaryLiteralClass");
+ case Stmt::ObjCEncodeExprClass:
+ zig_panic("TODO handle C ObjCEncodeExprClass");
+ case Stmt::ObjCIndirectCopyRestoreExprClass:
+ zig_panic("TODO handle C ObjCIndirectCopyRestoreExprClass");
+ case Stmt::ObjCIsaExprClass:
+ zig_panic("TODO handle C ObjCIsaExprClass");
+ case Stmt::ObjCIvarRefExprClass:
+ zig_panic("TODO handle C ObjCIvarRefExprClass");
+ case Stmt::ObjCMessageExprClass:
+ zig_panic("TODO handle C ObjCMessageExprClass");
+ case Stmt::ObjCPropertyRefExprClass:
+ zig_panic("TODO handle C ObjCPropertyRefExprClass");
+ case Stmt::ObjCProtocolExprClass:
+ zig_panic("TODO handle C ObjCProtocolExprClass");
+ case Stmt::ObjCSelectorExprClass:
+ zig_panic("TODO handle C ObjCSelectorExprClass");
+ case Stmt::ObjCStringLiteralClass:
+ zig_panic("TODO handle C ObjCStringLiteralClass");
+ case Stmt::ObjCSubscriptRefExprClass:
+ zig_panic("TODO handle C ObjCSubscriptRefExprClass");
+ case Stmt::OffsetOfExprClass:
+ zig_panic("TODO handle C OffsetOfExprClass");
+ case Stmt::OpaqueValueExprClass:
+ zig_panic("TODO handle C OpaqueValueExprClass");
+ case Stmt::UnresolvedLookupExprClass:
+ zig_panic("TODO handle C UnresolvedLookupExprClass");
+ case Stmt::UnresolvedMemberExprClass:
+ zig_panic("TODO handle C UnresolvedMemberExprClass");
+ case Stmt::PackExpansionExprClass:
+ zig_panic("TODO handle C PackExpansionExprClass");
+ case Stmt::ParenExprClass:
+ zig_panic("TODO handle C ParenExprClass");
+ case Stmt::ParenListExprClass:
+ zig_panic("TODO handle C ParenListExprClass");
+ case Stmt::PredefinedExprClass:
+ zig_panic("TODO handle C PredefinedExprClass");
+ case Stmt::PseudoObjectExprClass:
+ zig_panic("TODO handle C PseudoObjectExprClass");
+ case Stmt::ShuffleVectorExprClass:
+ zig_panic("TODO handle C ShuffleVectorExprClass");
+ case Stmt::SizeOfPackExprClass:
+ zig_panic("TODO handle C SizeOfPackExprClass");
+ case Stmt::StmtExprClass:
+ zig_panic("TODO handle C StmtExprClass");
+ case Stmt::StringLiteralClass:
+ zig_panic("TODO handle C StringLiteralClass");
+ case Stmt::SubstNonTypeTemplateParmExprClass:
+ zig_panic("TODO handle C SubstNonTypeTemplateParmExprClass");
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
+ zig_panic("TODO handle C SubstNonTypeTemplateParmPackExprClass");
+ case Stmt::TypeTraitExprClass:
+ zig_panic("TODO handle C TypeTraitExprClass");
+ case Stmt::TypoExprClass:
+ zig_panic("TODO handle C TypoExprClass");
+ case Stmt::UnaryExprOrTypeTraitExprClass:
+ zig_panic("TODO handle C UnaryExprOrTypeTraitExprClass");
+ case Stmt::UnaryOperatorClass:
+ zig_panic("TODO handle C UnaryOperatorClass");
+ case Stmt::VAArgExprClass:
+ zig_panic("TODO handle C VAArgExprClass");
+ case Stmt::ForStmtClass:
+ zig_panic("TODO handle C ForStmtClass");
+ case Stmt::GotoStmtClass:
+ zig_panic("TODO handle C GotoStmtClass");
+ case Stmt::IfStmtClass:
+ zig_panic("TODO handle C IfStmtClass");
+ case Stmt::IndirectGotoStmtClass:
+ zig_panic("TODO handle C IndirectGotoStmtClass");
+ case Stmt::LabelStmtClass:
+ zig_panic("TODO handle C LabelStmtClass");
+ case Stmt::MSDependentExistsStmtClass:
+ zig_panic("TODO handle C MSDependentExistsStmtClass");
+ case Stmt::NullStmtClass:
+ zig_panic("TODO handle C NullStmtClass");
+ case Stmt::OMPAtomicDirectiveClass:
+ zig_panic("TODO handle C OMPAtomicDirectiveClass");
+ case Stmt::OMPBarrierDirectiveClass:
+ zig_panic("TODO handle C OMPBarrierDirectiveClass");
+ case Stmt::OMPCancelDirectiveClass:
+ zig_panic("TODO handle C OMPCancelDirectiveClass");
+ case Stmt::OMPCancellationPointDirectiveClass:
+ zig_panic("TODO handle C OMPCancellationPointDirectiveClass");
+ case Stmt::OMPCriticalDirectiveClass:
+ zig_panic("TODO handle C OMPCriticalDirectiveClass");
+ case Stmt::OMPFlushDirectiveClass:
+ zig_panic("TODO handle C OMPFlushDirectiveClass");
+ case Stmt::OMPDistributeDirectiveClass:
+ zig_panic("TODO handle C OMPDistributeDirectiveClass");
+ case Stmt::OMPDistributeParallelForDirectiveClass:
+ zig_panic("TODO handle C OMPDistributeParallelForDirectiveClass");
+ case Stmt::OMPDistributeParallelForSimdDirectiveClass:
+ zig_panic("TODO handle C OMPDistributeParallelForSimdDirectiveClass");
+ case Stmt::OMPDistributeSimdDirectiveClass:
+ zig_panic("TODO handle C OMPDistributeSimdDirectiveClass");
+ case Stmt::OMPForDirectiveClass:
+ zig_panic("TODO handle C OMPForDirectiveClass");
+ case Stmt::OMPForSimdDirectiveClass:
+ zig_panic("TODO handle C OMPForSimdDirectiveClass");
+ case Stmt::OMPParallelForDirectiveClass:
+ zig_panic("TODO handle C OMPParallelForDirectiveClass");
+ case Stmt::OMPParallelForSimdDirectiveClass:
+ zig_panic("TODO handle C OMPParallelForSimdDirectiveClass");
+ case Stmt::OMPSimdDirectiveClass:
+ zig_panic("TODO handle C OMPSimdDirectiveClass");
+ case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTargetParallelForSimdDirectiveClass");
+ case Stmt::OMPTargetSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTargetSimdDirectiveClass");
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ zig_panic("TODO handle C OMPTargetTeamsDistributeDirectiveClass");
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
+ case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
+ case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
+ case Stmt::OMPTaskLoopDirectiveClass:
+ zig_panic("TODO handle C OMPTaskLoopDirectiveClass");
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTaskLoopSimdDirectiveClass");
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ zig_panic("TODO handle C OMPTeamsDistributeDirectiveClass");
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ zig_panic("TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ zig_panic("TODO handle C OMPTeamsDistributeSimdDirectiveClass");
+ case Stmt::OMPMasterDirectiveClass:
+ zig_panic("TODO handle C OMPMasterDirectiveClass");
+ case Stmt::OMPOrderedDirectiveClass:
+ zig_panic("TODO handle C OMPOrderedDirectiveClass");
+ case Stmt::OMPParallelDirectiveClass:
+ zig_panic("TODO handle C OMPParallelDirectiveClass");
+ case Stmt::OMPParallelSectionsDirectiveClass:
+ zig_panic("TODO handle C OMPParallelSectionsDirectiveClass");
+ case Stmt::OMPSectionDirectiveClass:
+ zig_panic("TODO handle C OMPSectionDirectiveClass");
+ case Stmt::OMPSectionsDirectiveClass:
+ zig_panic("TODO handle C OMPSectionsDirectiveClass");
+ case Stmt::OMPSingleDirectiveClass:
+ zig_panic("TODO handle C OMPSingleDirectiveClass");
+ case Stmt::OMPTargetDataDirectiveClass:
+ zig_panic("TODO handle C OMPTargetDataDirectiveClass");
+ case Stmt::OMPTargetDirectiveClass:
+ zig_panic("TODO handle C OMPTargetDirectiveClass");
+ case Stmt::OMPTargetEnterDataDirectiveClass:
+ zig_panic("TODO handle C OMPTargetEnterDataDirectiveClass");
+ case Stmt::OMPTargetExitDataDirectiveClass:
+ zig_panic("TODO handle C OMPTargetExitDataDirectiveClass");
+ case Stmt::OMPTargetParallelDirectiveClass:
+ zig_panic("TODO handle C OMPTargetParallelDirectiveClass");
+ case Stmt::OMPTargetParallelForDirectiveClass:
+ zig_panic("TODO handle C OMPTargetParallelForDirectiveClass");
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ zig_panic("TODO handle C OMPTargetTeamsDirectiveClass");
+ case Stmt::OMPTargetUpdateDirectiveClass:
+ zig_panic("TODO handle C OMPTargetUpdateDirectiveClass");
+ case Stmt::OMPTaskDirectiveClass:
+ zig_panic("TODO handle C OMPTaskDirectiveClass");
+ case Stmt::OMPTaskgroupDirectiveClass:
+ zig_panic("TODO handle C OMPTaskgroupDirectiveClass");
+ case Stmt::OMPTaskwaitDirectiveClass:
+ zig_panic("TODO handle C OMPTaskwaitDirectiveClass");
+ case Stmt::OMPTaskyieldDirectiveClass:
+ zig_panic("TODO handle C OMPTaskyieldDirectiveClass");
+ case Stmt::OMPTeamsDirectiveClass:
+ zig_panic("TODO handle C OMPTeamsDirectiveClass");
+ case Stmt::ObjCAtCatchStmtClass:
+ zig_panic("TODO handle C ObjCAtCatchStmtClass");
+ case Stmt::ObjCAtFinallyStmtClass:
+ zig_panic("TODO handle C ObjCAtFinallyStmtClass");
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ zig_panic("TODO handle C ObjCAtSynchronizedStmtClass");
+ case Stmt::ObjCAtThrowStmtClass:
+ zig_panic("TODO handle C ObjCAtThrowStmtClass");
+ case Stmt::ObjCAtTryStmtClass:
+ zig_panic("TODO handle C ObjCAtTryStmtClass");
+ case Stmt::ObjCAutoreleasePoolStmtClass:
+ zig_panic("TODO handle C ObjCAutoreleasePoolStmtClass");
+ case Stmt::ObjCForCollectionStmtClass:
+ zig_panic("TODO handle C ObjCForCollectionStmtClass");
+ case Stmt::SEHExceptStmtClass:
+ zig_panic("TODO handle C SEHExceptStmtClass");
+ case Stmt::SEHFinallyStmtClass:
+ zig_panic("TODO handle C SEHFinallyStmtClass");
+ case Stmt::SEHLeaveStmtClass:
+ zig_panic("TODO handle C SEHLeaveStmtClass");
+ case Stmt::SEHTryStmtClass:
+ zig_panic("TODO handle C SEHTryStmtClass");
+ }
+ zig_unreachable();
+}
+
static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
+ if (fn_decl->hasBody()) {
+ fprintf(stderr, "fn %s\n", buf_ptr(fn_name));
+ Stmt *body = fn_decl->getBody();
+ AstNode *body_node = ast_trans_stmt(c, body);
+ ast_render(c->codegen, stderr, body_node, 4);
+ fprintf(stderr, "\n");
+ }
+
if (get_global(c, fn_name)) {
// we already saw this function
return;
@@ -1373,7 +1843,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>();
- bool skip_function_bodies = true;
+ bool skip_function_bodies = false;
bool only_local_decls = true;
bool capture_diagnostics = true;
bool user_files_are_volatile = true;
@@ -1390,7 +1860,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
nullptr));
-
// Early failures in LoadFromCommandLine may return with ErrUnit unset.
if (!ast_unit && !err_unit) {
return ErrorFileSystem;
@@ -1416,29 +1885,36 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
break;
}
StringRef msg_str_ref = it->getMessage();
- FullSourceLoc fsl = it->getLocation();
- FileID file_id = fsl.getFileID();
- StringRef filename = fsl.getManager().getFilename(fsl);
- unsigned line = fsl.getSpellingLineNumber() - 1;
- unsigned column = fsl.getSpellingColumnNumber() - 1;
- unsigned offset = fsl.getManager().getFileOffset(fsl);
- const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin());
- Buf *path;
- if (filename.empty()) {
- path = buf_alloc();
- } else {
- path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size());
- }
+ FullSourceLoc fsl = it->getLocation();
+ if (fsl.hasManager()) {
+ FileID file_id = fsl.getFileID();
+ StringRef filename = fsl.getManager().getFilename(fsl);
+ unsigned line = fsl.getSpellingLineNumber() - 1;
+ unsigned column = fsl.getSpellingColumnNumber() - 1;
+ unsigned offset = fsl.getManager().getFileOffset(fsl);
+ const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
+ Buf *path;
+ if (filename.empty()) {
+ path = buf_alloc();
+ } else {
+ path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size());
+ }
- ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
+ ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
- c->errors->append(err_msg);
+ c->errors->append(err_msg);
+ } else {
+ // NOTE the only known way this gets triggered right now is if you have a lot of errors
+ // clang emits "too many errors emitted, stopping now"
+ fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg));
+ }
}
return 0;
}
+ c->ctx = &ast_unit->getASTContext();
c->source_manager = &ast_unit->getSourceManager();
ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
src/parser.cpp
@@ -20,7 +20,6 @@ struct ParseContext {
ZigList<Token> *tokens;
ImportTableEntry *owner;
ErrColor err_color;
- uint32_t *next_node_index;
// These buffers are used freqently so we preallocate them once here.
Buf *void_buf;
Buf *empty_buf;
@@ -70,8 +69,6 @@ static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) {
AstNode *node = allocate<AstNode>(1);
node->type = type;
node->owner = pc->owner;
- node->create_index = *pc->next_node_index;
- *pc->next_node_index += 1;
return node;
}
@@ -2611,7 +2608,7 @@ static AstNode *ast_parse_root(ParseContext *pc, size_t *token_index) {
}
AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner,
- ErrColor err_color, uint32_t *next_node_index)
+ ErrColor err_color)
{
ParseContext pc = {0};
pc.void_buf = buf_create_from_str("void");
@@ -2620,7 +2617,6 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner,
pc.owner = owner;
pc.buf = buf;
pc.tokens = tokens;
- pc.next_node_index = next_node_index;
size_t token_index = 0;
pc.root = ast_parse_root(&pc, &token_index);
return pc.root;
src/parser.hpp
@@ -17,8 +17,7 @@ void ast_token_error(Token *token, const char *format, ...);
// This function is provided by generated code, generated by parsergen.cpp
-AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, ErrColor err_color,
- uint32_t *next_node_index);
+AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, ErrColor err_color);
void ast_print(AstNode *node, int indent);
std/zlib/deflate.zig
@@ -0,0 +1,522 @@
+const z_stream = struct {
+ /// next input byte */
+ next_in: &const u8,
+
+ /// number of bytes available at next_in
+ avail_in: u16,
+ /// total number of input bytes read so far
+ total_in: u32,
+
+ /// next output byte will go here
+ next_out: u8,
+ /// remaining free space at next_out
+ avail_out: u16,
+ /// total number of bytes output so far
+ total_out: u32,
+
+ /// last error message, NULL if no error
+ msg: ?&const u8,
+ /// not visible by applications
+ state:
+ struct internal_state FAR *state; // not visible by applications */
+
+ alloc_func zalloc; // used to allocate the internal state */
+ free_func zfree; // used to free the internal state */
+ voidpf opaque; // private data object passed to zalloc and zfree */
+
+ int data_type; // best guess about the data type: binary or text
+ // for deflate, or the decoding state for inflate */
+ uint32_t adler; // Adler-32 or CRC-32 value of the uncompressed data */
+ uint32_t reserved; // reserved for future use */
+};
+
+typedef struct internal_state {
+ z_stream * strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ uint8_t *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ uint8_t *pending_out; /* next pending byte to output to the stream */
+ ulg pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ ulg gzindex; /* where in extra, name, or comment */
+ uint8_t method; /* can only be DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uint16_t w_size; /* LZ77 window size (32K by default) */
+ uint16_t w_bits; /* log2(w_size) (8..16) */
+ uint16_t w_mask; /* w_size - 1 */
+
+ uint8_t *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uint16_t ins_h; /* hash index of string to be inserted */
+ uint16_t hash_size; /* number of elements in hash table */
+ uint16_t hash_bits; /* log2(hash_size) */
+ uint16_t hash_mask; /* hash_size-1 */
+
+ uint16_t hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uint16_t match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uint16_t strstart; /* start of string to insert */
+ uint16_t match_start; /* start of matching string */
+ uint16_t lookahead; /* number of valid bytes ahead in window */
+
+ uint16_t prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uint16_t max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uint16_t max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uint16_t good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to suppress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uint16_t lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uint16_t last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uint16_t matches; /* number of string matches in current block */
+ uint16_t insert; /* bytes at end of window left to insert */
+
+#ifdef ZLIB_DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
+} FAR deflate_state;
+
+fn deflate(strm: &z_stream, flush: int) -> %void {
+
+}
+
+int deflate (z_stream * strm, int flush) {
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+ /* zlib header */
+ uint16_t header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uint16_t level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uint16_t)(strm->adler >> 16));
+ putShortMSB(s, (uint16_t)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#ifdef GZIP
+ if (s->status == GZIP_STATE) {
+ /* gzip header */
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == Z_NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (uint8_t)(s->gzhead->time & 0xff));
+ put_byte(s, (uint8_t)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (uint8_t)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (uint8_t)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != Z_NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ uint16_t left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
+ while (s->pending + left > s->pending_buf_size) {
+ uint16_t copy = s->pending_buf_size - s->pending;
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, copy);
+ s->pending = s->pending_buf_size;
+ HCRC_UPDATE(beg);
+ s->gzindex += copy;
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ left -= copy;
+ }
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, left);
+ s->pending += left;
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ }
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size) {
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ put_byte(s, (uint8_t)(strm->adler & 0xff));
+ put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ }
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#endif
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = s->level == 0 ? deflate_stored(s, flush) :
+ s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (uint8_t)(strm->adler & 0xff));
+ put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff));
+ put_byte(s, (uint8_t)((strm->adler >> 16) & 0xff));
+ put_byte(s, (uint8_t)((strm->adler >> 24) & 0xff));
+ put_byte(s, (uint8_t)(strm->total_in & 0xff));
+ put_byte(s, (uint8_t)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (uint8_t)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (uint8_t)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uint16_t)(strm->adler >> 16));
+ putShortMSB(s, (uint16_t)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
std/zlib/inflate.zig
@@ -0,0 +1,969 @@
+
+error Z_STREAM_ERROR;
+error Z_STREAM_END;
+error Z_NEED_DICT;
+error Z_ERRNO;
+error Z_STREAM_ERROR;
+error Z_DATA_ERROR;
+error Z_MEM_ERROR;
+error Z_BUF_ERROR;
+error Z_VERSION_ERROR;
+
+pub Flush = enum {
+ NO_FLUSH,
+ PARTIAL_FLUSH,
+ SYNC_FLUSH,
+ FULL_FLUSH,
+ FINISH,
+ BLOCK,
+ TREES,
+};
+
+const code = struct {
+ /// operation, extra bits, table bits
+ op: u8,
+ /// bits in this part of the code
+ bits: u8,
+ /// offset in table or code value
+ val: u16,
+};
+
+/// State maintained between inflate() calls -- approximately 7K bytes, not
+/// including the allocated sliding window, which is up to 32K bytes.
+const inflate_state = struct {
+ z_stream * strm; /* pointer back to this zlib stream */
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
+ bit 2 true to validate check value */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ u8 FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ int sane; /* if false, allow invalid distance too far */
+ int back; /* bits back of last unprocessed length/lit */
+ unsigned was; /* initial length of match */
+};
+
+const alloc_func = fn(opaque: &c_void, items: u16, size: u16);
+const free_func = fn(opaque: &c_void, address: &c_void);
+
+const z_stream = struct {
+ /// next input byte
+ next_in: &u8,
+ /// number of bytes available at next_in
+ avail_in: u16,
+ /// total number of input bytes read so far
+ total_in: u32,
+
+ /// next output byte will go here
+ next_out: &u8,
+ /// remaining free space at next_out
+ avail_out: u16,
+ /// total number of bytes output so far */
+ total_out: u32,
+
+ /// last error message, NULL if no error
+ msg: &const u8,
+ /// not visible by applications
+ state: &inflate_state,
+
+ /// used to allocate the internal state
+ zalloc: alloc_func,
+ /// used to free the internal state
+ zfree: free_func,
+ /// private data object passed to zalloc and zfree
+ opaque: &c_void,
+
+ /// best guess about the data type: binary or text
+ /// for deflate, or the decoding state for inflate
+ data_type: i32,
+
+ /// Adler-32 or CRC-32 value of the uncompressed data
+ adler: u32,
+};
+
+// Possible inflate modes between inflate() calls
+/// i: waiting for magic header
+pub const HEAD = 16180;
+/// i: waiting for method and flags (gzip)
+pub const FLAGS = 16181;
+/// i: waiting for modification time (gzip)
+pub const TIME = 16182;
+/// i: waiting for extra flags and operating system (gzip)
+pub const OS = 16183;
+/// i: waiting for extra length (gzip)
+pub const EXLEN = 16184;
+/// i: waiting for extra bytes (gzip)
+pub const EXTRA = 16185;
+/// i: waiting for end of file name (gzip)
+pub const NAME = 16186;
+/// i: waiting for end of comment (gzip)
+pub const COMMENT = 16187;
+/// i: waiting for header crc (gzip)
+pub const HCRC = 16188;
+/// i: waiting for dictionary check value
+pub const DICTID = 16189;
+/// waiting for inflateSetDictionary() call
+pub const DICT = 16190;
+/// i: waiting for type bits, including last-flag bit
+pub const TYPE = 16191;
+/// i: same, but skip check to exit inflate on new block
+pub const TYPEDO = 16192;
+/// i: waiting for stored size (length and complement)
+pub const STORED = 16193;
+/// i/o: same as COPY below, but only first time in
+pub const COPY_ = 16194;
+/// i/o: waiting for input or output to copy stored block
+pub const COPY = 16195;
+/// i: waiting for dynamic block table lengths
+pub const TABLE = 16196;
+/// i: waiting for code length code lengths
+pub const LENLENS = 16197;
+/// i: waiting for length/lit and distance code lengths
+pub const CODELENS = 16198;
+/// i: same as LEN below, but only first time in
+pub const LEN_ = 16199;
+/// i: waiting for length/lit/eob code
+pub const LEN = 16200;
+/// i: waiting for length extra bits
+pub const LENEXT = 16201;
+/// i: waiting for distance code
+pub const DIST = 16202;
+/// i: waiting for distance extra bits
+pub const DISTEXT = 16203;
+/// o: waiting for output space to copy string
+pub const MATCH = 16204;
+/// o: waiting for output space to write literal
+pub const LIT = 16205;
+/// i: waiting for 32-bit check value
+pub const CHECK = 16206;
+/// i: waiting for 32-bit length (gzip)
+pub const LENGTH = 16207;
+/// finished check, done -- remain here until reset
+pub const DONE = 16208;
+/// got a data error -- remain here until reset
+pub const BAD = 16209;
+/// got an inflate() memory error -- remain here until reset
+pub const MEM = 16210;
+/// looking for synchronization bytes to restart inflate() */
+pub const SYNC = 16211;
+
+/// inflate() uses a state machine to process as much input data and generate as
+/// much output data as possible before returning. The state machine is
+/// structured roughly as follows:
+///
+/// for (;;) switch (state) {
+/// ...
+/// case STATEn:
+/// if (not enough input data or output space to make progress)
+/// return;
+/// ... make progress ...
+/// state = STATEm;
+/// break;
+/// ...
+/// }
+///
+/// so when inflate() is called again, the same case is attempted again, and
+/// if the appropriate resources are provided, the machine proceeds to the
+/// next state. The NEEDBITS() macro is usually the way the state evaluates
+/// whether it can proceed or should return. NEEDBITS() does the return if
+/// the requested bits are not available. The typical use of the BITS macros
+/// is:
+///
+/// NEEDBITS(n);
+/// ... do something with BITS(n) ...
+/// DROPBITS(n);
+///
+/// where NEEDBITS(n) either returns from inflate() if there isn't enough
+/// input left to load n bits into the accumulator, or it continues. BITS(n)
+/// gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+/// the low n bits off the accumulator. INITBITS() clears the accumulator
+/// and sets the number of available bits to zero. BYTEBITS() discards just
+/// enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+/// and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+///
+/// NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+/// if there is no input available. The decoding of variable length codes uses
+/// PULLBYTE() directly in order to pull just enough bytes to decode the next
+/// code, and no more.
+///
+/// Some states loop until they get enough input, making sure that enough
+/// state information is maintained to continue the loop where it left off
+/// if NEEDBITS() returns in the loop. For example, want, need, and keep
+/// would all have to actually be part of the saved state in case NEEDBITS()
+/// returns:
+///
+/// case STATEw:
+/// while (want < need) {
+/// NEEDBITS(n);
+/// keep[want++] = BITS(n);
+/// DROPBITS(n);
+/// }
+/// state = STATEx;
+/// case STATEx:
+///
+/// As shown above, if the next state is also the next case, then the break
+/// is omitted.
+///
+/// A state may also return if there is not enough output space available to
+/// complete that state. Those states are copying stored data, writing a
+/// literal byte, and copying a matching string.
+///
+/// When returning, a "goto inf_leave" is used to update the total counters,
+/// update the check value, and determine whether any progress has been made
+/// during that inflate() call in order to return the proper return code.
+/// Progress is defined as a change in either strm->avail_in or strm->avail_out.
+/// When there is a window, goto inf_leave will update the window with the last
+/// output written. If a goto inf_leave occurs in the middle of decompression
+/// and there is no window currently, goto inf_leave will create one and copy
+/// output to the window for the next call of inflate().
+///
+/// In this implementation, the flush parameter of inflate() only affects the
+/// return code (per zlib.h). inflate() always writes as much as possible to
+/// strm->next_out, given the space available and the provided input--the effect
+/// documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+/// the allocation of and copying into a sliding window until necessary, which
+/// provides the effect documented in zlib.h for Z_FINISH when the entire input
+/// stream available. So the only thing the flush parameter actually does is:
+/// when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+/// will return Z_BUF_ERROR if it has not reached the end of the stream.
+pub fn inflate(strm: &z_stream, flush: Flush, gunzip: bool) -> %void {
+ // next input
+ var next: &const u8 = undefined;
+ // next output
+ var put: &u8 = undefined;
+
+ // available input and output
+ var have: u16 = undefined;
+ var left: u16 = undefined;
+
+ // bit buffer
+ var hold: u32 = undefined;
+ // bits in bit buffer
+ var bits: u16 = undefined;
+ // save starting available input and output
+ var in: u16 = undefined;
+ var out: u16 = undefined;
+ // number of stored or match bytes to copy
+ var copy: u16 = undefined;
+ // where to copy match bytes from
+ var from: &u8 = undefined;
+ // current decoding table entry
+ var here: code = undefined;
+ // parent table entry
+ var last: code = undefined;
+ // length to copy for repeats, bits to drop
+ var len: u16 = undefined;
+
+ // return code
+ var ret: error = undefined;
+
+ // buffer for gzip header crc calculation
+ var hbuf: [4]u8 = undefined;
+
+ // permutation of code lengths
+ const short_order = []u16 = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (inflateStateCheck(strm) or strm.next_out == Z_NULL or (strm.next_in == Z_NULL and strm.avail_in != 0)) {
+ return error.Z_STREAM_ERROR;
+ }
+
+ var state: &inflate_state = strm.state;
+ if (state.mode == TYPE) {
+ state.mode = TYPEDO; // skip check
+ }
+ put = strm.next_out; \
+ left = strm.avail_out; \
+ next = strm.next_in; \
+ have = strm.avail_in; \
+ hold = state.hold; \
+ bits = state.bits; \
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state.mode) {
+ case HEAD:
+ if (state.wrap == 0) {
+ state.mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state.wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ if (state.wbits == 0)
+ state.wbits = 15;
+ state.check = crc32(0L, Z_NULL, 0);
+ CRC2(state.check, hold);
+ INITBITS();
+ state.mode = FLAGS;
+ break;
+ }
+ state.flags = 0; /* expect zlib header */
+ if (state.head != Z_NULL)
+ state.head.done = -1;
+ if (!(state.wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm.msg = (char *)"incorrect header check";
+ state.mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm.msg = (char *)"unknown compression method";
+ state.mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (state.wbits == 0)
+ state.wbits = len;
+ if (len > 15 || len > state.wbits) {
+ strm.msg = (char *)"invalid window size";
+ state.mode = BAD;
+ break;
+ }
+ state.dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm.adler = state.check = adler32(0L, Z_NULL, 0);
+ state.mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state.flags = (int)(hold);
+ if ((state.flags & 0xff) != Z_DEFLATED) {
+ strm.msg = (char *)"unknown compression method";
+ state.mode = BAD;
+ break;
+ }
+ if (state.flags & 0xe000) {
+ strm.msg = (char *)"unknown header flags set";
+ state.mode = BAD;
+ break;
+ }
+ if (state.head != Z_NULL)
+ state.head.text = (int)((hold >> 8) & 1);
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ CRC2(state.check, hold);
+ INITBITS();
+ state.mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state.head != Z_NULL)
+ state.head.time = hold;
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ CRC4(state.check, hold);
+ INITBITS();
+ state.mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state.head != Z_NULL) {
+ state.head.xflags = (int)(hold & 0xff);
+ state.head.os = (int)(hold >> 8);
+ }
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ CRC2(state.check, hold);
+ INITBITS();
+ state.mode = EXLEN;
+ case EXLEN:
+ if (state.flags & 0x0400) {
+ NEEDBITS(16);
+ state.length = (unsigned)(hold);
+ if (state.head != Z_NULL)
+ state.head.extra_len = (unsigned)hold;
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ CRC2(state.check, hold);
+ INITBITS();
+ }
+ else if (state.head != Z_NULL)
+ state.head.extra = Z_NULL;
+ state.mode = EXTRA;
+ case EXTRA:
+ if (state.flags & 0x0400) {
+ copy = state.length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state.head != Z_NULL &&
+ state.head.extra != Z_NULL) {
+ len = state.head.extra_len - state.length;
+ zmemcpy(state.head.extra + len, next,
+ len + copy > state.head.extra_max ?
+ state.head.extra_max - len : copy);
+ }
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ state.check = crc32(state.check, next, copy);
+ have -= copy;
+ next += copy;
+ state.length -= copy;
+ }
+ if (state.length) goto inf_leave;
+ }
+ state.length = 0;
+ state.mode = NAME;
+ case NAME:
+ if (state.flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state.head != Z_NULL &&
+ state.head.name != Z_NULL &&
+ state.length < state.head.name_max)
+ state.head.name[state.length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ state.check = crc32(state.check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state.head != Z_NULL)
+ state.head.name = Z_NULL;
+ state.length = 0;
+ state.mode = COMMENT;
+ case COMMENT:
+ if (state.flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state.head != Z_NULL &&
+ state.head.comment != Z_NULL &&
+ state.length < state.head.comm_max)
+ state.head.comment[state.length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state.flags & 0x0200) && (state.wrap & 4))
+ state.check = crc32(state.check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state.head != Z_NULL)
+ state.head.comment = Z_NULL;
+ state.mode = HCRC;
+ case HCRC:
+ if (state.flags & 0x0200) {
+ NEEDBITS(16);
+ if ((state.wrap & 4) && hold != (state.check & 0xffff)) {
+ strm.msg = (char *)"header crc mismatch";
+ state.mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state.head != Z_NULL) {
+ state.head.hcrc = (int)((state.flags >> 9) & 1);
+ state.head.done = 1;
+ }
+ strm.adler = state.check = crc32(0L, Z_NULL, 0);
+ state.mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm.adler = state.check = ZSWAP32(hold);
+ INITBITS();
+ state.mode = DICT;
+ case DICT:
+ if (state.havedict == 0) {
+ strm.next_out = put; \
+ strm.avail_out = left; \
+ strm.next_in = next; \
+ strm.avail_in = have; \
+ state.hold = hold; \
+ state.bits = bits; \
+ return Z_NEED_DICT;
+ }
+ strm.adler = state.check = adler32(0L, Z_NULL, 0);
+ state.mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ case TYPEDO:
+ if (state.last) {
+ BYTEBITS();
+ state.mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state.last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state.last ? " (last)" : ""));
+ state.mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state.last ? " (last)" : ""));
+ state.mode = LEN_; /* decode codes */
+ if (flush == Z_TREES) {
+ DROPBITS(2);
+ goto inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state.last ? " (last)" : ""));
+ state.mode = TABLE;
+ break;
+ case 3:
+ strm.msg = (char *)"invalid block type";
+ state.mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm.msg = (char *)"invalid stored block lengths";
+ state.mode = BAD;
+ break;
+ }
+ state.length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state.length));
+ INITBITS();
+ state.mode = COPY_;
+ if (flush == Z_TREES) goto inf_leave;
+ case COPY_:
+ state.mode = COPY;
+ case COPY:
+ copy = state.length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state.length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state.mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state.nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state.ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state.ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state.nlen > 286 || state.ndist > 30) {
+ strm.msg = (char *)"too many length or distance symbols";
+ state.mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state.have = 0;
+ state.mode = LENLENS;
+ case LENLENS:
+ while (state.have < state.ncode) {
+ NEEDBITS(3);
+ state.lens[order[state.have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state.have < 19)
+ state.lens[order[state.have++]] = 0;
+ state.next = state.codes;
+ state.lencode = (const code FAR *)(state.next);
+ state.lenbits = 7;
+ ret = inflate_table(CODES, state.lens, 19, &(state.next),
+ &(state.lenbits), state.work);
+ if (ret) {
+ strm.msg = (char *)"invalid code lengths set";
+ state.mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state.have = 0;
+ state.mode = CODELENS;
+ case CODELENS:
+ while (state.have < state.nlen + state.ndist) {
+ for (;;) {
+ here = state.lencode[BITS(state.lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state.lens[state.have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state.have == 0) {
+ strm.msg = (char *)"invalid bit length repeat";
+ state.mode = BAD;
+ break;
+ }
+ len = state.lens[state.have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state.have + copy > state.nlen + state.ndist) {
+ strm.msg = (char *)"invalid bit length repeat";
+ state.mode = BAD;
+ break;
+ }
+ while (copy--)
+ state.lens[state.have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state.mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state.lens[256] == 0) {
+ strm.msg = (char *)"invalid code -- missing end-of-block";
+ state.mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state.next = state.codes;
+ state.lencode = (const code FAR *)(state.next);
+ state.lenbits = 9;
+ ret = inflate_table(LENS, state.lens, state.nlen, &(state.next),
+ &(state.lenbits), state.work);
+ if (ret) {
+ strm.msg = (char *)"invalid literal/lengths set";
+ state.mode = BAD;
+ break;
+ }
+ state.distcode = (const code FAR *)(state.next);
+ state.distbits = 6;
+ ret = inflate_table(DISTS, state.lens + state.nlen, state.ndist,
+ &(state.next), &(state.distbits), state.work);
+ if (ret) {
+ strm.msg = (char *)"invalid distances set";
+ state.mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state.mode = LEN_;
+ if (flush == Z_TREES) goto inf_leave;
+ case LEN_:
+ state.mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ strm.next_out = put; \
+ strm.avail_out = left; \
+ strm.next_in = next; \
+ strm.avail_in = have; \
+ state.hold = hold; \
+ state.bits = bits; \
+
+ inflate_fast(strm, out);
+
+ put = strm.next_out; \
+ left = strm.avail_out; \
+ next = strm.next_in; \
+ have = strm.avail_in; \
+ hold = state.hold; \
+ bits = state.bits; \
+ if (state.mode == TYPE)
+ state.back = -1;
+ break;
+ }
+ state.back = 0;
+ for (;;) {
+ here = state.lencode[BITS(state.lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state.lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state.back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state.back += here.bits;
+ state.length = (unsigned)here.val;
+ if ((int)(here.op) == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ state.mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state.back = -1;
+ state.mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm.msg = (char *)"invalid literal/length code";
+ state.mode = BAD;
+ break;
+ }
+ state.extra = (unsigned)(here.op) & 15;
+ state.mode = LENEXT;
+ case LENEXT:
+ if (state.extra) {
+ NEEDBITS(state.extra);
+ state.length += BITS(state.extra);
+ DROPBITS(state.extra);
+ state.back += state.extra;
+ }
+ Tracevv((stderr, "inflate: length %u\n", state.length));
+ state.was = state.length;
+ state.mode = DIST;
+ case DIST:
+ for (;;) {
+ here = state.distcode[BITS(state.distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state.distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state.back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state.back += here.bits;
+ if (here.op & 64) {
+ strm.msg = (char *)"invalid distance code";
+ state.mode = BAD;
+ break;
+ }
+ state.offset = (unsigned)here.val;
+ state.extra = (unsigned)(here.op) & 15;
+ state.mode = DISTEXT;
+ case DISTEXT:
+ if (state.extra) {
+ NEEDBITS(state.extra);
+ state.offset += BITS(state.extra);
+ DROPBITS(state.extra);
+ state.back += state.extra;
+ }
+#ifdef INFLATE_STRICT
+ if (state.offset > state.dmax) {
+ strm.msg = (char *)"invalid distance too far back";
+ state.mode = BAD;
+ break;
+ }
+#endif
+ Tracevv((stderr, "inflate: distance %u\n", state.offset));
+ state.mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state.offset > copy) { /* copy from window */
+ copy = state.offset - copy;
+ if (copy > state.whave) {
+ if (state.sane) {
+ strm.msg = (char *)"invalid distance too far back";
+ state.mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state.whave;
+ if (copy > state.length) copy = state.length;
+ if (copy > left) copy = left;
+ left -= copy;
+ state.length -= copy;
+ do {
+ *put++ = 0;
+ } while (--copy);
+ if (state.length == 0) state.mode = LEN;
+ break;
+#endif
+ }
+ if (copy > state.wnext) {
+ copy -= state.wnext;
+ from = state.window + (state.wsize - copy);
+ }
+ else
+ from = state.window + (state.wnext - copy);
+ if (copy > state.length) copy = state.length;
+ }
+ else { /* copy from output */
+ from = put - state.offset;
+ copy = state.length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state.length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state.length == 0) state.mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (u8)(state.length);
+ left--;
+ state.mode = LEN;
+ break;
+ case CHECK:
+ if (state.wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm.total_out += out;
+ state.total += out;
+ if ((state.wrap & 4) && out)
+ strm.adler = state.check =
+ UPDATE(state.check, put - out, out);
+ out = left;
+ if ((state.wrap & 4) && (
+#ifdef GUNZIP
+ state.flags ? hold :
+#endif
+ ZSWAP32(hold)) != state.check) {
+ strm.msg = (char *)"incorrect data check";
+ state.mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state.mode = LENGTH;
+ case LENGTH:
+ if (state.wrap && state.flags) {
+ NEEDBITS(32);
+ if (hold != (state.total & 0xffffffffUL)) {
+ strm.msg = (char *)"incorrect length check";
+ state.mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state.mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ strm.next_out = put; \
+ strm.avail_out = left; \
+ strm.next_in = next; \
+ strm.avail_in = have; \
+ state.hold = hold; \
+ state.bits = bits; \
+ if (state.wsize || (out != strm.avail_out && state.mode < BAD &&
+ (state.mode < CHECK || flush != Z_FINISH)))
+ if (updatewindow(strm, strm.next_out, out - strm.avail_out)) {
+ state.mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm.avail_in;
+ out -= strm.avail_out;
+ strm.total_in += in;
+ strm.total_out += out;
+ state.total += out;
+ if ((state.wrap & 4) && out)
+ strm.adler = state.check =
+ UPDATE(state.check, strm.next_out - out, out);
+ strm.data_type = (int)state.bits + (state.last ? 64 : 0) +
+ (state.mode == TYPE ? 128 : 0) +
+ (state.mode == LEN_ || state.mode == COPY_ ? 256 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+local int inflateStateCheck(z_stream * strm) {
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL ||
+ strm.zalloc == (alloc_func)0 || strm.zfree == (free_func)0)
+ return 1;
+ state = (struct inflate_state FAR *)strm.state;
+ if (state == Z_NULL || state.strm != strm ||
+ state.mode < HEAD || state.mode > SYNC)
+ return 1;
+ return 0;
+}