<commit_before>#include "GLTexture.hpp"

#include <GL/glew.h>

#include <wx/image.h>

#include <vector>
#include <algorithm>

namespace Slic3r {
namespace GUI {

GLTexture::GLTexture()
    : m_id(0)
    , m_width(0)
    , m_height(0)
    , m_source("")
{
}

GLTexture::~GLTexture()
{
    reset();
}

bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmaps)
{
    reset();

    // Load a PNG with an alpha channel.
    wxImage image;
    if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
    {
        reset();
        return false;
    }

    m_width = image.GetWidth();
    m_height = image.GetHeight();
    int n_pixels = m_width * m_height;

    if (n_pixels <= 0)
    {
        reset();
        return false;
    }

    // Get RGB & alpha raw data from wxImage, pack them into an array.
    unsigned char* img_rgb = image.GetData();
    if (img_rgb == nullptr)
    {
        reset();
        return false;
    }

    unsigned char* img_alpha = image.GetAlpha();

    std::vector<unsigned char> data(n_pixels * 4, 0);
    for (int i = 0; i < n_pixels; ++i)
    {
        int data_id = i * 4;
        int img_id = i * 3;
        data[data_id + 0] = img_rgb[img_id + 0];
        data[data_id + 1] = img_rgb[img_id + 1];
        data[data_id + 2] = img_rgb[img_id + 2];
        data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
    }

    // sends data to gpu
    ::glGenTextures(1, &m_id);
    ::glBindTexture(GL_TEXTURE_2D, m_id);
    ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
    if (generate_mipmaps)
    {
        // we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
        _generate_mipmaps(image);
        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    }
    else
    {
        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
    }
    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    ::glBindTexture(GL_TEXTURE_2D, 0);

    m_source = filename;
    return true;
}

void GLTexture::reset()
{
    if (m_id != 0)
        ::glDeleteTextures(1, &m_id);

    m_id = 0;
    m_width = 0;
    m_height = 0;
    m_source = "";
}

unsigned int GLTexture::get_id() const
{
    return m_id;
}

int GLTexture::get_width() const
{
    return m_width;
}

int GLTexture::get_height() const
{
    return m_height;
}

const std::string& GLTexture::get_source() const
{
    return m_source;
}

void GLTexture::render_texture(unsigned int tex_id, float left, float right, float bottom, float top)
{
    ::glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    ::glDisable(GL_LIGHTING);
    ::glEnable(GL_BLEND);
    ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    ::glEnable(GL_TEXTURE_2D);

    ::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id);

    ::glBegin(GL_QUADS);
    ::glTexCoord2d(0.0f, 1.0f); ::glVertex3f(left, bottom, 0.0f);
    ::glTexCoord2d(1.0f, 1.0f); ::glVertex3f(right, bottom, 0.0f);
    ::glTexCoord2d(1.0f, 0.0f); ::glVertex3f(right, top, 0.0f);
    ::glTexCoord2d(0.0f, 0.0f); ::glVertex3f(left, top, 0.0f);
    ::glEnd();

    ::glBindTexture(GL_TEXTURE_2D, 0);

    ::glDisable(GL_TEXTURE_2D);
    ::glDisable(GL_BLEND);
    ::glEnable(GL_LIGHTING);
}

void GLTexture::_generate_mipmaps(wxImage& image)
{
    int w = image.GetWidth();
    int h = image.GetHeight();
    GLint level = 0;
    std::vector<unsigned char> data(w * h * 4, 0);

    while ((w > 1) && (h > 1))
    {
        ++level;

        w = std::max(w / 2, 1);
        h = std::max(h / 2, 1);

        int n_pixels = w * h;

        image = image.ResampleBicubic(w, h);

        unsigned char* img_rgb = image.GetData();
        unsigned char* img_alpha = image.GetAlpha();

        data.resize(n_pixels * 4);
        for (int i = 0; i < n_pixels; ++i)
        {
            int data_id = i * 4;
            int img_id = i * 3;
            data[data_id + 0] = img_rgb[img_id + 0];
            data[data_id + 1] = img_rgb[img_id + 1];
            data[data_id + 2] = img_rgb[img_id + 2];
            data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
        }

        ::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
    }
}

} // namespace GUI
} // namespace Slic3r
<commit_msg>Removed error dialog when texture file does not exist<commit_after>#include "GLTexture.hpp"

#include <GL/glew.h>

#include <wx/image.h>

#include <boost/filesystem.hpp>

#include <vector>
#include <algorithm>

namespace Slic3r {
namespace GUI {

GLTexture::GLTexture()
    : m_id(0)
    , m_width(0)
    , m_height(0)
    , m_source("")
{
}

GLTexture::~GLTexture()
{
    reset();
}

bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmaps)
{
    reset();

    if (!boost::filesystem::exists(filename))
        return false;

    // Load a PNG with an alpha channel.
    wxImage image;
    if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
    {
        reset();
        return false;
    }

    m_width = image.GetWidth();
    m_height = image.GetHeight();
    int n_pixels = m_width * m_height;

    if (n_pixels <= 0)
    {
        reset();
        return false;
    }

    // Get RGB & alpha raw data from wxImage, pack them into an array.
    unsigned char* img_rgb = image.GetData();
    if (img_rgb == nullptr)
    {
        reset();
        return false;
    }

    unsigned char* img_alpha = image.GetAlpha();

    std::vector<unsigned char> data(n_pixels * 4, 0);
    for (int i = 0; i < n_pixels; ++i)
    {
        int data_id = i * 4;
        int img_id = i * 3;
        data[data_id + 0] = img_rgb[img_id + 0];
        data[data_id + 1] = img_rgb[img_id + 1];
        data[data_id + 2] = img_rgb[img_id + 2];
        data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
    }

    // sends data to gpu
    ::glGenTextures(1, &m_id);
    ::glBindTexture(GL_TEXTURE_2D, m_id);
    ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
    if (generate_mipmaps)
    {
        // we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
        _generate_mipmaps(image);
        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    }
    else
    {
        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
    }
    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    ::glBindTexture(GL_TEXTURE_2D, 0);

    m_source = filename;
    return true;
}

void GLTexture::reset()
{
    if (m_id != 0)
        ::glDeleteTextures(1, &m_id);

    m_id = 0;
    m_width = 0;
    m_height = 0;
    m_source = "";
}

unsigned int GLTexture::get_id() const
{
    return m_id;
}

int GLTexture::get_width() const
{
    return m_width;
}

int GLTexture::get_height() const
{
    return m_height;
}

const std::string& GLTexture::get_source() const
{
    return m_source;
}

void GLTexture::render_texture(unsigned int tex_id, float left, float right, float bottom, float top)
{
    ::glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    ::glDisable(GL_LIGHTING);
    ::glEnable(GL_BLEND);
    ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    ::glEnable(GL_TEXTURE_2D);

    ::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id);

    ::glBegin(GL_QUADS);
    ::glTexCoord2d(0.0f, 1.0f); ::glVertex3f(left, bottom, 0.0f);
    ::glTexCoord2d(1.0f, 1.0f); ::glVertex3f(right, bottom, 0.0f);
    ::glTexCoord2d(1.0f, 0.0f); ::glVertex3f(right, top, 0.0f);
    ::glTexCoord2d(0.0f, 0.0f); ::glVertex3f(left, top, 0.0f);
    ::glEnd();

    ::glBindTexture(GL_TEXTURE_2D, 0);

    ::glDisable(GL_TEXTURE_2D);
    ::glDisable(GL_BLEND);
    ::glEnable(GL_LIGHTING);
}

void GLTexture::_generate_mipmaps(wxImage& image)
{
    int w = image.GetWidth();
    int h = image.GetHeight();
    GLint level = 0;
    std::vector<unsigned char> data(w * h * 4, 0);

    while ((w > 1) && (h > 1))
    {
        ++level;

        w = std::max(w / 2, 1);
        h = std::max(h / 2, 1);

        int n_pixels = w * h;

        image = image.ResampleBicubic(w, h);

        unsigned char* img_rgb = image.GetData();
        unsigned char* img_alpha = image.GetAlpha();

        data.resize(n_pixels * 4);
        for (int i = 0; i < n_pixels; ++i)
        {
            int data_id = i * 4;
            int img_id = i * 3;
            data[data_id + 0] = img_rgb[img_id + 0];
            data[data_id + 1] = img_rgb[img_id + 1];
            data[data_id + 2] = img_rgb[img_id + 2];
            data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
        }

        ::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
    }
}

} // namespace GUI
} // namespace Slic3r
<|endoftext|>


<commit_before>//===-- InstCount.cpp - Collects the count of all instructions ------------===//
//
// This pass collects the count of all instructions and reports them
//
//
//===----------------------------------------------------------------------===//

#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/iOperators.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/InstIterator.h"
#include "Support/Statistic.h"
#include <algorithm>

namespace {
  static Statistic<> NumReturnInst("instcount","Number of ReturnInsts");
  static Statistic<> NumBranchInst("instcount", "Number of BranchInsts");
  static Statistic<> NumPHINode("instcount", "Number of PHINodes");
  static Statistic<> NumCastInst("instcount", "Number of CastInsts");
  static Statistic<> NumCallInst("instcount", "Number of CallInsts");
  static Statistic<> NumMallocInst("instcount", "Number of MallocInsts");
  static Statistic<> NumAllocaInst("instcount", "Number of AllocaInsts");
  static Statistic<> NumFreeInst("instcount", "Number of FreeInsts");
  static Statistic<> NumLoadInst("instcount", "Number of LoadInsts");
  static Statistic<> NumStoreInst("instcount", "Number of StoreInsts");
  static Statistic<> NumGetElementPtrInst("instcount",
					  "Number of GetElementPtrInsts");

  static Statistic<> NumSwitchInst("instcount", "Number of SwitchInsts");
  static Statistic<> NumInvokeInst("instcount", "Number of InvokeInsts");
  static Statistic<> NumBinaryOperator("instcount",
				       "Total Number of BinaryOperators");

  static Statistic<> NumShiftInst("instcount", " Total Number of ShiftInsts");
  static Statistic<> NumShlInst("instcount", "Number of Left ShiftInsts");

  static Statistic<> NumShrInst("instcount", "Number of Right ShiftInsts");

  static Statistic<> NumAddInst("instcount", "Number of AddInsts");
  static Statistic<> NumSubInst("instcount", "Number of SubInsts");
  static Statistic<> NumMulInst("instcount", "Number of MulInsts");
  static Statistic<> NumDivInst("instcount", "Number of DivInsts");
  static Statistic<> NumRemInst("instcount", "Number of RemInsts");
  static Statistic<> NumAndInst("instcount", "Number of AndInsts");
  static Statistic<> NumOrInst("instcount", "Number of OrInsts");
  static Statistic<> NumXorInst("instcount", "Number of XorInsts");
  static Statistic<> NumSetCondInst("instcount", "Total Number of SetCondInsts");
  static Statistic<> NumSetEQInst("instcount", "Number of SetEQInsts");
  static Statistic<> NumSetNEInst("instcount", "Number of SetNEInsts");
  static Statistic<> NumSetLEInst("instcount", "Number of SetLEInsts");
  static Statistic<> NumSetGEInst("instcount", "Number of SetGEInsts");
  static Statistic<> NumSetLTInst("instcount", "Number of SetLTInsts");
  static Statistic<> NumSetGTInst("instcount", "Number of SetGTInsts");

  class InstCount : public Pass, public InstVisitor<InstCount> {
  private:
        friend class InstVisitor<InstCount>;

    void visitBinaryOperator(BinaryOperator &I);
    void visitShiftInst(ShiftInst &I);
    void visitSetCondInst(SetCondInst &I);

    inline void visitSwitchInst(SwitchInst &I) { NumSwitchInst++; }
    inline void visitInvokeInst(InvokeInst &I) { NumInvokeInst++; }
    inline void visitReturnInst(ReturnInst &I) { NumReturnInst++; }
    inline void visitBranchInst(BranchInst &I) { NumBranchInst++; }
    inline void visitPHINode(PHINode &I) { NumPHINode++; }
    inline void visitCastInst (CastInst &I) { NumCastInst++; }
    inline void visitCallInst (CallInst &I) { NumCastInst++; }
    inline void visitMallocInst(MallocInst &I) { NumMallocInst++; }
    inline void visitAllocaInst(AllocaInst &I) { NumAllocaInst++; }
    inline void visitFreeInst  (FreeInst   &I) { NumFreeInst++; }
    inline void visitLoadInst  (LoadInst   &I) { NumLoadInst++; }
    inline void visitStoreInst (StoreInst  &I) { NumStoreInst++; }
    inline void visitGetElementPtrInst(GetElementPtrInst &I) {
      NumGetElementPtrInst++; }

    inline void visitInstruction(Instruction &I) {
      std::cerr << "Instruction Count does not know about " << I;
      abort();
    }
  public:
    virtual bool run(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  RegisterOpt<InstCount> X("instcount",
			   "Counts the various types of Instructions");

}

// createInstCountPass - The public interface to this file...
Pass *createInstCountPass() { return new InstCount(); }

// InstCount::run - This is the main Analysis entry point for a
// function.
//
bool InstCount::run(Module &M) {
    /* Initialization */
  NumReturnInst = 0;
  NumBranchInst = 0;
  NumPHINode = 0;
  NumCastInst = 0;
  NumCallInst = 0;
  NumMallocInst = 0;
  NumAllocaInst = 0;
  NumFreeInst = 0;
  NumLoadInst = 0;
  NumStoreInst = 0;
  NumGetElementPtrInst = 0;
  NumSwitchInst = 0;
  NumInvokeInst = 0;
  NumBinaryOperator = 0;
  NumShiftInst = 0;
  NumShlInst = 0;
  NumShrInst = 0;
  NumAddInst = 0;
  NumSubInst = 0;
  NumMulInst = 0;
  NumDivInst = 0;
  NumRemInst = 0;
  NumAndInst = 0;
  NumOrInst = 0;
  NumXorInst = 0;
  NumSetCondInst = 0;
  NumSetEQInst = 0;
  NumSetNEInst = 0;
  NumSetLEInst = 0;
  NumSetGEInst = 0;
  NumSetLTInst = 0;
  NumSetGTInst = 0;

  for (Module::iterator mI = M.begin(), mE = M.end(); mI != mE; ++mI)
    for (inst_iterator I = inst_begin(*mI), E = inst_end(*mI); I != E; ++I)
      visit(*I);
  return false;
}

void InstCount::visitBinaryOperator(BinaryOperator &I) {
  NumBinaryOperator++;
  switch (I.getOpcode()) {
  case Instruction::Add: NumAddInst++; break;
  case Instruction::Sub: NumSubInst++; break;
  case Instruction::Mul: NumMulInst++; break;
  case Instruction::Div: NumDivInst++; break;
  case Instruction::Rem: NumRemInst++; break;
  case Instruction::And: NumAndInst++; break;
  case Instruction::Or: NumOrInst++; break;
  case Instruction::Xor: NumXorInst++; break;
  default : std::cerr<< " Wrong binary operator \n";
  }
}

void InstCount::visitSetCondInst(SetCondInst &I) {
  NumBinaryOperator++;
  NumSetCondInst++;
  switch (I.getOpcode()) {
  case Instruction::SetEQ: NumSetEQInst++; break;
  case Instruction::SetNE: NumSetNEInst++; break;
  case Instruction::SetLE: NumSetLEInst++; break;
  case Instruction::SetGE: NumSetGEInst++; break;
  case Instruction::SetLT: NumSetLTInst++; break;
  case Instruction::SetGT: NumSetGTInst++; break;
  default : std::cerr<< " Wrong SetCond Inst \n";
  }
}

void InstCount::visitShiftInst(ShiftInst &I) {
  NumShiftInst++;
  switch (I.getOpcode()) {
  case Instruction::Shl: NumShlInst++; break;
  case Instruction::Shr: NumShrInst++; break;
  default : std::cerr<< " Wrong ShiftInst \n";
  }
}
<commit_msg>Count CallInsts correctly, remove unneccesary initializers S: ----------------------------------------------------------------------<commit_after>//===-- InstCount.cpp - Collects the count of all instructions ------------===//
//
// This pass collects the count of all instructions and reports them
//
//
//===----------------------------------------------------------------------===//

#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/iOperators.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/InstIterator.h"
#include "Support/Statistic.h"
#include <algorithm>

namespace {
  static Statistic<> NumReturnInst("instcount","Number of ReturnInsts");
  static Statistic<> NumBranchInst("instcount", "Number of BranchInsts");
  static Statistic<> NumPHINode("instcount", "Number of PHINodes");
  static Statistic<> NumCastInst("instcount", "Number of CastInsts");
  static Statistic<> NumCallInst("instcount", "Number of CallInsts");
  static Statistic<> NumMallocInst("instcount", "Number of MallocInsts");
  static Statistic<> NumAllocaInst("instcount", "Number of AllocaInsts");
  static Statistic<> NumFreeInst("instcount", "Number of FreeInsts");
  static Statistic<> NumLoadInst("instcount", "Number of LoadInsts");
  static Statistic<> NumStoreInst("instcount", "Number of StoreInsts");
  static Statistic<> NumGetElementPtrInst("instcount",
					  "Number of GetElementPtrInsts");

  static Statistic<> NumSwitchInst("instcount", "Number of SwitchInsts");
  static Statistic<> NumInvokeInst("instcount", "Number of InvokeInsts");
  static Statistic<> NumBinaryOperator("instcount",
				       "Total Number of BinaryOperators");

  static Statistic<> NumShiftInst("instcount", " Total Number of ShiftInsts");
  static Statistic<> NumShlInst("instcount", "Number of Left ShiftInsts");

  static Statistic<> NumShrInst("instcount", "Number of Right ShiftInsts");

  static Statistic<> NumAddInst("instcount", "Number of AddInsts");
  static Statistic<> NumSubInst("instcount", "Number of SubInsts");
  static Statistic<> NumMulInst("instcount", "Number of MulInsts");
  static Statistic<> NumDivInst("instcount", "Number of DivInsts");
  static Statistic<> NumRemInst("instcount", "Number of RemInsts");
  static Statistic<> NumAndInst("instcount", "Number of AndInsts");
  static Statistic<> NumOrInst("instcount", "Number of OrInsts");
  static Statistic<> NumXorInst("instcount", "Number of XorInsts");
  static Statistic<> NumSetCondInst("instcount", "Total Number of SetCondInsts");
  static Statistic<> NumSetEQInst("instcount", "Number of SetEQInsts");
  static Statistic<> NumSetNEInst("instcount", "Number of SetNEInsts");
  static Statistic<> NumSetLEInst("instcount", "Number of SetLEInsts");
  static Statistic<> NumSetGEInst("instcount", "Number of SetGEInsts");
  static Statistic<> NumSetLTInst("instcount", "Number of SetLTInsts");
  static Statistic<> NumSetGTInst("instcount", "Number of SetGTInsts");

  class InstCount : public Pass, public InstVisitor<InstCount> {
  private:
        friend class InstVisitor<InstCount>;

    void visitBinaryOperator(BinaryOperator &I);
    void visitShiftInst(ShiftInst &I);
    void visitSetCondInst(SetCondInst &I);

    inline void visitSwitchInst(SwitchInst &I) { NumSwitchInst++; }
    inline void visitInvokeInst(InvokeInst &I) { NumInvokeInst++; }
    inline void visitReturnInst(ReturnInst &I) { NumReturnInst++; }
    inline void visitBranchInst(BranchInst &I) { NumBranchInst++; }
    inline void visitPHINode(PHINode &I) { NumPHINode++; }
    inline void visitCastInst (CastInst &I) { NumCastInst++; }
    inline void visitCallInst (CallInst &I) { NumCallInst++; }
    inline void visitMallocInst(MallocInst &I) { NumMallocInst++; }
    inline void visitAllocaInst(AllocaInst &I) { NumAllocaInst++; }
    inline void visitFreeInst  (FreeInst   &I) { NumFreeInst++; }
    inline void visitLoadInst  (LoadInst   &I) { NumLoadInst++; }
    inline void visitStoreInst (StoreInst  &I) { NumStoreInst++; }
    inline void visitGetElementPtrInst(GetElementPtrInst &I) {
      NumGetElementPtrInst++; }

    inline void visitInstruction(Instruction &I) {
      std::cerr << "Instruction Count does not know about " << I;
      abort();
    }
  public:
    virtual bool run(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  RegisterAnalysis<InstCount> X("instcount",
		    	   "Counts the various types of Instructions");

}

// createInstCountPass - The public interface to this file...
Pass *createInstCountPass() { return new InstCount(); }

// InstCount::run - This is the main Analysis entry point for a
// function.
//
bool InstCount::run(Module &M) {
  for (Module::iterator mI = M.begin(), mE = M.end(); mI != mE; ++mI)
    for (inst_iterator I = inst_begin(*mI), E = inst_end(*mI); I != E; ++I)
      visit(*I);
  return false;
}

void InstCount::visitBinaryOperator(BinaryOperator &I) {
  NumBinaryOperator++;
  switch (I.getOpcode()) {
  case Instruction::Add: NumAddInst++; break;
  case Instruction::Sub: NumSubInst++; break;
  case Instruction::Mul: NumMulInst++; break;
  case Instruction::Div: NumDivInst++; break;
  case Instruction::Rem: NumRemInst++; break;
  case Instruction::And: NumAndInst++; break;
  case Instruction::Or: NumOrInst++; break;
  case Instruction::Xor: NumXorInst++; break;
  default : std::cerr<< " Wrong binary operator \n";
  }
}

void InstCount::visitSetCondInst(SetCondInst &I) {
  NumBinaryOperator++;
  NumSetCondInst++;
  switch (I.getOpcode()) {
  case Instruction::SetEQ: NumSetEQInst++; break;
  case Instruction::SetNE: NumSetNEInst++; break;
  case Instruction::SetLE: NumSetLEInst++; break;
  case Instruction::SetGE: NumSetGEInst++; break;
  case Instruction::SetLT: NumSetLTInst++; break;
  case Instruction::SetGT: NumSetGTInst++; break;
  default : std::cerr<< " Wrong SetCond Inst \n";
  }
}

void InstCount::visitShiftInst(ShiftInst &I) {
  NumShiftInst++;
  switch (I.getOpcode()) {
  case Instruction::Shl: NumShlInst++; break;
  case Instruction::Shr: NumShrInst++; break;
  default : std::cerr<< " Wrong ShiftInst \n";
  }
}
<|endoftext|>


<commit_before>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits) const {
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(unsigned NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      if (NumZeros >= 8 && Data64bitsDirective) {
        for (; NumZeros >= 8; NumZeros -= 8)
          O << Data64bitsDirective << "0\n";
      }
      for (; NumZeros >= 4; NumZeros -= 4)
        O << Data32bitsDirective << "0\n";
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue())
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (unsigned long long)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV))
    // This is a constant address for a global variable or function.  Use the
    // name of the variable or function as the address value.
    O << Mang->getValueName(CV);
  else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        O << "(";
        emitConstantValueOnly(ptrVal);
        O << ") + " << Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// getAsCString - Return the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
    unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue()) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      O << AsciiDirective;
      printAsCString(O, CVA);
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    unsigned sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      unsigned fieldSize = TD.getTypeSize(field->getType());
      unsigned padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      union DU {                            // Abide by C TBAA rules
        double FVal;
        uint64_t UVal;
      } U;
      U.FVal = Val;

      if (Data64bitsDirective)
        O << Data64bitsDirective << U.UVal << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      union FU {                            // Abide by C TBAA rules
        float FVal;
        int32_t UVal;
      } U;
      U.FVal = Val;

      O << Data32bitsDirective << U.UVal << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::BoolTyID:
  case Type::PointerTyID:
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert (0 && "Should have already output double-word constant.");
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<commit_msg>Do not use .xword and friends to emit zeros on V9.  Apparently there are issues with emitting .xwords when not on an 8-byte boundary (.xword 0 is not the same as 8 .byte 0's).  Because we do not know when or when we are not aligned, just emit bytes like the old V9 asmprinter did.<commit_after>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits) const {
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(unsigned NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue())
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (unsigned long long)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV))
    // This is a constant address for a global variable or function.  Use the
    // name of the variable or function as the address value.
    O << Mang->getValueName(CV);
  else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        O << "(";
        emitConstantValueOnly(ptrVal);
        O << ") + " << Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// getAsCString - Return the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
    unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue()) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      O << AsciiDirective;
      printAsCString(O, CVA);
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    unsigned sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      unsigned fieldSize = TD.getTypeSize(field->getType());
      unsigned padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      union DU {                            // Abide by C TBAA rules
        double FVal;
        uint64_t UVal;
      } U;
      U.FVal = Val;

      if (Data64bitsDirective)
        O << Data64bitsDirective << U.UVal << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      union FU {                            // Abide by C TBAA rules
        float FVal;
        int32_t UVal;
      } U;
      U.FVal = Val;

      O << Data32bitsDirective << U.UVal << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::BoolTyID:
  case Type::PointerTyID:
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert (0 && "Should have already output double-word constant.");
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<|endoftext|>


<commit_before>//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"

#include "clang/Driver/Action.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Program.h"
#include <sys/stat.h>
#include <errno.h>
using namespace clang::driver;

Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
                         InputArgList *_Args, DerivedArgList *_TranslatedArgs)
  : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
    TranslatedArgs(_TranslatedArgs) {
}

Compilation::~Compilation() {
  delete TranslatedArgs;
  delete Args;

  // Free any derived arg lists.
  for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
                      DerivedArgList*>::iterator it = TCArgs.begin(),
         ie = TCArgs.end(); it != ie; ++it)
    if (it->second != TranslatedArgs)
      delete it->second;

  // Free the actions, if built.
  for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
       it != ie; ++it)
    delete *it;
}

const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
                                                       const char *BoundArch) {
  if (!TC)
    TC = &DefaultToolChain;

  DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
  if (!Entry) {
    Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
    if (!Entry)
      Entry = TranslatedArgs;
  }

  return *Entry;
}

void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
                           const char *Terminator, bool Quote) const {
  if (const Command *C = dyn_cast<Command>(&J)) {
    OS << " \"" << C->getExecutable() << '"';
    for (ArgStringList::const_iterator it = C->getArguments().begin(),
           ie = C->getArguments().end(); it != ie; ++it) {
      OS << ' ';
      if (!Quote) {
        OS << *it;
        continue;
      }

      // Quote the argument and escape shell special characters; this isn't
      // really complete but is good enough.
      OS << '"';
      for (const char *s = *it; *s; ++s) {
        if (*s == '"' || *s == '\\' || *s == '$')
          OS << '\\';
        OS << *s;
      }
      OS << '"';
    }
    OS << Terminator;
  } else {
    const JobList *Jobs = cast<JobList>(&J);
    for (JobList::const_iterator
           it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
      PrintJob(OS, **it, Terminator, Quote);
  }
}

bool Compilation::CleanupFileList(const ArgStringList &Files,
                                  bool IssueErrors) const {
  bool Success = true;

  for (ArgStringList::const_iterator
         it = Files.begin(), ie = Files.end(); it != ie; ++it) {

    llvm::sys::Path P(*it);
    std::string Error;

    if (P.eraseFromDisk(false, &Error)) {
      // Failure is only failure if the file exists and is "regular". There is
      // a race condition here due to the limited interface of
      // llvm::sys::Path, we want to know if the removal gave ENOENT.

      // FIXME: Grumble, P.exists() is broken. PR3837.
      struct stat buf;
      if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG :
                                         (errno != ENOENT)) {
        if (IssueErrors)
          getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
            << Error;
        Success = false;
      }
    }
  }

  return Success;
}

int Compilation::ExecuteCommand(const Command &C,
                                const Command *&FailingCommand) const {
  llvm::sys::Path Prog(C.getExecutable());
  const char **Argv = new const char*[C.getArguments().size() + 2];
  Argv[0] = C.getExecutable();
  std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
  Argv[C.getArguments().size() + 1] = 0;

  if (getDriver().CCCEcho || getDriver().CCPrintOptions ||
      getArgs().hasArg(options::OPT_v)) {
    llvm::raw_ostream *OS = &llvm::errs();

    // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
    // output stream.
    if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
      std::string Error;
      OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename,
                                    Error,
                                    llvm::raw_fd_ostream::F_Append);
      if (!Error.empty()) {
        getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
          << Error;
        FailingCommand = &C;
        delete OS;
        return 1;
      }
    }

    if (getDriver().CCPrintOptions)
      *OS << "[Logging clang options]";

    PrintJob(*OS, C, "\n", /*Quote=*/getDriver().CCPrintOptions);

    if (OS != &llvm::errs())
      delete OS;
  }

  std::string Error;
  int Res =
    llvm::sys::Program::ExecuteAndWait(Prog, Argv,
                                       /*env*/0, /*redirects*/0,
                                       /*secondsToWait*/0, /*memoryLimit*/0,
                                       &Error);
  if (!Error.empty()) {
    assert(Res && "Error string set with 0 result code!");
    getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
  }

  if (Res)
    FailingCommand = &C;

  delete[] Argv;
  return Res;
}

int Compilation::ExecuteJob(const Job &J,
                            const Command *&FailingCommand) const {
  if (const Command *C = dyn_cast<Command>(&J)) {
    return ExecuteCommand(*C, FailingCommand);
  } else {
    const JobList *Jobs = cast<JobList>(&J);
    for (JobList::const_iterator
           it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
      if (int Res = ExecuteJob(**it, FailingCommand))
        return Res;
    return 0;
  }
}
<commit_msg>Driver: When compilation fails, don't try to remove output files we don't have write access to.<commit_after>//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"

#include "clang/Driver/Action.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Program.h"
#include <sys/stat.h>
#include <errno.h>
using namespace clang::driver;

Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
                         InputArgList *_Args, DerivedArgList *_TranslatedArgs)
  : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
    TranslatedArgs(_TranslatedArgs) {
}

Compilation::~Compilation() {
  delete TranslatedArgs;
  delete Args;

  // Free any derived arg lists.
  for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
                      DerivedArgList*>::iterator it = TCArgs.begin(),
         ie = TCArgs.end(); it != ie; ++it)
    if (it->second != TranslatedArgs)
      delete it->second;

  // Free the actions, if built.
  for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
       it != ie; ++it)
    delete *it;
}

const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
                                                       const char *BoundArch) {
  if (!TC)
    TC = &DefaultToolChain;

  DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
  if (!Entry) {
    Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
    if (!Entry)
      Entry = TranslatedArgs;
  }

  return *Entry;
}

void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
                           const char *Terminator, bool Quote) const {
  if (const Command *C = dyn_cast<Command>(&J)) {
    OS << " \"" << C->getExecutable() << '"';
    for (ArgStringList::const_iterator it = C->getArguments().begin(),
           ie = C->getArguments().end(); it != ie; ++it) {
      OS << ' ';
      if (!Quote) {
        OS << *it;
        continue;
      }

      // Quote the argument and escape shell special characters; this isn't
      // really complete but is good enough.
      OS << '"';
      for (const char *s = *it; *s; ++s) {
        if (*s == '"' || *s == '\\' || *s == '$')
          OS << '\\';
        OS << *s;
      }
      OS << '"';
    }
    OS << Terminator;
  } else {
    const JobList *Jobs = cast<JobList>(&J);
    for (JobList::const_iterator
           it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
      PrintJob(OS, **it, Terminator, Quote);
  }
}

bool Compilation::CleanupFileList(const ArgStringList &Files,
                                  bool IssueErrors) const {
  bool Success = true;

  for (ArgStringList::const_iterator
         it = Files.begin(), ie = Files.end(); it != ie; ++it) {

    llvm::sys::Path P(*it);
    std::string Error;

    // Don't try to remove files which we don't have write access to (but may be
    // able to remove). Underlying tools may have intentionally not overwritten
    // them.
    if (!P.canWrite())
      continue;

    if (P.eraseFromDisk(false, &Error)) {
      // Failure is only failure if the file exists and is "regular". There is
      // a race condition here due to the limited interface of
      // llvm::sys::Path, we want to know if the removal gave ENOENT.

      // FIXME: Grumble, P.exists() is broken. PR3837.
      struct stat buf;
      if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG :
                                         (errno != ENOENT)) {
        if (IssueErrors)
          getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
            << Error;
        Success = false;
      }
    }
  }

  return Success;
}

int Compilation::ExecuteCommand(const Command &C,
                                const Command *&FailingCommand) const {
  llvm::sys::Path Prog(C.getExecutable());
  const char **Argv = new const char*[C.getArguments().size() + 2];
  Argv[0] = C.getExecutable();
  std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
  Argv[C.getArguments().size() + 1] = 0;

  if (getDriver().CCCEcho || getDriver().CCPrintOptions ||
      getArgs().hasArg(options::OPT_v)) {
    llvm::raw_ostream *OS = &llvm::errs();

    // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
    // output stream.
    if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
      std::string Error;
      OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename,
                                    Error,
                                    llvm::raw_fd_ostream::F_Append);
      if (!Error.empty()) {
        getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
          << Error;
        FailingCommand = &C;
        delete OS;
        return 1;
      }
    }

    if (getDriver().CCPrintOptions)
      *OS << "[Logging clang options]";

    PrintJob(*OS, C, "\n", /*Quote=*/getDriver().CCPrintOptions);

    if (OS != &llvm::errs())
      delete OS;
  }

  std::string Error;
  int Res =
    llvm::sys::Program::ExecuteAndWait(Prog, Argv,
                                       /*env*/0, /*redirects*/0,
                                       /*secondsToWait*/0, /*memoryLimit*/0,
                                       &Error);
  if (!Error.empty()) {
    assert(Res && "Error string set with 0 result code!");
    getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
  }

  if (Res)
    FailingCommand = &C;

  delete[] Argv;
  return Res;
}

int Compilation::ExecuteJob(const Job &J,
                            const Command *&FailingCommand) const {
  if (const Command *C = dyn_cast<Command>(&J)) {
    return ExecuteCommand(*C, FailingCommand);
  } else {
    const JobList *Jobs = cast<JobList>(&J);
    for (JobList::const_iterator
           it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
      if (int Res = ExecuteJob(**it, FailingCommand))
        return Res;
    return 0;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 WinT 3794 <http://wint3794.org>
 *
 * 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 "Ports.h"
#include "Receiver.h"

DS_Receiver::DS_Receiver()
{
    m_socket.bind (DS_Ports::Client, QUdpSocket::ShareAddress);
    connect (&m_socket, SIGNAL (readyRead()), this, SLOT (onDataReceived()));
}

void DS_Receiver::onDataReceived()
{
    while (m_socket.hasPendingDatagrams()) {

        /* Read the socket data */
        QByteArray data;
        data.resize (m_socket.pendingDatagramSize());
        m_socket.readDatagram (data.data(), data.size());

        /* Process downloaded data into a DS_RobotPacket */
        DS_RobotPacket packet = getRobotPacket (data);

        /* Read the values of the packet and notify other objects */
        emit voltageChanged (packet.voltage);
        emit voltageChanged (packet.voltageString);

        /* Only notify about code change if necessary */
        if (m_code != packet.hasCode) {
            m_code = packet.hasCode;
            emit userCodeChanged (m_code);
        }

        /* Send current date/time to robot */
        if (packet.requestDateTime) {
            /* TODO */
        }
    }
}

DS_RobotPacket DS_Receiver::getRobotPacket (QByteArray data)
{
    DS_RobotPacket receiver;

    /* Get communication version, god knows if we will use it... */
    receiver.commVersion = data.at (2);

    /* Get the pong data */
    receiver.pongData.byte1 = data.at (0);
    receiver.pongData.byte2 = data.at (1);

    /* Decide if we must send current date/time to robot */
    receiver.requestDateTime = (data.at (7) == 0x01);

    /* Get the confirmation code of control mode */
    receiver.controlMode = (DS_ControlMode) data.at (3);

    /* Get current mode and determine if user code is present */
    receiver.programMode = (DS_ProgramMode) data.at (4);
    receiver.hasCode = (receiver.programMode != DS_ProgramNoCode);

    /* Calculate the voltage */
    QString major = QString::number (data.at (5));
    QString minor = QString::number (data.at (6));

    if (minor.length() > 2)
        minor = QString ("%1%2").arg (minor.at (0), minor.at (1));

    else if (minor.length() == 1)
        minor = QString ("0%1").arg (minor);

    receiver.voltageString = QString ("%1.%2").arg (major, minor);
    receiver.voltageString = receiver.voltageString.replace ("-", "");
    receiver.voltage = receiver.voltageString.toDouble();

    return receiver;
}<commit_msg>Update Receiver.cpp<commit_after>/*
 * Copyright (c) 2015 WinT 3794 <http://wint3794.org>
 *
 * 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 "Ports.h"
#include "Receiver.h"

DS_Receiver::DS_Receiver()
{
    m_socket.bind (DS_Ports::Client, QUdpSocket::ShareAddress);
    connect (&m_socket, SIGNAL (readyRead()), this, SLOT (onDataReceived()));
}

void DS_Receiver::onDataReceived()
{
    while (m_socket.hasPendingDatagrams()) {

        /* Read the socket data */
        QByteArray data;
        data.resize (m_socket.pendingDatagramSize());
        m_socket.readDatagram (data.data(), data.size());

        /* Process downloaded data into a DS_RobotPacket */
        DS_RobotPacket packet = getRobotPacket (data);

        /* Read the values of the packet and notify other objects */
        emit voltageChanged (packet.voltage);
        emit voltageChanged (packet.voltageString);

        /* Only notify about code change if necessary */
        if (m_code != packet.hasCode) {
            m_code = packet.hasCode;
            emit userCodeChanged (m_code);
        }

        /* Send current date/time to robot */
        if (packet.requestDateTime) {
            /* TODO */
        }
    }
}

DS_RobotPacket DS_Receiver::getRobotPacket (QByteArray data)
{
    DS_RobotPacket receiver;

    /* Get communication version, god knows if we will use it... */
    receiver.commVersion = data.at (2);

    /* Get the pong data */
    receiver.pongData.byte1 = data.at (0);
    receiver.pongData.byte2 = data.at (1);

    /* Decide if we must send current date/time to robot */
    receiver.requestDateTime = (data.at (7) == 0x01);

    /* Get the confirmation code of control mode */
    receiver.controlMode = (DS_ControlMode) data.at (3);

    /* Get current mode and determine if user code is present */
    receiver.programMode = (DS_ProgramMode) data.at (4);
    receiver.hasCode = (receiver.programMode != DS_ProgramNoCode);

    /* Calculate the voltage */
    QString major = QString::number (data.at (5));
    QString minor = QString::number (data.at (6));

    if (minor.length() > 2)
        minor = QString ("%1%2").arg (minor.at (0), minor.at (1));

    else if (minor.length() == 1)
        minor = QString ("0%1").arg (minor);

    receiver.voltageString = QString ("%1.%2").arg (major, minor);
    receiver.voltageString = receiver.voltageString.replace ("-", "");
    receiver.voltage = receiver.voltageString.toDouble();

    return receiver;
}<|endoftext|>


<commit_before>/*
  Citizen Weather Observer Program Reporting Library for Particle (CWOP-Particle)
  License: CC-0 (Public Domain)
  @author: Andrew Keyser <legoguy@gmail.com>
  */

#include "cwop-particle.h"

CWOP_Particle::CWOP_Particle()
{
}

void CWOP_Particle::begin(Client &client, const char *regNumber)
{
  begin(client);
  this->setRegNumber(regNumber);
}

void CWOP_Particle::begin(Client &client)
{
#ifdef PRINT_DEBUG_MESSAGES
  Serial.print("cwop::cwopBegin");
#endif
  this->setClient(&client);
}

void CWOP_Particle::setClient(Client *client) { this->client = client; }

void CWOP_Particle::setRegNumber(const char *number)
{
  this->regNumber = String(number);
}

/* LAT/LONG FORMATS - FROM WXQA.COM
 * The format is "ddmm.hhN/dddmm.hhW" without the quotation marks, where d is degrees, m is minutes and h is hundredths
 * of minutes. The first eight characters represent latitude (north in this case), and the last nine characters
 * represent longitude (west in this case). The hemispheres are represented by capital letters; N, E, S, W and remove
 * the need for plus or minus signs on the latitude and longitude. Note that LEADING ZEROS ARE REQUIRED. Also note that
 * there must be only two numbers to the right of the decimal point in the latitude or longitude, and that colons are
 * not allowed.
 */
void CWOP_Particle::setLatitude(int degrees, double minutes, char hemisphere)
{
  this->latitude = String::format("%02d%05.2f%c",
                                  degrees,
                                  minutes,
                                  hemisphere);
}

void CWOP_Particle::setLongitude(int degrees, double minutes, char hemisphere)
{
  this->longitude = String::format("%03d%05.2f%c",
                                   degrees,
                                   minutes,
                                   hemisphere);
}

void CWOP_Particle::setWindDegrees(double windDeg) { this->windDeg = windDeg; }
void CWOP_Particle::setWindMph(double windMph) { this->windMph = windMph; }
void CWOP_Particle::setWindGustMph(double windGustMph) { this->windGustMph = windGustMph; }
void CWOP_Particle::setTempF(double tempF) { this->tempF = tempF; }
void CWOP_Particle::setRain1hIn(double rain1hIn) { this->rain1hIn = rain1hIn; }
void CWOP_Particle::setRain24hIn(double rain24hIn) { this->rain24hIn = rain24hIn; }
void CWOP_Particle::setRainSinceMidnightIn(double rainSinceMidnightIn) { this->rainSinceMidnightIn = rainSinceMidnightIn; }
void CWOP_Particle::setHumidityPct(double humidityPct) { this->humidityPct = humidityPct; }
void CWOP_Particle::setPressureMb(double pressureMb) { this->pressureMb = pressureMb; }
void CWOP_Particle::setLuminosityWM2(double luminosityWM2) { this->luminosityWM2 = luminosityWM2; }
void CWOP_Particle::setSnow24hIn(double snow24hIn) { this->snow24hIn = snow24hIn; }

bool CWOP_Particle::connect()
{
  bool connectSuccess = false;
  connectSuccess = this->client->connect(CWOP_SERVER, CWOP_PORTNUMBER);
  if (!connectSuccess)
  {
#ifdef PRINT_DEBUG_MESSAGES
    Serial.print("Failed. Try default IP...");
#endif
    connectSuccess = this->client->connect(CWOP_IPADDRESS, CWOP_PORTNUMBER);
  }

#ifdef PRINT_DEBUG_MESSAGES
  if (connectSuccess)
  {
    Particle.publish(PARTICLE_PUBLISH_TOPIC, "Connection Success", PARTICLE_PUBLISH_TTL, PRIVATE);
  }
  else
  {
    Particle.publish(PARTICLE_PUBLISH_TOPIC, "Connection Failure", PARTICLE_PUBLISH_TTL, PRIVATE);
  }
#endif
  return connectSuccess;
}

const char *CWOP_Particle::createAPRS()
{
  nextAPRS[0] = '\0';
  char tempstring[128] = "";

  /* http://www.aprs.org/doc/APRS101.PDF */
  /* http://aprs.org/aprs12/weather-new.txt */
  /* http://www.aprs.org/aprs11/spec-wx.txt */
  /* http://www.aprs.org/APRS-docs/WX.TXT */
  /* BUILD THE DATA STRING, START WITH STATION ID, TIMESTAMP, AND POSITION */
  sprintf(nextAPRS, "%s>APRS,TCPIP*:%s%s/%s_",
          this->regNumber.c_str(),                                            // Build weather record
          Time.format(Time.now() - (Time.zone() * 3600), "@%d%H%Mz").c_str(), // Add date time
          this->latitude.c_str(), this->longitude.c_str());                   // Add Lat Lon

  /* WIND DIRECTION ("COURSE") - required - "..." as fallback */
  if (!isnan(this->windDeg))
  {
    sprintf(tempstring, "%03.0f", this->windDeg);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "_...");
  }

  /* WIND SPEED - required - "..." as fallback */
  if (!isnan(this->windMph))
  {
    sprintf(tempstring, "/%03.0f", this->windMph);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "/...");
  }

  /* WIND GUST (g) - required - "..." as fallback */
  if (!isnan(this->windGustMph))
  {
    sprintf(tempstring, "g%03.0f", this->windGustMph);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "g...");
  }

  /* TEMPERATURE OUTDOOR (t) - required - "..." as fallback */
  if (!isnan(this->tempF))
  {
    sprintf(tempstring, "t%03.0f", this->tempF);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "t...");
  }

  /* RAIN 1H (r) - not required */
  if (!isnan(this->rain1hIn))
  {
    sprintf(tempstring, "r%03.0f", this->rain1hIn * 100); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* READ RAIN 24H (p) - not required */
  if (!isnan(this->rain24hIn))
  {
    sprintf(tempstring, "p%03.0f", this->rain24hIn * 100); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* RAIN SINCE MIDNIGHT (P) - not required */
  if (!isnan(this->rainSinceMidnightIn))
  {
    sprintf(tempstring, "P%03.0f", this->rainSinceMidnightIn * 100); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* SNOW (s) - not required */
  if (!isnan(this->snow24hIn))
  {
    sprintf(tempstring, "s%03.1f", this->snow24hIn); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* RELATIVE HUMIDITY OUTDOOR (h) - not required */
  if (!isnan(this->humidityPct))
  {
    sprintf(tempstring, "h%02.0f", this->humidityPct >= 99.5 ? 0 : this->humidityPct); // report >=99.5 as '00'
    strcat(nextAPRS, tempstring);
  }

  /* BAROMETRIC PRESSURE (b) - not required */
  if (!isnan(this->pressureMb))
  {
    sprintf(tempstring, "b%05.0f", (this->pressureMb * 10)); // tenths of milibars
    strcat(nextAPRS, tempstring);
  }

  /* LUMINOSITY (L/l) - not required */
  if (!isnan(this->luminosityWM2))
  {
    if (round(this->luminosityWM2) < 1000)
    {
      sprintf(tempstring, "L%03.0f", this->luminosityWM2);
    }
    else
    {
      sprintf(tempstring, "l%03.0f", this->luminosityWM2 - 1000);
    }
    strcat(nextAPRS, tempstring);
  }

  /* SOFTWARE TYPE AND ACTION (.) */
  sprintf(tempstring, ".%s%s", CWOP_DEVICE, CWOP_VERSION);
  strcat(nextAPRS, tempstring);
  return nextAPRS;
}

bool CWOP_Particle::writeHeader()
{
  if (!this->client->print(String::format("user %s pass -1 vers %s %s\r\n", this->regNumber.c_str(), CWOP_DEVICE, CWOP_VERSION).c_str()))
    return false;
  return true;
}

bool CWOP_Particle::writeData()
{
  if (!this->client->print(String::format("%s\r\n", this->nextAPRS).c_str()))
    return false;
  return true;
}

int CWOP_Particle::writePacket()
{
  if (!connect())
  {
    // Failed to connect
    return ERR_CONNECT_FAILED;
  }

  if (!this->writeHeader())
    return abortWritePacket();
  this->createAPRS();
  if (!this->writeData())
    return abortWritePacket();

  delay(500); // hopefully this is enough time to send the data.

  if (this->client->available() > 0)
  {
    String connect_msg = this->client->readStringUntil('\r');
    Particle.publish(PARTICLE_PUBLISH_TOPIC, connect_msg, PARTICLE_PUBLISH_TTL, PRIVATE);
  }

  this->client->stop();

  return OK_SUCCESS;
}

int CWOP_Particle::abortWritePacket()
{
  this->client->stop();
#ifdef PRINT_DEBUG_MESSAGES
  Particle.publish(PARTICLE_PUBLISH_TOPIC, "Aborted packet!", PARTICLE_PUBLISH_TTL, PRIVATE);
#endif
  return ERR_UNEXPECTED_FAIL;
}<commit_msg>Remove leftover debug messages from cwop-particle.cpp<commit_after>/*
  Citizen Weather Observer Program Reporting Library for Particle (CWOP-Particle)
  License: CC-0 (Public Domain)
  @author: Andrew Keyser <legoguy@gmail.com>
  */

#include "cwop-particle.h"

CWOP_Particle::CWOP_Particle()
{
}

void CWOP_Particle::begin(Client &client, const char *regNumber)
{
  begin(client);
  this->setRegNumber(regNumber);
}

void CWOP_Particle::begin(Client &client)
{
  this->setClient(&client);
}

void CWOP_Particle::setClient(Client *client) { this->client = client; }

void CWOP_Particle::setRegNumber(const char *number)
{
  this->regNumber = String(number);
}

/* LAT/LONG FORMATS - FROM WXQA.COM
 * The format is "ddmm.hhN/dddmm.hhW" without the quotation marks, where d is degrees, m is minutes and h is hundredths
 * of minutes. The first eight characters represent latitude (north in this case), and the last nine characters
 * represent longitude (west in this case). The hemispheres are represented by capital letters; N, E, S, W and remove
 * the need for plus or minus signs on the latitude and longitude. Note that LEADING ZEROS ARE REQUIRED. Also note that
 * there must be only two numbers to the right of the decimal point in the latitude or longitude, and that colons are
 * not allowed.
 */
void CWOP_Particle::setLatitude(int degrees, double minutes, char hemisphere)
{
  this->latitude = String::format("%02d%05.2f%c",
                                  degrees,
                                  minutes,
                                  hemisphere);
}

void CWOP_Particle::setLongitude(int degrees, double minutes, char hemisphere)
{
  this->longitude = String::format("%03d%05.2f%c",
                                   degrees,
                                   minutes,
                                   hemisphere);
}

void CWOP_Particle::setWindDegrees(double windDeg) { this->windDeg = windDeg; }
void CWOP_Particle::setWindMph(double windMph) { this->windMph = windMph; }
void CWOP_Particle::setWindGustMph(double windGustMph) { this->windGustMph = windGustMph; }
void CWOP_Particle::setTempF(double tempF) { this->tempF = tempF; }
void CWOP_Particle::setRain1hIn(double rain1hIn) { this->rain1hIn = rain1hIn; }
void CWOP_Particle::setRain24hIn(double rain24hIn) { this->rain24hIn = rain24hIn; }
void CWOP_Particle::setRainSinceMidnightIn(double rainSinceMidnightIn) { this->rainSinceMidnightIn = rainSinceMidnightIn; }
void CWOP_Particle::setHumidityPct(double humidityPct) { this->humidityPct = humidityPct; }
void CWOP_Particle::setPressureMb(double pressureMb) { this->pressureMb = pressureMb; }
void CWOP_Particle::setLuminosityWM2(double luminosityWM2) { this->luminosityWM2 = luminosityWM2; }
void CWOP_Particle::setSnow24hIn(double snow24hIn) { this->snow24hIn = snow24hIn; }

bool CWOP_Particle::connect()
{
  bool connectSuccess = false;
  connectSuccess = this->client->connect(CWOP_SERVER, CWOP_PORTNUMBER);
  if (!connectSuccess)
  {
    connectSuccess = this->client->connect(CWOP_IPADDRESS, CWOP_PORTNUMBER);
  }

#ifdef PRINT_DEBUG_MESSAGES
  if (connectSuccess)
  {
    Particle.publish(PARTICLE_PUBLISH_TOPIC, "Connection Success", PARTICLE_PUBLISH_TTL, PRIVATE);
  }
  else
  {
    Particle.publish(PARTICLE_PUBLISH_TOPIC, "Connection Failure", PARTICLE_PUBLISH_TTL, PRIVATE);
  }
#endif
  return connectSuccess;
}

const char *CWOP_Particle::createAPRS()
{
  nextAPRS[0] = '\0';
  char tempstring[128] = "";

  /* http://www.aprs.org/doc/APRS101.PDF */
  /* http://aprs.org/aprs12/weather-new.txt */
  /* http://www.aprs.org/aprs11/spec-wx.txt */
  /* http://www.aprs.org/APRS-docs/WX.TXT */
  /* BUILD THE DATA STRING, START WITH STATION ID, TIMESTAMP, AND POSITION */
  sprintf(nextAPRS, "%s>APRS,TCPIP*:%s%s/%s_",
          this->regNumber.c_str(),                                            // Build weather record
          Time.format(Time.now() - (Time.zone() * 3600), "@%d%H%Mz").c_str(), // Add date time
          this->latitude.c_str(), this->longitude.c_str());                   // Add Lat Lon

  /* WIND DIRECTION ("COURSE") - required - "..." as fallback */
  if (!isnan(this->windDeg))
  {
    sprintf(tempstring, "%03.0f", this->windDeg);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "_...");
  }

  /* WIND SPEED - required - "..." as fallback */
  if (!isnan(this->windMph))
  {
    sprintf(tempstring, "/%03.0f", this->windMph);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "/...");
  }

  /* WIND GUST (g) - required - "..." as fallback */
  if (!isnan(this->windGustMph))
  {
    sprintf(tempstring, "g%03.0f", this->windGustMph);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "g...");
  }

  /* TEMPERATURE OUTDOOR (t) - required - "..." as fallback */
  if (!isnan(this->tempF))
  {
    sprintf(tempstring, "t%03.0f", this->tempF);
    strcat(nextAPRS, tempstring);
  }
  else
  {
    strcat(nextAPRS, "t...");
  }

  /* RAIN 1H (r) - not required */
  if (!isnan(this->rain1hIn))
  {
    sprintf(tempstring, "r%03.0f", this->rain1hIn * 100); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* READ RAIN 24H (p) - not required */
  if (!isnan(this->rain24hIn))
  {
    sprintf(tempstring, "p%03.0f", this->rain24hIn * 100); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* RAIN SINCE MIDNIGHT (P) - not required */
  if (!isnan(this->rainSinceMidnightIn))
  {
    sprintf(tempstring, "P%03.0f", this->rainSinceMidnightIn * 100); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* SNOW (s) - not required */
  if (!isnan(this->snow24hIn))
  {
    sprintf(tempstring, "s%03.1f", this->snow24hIn); // hundredths of an inch
    strcat(nextAPRS, tempstring);
  }

  /* RELATIVE HUMIDITY OUTDOOR (h) - not required */
  if (!isnan(this->humidityPct))
  {
    sprintf(tempstring, "h%02.0f", this->humidityPct >= 99.5 ? 0 : this->humidityPct); // report >=99.5 as '00'
    strcat(nextAPRS, tempstring);
  }

  /* BAROMETRIC PRESSURE (b) - not required */
  if (!isnan(this->pressureMb))
  {
    sprintf(tempstring, "b%05.0f", (this->pressureMb * 10)); // tenths of milibars
    strcat(nextAPRS, tempstring);
  }

  /* LUMINOSITY (L/l) - not required */
  if (!isnan(this->luminosityWM2))
  {
    if (round(this->luminosityWM2) < 1000)
    {
      sprintf(tempstring, "L%03.0f", this->luminosityWM2);
    }
    else
    {
      sprintf(tempstring, "l%03.0f", this->luminosityWM2 - 1000);
    }
    strcat(nextAPRS, tempstring);
  }

  /* SOFTWARE TYPE AND ACTION (.) */
  sprintf(tempstring, ".%s%s", CWOP_DEVICE, CWOP_VERSION);
  strcat(nextAPRS, tempstring);
  return nextAPRS;
}

bool CWOP_Particle::writeHeader()
{
  if (!this->client->print(String::format("user %s pass -1 vers %s %s\r\n", this->regNumber.c_str(), CWOP_DEVICE, CWOP_VERSION).c_str()))
    return false;
  return true;
}

bool CWOP_Particle::writeData()
{
  if (!this->client->print(String::format("%s\r\n", this->nextAPRS).c_str()))
    return false;
  return true;
}

int CWOP_Particle::writePacket()
{
  if (!connect())
  {
    // Failed to connect
    return ERR_CONNECT_FAILED;
  }

  if (!this->writeHeader())
    return abortWritePacket();
  this->createAPRS();
  if (!this->writeData())
    return abortWritePacket();

  delay(500); // hopefully this is enough time to send the data.

  if (this->client->available() > 0)
  {
    String connect_msg = this->client->readStringUntil('\r');
#ifdef PRINT_DEBUG_MESSAGES
    Particle.publish(PARTICLE_PUBLISH_TOPIC, String("received message: " + connect_msg), PARTICLE_PUBLISH_TTL, PRIVATE);
#endif
  }

  this->client->stop();

  return OK_SUCCESS;
}

int CWOP_Particle::abortWritePacket()
{
  this->client->stop();
#ifdef PRINT_DEBUG_MESSAGES
  Particle.publish(PARTICLE_PUBLISH_TOPIC, "Aborted packet!", PARTICLE_PUBLISH_TTL, PRIVATE);
#endif
  return ERR_UNEXPECTED_FAIL;
}
<|endoftext|>