<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/page/PrintContext.h"

#include "core/dom/Document.h"
#include "core/html/HTMLElement.h"
#include "core/testing/DummyPageHolder.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/testing/SkiaForCoreTesting.h"
#include "platform/text/TextStream.h"
#include <gtest/gtest.h>

namespace blink {

const int kPageWidth = 800;
const int kPageHeight = 600;

class MockPrintContext : public PrintContext {
public:
    MockPrintContext(LocalFrame* frame) : PrintContext(frame) { }

    void outputLinkAndLinkedDestinations(GraphicsContext& context, Node* node, const IntRect& pageRect)
    {
        PrintContext::outputLinkAndLinkedDestinations(context, node, pageRect);
    }
};

class MockCanvas : public SkCanvas {
public:
    enum OperationType {
        DrawRect,
        DrawPoint
    };

    struct Operation {
        OperationType type;
        SkRect rect;
    };

    MockCanvas() : SkCanvas(kPageWidth, kPageHeight) { }

    virtual void drawRect(const SkRect& rect, const SkPaint& paint) override
    {
        ASSERT_TRUE(paint.getAnnotation());
        Operation operation = { DrawRect, rect };
        m_recordedOperations.append(operation);
    }

    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) override
    {
        ASSERT_EQ(1u, count); // Only called from drawPoint().
        ASSERT_TRUE(paint.getAnnotation());
        Operation operation = { DrawPoint, SkRect::MakeXYWH(pts[0].x(), pts[0].y(), 0, 0) };
        m_recordedOperations.append(operation);
    }

    const Vector<Operation>& recordedOperations() const { return m_recordedOperations; }

private:
    Vector<Operation> m_recordedOperations;
};

class PrintContextTest : public testing::Test {
protected:
    PrintContextTest()
        : m_pageHolder(DummyPageHolder::create(IntSize(kPageWidth, kPageHeight)))
        , m_printContext(adoptPtrWillBeNoop(new MockPrintContext(document().frame()))) { }

    Document& document() const { return m_pageHolder->document(); }
    MockPrintContext& printContext() { return *m_printContext.get(); }

    void setBodyInnerHTML(String bodyContent)
    {
        document().body()->setInnerHTML(bodyContent, ASSERT_NO_EXCEPTION);
    }

    void printSinglePage(SkCanvas& canvas)
    {
        IntRect pageRect(0, 0, kPageWidth, kPageHeight);
        GraphicsContext context(&canvas, nullptr);
        printContext().begin(kPageWidth, kPageHeight);
        printContext().outputLinkAndLinkedDestinations(context, &document(), pageRect);
        printContext().end();
    }

    static String htmlForLink(int x, int y, int width, int height, const char* url)
    {
        TextStream ts;
        ts << "<a style='position: absolute; left: " << x << "px; top: " << y << "px; width: " << width << "px; height: " << height
            << "px' href='" << url << "'>" << url << "";
        return ts.release();
    }

    static String htmlForAnchor(int x, int y, const char* name)
    {
        TextStream ts;
        ts << "<a name='" << name << "' style='position: absolute; left: " << x << "px; top: " << y << "px'>" << name << "";
        return ts.release();
    }

private:
    OwnPtr<DummyPageHolder> m_pageHolder;
    OwnPtrWillBePersistent<MockPrintContext> m_printContext;
};

#define EXPECT_SKRECT_EQ(expectedX, expectedY, expectedWidth, expectedHeight, actualRect) \
    EXPECT_EQ(expectedX, actualRect.x()); \
    EXPECT_EQ(expectedY, actualRect.y()); \
    EXPECT_EQ(expectedWidth, actualRect.width()); \
    EXPECT_EQ(expectedHeight, actualRect.height());

TEST_F(PrintContextTest, LinkTarget)
{
    MockCanvas canvas;
    setBodyInnerHTML(htmlForLink(50, 60, 70, 80, "http://www.google.com")
        + htmlForLink(150, 160, 170, 180, "http://www.google.com#fragment"));
    printSinglePage(canvas);

    const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations();
    ASSERT_EQ(2u, operations.size());

    // The items in the result can be in any sequence.
    size_t firstIndex = operations[0].rect.x() == 50 ? 0 : 1;
    EXPECT_EQ(MockCanvas::DrawRect, operations[firstIndex].type);
    EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[firstIndex].rect);
    // We should also check if the annotation is correct but Skia doesn't export
    // SkAnnotation API.

    size_t secondIndex = firstIndex == 0 ? 1 : 0;
    EXPECT_EQ(MockCanvas::DrawRect, operations[secondIndex].type);
    EXPECT_SKRECT_EQ(150, 160, 170, 180, operations[secondIndex].rect);
}

TEST_F(PrintContextTest, LinkedTarget)
{
    MockCanvas canvas;
    document().setBaseURLOverride(KURL(ParsedURLString, "http://a.com/"));
    setBodyInnerHTML(htmlForLink(50, 60, 70, 80, "#fragment") // Generates a Link_Named_Dest_Key annotation
        + htmlForLink(150, 160, 170, 180, "#not-found") // Generates no annotation
        + htmlForAnchor(250, 260, "fragment") // Generates a Define_Named_Dest_Key annotation
        + htmlForAnchor(350, 360, "fragment-not-used")); // Generates no annotation
    printSinglePage(canvas);

    const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations();
    ASSERT_EQ(2u, operations.size());

    size_t firstIndex = operations[0].rect.x() == 50 ? 0 : 1;
    EXPECT_EQ(MockCanvas::DrawRect, operations[firstIndex].type);
    EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[firstIndex].rect);

    size_t secondIndex = firstIndex == 0 ? 1 : 0;
    EXPECT_EQ(MockCanvas::DrawPoint, operations[secondIndex].type);
    EXPECT_SKRECT_EQ(250, 260, 0, 0, operations[secondIndex].rect);
}

} // namespace blink
<commit_msg>catch last case of converting to onDraw<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/page/PrintContext.h"

#include "core/dom/Document.h"
#include "core/html/HTMLElement.h"
#include "core/testing/DummyPageHolder.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/testing/SkiaForCoreTesting.h"
#include "platform/text/TextStream.h"
#include <gtest/gtest.h>

namespace blink {

const int kPageWidth = 800;
const int kPageHeight = 600;

class MockPrintContext : public PrintContext {
public:
    MockPrintContext(LocalFrame* frame) : PrintContext(frame) { }

    void outputLinkAndLinkedDestinations(GraphicsContext& context, Node* node, const IntRect& pageRect)
    {
        PrintContext::outputLinkAndLinkedDestinations(context, node, pageRect);
    }
};

class MockCanvas : public SkCanvas {
public:
    enum OperationType {
        DrawRect,
        DrawPoint
    };

    struct Operation {
        OperationType type;
        SkRect rect;
    };

    MockCanvas() : SkCanvas(kPageWidth, kPageHeight) { }

    virtual void onDrawRect(const SkRect& rect, const SkPaint& paint) override
    {
        ASSERT_TRUE(paint.getAnnotation());
        Operation operation = { DrawRect, rect };
        m_recordedOperations.append(operation);
    }

    virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) override
    {
        ASSERT_EQ(1u, count); // Only called from drawPoint().
        ASSERT_TRUE(paint.getAnnotation());
        Operation operation = { DrawPoint, SkRect::MakeXYWH(pts[0].x(), pts[0].y(), 0, 0) };
        m_recordedOperations.append(operation);
    }

    const Vector<Operation>& recordedOperations() const { return m_recordedOperations; }

private:
    Vector<Operation> m_recordedOperations;
};

class PrintContextTest : public testing::Test {
protected:
    PrintContextTest()
        : m_pageHolder(DummyPageHolder::create(IntSize(kPageWidth, kPageHeight)))
        , m_printContext(adoptPtrWillBeNoop(new MockPrintContext(document().frame()))) { }

    Document& document() const { return m_pageHolder->document(); }
    MockPrintContext& printContext() { return *m_printContext.get(); }

    void setBodyInnerHTML(String bodyContent)
    {
        document().body()->setInnerHTML(bodyContent, ASSERT_NO_EXCEPTION);
    }

    void printSinglePage(SkCanvas& canvas)
    {
        IntRect pageRect(0, 0, kPageWidth, kPageHeight);
        GraphicsContext context(&canvas, nullptr);
        printContext().begin(kPageWidth, kPageHeight);
        printContext().outputLinkAndLinkedDestinations(context, &document(), pageRect);
        printContext().end();
    }

    static String htmlForLink(int x, int y, int width, int height, const char* url)
    {
        TextStream ts;
        ts << "<a style='position: absolute; left: " << x << "px; top: " << y << "px; width: " << width << "px; height: " << height
            << "px' href='" << url << "'>" << url << "";
        return ts.release();
    }

    static String htmlForAnchor(int x, int y, const char* name)
    {
        TextStream ts;
        ts << "<a name='" << name << "' style='position: absolute; left: " << x << "px; top: " << y << "px'>" << name << "";
        return ts.release();
    }

private:
    OwnPtr<DummyPageHolder> m_pageHolder;
    OwnPtrWillBePersistent<MockPrintContext> m_printContext;
};

#define EXPECT_SKRECT_EQ(expectedX, expectedY, expectedWidth, expectedHeight, actualRect) \
    EXPECT_EQ(expectedX, actualRect.x()); \
    EXPECT_EQ(expectedY, actualRect.y()); \
    EXPECT_EQ(expectedWidth, actualRect.width()); \
    EXPECT_EQ(expectedHeight, actualRect.height());

TEST_F(PrintContextTest, LinkTarget)
{
    MockCanvas canvas;
    setBodyInnerHTML(htmlForLink(50, 60, 70, 80, "http://www.google.com")
        + htmlForLink(150, 160, 170, 180, "http://www.google.com#fragment"));
    printSinglePage(canvas);

    const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations();
    ASSERT_EQ(2u, operations.size());

    // The items in the result can be in any sequence.
    size_t firstIndex = operations[0].rect.x() == 50 ? 0 : 1;
    EXPECT_EQ(MockCanvas::DrawRect, operations[firstIndex].type);
    EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[firstIndex].rect);
    // We should also check if the annotation is correct but Skia doesn't export
    // SkAnnotation API.

    size_t secondIndex = firstIndex == 0 ? 1 : 0;
    EXPECT_EQ(MockCanvas::DrawRect, operations[secondIndex].type);
    EXPECT_SKRECT_EQ(150, 160, 170, 180, operations[secondIndex].rect);
}

TEST_F(PrintContextTest, LinkedTarget)
{
    MockCanvas canvas;
    document().setBaseURLOverride(KURL(ParsedURLString, "http://a.com/"));
    setBodyInnerHTML(htmlForLink(50, 60, 70, 80, "#fragment") // Generates a Link_Named_Dest_Key annotation
        + htmlForLink(150, 160, 170, 180, "#not-found") // Generates no annotation
        + htmlForAnchor(250, 260, "fragment") // Generates a Define_Named_Dest_Key annotation
        + htmlForAnchor(350, 360, "fragment-not-used")); // Generates no annotation
    printSinglePage(canvas);

    const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations();
    ASSERT_EQ(2u, operations.size());

    size_t firstIndex = operations[0].rect.x() == 50 ? 0 : 1;
    EXPECT_EQ(MockCanvas::DrawRect, operations[firstIndex].type);
    EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[firstIndex].rect);

    size_t secondIndex = firstIndex == 0 ? 1 : 0;
    EXPECT_EQ(MockCanvas::DrawPoint, operations[secondIndex].type);
    EXPECT_SKRECT_EQ(250, 260, 0, 0, operations[secondIndex].rect);
}

} // namespace blink
<|endoftext|>


<commit_before>//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Decl nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Type.h"
using namespace clang;
using namespace CodeGen;

void CodeGenFunction::EmitDecl(const Decl &D) {
  switch (D.getKind()) {
  default: assert(0 && "Unknown decl kind!");
  case Decl::ParmVar:
    assert(0 && "Parmdecls should not be in declstmts!");
  case Decl::Function:  // void X();
  case Decl::Record:    // struct/union/class X;
  case Decl::Enum:      // enum X;
  case Decl::EnumConstant: // enum ? { X = ? }
  case Decl::CXXRecord: // struct/union/class X; [C++]
    // None of these decls require codegen support.
    return;

  case Decl::Var: {
    const VarDecl &VD = cast<VarDecl>(D);
    assert(VD.isBlockVarDecl() &&
           "Should not see file-scope variables inside a function!");
    return EmitBlockVarDecl(VD);
  }

  case Decl::Typedef: {   // typedef int X;
    const TypedefDecl &TD = cast<TypedefDecl>(D);
    QualType Ty = TD.getUnderlyingType();

    if (Ty->isVariablyModifiedType())
      EmitVLASize(Ty);
  }
  }
}

/// EmitBlockVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
  switch (D.getStorageClass()) {
  case VarDecl::Static:
    return EmitStaticBlockVarDecl(D);
  case VarDecl::Extern:
    // Don't emit it now, allow it to be emitted lazily on its first use.
    return;
  default:
    assert((D.getStorageClass() == VarDecl::None ||
            D.getStorageClass() == VarDecl::Auto ||
            D.getStorageClass() == VarDecl::Register) &&
           "Unknown storage class");
    return EmitLocalBlockVarDecl(D);
  }
}

llvm::GlobalValue *
CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D,
                                            bool NoInit,
                                            const char *Separator,
                                            llvm::GlobalValue
					    	::LinkageTypes Linkage) {
  QualType Ty = D.getType();
  assert(Ty->isConstantSizeType() && "VLAs can't be static");

  const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
  llvm::Constant *Init = 0;
  if ((D.getInit() == 0) || NoInit) {
    Init = llvm::Constant::getNullValue(LTy);
  } else {
    Init = CGM.EmitConstantExpr(D.getInit(), this);

    // If constant emission failed, then this should be a C++ static
    // initializer.
    if (!Init) {
      if (!getContext().getLangOptions().CPlusPlus) {
        CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
        Init = llvm::Constant::getNullValue(LTy);
      } else {
        return GenerateStaticCXXBlockVarDecl(D);
      }
    }
  }

  assert(Init && "Unable to create initialiser for static decl");

  std::string ContextName;
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
    ContextName = CGM.getMangledName(FD);
  else if (isa<ObjCMethodDecl>(CurFuncDecl))
    ContextName = std::string(CurFn->getNameStart(),
                              CurFn->getNameStart() + CurFn->getNameLen());
  else
    assert(0 && "Unknown context for block var decl");

  llvm::GlobalValue *GV =
    new llvm::GlobalVariable(Init->getType(), Ty.isConstant(getContext()),
                             Linkage,
                             Init, ContextName + Separator +D.getNameAsString(),
                             &CGM.getModule(), 0, Ty.getAddressSpace());

  return GV;
}

void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {

  llvm::Value *&DMEntry = LocalDeclMap[&D];
  assert(DMEntry == 0 && "Decl already exists in localdeclmap!");

  llvm::GlobalValue *GV;
  GV = GenerateStaticBlockVarDecl(D, false, ".",
                                  llvm::GlobalValue::InternalLinkage);

  // FIXME: Merge attribute handling.
  if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
    SourceManager &SM = CGM.getContext().getSourceManager();
    llvm::Constant *Ann =
      CGM.EmitAnnotateAttr(GV, AA,
                           SM.getInstantiationLineNumber(D.getLocation()));
    CGM.AddAnnotation(Ann);
  }

  if (const SectionAttr *SA = D.getAttr<SectionAttr>())
    GV->setSection(SA->getName());

  if (D.getAttr<UsedAttr>())
    CGM.AddUsedGlobal(GV);

  const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
  const llvm::Type *LPtrTy =
    llvm::PointerType::get(LTy, D.getType().getAddressSpace());
  DMEntry = llvm::ConstantExpr::getBitCast(GV, LPtrTy);

  // Emit global variable debug descriptor for static vars.
  CGDebugInfo *DI = getDebugInfo();
  if (DI) {
    DI->setLocation(D.getLocation());
    DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D);
  }
}

/// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
  QualType Ty = D.getType();

  llvm::Value *DeclPtr;
  if (Ty->isConstantSizeType()) {
    if (!Target.useGlobalsForAutomaticVariables()) {
      // A normal fixed sized variable becomes an alloca in the entry block.
      const llvm::Type *LTy = ConvertType(Ty);
      llvm::AllocaInst *Alloc =
        CreateTempAlloca(LTy, CGM.getMangledName(&D));
      unsigned align = getContext().getTypeAlign(Ty);
      if (const AlignedAttr* AA = D.getAttr<AlignedAttr>())
        align = std::max(align, AA->getAlignment());
      Alloc->setAlignment(align >> 3);
      DeclPtr = Alloc;
    } else {
      // Targets that don't support recursion emit locals as globals.
      const char *Class =
        D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto.";
      DeclPtr = GenerateStaticBlockVarDecl(D, true, Class,
                                           llvm::GlobalValue
                                           ::InternalLinkage);
    }

    if (Ty->isVariablyModifiedType())
      EmitVLASize(Ty);
  } else {
    if (!DidCallStackSave) {
      // Save the stack.
      const llvm::Type *LTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
      llvm::Value *Stack = CreateTempAlloca(LTy, "saved_stack");

      llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
      llvm::Value *V = Builder.CreateCall(F);

      Builder.CreateStore(V, Stack);

      DidCallStackSave = true;

      {
        // Push a cleanup block and restore the stack there.
        CleanupScope scope(*this);

        V = Builder.CreateLoad(Stack, "tmp");
        llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
        Builder.CreateCall(F, V);
      }
    }

    // Get the element type.
    const llvm::Type *LElemTy = ConvertType(Ty);
    const llvm::Type *LElemPtrTy =
      llvm::PointerType::get(LElemTy, D.getType().getAddressSpace());

    llvm::Value *VLASize = EmitVLASize(Ty);

    // Downcast the VLA size expression
    VLASize = Builder.CreateIntCast(VLASize, llvm::Type::Int32Ty, false, "tmp");

    // Allocate memory for the array.
    llvm::Value *VLA = Builder.CreateAlloca(llvm::Type::Int8Ty, VLASize, "vla");
    DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
  }

  llvm::Value *&DMEntry = LocalDeclMap[&D];
  assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
  DMEntry = DeclPtr;

  // Emit debug info for local var declaration.
  if (CGDebugInfo *DI = getDebugInfo()) {
    DI->setLocation(D.getLocation());
    DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
  }

  // If this local has an initializer, emit it now.
  if (const Expr *Init = D.getInit()) {
    if (!hasAggregateLLVMType(Init->getType())) {
      llvm::Value *V = EmitScalarExpr(Init);
      Builder.CreateStore(V, DeclPtr, D.getType().isVolatileQualified());
    } else if (Init->getType()->isAnyComplexType()) {
      EmitComplexExprIntoAddr(Init, DeclPtr, D.getType().isVolatileQualified());
    } else {
      EmitAggExpr(Init, DeclPtr, D.getType().isVolatileQualified());
    }
  }

  // Handle the cleanup attribute
  if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
    const FunctionDecl *FD = CA->getFunctionDecl();

    llvm::Constant* F = CGM.GetAddrOfFunction(FD);
    assert(F && "Could not find function!");

    CleanupScope scope(*this);

    CallArgList Args;
    Args.push_back(std::make_pair(RValue::get(DeclPtr),
                                  getContext().getPointerType(D.getType())));

    EmitCall(CGM.getTypes().getFunctionInfo(FD), F, Args);
  }
}

/// Emit an alloca (or GlobalValue depending on target)
/// for the specified parameter and set up LocalDeclMap.
void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
  // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
  assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
         "Invalid argument to EmitParmDecl");
  QualType Ty = D.getType();

  llvm::Value *DeclPtr;
  if (!Ty->isConstantSizeType()) {
    // Variable sized values always are passed by-reference.
    DeclPtr = Arg;
  } else if (Target.useGlobalsForAutomaticVariables()) {
    // Targets that don't have stack use global address space for parameters.
    // Specify external linkage for such globals so that llvm optimizer do
    // not assume there values initialized as zero.
    DeclPtr = GenerateStaticBlockVarDecl(D, true, ".auto.",
                                         llvm::GlobalValue::ExternalLinkage);
  } else {
    // A fixed sized single-value variable becomes an alloca in the entry block.
    const llvm::Type *LTy = ConvertType(Ty);
    if (LTy->isSingleValueType()) {
      // TODO: Alignment
      std::string Name = D.getNameAsString();
      Name += ".addr";
      DeclPtr = CreateTempAlloca(LTy, Name.c_str());

      // Store the initial value into the alloca.
      Builder.CreateStore(Arg, DeclPtr,Ty.isVolatileQualified());
    } else {
      // Otherwise, if this is an aggregate, just use the input pointer.
      DeclPtr = Arg;
    }
    Arg->setName(D.getNameAsString());
  }

  llvm::Value *&DMEntry = LocalDeclMap[&D];
  assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
  DMEntry = DeclPtr;

  // Emit debug info for param declaration.
  if (CGDebugInfo *DI = getDebugInfo()) {
    DI->setLocation(D.getLocation());
    DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder);
  }
}

<commit_msg>Last part of PR3254: use the same alignment computation in Sema and  CodeGen.  I'm not sure whether this actually makes any visible  difference, but it's better to be consistent anyway.<commit_after>//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Decl nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Type.h"
using namespace clang;
using namespace CodeGen;

void CodeGenFunction::EmitDecl(const Decl &D) {
  switch (D.getKind()) {
  default: assert(0 && "Unknown decl kind!");
  case Decl::ParmVar:
    assert(0 && "Parmdecls should not be in declstmts!");
  case Decl::Function:  // void X();
  case Decl::Record:    // struct/union/class X;
  case Decl::Enum:      // enum X;
  case Decl::EnumConstant: // enum ? { X = ? }
  case Decl::CXXRecord: // struct/union/class X; [C++]
    // None of these decls require codegen support.
    return;

  case Decl::Var: {
    const VarDecl &VD = cast<VarDecl>(D);
    assert(VD.isBlockVarDecl() &&
           "Should not see file-scope variables inside a function!");
    return EmitBlockVarDecl(VD);
  }

  case Decl::Typedef: {   // typedef int X;
    const TypedefDecl &TD = cast<TypedefDecl>(D);
    QualType Ty = TD.getUnderlyingType();

    if (Ty->isVariablyModifiedType())
      EmitVLASize(Ty);
  }
  }
}

/// EmitBlockVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
  switch (D.getStorageClass()) {
  case VarDecl::Static:
    return EmitStaticBlockVarDecl(D);
  case VarDecl::Extern:
    // Don't emit it now, allow it to be emitted lazily on its first use.
    return;
  default:
    assert((D.getStorageClass() == VarDecl::None ||
            D.getStorageClass() == VarDecl::Auto ||
            D.getStorageClass() == VarDecl::Register) &&
           "Unknown storage class");
    return EmitLocalBlockVarDecl(D);
  }
}

llvm::GlobalValue *
CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D,
                                            bool NoInit,
                                            const char *Separator,
                                            llvm::GlobalValue
					    	::LinkageTypes Linkage) {
  QualType Ty = D.getType();
  assert(Ty->isConstantSizeType() && "VLAs can't be static");

  const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
  llvm::Constant *Init = 0;
  if ((D.getInit() == 0) || NoInit) {
    Init = llvm::Constant::getNullValue(LTy);
  } else {
    Init = CGM.EmitConstantExpr(D.getInit(), this);

    // If constant emission failed, then this should be a C++ static
    // initializer.
    if (!Init) {
      if (!getContext().getLangOptions().CPlusPlus) {
        CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
        Init = llvm::Constant::getNullValue(LTy);
      } else {
        return GenerateStaticCXXBlockVarDecl(D);
      }
    }
  }

  assert(Init && "Unable to create initialiser for static decl");

  std::string ContextName;
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
    ContextName = CGM.getMangledName(FD);
  else if (isa<ObjCMethodDecl>(CurFuncDecl))
    ContextName = std::string(CurFn->getNameStart(),
                              CurFn->getNameStart() + CurFn->getNameLen());
  else
    assert(0 && "Unknown context for block var decl");

  llvm::GlobalValue *GV =
    new llvm::GlobalVariable(Init->getType(), Ty.isConstant(getContext()),
                             Linkage,
                             Init, ContextName + Separator +D.getNameAsString(),
                             &CGM.getModule(), 0, Ty.getAddressSpace());

  return GV;
}

void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {

  llvm::Value *&DMEntry = LocalDeclMap[&D];
  assert(DMEntry == 0 && "Decl already exists in localdeclmap!");

  llvm::GlobalValue *GV;
  GV = GenerateStaticBlockVarDecl(D, false, ".",
                                  llvm::GlobalValue::InternalLinkage);

  // FIXME: Merge attribute handling.
  if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
    SourceManager &SM = CGM.getContext().getSourceManager();
    llvm::Constant *Ann =
      CGM.EmitAnnotateAttr(GV, AA,
                           SM.getInstantiationLineNumber(D.getLocation()));
    CGM.AddAnnotation(Ann);
  }

  if (const SectionAttr *SA = D.getAttr<SectionAttr>())
    GV->setSection(SA->getName());

  if (D.getAttr<UsedAttr>())
    CGM.AddUsedGlobal(GV);

  const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
  const llvm::Type *LPtrTy =
    llvm::PointerType::get(LTy, D.getType().getAddressSpace());
  DMEntry = llvm::ConstantExpr::getBitCast(GV, LPtrTy);

  // Emit global variable debug descriptor for static vars.
  CGDebugInfo *DI = getDebugInfo();
  if (DI) {
    DI->setLocation(D.getLocation());
    DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D);
  }
}

/// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
  QualType Ty = D.getType();

  llvm::Value *DeclPtr;
  if (Ty->isConstantSizeType()) {
    if (!Target.useGlobalsForAutomaticVariables()) {
      // A normal fixed sized variable becomes an alloca in the entry block.
      const llvm::Type *LTy = ConvertType(Ty);
      llvm::AllocaInst *Alloc =
        CreateTempAlloca(LTy, CGM.getMangledName(&D));
      Alloc->setAlignment(getContext().getDeclAlignInBytes(&D));
      DeclPtr = Alloc;
    } else {
      // Targets that don't support recursion emit locals as globals.
      const char *Class =
        D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto.";
      DeclPtr = GenerateStaticBlockVarDecl(D, true, Class,
                                           llvm::GlobalValue
                                           ::InternalLinkage);
    }

    if (Ty->isVariablyModifiedType())
      EmitVLASize(Ty);
  } else {
    if (!DidCallStackSave) {
      // Save the stack.
      const llvm::Type *LTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
      llvm::Value *Stack = CreateTempAlloca(LTy, "saved_stack");

      llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
      llvm::Value *V = Builder.CreateCall(F);

      Builder.CreateStore(V, Stack);

      DidCallStackSave = true;

      {
        // Push a cleanup block and restore the stack there.
        CleanupScope scope(*this);

        V = Builder.CreateLoad(Stack, "tmp");
        llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
        Builder.CreateCall(F, V);
      }
    }

    // Get the element type.
    const llvm::Type *LElemTy = ConvertType(Ty);
    const llvm::Type *LElemPtrTy =
      llvm::PointerType::get(LElemTy, D.getType().getAddressSpace());

    llvm::Value *VLASize = EmitVLASize(Ty);

    // Downcast the VLA size expression
    VLASize = Builder.CreateIntCast(VLASize, llvm::Type::Int32Ty, false, "tmp");

    // Allocate memory for the array.
    llvm::Value *VLA = Builder.CreateAlloca(llvm::Type::Int8Ty, VLASize, "vla");
    DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
  }

  llvm::Value *&DMEntry = LocalDeclMap[&D];
  assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
  DMEntry = DeclPtr;

  // Emit debug info for local var declaration.
  if (CGDebugInfo *DI = getDebugInfo()) {
    DI->setLocation(D.getLocation());
    DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
  }

  // If this local has an initializer, emit it now.
  if (const Expr *Init = D.getInit()) {
    if (!hasAggregateLLVMType(Init->getType())) {
      llvm::Value *V = EmitScalarExpr(Init);
      Builder.CreateStore(V, DeclPtr, D.getType().isVolatileQualified());
    } else if (Init->getType()->isAnyComplexType()) {
      EmitComplexExprIntoAddr(Init, DeclPtr, D.getType().isVolatileQualified());
    } else {
      EmitAggExpr(Init, DeclPtr, D.getType().isVolatileQualified());
    }
  }

  // Handle the cleanup attribute
  if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
    const FunctionDecl *FD = CA->getFunctionDecl();

    llvm::Constant* F = CGM.GetAddrOfFunction(FD);
    assert(F && "Could not find function!");

    CleanupScope scope(*this);

    CallArgList Args;
    Args.push_back(std::make_pair(RValue::get(DeclPtr),
                                  getContext().getPointerType(D.getType())));

    EmitCall(CGM.getTypes().getFunctionInfo(FD), F, Args);
  }
}

/// Emit an alloca (or GlobalValue depending on target)
/// for the specified parameter and set up LocalDeclMap.
void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
  // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
  assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
         "Invalid argument to EmitParmDecl");
  QualType Ty = D.getType();

  llvm::Value *DeclPtr;
  if (!Ty->isConstantSizeType()) {
    // Variable sized values always are passed by-reference.
    DeclPtr = Arg;
  } else if (Target.useGlobalsForAutomaticVariables()) {
    // Targets that don't have stack use global address space for parameters.
    // Specify external linkage for such globals so that llvm optimizer do
    // not assume there values initialized as zero.
    DeclPtr = GenerateStaticBlockVarDecl(D, true, ".auto.",
                                         llvm::GlobalValue::ExternalLinkage);
  } else {
    // A fixed sized single-value variable becomes an alloca in the entry block.
    const llvm::Type *LTy = ConvertType(Ty);
    if (LTy->isSingleValueType()) {
      // TODO: Alignment
      std::string Name = D.getNameAsString();
      Name += ".addr";
      DeclPtr = CreateTempAlloca(LTy, Name.c_str());

      // Store the initial value into the alloca.
      Builder.CreateStore(Arg, DeclPtr,Ty.isVolatileQualified());
    } else {
      // Otherwise, if this is an aggregate, just use the input pointer.
      DeclPtr = Arg;
    }
    Arg->setName(D.getNameAsString());
  }

  llvm::Value *&DMEntry = LocalDeclMap[&D];
  assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
  DMEntry = DeclPtr;

  // Emit debug info for param declaration.
  if (CGDebugInfo *DI = getDebugInfo()) {
    DI->setLocation(D.getLocation());
    DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder);
  }
}

<|endoftext|>


<commit_before>#include <iostream>
#include <set>
#include <memory>

#include <gemmi/cif.hpp>
#include <gemmi/model.hpp>
#include <gemmi/mmcif.hpp>

#include "cif.hh"

static std::unique_ptr<std::set<int>>
get_models(const gemmi::cif::Document &doc)
{
    auto models = std::make_unique<std::set<int>> ();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"pdbx_PDB_model_num"})) {
            models->insert(gemmi::cif::as_int(site[0]));
        }
    }
    return models;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::cif::Document &doc)
{
    auto chains = std::make_unique<std::set<std::string>> ();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"auth_asym_id"})) {
            chains->insert(site[0]);
        }
    }
    return chains;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::Model& model)
{
    auto chains = std::make_unique<std::set<std::string>> ();

    for (auto& chain : model.chains)
    {
        chains->insert(chain.name);
    }

    return chains;
}

static const auto atom_site_columns = std::vector<std::string>({
    "group_PDB",
    "auth_asym_id",
    "auth_seq_id",
    "pdbx_PDB_ins_code",
    "auth_comp_id",
    "auth_atom_id",
    "label_alt_id",
    "type_symbol",
    "Cartn_x",
    "Cartn_y",
    "Cartn_z",
    "pdbx_PDB_model_num",
});

static freesasa_structure *
structure_from_doc(const gemmi::cif::Document &doc,
                   const std::set<int> &models,
                   const freesasa_classifier *classifier,
                   int structure_options)
{
    freesasa_structure *structure = freesasa_structure_new();

    for (auto block : doc.blocks) {
        auto prevAltId = '?';

        for (auto site : block.find("_atom_site.", atom_site_columns)) {
            if (site[0] != "ATOM" && !(structure_options & FREESASA_INCLUDE_HETATM)) {
                continue;
            }

            auto model = atoi(site[11].c_str());

            if (models.count(model) == 0) {
                continue;
            }

            freesasa_cif_atom atom = {
                .group_PDB = site[0].c_str(),
                .auth_asym_id = site[1][0],
                .auth_seq_id = site[2].c_str(),
                .pdbx_PDB_ins_code = site[3].c_str(),
                .auth_comp_id = site[4].c_str(),
                .auth_atom_id = site[5].c_str(),
                .label_alt_id = site[6].c_str(),
                .type_symbol = site[7].c_str(),
                .Cartn_x = atof(site[8].c_str()),
                .Cartn_y = atof(site[9].c_str()),
                .Cartn_z = atof(site[10].c_str())};

            auto currentAltId = site[6][0];

            if (!(structure_options & FREESASA_INCLUDE_HYDROGEN) && std::string(atom.type_symbol) == "H") {
                continue;
            }

            // Pick the first alternative conformation for an atom
            if (currentAltId != '.' && currentAltId != 'A') {
                continue;
            }

            freesasa_structure_add_cif_atom(structure, &atom, classifier, structure_options);
        }
    }
    return structure;
}

freesasa_structure *
freesasa_structure_from_cif(std::FILE *input,
                            const freesasa_classifier *classifier,
                            int structure_options)
{
    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");
    const auto models = get_models(doc);

    if (structure_options & FREESASA_JOIN_MODELS) {
        return structure_from_doc(doc, *models, classifier, structure_options);
    } else {
        auto firstModel = models->begin();
        auto singleModel = std::set<int>();
        singleModel.insert(*firstModel);

        return structure_from_doc(doc, singleModel, classifier, structure_options);
    }
}

std::vector<freesasa_structure*>
get_array_of_all_models(const gemmi::cif::Document &doc, int *n, const freesasa_classifier *classifier)
{
    const auto models = get_models(doc);

    std::vector<freesasa_structure*> ss;

    for (int i=0; i < models->size(); ++i)
    {
        ss.emplace_back(freesasa_structure_new());
    }
    return ss;
}

freesasa_structure*
chain_structure_from_doc(const gemmi::cif::Document doc,
                         const std::string &chName,
                         const freesasa_classifier *classifier,
                         int structure_options)
{
    std::cout << "Creating a freesasa structure from chain!" << std::endl;
    freesasa_structure *structure = freesasa_structure_new();

    //TODO fill in structure with chain data

    return structure;
}

freesasa_structure*
model_structure_from_doc(const gemmi::cif::Document &doc,
                         const int model,
                         const freesasa_classifier *classifier,
                         int structure_options)
{
    std::cout << "Creating a freesasa structure from model!" << std::endl;
    freesasa_structure *structure = freesasa_structure_new();

    //TODO fill in structure with model data

    return structure;
}

std::vector<freesasa_structure*>
freesasa_cif_structure_array(std::FILE *input,
                         int *n,
                         const freesasa_classifier *classifier,
                         int options)
{
    int n_models = 0, n_chains = 0;

    std::vector<freesasa_structure*> ss;

    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");

    gemmi::Structure gemmi_struct = gemmi::make_structure_from_block(doc.blocks[0]);

    const auto models = gemmi_struct.models;

    n_models = models.size();

    std::cout << "Number of models: " << n_models << std::endl;

    /* only keep first model if option not provided */
    if (!(options & FREESASA_SEPARATE_MODELS)) n_models = 1;

    /* for each model read chains if requested */
    if (options & FREESASA_SEPARATE_CHAINS)
    {
        for (auto& model : models)
        {
            auto chain_names  = get_chains(model);
            int n_new_chains  = chain_names->size();
            n_chains         +=  n_new_chains;

            if (n_new_chains == FREESASA_FAIL) gemmi::fail("No chains in protein");
            if (n_new_chains == 0) {
                // TODO Cant get this to link with freesasa.a for some reason.
                //freesasa_warn("in %s(): no chains found (in model %s)", __func__, model.name.c_str());
                continue;
            }

            ss.reserve(n_new_chains);
            for (auto& chain_name : *chain_names)
            {
                ss.emplace_back(
                    // TODO add model to freesasa_structure: implement this line from structure.c (ss[j0 + j]->model = i + 1;)
                    chain_structure_from_doc(doc, chain_name, classifier, options)
                );
            }
        }
        *n = n_chains;
    }

    else
    {
        ss.reserve(n_models);
        for (auto& model : models)
        {
            ss.emplace_back(
                // TODO add model to freesasa_structure: implement this line from structure.c (ss[j0 + j]->model = i + 1;)
                model_structure_from_doc(doc, std::stoi(model.name), classifier, options)
            );
        }
        *n = n_models;
    }
    return ss;
}
<commit_msg>populated freesasa_structure with data for --separate-chains and --separate-models<commit_after>#include <iostream>
#include <set>
#include <memory>

#include <gemmi/cif.hpp>
#include <gemmi/model.hpp>
#include <gemmi/mmcif.hpp>

#include "cif.hh"

static std::unique_ptr<std::set<int>>
get_models(const gemmi::cif::Document &doc)
{
    auto models = std::make_unique<std::set<int>> ();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"pdbx_PDB_model_num"})) {
            models->insert(gemmi::cif::as_int(site[0]));
        }
    }
    return models;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::cif::Document &doc)
{
    auto chains = std::make_unique<std::set<std::string>> ();
    for (auto block : doc.blocks) {
        for (auto site : block.find("_atom_site.", {"auth_asym_id"})) {
            chains->insert(site[0]);
        }
    }
    return chains;
}

static std::unique_ptr<std::set<std::string>>
get_chains(const gemmi::Model& model)
{
    auto chains = std::make_unique<std::set<std::string>> ();

    for (auto& chain : model.chains)
    {
        chains->insert(chain.name);
    }

    return chains;
}

static const auto atom_site_columns = std::vector<std::string>({
    "group_PDB",
    "auth_asym_id",
    "auth_seq_id",
    "pdbx_PDB_ins_code",
    "auth_comp_id",
    "auth_atom_id",
    "label_alt_id",
    "type_symbol",
    "Cartn_x",
    "Cartn_y",
    "Cartn_z",
    "pdbx_PDB_model_num",
});

static freesasa_structure *
structure_from_doc(const gemmi::cif::Document &doc,
                   const std::set<int> &models,
                   const freesasa_classifier *classifier,
                   int structure_options)
{
    freesasa_structure *structure = freesasa_structure_new();

    for (auto block : doc.blocks) {
        auto prevAltId = '?';

        for (auto site : block.find("_atom_site.", atom_site_columns)) {
            if (site[0] != "ATOM" && !(structure_options & FREESASA_INCLUDE_HETATM)) {
                continue;
            }

            auto model = atoi(site[11].c_str());

            if (models.count(model) == 0) {
                continue;
            }

            freesasa_cif_atom atom = {
                .group_PDB = site[0].c_str(),
                .auth_asym_id = site[1][0],
                .auth_seq_id = site[2].c_str(),
                .pdbx_PDB_ins_code = site[3].c_str(),
                .auth_comp_id = site[4].c_str(),
                .auth_atom_id = site[5].c_str(),
                .label_alt_id = site[6].c_str(),
                .type_symbol = site[7].c_str(),
                .Cartn_x = atof(site[8].c_str()),
                .Cartn_y = atof(site[9].c_str()),
                .Cartn_z = atof(site[10].c_str())};

            auto currentAltId = site[6][0];

            if (!(structure_options & FREESASA_INCLUDE_HYDROGEN) && std::string(atom.type_symbol) == "H") {
                continue;
            }

            // Pick the first alternative conformation for an atom
            if (currentAltId != '.' && currentAltId != 'A') {
                continue;
            }

            freesasa_structure_add_cif_atom(structure, &atom, classifier, structure_options);
        }
    }
    return structure;
}

freesasa_structure *
freesasa_structure_from_cif(std::FILE *input,
                            const freesasa_classifier *classifier,
                            int structure_options)
{
    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");
    const auto models = get_models(doc);

    if (structure_options & FREESASA_JOIN_MODELS) {
        return structure_from_doc(doc, *models, classifier, structure_options);
    } else {
        auto firstModel = models->begin();
        auto singleModel = std::set<int>();
        singleModel.insert(*firstModel);

        return structure_from_doc(doc, singleModel, classifier, structure_options);
    }
}

std::vector<freesasa_structure*>
get_array_of_all_models(const gemmi::cif::Document &doc, int *n, const freesasa_classifier *classifier)
{
    const auto models = get_models(doc);

    std::vector<freesasa_structure*> ss;

    for (int i=0; i < models->size(); ++i)
    {
        ss.emplace_back(freesasa_structure_new());
    }
    return ss;
}

freesasa_structure*
chain_structure_from_doc(const gemmi::cif::Document doc,
                         const std::string &chain_name,
                         const freesasa_classifier *classifier,
                         int structure_options)
{
    std::cout << "Creating a freesasa structure from chain!" << std::endl;
    freesasa_structure *structure = freesasa_structure_new();

    for (auto block : doc.blocks) {
        auto prevAltId = '?';

        for (auto site : block.find("_atom_site.", atom_site_columns)) {
            if (site[0] != "ATOM" && !(structure_options & FREESASA_INCLUDE_HETATM)) {
                continue;
            }

            if (chain_name != site[1]) {
                continue;
            }

            freesasa_cif_atom atom = {
                .group_PDB = site[0].c_str(),
                .auth_asym_id = site[1][0],
                .auth_seq_id = site[2].c_str(),
                .pdbx_PDB_ins_code = site[3].c_str(),
                .auth_comp_id = site[4].c_str(),
                .auth_atom_id = site[5].c_str(),
                .label_alt_id = site[6].c_str(),
                .type_symbol = site[7].c_str(),
                .Cartn_x = atof(site[8].c_str()),
                .Cartn_y = atof(site[9].c_str()),
                .Cartn_z = atof(site[10].c_str())};

            auto currentAltId = site[6][0];

            if (!(structure_options & FREESASA_INCLUDE_HYDROGEN) && std::string(atom.type_symbol) == "H") {
                continue;
            }

            // Pick the first alternative conformation for an atom
            if (currentAltId != '.' && currentAltId != 'A') {
                continue;
            }

            freesasa_structure_add_cif_atom(structure, &atom, classifier, structure_options);
        }
    }

    return structure;
}

freesasa_structure*
model_structure_from_doc(const gemmi::cif::Document &doc,
                         const std::string &model,
                         const freesasa_classifier *classifier,
                         int structure_options)
{
    std::cout << "Creating a freesasa structure from model!" << std::endl;
    freesasa_structure *structure = freesasa_structure_new();

    for (auto block : doc.blocks) {
        auto prevAltId = '?';

        for (auto site : block.find("_atom_site.", atom_site_columns)) {
            if (site[0] != "ATOM" && !(structure_options & FREESASA_INCLUDE_HETATM)) {
                continue;
            }

            if (model != site[11]) {
                continue;
            }

            freesasa_cif_atom atom = {
                .group_PDB = site[0].c_str(),
                .auth_asym_id = site[1][0],
                .auth_seq_id = site[2].c_str(),
                .pdbx_PDB_ins_code = site[3].c_str(),
                .auth_comp_id = site[4].c_str(),
                .auth_atom_id = site[5].c_str(),
                .label_alt_id = site[6].c_str(),
                .type_symbol = site[7].c_str(),
                .Cartn_x = atof(site[8].c_str()),
                .Cartn_y = atof(site[9].c_str()),
                .Cartn_z = atof(site[10].c_str())};

            auto currentAltId = site[6][0];

            if (!(structure_options & FREESASA_INCLUDE_HYDROGEN) && std::string(atom.type_symbol) == "H") {
                continue;
            }

            // Pick the first alternative conformation for an atom
            if (currentAltId != '.' && currentAltId != 'A') {
                continue;
            }

            freesasa_structure_add_cif_atom(structure, &atom, classifier, structure_options);
        }
    }

    return structure;
}

std::vector<freesasa_structure*>
freesasa_cif_structure_array(std::FILE *input,
                         int *n,
                         const freesasa_classifier *classifier,
                         int options)
{
    int n_models = 0, n_chains = 0;

    std::vector<freesasa_structure*> ss;

    const auto doc = gemmi::cif::read_cstream(input, 8192, "cif-input");

    gemmi::Structure gemmi_struct = gemmi::make_structure_from_block(doc.blocks[0]);

    const auto models = gemmi_struct.models;

    n_models = models.size();

    std::cout << "Number of models: " << n_models << std::endl;

    /* only keep first model if option not provided */
    if (!(options & FREESASA_SEPARATE_MODELS)) n_models = 1;

    /* for each model read chains if requested */
    if (options & FREESASA_SEPARATE_CHAINS)
    {
        for (auto& model : models)
        {
            auto chain_names  = get_chains(model);
            int n_new_chains  = chain_names->size();
            n_chains         +=  n_new_chains;

            if (n_new_chains == FREESASA_FAIL) gemmi::fail("No chains in protein");
            if (n_new_chains == 0) {
                // TODO Cant get this to link with freesasa.a for some reason.
                //freesasa_warn("in %s(): no chains found (in model %s)", __func__, model.name.c_str());
                continue;
            }

            ss.reserve(n_new_chains);
            for (auto& chain_name : *chain_names)
            {
                ss.emplace_back(
                    // TODO add model to freesasa_structure: implement this line from structure.c (ss[j0 + j]->model = i + 1;)
                    chain_structure_from_doc(doc, chain_name, classifier, options)
                );
            }
        }
        *n = n_chains;
    }

    else
    {
        ss.reserve(n_models);
        for (auto& model : models)
        {
            ss.emplace_back(
                // TODO add model to freesasa_structure: implement this line from structure.c (ss[j0 + j]->model = i + 1;)
                model_structure_from_doc(doc, model.name, classifier, options)
            );
        }
        *n = n_models;
    }
    return ss;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "log.h"

#include "utils.h"

#define BUFFER_SIZE (10 * 1024)

Log::Log(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup_)
	: wakeup(wakeup_),
	  str_start(str),
	  finished(false) { }

std::string
Log::str_format(const char *file, int line, const char *suffix, const char *prefix, void *, const char *format, va_list argptr)
{
	char* buffer = new char[BUFFER_SIZE];
	vsnprintf(buffer, BUFFER_SIZE, format, argptr);
	std::string result = "tid(" + get_thread_name() + "): " + file + ":" + std::to_string(line) + ": " + prefix + buffer + suffix;
	delete []buffer;
	return result;
}

std::shared_ptr<Log>
Log::log(std::chrono::time_point<std::chrono::system_clock> wakeup, const char *file, int line, const char *suffix, const char *prefix, void *obj, const char *format, ...)
{
	va_list argptr;
	va_start(argptr, format);
	std::string str(str_format(file, line, suffix, prefix, obj, format, argptr));
	va_end(argptr);

	return print(str, wakeup);
}

void
Log::clear()
{
	finished.store(true);
}

void
Log::unlog(const char *file, int line, const char *suffix, const char *prefix, void *obj, const char *format, ...)
{
	if (finished.exchange(true)) {
		va_list argptr;
		va_start(argptr, format);
		std::string str(str_format(file, line, suffix, prefix, obj, format, argptr));
		va_end(argptr);

		print(str);
	}
}

std::shared_ptr<Log>
Log::add(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup)
{
	static LogThread thread;

	// std::make_shared only can call a public constructor, for this reason
	// it is neccesary wrap the constructor in a struct.
	struct enable_make_shared : Log {
		enable_make_shared(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup)
			: Log(str, wakeup) { }
	};

	auto l_ptr = std::make_shared<enable_make_shared>(str, wakeup);
	thread.log_list.push_front(l_ptr->shared_from_this());

	if (thread.wakeup.load() > l_ptr->wakeup) {
		thread.wakeup_signal.notify_one();
	}

	return l_ptr;
}

std::shared_ptr<Log>
Log::print(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup)
{
	if (wakeup > std::chrono::system_clock::now()) {
		return add(str, wakeup);
	} else {
		static std::mutex log_mutex;
		std::lock_guard<std::mutex> lk(log_mutex);
		std::cerr << str;
		return std::shared_ptr<Log>();
	}
}

LogThread::LogThread()
	: running(true),
	  inner_thread(&LogThread::thread_function, this) { }

LogThread::~LogThread()
{
	running.store(false);
	wakeup_signal.notify_one();
	try {
		inner_thread.join();
	} catch (const std::system_error&) {
	}
}

void
LogThread::thread_function()
{
	std::mutex mtx;
	std::unique_lock<std::mutex> lk(mtx);
	while (running.load()) {
		auto now = std::chrono::system_clock::now();
		auto next_wakeup = now + 3s;
		for (auto it = log_list.begin(); it != log_list.end(); ++it) {
			if (it->use_count() == 1 || (*it)->finished.load()) {
				log_list.erase(it);
			} else if ((*it)->wakeup <= now) {
				(*it)->finished.store(true);
				Log::print((*it)->str_start);
				log_list.erase(it);
			} else if (next_wakeup > (*it)->wakeup) {
				next_wakeup = (*it)->wakeup;
			}
		}
		if (next_wakeup < now + 100ms) {
			next_wakeup = now + 100ms;
		}
		wakeup.store(next_wakeup);
		wakeup_signal.wait_until(lk, next_wakeup);
	}
}
<commit_msg>Print timestamp as part of the logs<commit_after>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "log.h"

#include "date.h"
#include "utils.h"

#define BUFFER_SIZE (10 * 1024)

Log::Log(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup_)
	: wakeup(wakeup_),
	  str_start(str),
	  finished(false) { }

std::string
Log::str_format(const char *file, int line, const char *suffix, const char *prefix, void *, const char *format, va_list argptr)
{
	char* buffer = new char[BUFFER_SIZE];
	vsnprintf(buffer, BUFFER_SIZE, format, argptr);
	auto tid = "tid(" + get_thread_name() + ")";
	auto iso8601 = "[" + date::to_string(std::chrono::system_clock::now()) + "]";
	auto location = ": " + std::string(file) + ":" + std::to_string(line);
	std::string result = iso8601 + " " + tid + location + ": " + prefix + buffer + suffix;
	delete []buffer;
	return result;
}

std::shared_ptr<Log>
Log::log(std::chrono::time_point<std::chrono::system_clock> wakeup, const char *file, int line, const char *suffix, const char *prefix, void *obj, const char *format, ...)
{
	va_list argptr;
	va_start(argptr, format);
	std::string str(str_format(file, line, suffix, prefix, obj, format, argptr));
	va_end(argptr);

	return print(str, wakeup);
}

void
Log::clear()
{
	finished.store(true);
}

void
Log::unlog(const char *file, int line, const char *suffix, const char *prefix, void *obj, const char *format, ...)
{
	if (finished.exchange(true)) {
		va_list argptr;
		va_start(argptr, format);
		std::string str(str_format(file, line, suffix, prefix, obj, format, argptr));
		va_end(argptr);

		print(str);
	}
}

std::shared_ptr<Log>
Log::add(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup)
{
	static LogThread thread;

	// std::make_shared only can call a public constructor, for this reason
	// it is neccesary wrap the constructor in a struct.
	struct enable_make_shared : Log {
		enable_make_shared(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup)
			: Log(str, wakeup) { }
	};

	auto l_ptr = std::make_shared<enable_make_shared>(str, wakeup);
	thread.log_list.push_front(l_ptr->shared_from_this());

	if (thread.wakeup.load() > l_ptr->wakeup) {
		thread.wakeup_signal.notify_one();
	}

	return l_ptr;
}

std::shared_ptr<Log>
Log::print(const std::string& str, std::chrono::time_point<std::chrono::system_clock> wakeup)
{
	if (wakeup > std::chrono::system_clock::now()) {
		return add(str, wakeup);
	} else {
		static std::mutex log_mutex;
		std::lock_guard<std::mutex> lk(log_mutex);
		std::cerr << str;
		return std::shared_ptr<Log>();
	}
}

LogThread::LogThread()
	: running(true),
	  inner_thread(&LogThread::thread_function, this) { }

LogThread::~LogThread()
{
	running.store(false);
	wakeup_signal.notify_one();
	try {
		inner_thread.join();
	} catch (const std::system_error&) {
	}
}

void
LogThread::thread_function()
{
	std::mutex mtx;
	std::unique_lock<std::mutex> lk(mtx);
	while (running.load()) {
		auto now = std::chrono::system_clock::now();
		auto next_wakeup = now + 3s;
		for (auto it = log_list.begin(); it != log_list.end(); ++it) {
			if (it->use_count() == 1 || (*it)->finished.load()) {
				log_list.erase(it);
			} else if ((*it)->wakeup <= now) {
				(*it)->finished.store(true);
				Log::print((*it)->str_start);
				log_list.erase(it);
			} else if (next_wakeup > (*it)->wakeup) {
				next_wakeup = (*it)->wakeup;
			}
		}
		if (next_wakeup < now + 100ms) {
			next_wakeup = now + 100ms;
		}
		wakeup.store(next_wakeup);
		wakeup_signal.wait_until(lk, next_wakeup);
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

int main(int argc, char** argv[]) {

	if (argc == 1) {

		char const *dirName = ".";
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
			return errno;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << endl;
			}
		}
		closedir(dirp);
	}

}

<commit_msg>added space at end of printf, cout << endl after loop<commit_after>#include <iostream>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

int main(int argc, char** argv[]) {

	if (argc == 1) {

		char const *dirName = ".";
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
			return errno;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
	}

}

<|endoftext|>


<commit_before>#include <iostream>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
using namespace std;

void getpath(char *pathname, char *path, char name[]){
	strcpy(pathname, path);
	strcat(pathname, "/");
	strcat(pathname, name);
}

void changeColor(int background, struct stat fileStat){
	if(background == 1) cout<<"\x1b[47m";

	if(S_ISDIR(fileStat.st_mode))
		cout<<"\x1b[34m";
	else if(fileStat.st_mode & S_IXUSR)
		cout<<"\x1b[32m";
}

void resetColor(){
	cout<<"\x1b[0m";
}

void head(char path[], char name[], struct stat sb, int background){
	struct passwd *log;
	struct passwd *grp;
	struct tm * timeinfo;
	char buffer [80];

	log = getpwuid(sb.st_uid);
	if(log == '\0') perror("Login error");

	grp = getpwuid(sb.st_gid);
	if(grp == '\0') perror("Group error");

	timeinfo = localtime(&sb.st_mtime);
	strftime(buffer,80, "%b %e %H:%M",timeinfo);

	 printf( (S_ISDIR(sb.st_mode)) ? "d" : "-");
    	 printf( (sb.st_mode & S_IRUSR) ? "r" : "-");
    	 printf( (sb.st_mode & S_IWUSR) ? "w" : "-");
   	 printf( (sb.st_mode & S_IXUSR) ? "x" : "-");
   	 printf( (sb.st_mode & S_IRGRP) ? "r" : "-");
   	 printf( (sb.st_mode & S_IWGRP) ? "w" : "-");
    	 printf( (sb.st_mode & S_IXGRP) ? "x" : "-");
    	 printf( (sb.st_mode & S_IROTH) ? "r" : "-");
    	 printf( (sb.st_mode & S_IWOTH) ? "w" : "-");
   	 printf( (sb.st_mode & S_IXOTH) ? "x" : "-");

	cout<<" "<<sb.st_blocks<<" "<<sb.st_nlink<<" "
	    <<log->pw_name<<" "
	    <<grp->pw_name<<" "
	    <<sb.st_size<<" "
	    <<buffer<<" ";
	    changeColor(background,sb);
	    cout<<name;
	    resetColor();
	    cout<<endl;
}

void ls(int flag, char directory[]){
	bool showFiles = false;
	bool showTotal = false;
	int total=0;
	DIR *dirp;

	if(!(dirp = opendir(directory))){
		perror("Opendir erro");
		return;
	}

	dirent *direntp;
	while((direntp = readdir(dirp))){

		if(errno != 0){
			 perror ("Readdir erro");
		}

		char fullpath[512];

		getpath(fullpath, directory, direntp->d_name);

		struct stat fileStat;
		if(stat(fullpath, &fileStat) == -1){
			perror("Stat error");
			exit(1);
		}

		switch(flag){
			//ls
			case 0:
				//avoid files starting with .
				if(direntp->d_name[0]!='.'){
					changeColor(0,fileStat);
					cout<<direntp->d_name<<"  ";
					resetColor();
				}
			break;

			//ls -a
			case 1:
				if(direntp->d_name[0]=='.')
					changeColor(1,fileStat);
				else
					changeColor(0,fileStat);

				cout<<direntp->d_name;
				resetColor();
				cout<<"  ";
			break;

			//ls -l
			case 2:
				if(!showTotal){
					ls(8,directory);
					showTotal = true;
				}
				//avoid files starting with .
				if(direntp->d_name[0]!='.')
					head(fullpath,direntp->d_name, fileStat,0);
			break;

			//ls -al
			case 3:
				if(!showTotal){
					ls(9,directory);
					showTotal = true;
				}
				if(direntp->d_name[0]=='.')
					head(fullpath, direntp->d_name,fileStat,1);
				else
					head(fullpath, direntp->d_name,fileStat,0);
			break;

			//ls -R
			case 4:
				//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls(0, directory);
                                        cout<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if(direntp->d_name[0]!='.'){
                                                cout<<endl;
						//entry a level and call ls again
						ls(flag,fullpath);
                                        }
				}
			break;

			//ls -aR
			case 5:
				//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls(1, directory);
                                        cout<<endl<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if((direntp->d_name[0]=='.'&& direntp->d_name[1]=='\0') || (direntp->d_name[0]=='.' && direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'));
                                        else{
						//entry a level and call ls again
						ls(flag,fullpath);
					}
				}
			break;

			//ls -lR
			case 6:
			//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls( 2, directory);
                                        cout<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if(direntp->d_name[0]!='.'){
						//entry a level and call ls again
						ls(flag,fullpath);
					}
				}
			break;

			//ls -laR
			case 7:
			//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls(3, directory);
                                        cout<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if((direntp->d_name[0]=='.'&& direntp->d_name[1]=='\0') || (direntp->d_name[0]=='.' && direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'));
                                        else{
						//entry a level and call ls again
						ls(flag,fullpath);
					}
				}
			break;
			//case 8 and 9 only calculates nd print total in case of flag -l
			case 8:
				if(direntp->d_name[0]!='.')
					total+=fileStat.st_blocks;
			break;
			case 9:
					total+=fileStat.st_blocks;
			break;
		}

	}
	closedir(dirp);
	if(flag==8 || flag == 9) cout<<"total "<<total/2<<endl;
}

int main(int argc, char **argv){

	char * find_flag;
	int flag=0;
	string path_folder="";

	for(int i=1; i<argc; i++){
		//checking how many flag are passed
		if(memcmp(argv[i],"-",1)==0){
			find_flag = strchr(argv[i],'a');
			if(find_flag != NULL){
				flag+= 1;
			}
			find_flag = strchr(argv[i],'l');
			if(find_flag != NULL){
				flag+=2;
			}
			find_flag = strchr(argv[i],'R');
			if(find_flag != NULL){
				flag+=4;
			}
		}else{
			//recieving folder as argument
			path_folder = argv[i];
		}
	}
	//if no folder has been passed as argument
	if(path_folder=="") path_folder = get_current_dir_name();

	char * directory = new char[path_folder.length()+1];
	strcpy(directory, path_folder.c_str());

	ls(flag, directory);
        if(flag == 0 || flag ==1) cout<<endl;
	delete[] directory;

	return 0;
}
<commit_msg>get group id fixed<commit_after>#include <iostream>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
using namespace std;

void getpath(char *pathname, char *path, char name[]){
	strcpy(pathname, path);
	strcat(pathname, "/");
	strcat(pathname, name);
}

void changeColor(int background, struct stat fileStat){
	if(background == 1) cout<<"\x1b[47m";

	if(S_ISDIR(fileStat.st_mode))
		cout<<"\x1b[34m";
	else if(fileStat.st_mode & S_IXUSR)
		cout<<"\x1b[32m";
}

void resetColor(){
	cout<<"\x1b[0m";
}

void head(char path[], char name[], struct stat sb, int background){
	struct passwd *log;
	struct group *grp;
	struct tm * timeinfo;
	char buffer [80];

	log = getpwuid(sb.st_uid);
	if(log == '\0') perror("Login error");

	grp = getgrgid(sb.st_gid);
	if(grp == '\0') perror("Group error");

	timeinfo = localtime(&sb.st_mtime);
	strftime(buffer,80, "%b %e %H:%M",timeinfo);

	 printf( (S_ISDIR(sb.st_mode)) ? "d" : "-");
    	 printf( (sb.st_mode & S_IRUSR) ? "r" : "-");
    	 printf( (sb.st_mode & S_IWUSR) ? "w" : "-");
   	 printf( (sb.st_mode & S_IXUSR) ? "x" : "-");
   	 printf( (sb.st_mode & S_IRGRP) ? "r" : "-");
   	 printf( (sb.st_mode & S_IWGRP) ? "w" : "-");
    	 printf( (sb.st_mode & S_IXGRP) ? "x" : "-");
    	 printf( (sb.st_mode & S_IROTH) ? "r" : "-");
    	 printf( (sb.st_mode & S_IWOTH) ? "w" : "-");
   	 printf( (sb.st_mode & S_IXOTH) ? "x" : "-");

	cout<<" "<<sb.st_nlink<<" "
	    <<log->pw_name<<" "
	    <<grp->gr_name<<" "
	    <<sb.st_size<<" "
	    <<buffer<<" ";
	    changeColor(background,sb);
	    cout<<name;
	    resetColor();
	    cout<<endl;
}

void ls(int flag, char directory[]){
	bool showFiles = false;
	bool showTotal = false;
	int total=0;
	DIR *dirp;

	if(!(dirp = opendir(directory))){
		perror("Opendir erro");
		return;
	}

	dirent *direntp;
	while((direntp = readdir(dirp))){

		if(errno != 0){
			 perror ("Readdir erro");
		}

		char fullpath[512];

		getpath(fullpath, directory, direntp->d_name);

		struct stat fileStat;
		if(stat(fullpath, &fileStat) == -1){
			perror("Stat error");
			exit(1);
		}

		switch(flag){
			//ls
			case 0:
				//avoid files starting with .
				if(direntp->d_name[0]!='.'){
					changeColor(0,fileStat);
					cout<<direntp->d_name<<"  ";
					resetColor();
				}
			break;

			//ls -a
			case 1:
				if(direntp->d_name[0]=='.')
					changeColor(1,fileStat);
				else
					changeColor(0,fileStat);

				cout<<direntp->d_name;
				resetColor();
				cout<<"  ";
			break;

			//ls -l
			case 2:
				if(!showTotal){
					ls(8,directory);
					showTotal = true;
				}
				//avoid files starting with .
				if(direntp->d_name[0]!='.')
					head(fullpath,direntp->d_name, fileStat,0);
			break;

			//ls -al
			case 3:
				if(!showTotal){
					ls(9,directory);
					showTotal = true;
				}
				if(direntp->d_name[0]=='.')
					head(fullpath, direntp->d_name,fileStat,1);
				else
					head(fullpath, direntp->d_name,fileStat,0);
			break;

			//ls -R
			case 4:
				//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls(0, directory);
                                        cout<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if(direntp->d_name[0]!='.'){
                                                cout<<endl;
						//entry a level and call ls again
						ls(flag,fullpath);
                                        }
				}
			break;

			//ls -aR
			case 5:
				//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls(1, directory);
                                        cout<<endl<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if((direntp->d_name[0]=='.'&& direntp->d_name[1]=='\0') || (direntp->d_name[0]=='.' && direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'));
                                        else{
						//entry a level and call ls again
						ls(flag,fullpath);
					}
				}
			break;

			//ls -lR
			case 6:
			//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls( 2, directory);
                                        cout<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if(direntp->d_name[0]!='.'){
						//entry a level and call ls again
						ls(flag,fullpath);
					}
				}
			break;

			//ls -laR
			case 7:
			//has this directory shown its files?
				if(!showFiles){
					showFiles = true;
					//show actual directory
					cout<<directory<<":"<<endl;
					//display its files
                                        ls(3, directory);
                                        cout<<endl;
				}
				//after showing the files, apply -R function
				//calling ls() to display the son directory
				if(direntp->d_type==DT_DIR){
					if((direntp->d_name[0]=='.'&& direntp->d_name[1]=='\0') || (direntp->d_name[0]=='.' && direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'));
                                        else{
						//entry a level and call ls again
						ls(flag,fullpath);
					}
				}
			break;
			//case 8 and 9 only calculates nd print total in case of flag -l
			case 8:
				if(direntp->d_name[0]!='.')
					total+=fileStat.st_blocks;
			break;
			case 9:
					total+=fileStat.st_blocks;
			break;
		}

	}
	closedir(dirp);
	if(flag==8 || flag == 9) cout<<"total "<<total/2<<endl;
}

int main(int argc, char **argv){

	char * find_flag;
	int flag=0;
	string path_folder="";

	for(int i=1; i<argc; i++){
		//checking how many flag are passed
		if(memcmp(argv[i],"-",1)==0){
			find_flag = strchr(argv[i],'a');
			if(find_flag != NULL){
				flag+= 1;
			}
			find_flag = strchr(argv[i],'l');
			if(find_flag != NULL){
				flag+=2;
			}
			find_flag = strchr(argv[i],'R');
			if(find_flag != NULL){
				flag+=4;
			}
		}else{
			//recieving folder as argument
			path_folder = argv[i];
		}
	}
	//if no folder has been passed as argument
	if(path_folder=="") path_folder = get_current_dir_name();

	char * directory = new char[path_folder.length()+1];
	strcpy(directory, path_folder.c_str());

	ls(flag, directory);
        if(flag == 0 || flag ==1) cout<<endl;
	delete[] directory;

	return 0;
}
<|endoftext|>


<commit_before>#include "CppUTest\CommandLineTestRunner.h"
#include <stdio.h>
#include "mbed.h"
#include "testrunner.h"
#include "test_env.h"

/**
Object 'console' is used to show prints on console.
It is declared in \cpputest\src\Platforms\armcc\UtestPlatform.cpp
*/
Serial console(STDIO_UART_TX, STDIO_UART_RX);

int main(int ac, char** av)
{
    unsigned failureCount = 0;
    {
        failureCount = CommandLineTestRunner::RunAllTests(ac, av);
    }

    notify_completion(failureCount == 0);
    return failureCount;
}
<commit_msg>Changed console object name from 'console' to something more unique like 'mbed_cpputest_console'<commit_after>#include "CppUTest\CommandLineTestRunner.h"
#include <stdio.h>
#include "mbed.h"
#include "testrunner.h"
#include "test_env.h"

/**
Object 'mbed_cpputest_console' is used to show prints on console.
It is declared in \cpputest\src\Platforms\armcc\UtestPlatform.cpp
*/
Serial mbed_cpputest_console(STDIO_UART_TX, STDIO_UART_RX);

int main(int ac, char** av)
{
    unsigned failureCount = 0;
    {
        failureCount = CommandLineTestRunner::RunAllTests(ac, av);
    }

    notify_completion(failureCount == 0);
    return failureCount;
}
<|endoftext|>


<commit_before>#include "TFile.h"
#include "TTree.h"
#include "TBrowser.h"
#include "TH2.h"
#include "TRandom.h"

// This example is a variant of hsimple.C but using a TTree instead
// of a TNtuple. It shows :
//   -how to fill a Tree with a few simple variables.
//   -how to read this Tree
//   -how to browse and analyze the Tree via the TBrowser and TTreeViewer
// This example can be run in many different ways:
//  way1:  .x tree1.C    using the CINT interpreter
//  way2:  .x tree1.C++  using the automatic compiler interface
//  way3:  .L tree1.C  or .L tree1.C++
//          tree1()
// One can also run the write and read parts in two separate sessions.
// For example following one of the sessions above, one can start the session:
//   .L tree1.C
//   tree1r();
//
//  Author: Rene Brun

void tree1w()
{
   //create a Tree file tree1.root

   //create the file, the Tree and a few branches
   TFile f("tree1.root","recreate");
   TTree t1("t1","a simple Tree with simple variables");
   Float_t px, py, pz;
   Double_t random;
   Int_t ev;
   t1.Branch("px",&px,"px/F");
   t1.Branch("py",&py,"py/F");
   t1.Branch("pz",&pz,"pz/F");
   t1.Branch("random",&random,"random/F");
   t1.Branch("ev",&ev,"ev/I");

   //fill the tree
   for (Int_t i=0;i<10000;i++) {
     gRandom->Rannor(px,py);
     pz = px*px + py*py;
     random = gRandom->Rndm();
     ev = i;
     t1.Fill();
  }

  //save the Tree header. The file will be automatically closed
  //when going out of the function scope
  t1.Write();
}

void tree1r()
{
   //read the Tree generated by tree1w and fill two histograms

   //note that we use "new" to create the TFile and TTree objects !
   //because we want to keep these objects alive when we leave this function.
   TFile *f = new TFile("tree1.root");
   TTree *t1 = (TTree*)f->Get("t1");
   Float_t px, py, pz;
   Double_t random;
   Int_t ev;
   t1->SetBranchAddress("px",&px);
   t1->SetBranchAddress("py",&py);
   t1->SetBranchAddress("pz",&pz);
   t1->SetBranchAddress("random",&random);
   t1->SetBranchAddress("ev",&ev);

   //create two histograms
   TH1F *hpx   = new TH1F("hpx","px distribution",100,-3,3);
   TH2F *hpxpy = new TH2F("hpxpy","py vs px",30,-3,3,30,-3,3);

   //read all entries and fill the histograms
   Int_t nentries = (Int_t)t1->GetEntries();
   for (Int_t i=0;i<nentries;i++) {
     t1->GetEntry(i);
     hpx->Fill(px);
     hpxpy->Fill(px,py);
  }

  //we do not close the file. We want to keep the generated histograms
  //we open a browser and the TreeViewer
  if (gROOT->IsBatch()) return;
  new TBrowser();
  t1->StartViewer();
  // in the browser, click on "ROOT Files", then on "tree1.root".
  //     you can click on the histogram icons in the right panel to draw them.
  // in the TreeViewer, follow the instructions in the Help button.
}

void tree1() {
   tree1w();
   tree1r();
}
<commit_msg>The leaf "random" must be declared "D (double) instead of "F" to the branch.<commit_after>#include "TFile.h"
#include "TTree.h"
#include "TBrowser.h"
#include "TH2.h"
#include "TRandom.h"

// This example is a variant of hsimple.C but using a TTree instead
// of a TNtuple. It shows :
//   -how to fill a Tree with a few simple variables.
//   -how to read this Tree
//   -how to browse and analyze the Tree via the TBrowser and TTreeViewer
// This example can be run in many different ways:
//  way1:  .x tree1.C    using the CINT interpreter
//  way2:  .x tree1.C++  using the automatic compiler interface
//  way3:  .L tree1.C  or .L tree1.C++
//          tree1()
// One can also run the write and read parts in two separate sessions.
// For example following one of the sessions above, one can start the session:
//   .L tree1.C
//   tree1r();
//
//  Author: Rene Brun

void tree1w()
{
   //create a Tree file tree1.root

   //create the file, the Tree and a few branches
   TFile f("tree1.root","recreate");
   TTree t1("t1","a simple Tree with simple variables");
   Float_t px, py, pz;
   Double_t random;
   Int_t ev;
   t1.Branch("px",&px,"px/F");
   t1.Branch("py",&py,"py/F");
   t1.Branch("pz",&pz,"pz/F");
   t1.Branch("random",&random,"random/D");
   t1.Branch("ev",&ev,"ev/I");

   //fill the tree
   for (Int_t i=0;i<10000;i++) {
     gRandom->Rannor(px,py);
     pz = px*px + py*py;
     random = gRandom->Rndm();
     ev = i;
     t1.Fill();
  }

  //save the Tree header. The file will be automatically closed
  //when going out of the function scope
  t1.Write();
}

void tree1r()
{
   //read the Tree generated by tree1w and fill two histograms

   //note that we use "new" to create the TFile and TTree objects !
   //because we want to keep these objects alive when we leave this function.
   TFile *f = new TFile("tree1.root");
   TTree *t1 = (TTree*)f->Get("t1");
   Float_t px, py, pz;
   Double_t random;
   Int_t ev;
   t1->SetBranchAddress("px",&px);
   t1->SetBranchAddress("py",&py);
   t1->SetBranchAddress("pz",&pz);
   t1->SetBranchAddress("random",&random);
   t1->SetBranchAddress("ev",&ev);

   //create two histograms
   TH1F *hpx   = new TH1F("hpx","px distribution",100,-3,3);
   TH2F *hpxpy = new TH2F("hpxpy","py vs px",30,-3,3,30,-3,3);

   //read all entries and fill the histograms
   Int_t nentries = (Int_t)t1->GetEntries();
   for (Int_t i=0;i<nentries;i++) {
     t1->GetEntry(i);
     hpx->Fill(px);
     hpxpy->Fill(px,py);
  }

  //we do not close the file. We want to keep the generated histograms
  //we open a browser and the TreeViewer
  if (gROOT->IsBatch()) return;
  new TBrowser();
  t1->StartViewer();
  // in the browser, click on "ROOT Files", then on "tree1.root".
  //     you can click on the histogram icons in the right panel to draw them.
  // in the TreeViewer, follow the instructions in the Help button.
}

void tree1() {
   tree1w();
   tree1r();
}
<|endoftext|>


<commit_before>#include <stan/math/prim/mat/meta/get.hpp>
#include <stan/math/prim/mat/meta/length.hpp>
#include <stan/math/prim/mat/meta/is_vector.hpp>
#include <stan/math/prim/mat/meta/is_vector_like.hpp>
#include <stan/math/prim/mat/fun/value_of_rec.hpp>
#include <gtest/gtest.h>
#include <stan/math/rev/core.hpp>
#include <stan/math/rev/scal/fun/cos.hpp>
#include <stan/math/rev/scal/fun/fabs.hpp>
#include <stan/math/rev/scal/fun/log.hpp>
#include <stan/math/rev/scal/fun/lgamma.hpp>
#include <stan/math/rev/scal/fun/floor.hpp>
#include <stan/math/rev/scal/fun/ceil.hpp>
#include <stan/math/rev/scal/fun/sin.hpp>
#include <stan/math/rev/scal/fun/tgamma.hpp>
#include <stan/math/rev/scal/fun/abs.hpp>
#include <stan/math/prim/mat/fun/value_of_rec.hpp>
#include <stan/math/rev/mat/fun/sum.hpp>
#include <stan/math/prim/mat/err/check_pos_definite.hpp>
#include <stan/math/prim/mat/err/check_symmetric.hpp>
#include <stan/math/rev/scal/fun/value_of_rec.hpp>
#include <stan/math/rev/scal/fun/tan.hpp>
#include <stan/math/rev/scal/fun/value_of.hpp>
#include <stan/math/rev/mat/fun/multiply.hpp>
#include <stan/math/prim/mat/prob/lkj_corr_log.hpp>
#include <stan/math/prim/mat/prob/lkj_corr_rng.hpp>
#include <stan/math/prim/mat/prob/lkj_corr_cholesky_log.hpp>
#include <stan/math/prim/mat/prob/lkj_corr_cholesky_rng.hpp>
#include <stan/math/prim/scal/prob/uniform_rng.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/math/distributions.hpp>

TEST(ProbDistributionsLkjCorr,var) {
  using stan::math::var;
  boost::random::mt19937 rng;
  int K = 4;
  Eigen::Matrix<var,Eigen::Dynamic,Eigen::Dynamic> Sigma(K,K);
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> Sigma_d(K,K);
  Sigma.setZero();
  Sigma.diagonal().setOnes();
  Sigma_d.setZero();
  Sigma_d.diagonal().setOnes();
  var eta = stan::math::uniform_rng(0,2,rng);
  var f = stan::math::do_lkj_constant(eta, K);
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_log(Sigma, eta).val());
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_log(Sigma_d, eta).val());
//  EXPECT_FLOAT_EQ(2.5177896, stan::math::lkj_corr_log(Sigma, eta).d_.val());
  eta = 1.0;
  double eta_d = 1.0;
  f = stan::math::do_lkj_constant(eta, K);
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_log(Sigma, eta).val());
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_log(Sigma, eta_d).val());
 // EXPECT_FLOAT_EQ(f.d_.val(), stan::math::lkj_corr_log(Sigma, eta).d_.val());
}

TEST(ProbDistributionsLkjCorrCholesky,var) {
  using stan::math::var;
  boost::random::mt19937 rng;
  int K = 4;
  Eigen::Matrix<var,Eigen::Dynamic,Eigen::Dynamic> Sigma(K,K);
  Sigma.setZero();
  Sigma.diagonal().setOnes();
  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> Sigma_d(K,K);
  Sigma_d.setZero();
  Sigma_d.diagonal().setOnes();
  var eta = stan::math::uniform_rng(0,2,rng);
  var f = stan::math::do_lkj_constant(eta, K);
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_cholesky_log(Sigma, eta).val());
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_cholesky_log(Sigma_d, eta).val());
//  EXPECT_FLOAT_EQ(6.7766843, stan::math::lkj_corr_cholesky_log(Sigma, eta).d_.val());
  eta = 1.0;
  double eta_d = 1.0;
  f = stan::math::do_lkj_constant(eta, K);
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_cholesky_log(Sigma, eta).val());
  EXPECT_FLOAT_EQ(f.val(), stan::math::lkj_corr_cholesky_log(Sigma, eta_d).val());
//  EXPECT_FLOAT_EQ(3, stan::math::lkj_corr_cholesky_log(Sigma, eta).d_.val());
}
<commit_msg>b f/i-1476 changes required to bring b uptodate with dev<commit_after><|endoftext|>