<commit_before>//*******************************************************************
//glfont2.cpp -- glFont Version 2.0 implementation
//Copyright (c) 1998-2002 Brad Fish
//See glfont.html for terms of use
//May 14, 2002
//*******************************************************************

//STL headers
#include <string>
#include <utility>
#include <iostream>
#include <fstream>
using namespace std;

//OpenGL headers
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <GL/gl.h>

//glFont header
#include "glfont2.h"
using namespace glfont;

#ifdef __BIG_ENDIAN__
inline void endian_swap(int& x)
{
    x = (x>>24) |
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
}
#endif

//*******************************************************************
//GLFont Class Implementation
//*******************************************************************
GLFont::GLFont ()
{
	//Initialize header to safe state
	header.tex = -1;
	header.tex_width = 0;
	header.tex_height = 0;
	header.start_char = 0;
	header.end_char = 0;
	header.chars = NULL;
}
//*******************************************************************
GLFont::~GLFont ()
{
	//Destroy the font
	Destroy();
}
//*******************************************************************
bool GLFont::Create (const char *file_name, int tex)
{
	ifstream input;
	int num_chars, num_tex_bytes;
	char *tex_bytes;

	//Destroy the old font if there was one, just to be safe
	Destroy();

	//Open input file
	input.open(file_name, ios::in | ios::binary);
	if (!input)
		return false;

	//Read the header from file
	//There is 4 byte space between the header data and the beginning of the
	//characters. this presumably was used to account for the 4 bytes taken
	//up by the pointer to the character array
	//on 64-bit the sizeof(header) is no longer correct and it reads to many
	//bytes
	input.read((char *)&header, sizeof(header) - (sizeof(void*) - 4));
	header.tex = tex;

	//Allocate space for character array
#ifdef __BIG_ENDIAN__
	endian_swap(header.end_char);
	endian_swap(header.start_char);
#endif
	num_chars = header.end_char - header.start_char + 1;
	if ((header.chars = new GLFontChar[num_chars]) == NULL)
		return false;

	//Read character array
	for(int i=0; i < num_chars; i++)
		input.read((char *)&header.chars[i], sizeof(GLFontChar));

	//Read texture pixel data
	num_tex_bytes = header.tex_width * header.tex_height * 2;
	tex_bytes = new char[num_tex_bytes];
	input.read(tex_bytes, num_tex_bytes);

	//Create OpenGL texture
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexImage2D(GL_TEXTURE_2D, 0, 2, header.tex_width,
		header.tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
		(void *)tex_bytes);

	//Free texture pixels memory
	delete[] tex_bytes;

	//Close input file
	input.close();

	//Return successfully

	//Uncomment to print out the data structure. Useful for finding differences between systems

/*	cout << "Start: " << header.start_char << ", End: " << header.end_char << ", Chars: " << header.chars << endl;
	cout << "Height: " << header.tex_height << ", Width: " << header.tex_width << endl;
	//Read character array
	for(int i=header.start_char; i < header.end_char; i++)
	{
		GLFontChar c = header.chars[i - header.start_char];
		cout << "Char: " << i << ", dx: " << c.dx << ", dy: " << c.dy << endl;
		cout << "ty1: " << c.ty1 << ", ty2: " << c.ty2 << ", tx1: " << c.tx1 << ", tx2: " << c.tx2 << endl;
	}*/

	return true;
}
//*******************************************************************
bool GLFont::Create (const std::string &file_name, int tex)
{
	return Create(file_name.c_str(), tex);
}
//*******************************************************************
void GLFont::Destroy (void)
{
	//Delete the character array if necessary
	if (header.chars)
	{
		delete[] header.chars;
		header.chars = NULL;
	}
}
//*******************************************************************
void GLFont::GetTexSize (std::pair<int, int> *size)
{
	//Retrieve texture size
	size->first = header.tex_width;
	size->second = header.tex_height;
}
//*******************************************************************
int GLFont::GetTexWidth (void)
{
	//Return texture width
	return header.tex_width;
}
//*******************************************************************
int GLFont::GetTexHeight (void)
{
	//Return texture height
	return header.tex_height;
}
//*******************************************************************
void GLFont::GetCharInterval (std::pair<int, int> *interval)
{
	//Retrieve character interval
	interval->first = header.start_char;
	interval->second = header.end_char;
}
//*******************************************************************
int GLFont::GetStartChar (void)
{
	//Return start character
	return header.start_char;
}
//*******************************************************************
int GLFont::GetEndChar (void)
{
	//Return end character
	return header.end_char;
}
//*******************************************************************
void GLFont::GetCharSize (int c, std::pair<int, int> *size)
{
	//Make sure character is in range
	if (c < header.start_char || c > header.end_char)
	{
		//Not a valid character, so it obviously has no size
		size->first = 0;
		size->second = 0;
	}
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character size
		glfont_char = &header.chars[c - header.start_char];
		size->first = (int)(glfont_char->dx * header.tex_width);
		size->second = (int)(glfont_char->dy *
			header.tex_height);
	}
}
//*******************************************************************
int GLFont::GetCharWidth (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character width
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dx * header.tex_width);
	}
}
//*******************************************************************
int GLFont::GetCharHeight (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character height
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dy * header.tex_height);
	}
}
//*******************************************************************
void GLFont::Begin (void)
{
	//Bind to font texture
	glBindTexture(GL_TEXTURE_2D, header.tex);
}
//*******************************************************************

wchar_t GLFont::get_unaccented_character( wchar_t c)
{
  switch(c)
  {
    case 225:
    case 224:
      return 'a';
    case 193:
    case 192:
      return 'A';
    case 233:
    case 232:
      return 'e';
    case 201:
    case 200:
      return 'E';
    case 237:
    case 236:
      return 'i';
    case 205:
    case 204:
      return 'I';
    case 243:
    case 242:
      return 'o';
    case 211:
    case 210:
      return 'O';
    case 250:
    case 249:
      return 'u';
    case 218:
    case 217:
      return 'U';
    case 241:
      return 'n';
    case 209:
      return 'N';
    case 252:
      return 'u';
    case 220:
      return 'U';
    default:
      return c;
  }
}

//End of file

<commit_msg>GLFont2: remove accent from ê and Ê<commit_after>//*******************************************************************
//glfont2.cpp -- glFont Version 2.0 implementation
//Copyright (c) 1998-2002 Brad Fish
//See glfont.html for terms of use
//May 14, 2002
//*******************************************************************

//STL headers
#include <string>
#include <utility>
#include <iostream>
#include <fstream>
using namespace std;

//OpenGL headers
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <GL/gl.h>

//glFont header
#include "glfont2.h"
using namespace glfont;

#ifdef __BIG_ENDIAN__
inline void endian_swap(int& x)
{
    x = (x>>24) |
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
}
#endif

//*******************************************************************
//GLFont Class Implementation
//*******************************************************************
GLFont::GLFont ()
{
	//Initialize header to safe state
	header.tex = -1;
	header.tex_width = 0;
	header.tex_height = 0;
	header.start_char = 0;
	header.end_char = 0;
	header.chars = NULL;
}
//*******************************************************************
GLFont::~GLFont ()
{
	//Destroy the font
	Destroy();
}
//*******************************************************************
bool GLFont::Create (const char *file_name, int tex)
{
	ifstream input;
	int num_chars, num_tex_bytes;
	char *tex_bytes;

	//Destroy the old font if there was one, just to be safe
	Destroy();

	//Open input file
	input.open(file_name, ios::in | ios::binary);
	if (!input)
		return false;

	//Read the header from file
	//There is 4 byte space between the header data and the beginning of the
	//characters. this presumably was used to account for the 4 bytes taken
	//up by the pointer to the character array
	//on 64-bit the sizeof(header) is no longer correct and it reads to many
	//bytes
	input.read((char *)&header, sizeof(header) - (sizeof(void*) - 4));
	header.tex = tex;

	//Allocate space for character array
#ifdef __BIG_ENDIAN__
	endian_swap(header.end_char);
	endian_swap(header.start_char);
#endif
	num_chars = header.end_char - header.start_char + 1;
	if ((header.chars = new GLFontChar[num_chars]) == NULL)
		return false;

	//Read character array
	for(int i=0; i < num_chars; i++)
		input.read((char *)&header.chars[i], sizeof(GLFontChar));

	//Read texture pixel data
	num_tex_bytes = header.tex_width * header.tex_height * 2;
	tex_bytes = new char[num_tex_bytes];
	input.read(tex_bytes, num_tex_bytes);

	//Create OpenGL texture
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexImage2D(GL_TEXTURE_2D, 0, 2, header.tex_width,
		header.tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
		(void *)tex_bytes);

	//Free texture pixels memory
	delete[] tex_bytes;

	//Close input file
	input.close();

	//Return successfully

	//Uncomment to print out the data structure. Useful for finding differences between systems

/*	cout << "Start: " << header.start_char << ", End: " << header.end_char << ", Chars: " << header.chars << endl;
	cout << "Height: " << header.tex_height << ", Width: " << header.tex_width << endl;
	//Read character array
	for(int i=header.start_char; i < header.end_char; i++)
	{
		GLFontChar c = header.chars[i - header.start_char];
		cout << "Char: " << i << ", dx: " << c.dx << ", dy: " << c.dy << endl;
		cout << "ty1: " << c.ty1 << ", ty2: " << c.ty2 << ", tx1: " << c.tx1 << ", tx2: " << c.tx2 << endl;
	}*/

	return true;
}
//*******************************************************************
bool GLFont::Create (const std::string &file_name, int tex)
{
	return Create(file_name.c_str(), tex);
}
//*******************************************************************
void GLFont::Destroy (void)
{
	//Delete the character array if necessary
	if (header.chars)
	{
		delete[] header.chars;
		header.chars = NULL;
	}
}
//*******************************************************************
void GLFont::GetTexSize (std::pair<int, int> *size)
{
	//Retrieve texture size
	size->first = header.tex_width;
	size->second = header.tex_height;
}
//*******************************************************************
int GLFont::GetTexWidth (void)
{
	//Return texture width
	return header.tex_width;
}
//*******************************************************************
int GLFont::GetTexHeight (void)
{
	//Return texture height
	return header.tex_height;
}
//*******************************************************************
void GLFont::GetCharInterval (std::pair<int, int> *interval)
{
	//Retrieve character interval
	interval->first = header.start_char;
	interval->second = header.end_char;
}
//*******************************************************************
int GLFont::GetStartChar (void)
{
	//Return start character
	return header.start_char;
}
//*******************************************************************
int GLFont::GetEndChar (void)
{
	//Return end character
	return header.end_char;
}
//*******************************************************************
void GLFont::GetCharSize (int c, std::pair<int, int> *size)
{
	//Make sure character is in range
	if (c < header.start_char || c > header.end_char)
	{
		//Not a valid character, so it obviously has no size
		size->first = 0;
		size->second = 0;
	}
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character size
		glfont_char = &header.chars[c - header.start_char];
		size->first = (int)(glfont_char->dx * header.tex_width);
		size->second = (int)(glfont_char->dy *
			header.tex_height);
	}
}
//*******************************************************************
int GLFont::GetCharWidth (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character width
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dx * header.tex_width);
	}
}
//*******************************************************************
int GLFont::GetCharHeight (int c)
{
	//Make sure in range
	if (c < header.start_char || c > header.end_char)
		return 0;
	else
	{
		GLFontChar *glfont_char;

		//Retrieve character height
		glfont_char = &header.chars[c - header.start_char];
		return (int)(glfont_char->dy * header.tex_height);
	}
}
//*******************************************************************
void GLFont::Begin (void)
{
	//Bind to font texture
	glBindTexture(GL_TEXTURE_2D, header.tex);
}
//*******************************************************************

wchar_t GLFont::get_unaccented_character( wchar_t c)
{
  switch(c)
  {
    case 225:
    case 224:
      return 'a';
    case 193:
    case 192:
      return 'A';
    case 234:
    case 233:
    case 232:
      return 'e';
    case 202:
    case 201:
    case 200:
      return 'E';
    case 237:
    case 236:
      return 'i';
    case 205:
    case 204:
      return 'I';
    case 243:
    case 242:
      return 'o';
    case 211:
    case 210:
      return 'O';
    case 250:
    case 249:
      return 'u';
    case 218:
    case 217:
      return 'U';
    case 241:
      return 'n';
    case 209:
      return 'N';
    case 252:
      return 'u';
    case 220:
      return 'U';
    default:
      return c;
  }
}

//End of file

<|endoftext|>


<commit_before>// GRSimpleVals.cpp - Transfer functions for tracking simple values -*- C++ -*--
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines GRSimpleVals, a sub-class of GRTransferFuncs that
//  provides transfer functions for performing simple value tracking with
//  limited support for symbolics.
//
//===----------------------------------------------------------------------===//

#include "GRSimpleVals.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Basic/Diagnostic.h"
#include <sstream>

using namespace clang;

namespace clang {

template <typename ITERATOR>
static inline const PostStmt& GetLocation(ITERATOR I) {
  return cast<PostStmt>((*I)->getLocation());
}

template <>
static inline const PostStmt& GetLocation(GRExprEngine::undef_arg_iterator I) {
  return cast<PostStmt>(I->first->getLocation());
}

template <typename ITERATOR>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, ITERATOR I) {

  Expr* Exp = cast<Expr>(GetLocation(I).getStmt());
  cast<Expr>(GetLocation(I).getStmt());
  Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag);
}

template <>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, GRExprEngine::undef_arg_iterator I) {

  Expr* E1 = cast<Expr>(GetLocation(I).getStmt());
  Expr* E2 = cast<Expr>(I->second);

  SourceLocation Loc = E1->getExprLoc();
  SourceRange R = E2->getSourceRange();
  Diag.Report(FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1);
}

template <typename ITERATOR>
static void EmitWarning(Diagnostic& Diag, SourceManager& SrcMgr,
                        ITERATOR I, ITERATOR E, const char* msg) {

  std::ostringstream Out;
  Out << "[CHECKER] " << msg;
  msg = Out.str().c_str();

  bool isFirst = true;
  unsigned ErrorDiag;
  llvm::SmallPtrSet<void*,10> CachedErrors;

  for (; I != E; ++I) {

    if (isFirst) {
      isFirst = false;
      ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
    }
    else {

      // HACK: Cache the location of the error.  Don't emit the same
      // warning for the same error type that occurs at the same program
      // location but along a different path.
      void* p = GetLocation(I).getRawData();

      if (CachedErrors.count(p))
        continue;

      CachedErrors.insert(p);
    }

    EmitDiag(Diag, SrcMgr, ErrorDiag, I);
  }
}

unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
                         Diagnostic& Diag, bool Visualize, bool TrimGraph) {

  if (Diag.hasErrorOccurred())
    return 0;

  GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
  GRExprEngine* CheckerState = &Engine.getCheckerState();
  GRSimpleVals GRSV;
  CheckerState->setTransferFunctions(GRSV);

  // Execute the worklist algorithm.
  Engine.ExecuteWorkList(20000);

  SourceManager& SrcMgr = Ctx.getSourceManager();

  EmitWarning(Diag, SrcMgr,
              CheckerState->null_derefs_begin(),
              CheckerState->null_derefs_end(),
              "NULL pointer is dereferenced after it is checked for NULL.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->explicit_bad_divides_begin(),
              CheckerState->explicit_bad_divides_end(),
              "Division by zero/undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_results_begin(),
              CheckerState->undef_results_end(),
              "Result of operation is undefined.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->bad_calls_begin(),
              CheckerState->bad_calls_end(),
              "Call using a NULL or undefined function pointer value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_arg_begin(),
              CheckerState->undef_arg_end(),
      "Pass-by-value argument in function or message expression is undefined.");

#ifndef NDEBUG
  if (Visualize) CheckerState->ViewGraph(TrimGraph);
#endif

  return Engine.getGraph().size();
}

} // end clang namespace

//===----------------------------------------------------------------------===//
// Transfer function for Casts.
//===----------------------------------------------------------------------===//

RVal GRSimpleVals::EvalCast(BasicValueFactory& BasicVals, NonLVal X, QualType T) {

  if (!isa<nonlval::ConcreteInt>(X))
    return UnknownVal();

  llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(BasicVals.getContext().getTypeSize(T));

  if (T->isPointerType())
    return lval::ConcreteInt(BasicVals.getValue(V));
  else
    return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Casts.

RVal GRSimpleVals::EvalCast(BasicValueFactory& BasicVals, LVal X, QualType T) {

  if (T->isPointerType() || T->isReferenceType())
    return X;

  assert (T->isIntegerType());

  if (!isa<lval::ConcreteInt>(X))
    return UnknownVal();

  llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(BasicVals.getContext().getTypeSize(T));

  return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Unary operators.

RVal GRSimpleVals::EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U, NonLVal X){

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalMinus(BasicVals, U);

    default:
      return UnknownVal();
  }
}

RVal GRSimpleVals::EvalComplement(BasicValueFactory& BasicVals, NonLVal X) {

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalComplement(BasicVals);

    default:
      return UnknownVal();
  }
}

// Binary operators.

RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                             NonLVal L, NonLVal R)  {
  while (1) {

    switch (L.getSubKind()) {
      default:
        return UnknownVal();

      case nonlval::ConcreteIntKind:

        if (isa<nonlval::ConcreteInt>(R)) {
          const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
          const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
          return L_CI.EvalBinOp(BasicVals, Op, R_CI);
        }
        else {
          NonLVal tmp = R;
          R = L;
          L = tmp;
          continue;
        }

      case nonlval::SymbolValKind: {

        if (isa<nonlval::ConcreteInt>(R)) {
          const SymIntConstraint& C =
            BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
                                 cast<nonlval::ConcreteInt>(R).getValue());

          return nonlval::SymIntConstraintVal(C);
        }
        else
          return UnknownVal();
      }
    }
  }
}

// Binary Operators (except assignments and comma).

RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                             LVal L, LVal R) {

  switch (Op) {

    default:
      return UnknownVal();

    case BinaryOperator::EQ:
      return EvalEQ(BasicVals, L, R);

    case BinaryOperator::NE:
      return EvalNE(BasicVals, L, R);
  }
}

// Pointer arithmetic.

RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                             LVal L, NonLVal R) {
  return UnknownVal();
}

// Equality operators for LVals.

RVal GRSimpleVals::EvalEQ(BasicValueFactory& BasicVals, LVal L, LVal R) {

  switch (L.getSubKind()) {

    default:
      assert(false && "EQ not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() ==
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {

        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {

      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement == for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L == R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, false);
}

RVal GRSimpleVals::EvalNE(BasicValueFactory& BasicVals, LVal L, LVal R) {

  switch (L.getSubKind()) {

    default:
      assert(false && "NE not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() !=
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                               BinaryOperator::NE,
                               cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {
      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                               BinaryOperator::NE,
                               cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement != for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();

      break;
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L != R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, true);
}

//===----------------------------------------------------------------------===//
// Transfer function for Function Calls.
//===----------------------------------------------------------------------===//

void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
                            ValueStateManager& StateMgr,
                            GRStmtNodeBuilder<ValueState>& Builder,
                            BasicValueFactory& BasicVals,
                            CallExpr* CE, LVal L,
                            ExplodedNode<ValueState>* Pred) {

  ValueState* St = Pred->getState();

  // Invalidate all arguments passed in by reference (LVals).

  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
        I != E; ++I) {

    RVal V = StateMgr.GetRVal(St, *I);

    if (isa<LVal>(V))
      St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
  }

  Builder.Nodify(Dst, CE, Pred, St);
}
<commit_msg>Increased worklist limit for GRSimpleVals.<commit_after>// GRSimpleVals.cpp - Transfer functions for tracking simple values -*- C++ -*--
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines GRSimpleVals, a sub-class of GRTransferFuncs that
//  provides transfer functions for performing simple value tracking with
//  limited support for symbolics.
//
//===----------------------------------------------------------------------===//

#include "GRSimpleVals.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Basic/Diagnostic.h"
#include <sstream>

using namespace clang;

namespace clang {

template <typename ITERATOR>
static inline const PostStmt& GetLocation(ITERATOR I) {
  return cast<PostStmt>((*I)->getLocation());
}

template <>
static inline const PostStmt& GetLocation(GRExprEngine::undef_arg_iterator I) {
  return cast<PostStmt>(I->first->getLocation());
}

template <typename ITERATOR>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, ITERATOR I) {

  Expr* Exp = cast<Expr>(GetLocation(I).getStmt());
  cast<Expr>(GetLocation(I).getStmt());
  Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag);
}

template <>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, GRExprEngine::undef_arg_iterator I) {

  Expr* E1 = cast<Expr>(GetLocation(I).getStmt());
  Expr* E2 = cast<Expr>(I->second);

  SourceLocation Loc = E1->getExprLoc();
  SourceRange R = E2->getSourceRange();
  Diag.Report(FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1);
}

template <typename ITERATOR>
static void EmitWarning(Diagnostic& Diag, SourceManager& SrcMgr,
                        ITERATOR I, ITERATOR E, const char* msg) {

  std::ostringstream Out;
  Out << "[CHECKER] " << msg;
  msg = Out.str().c_str();

  bool isFirst = true;
  unsigned ErrorDiag;
  llvm::SmallPtrSet<void*,10> CachedErrors;

  for (; I != E; ++I) {

    if (isFirst) {
      isFirst = false;
      ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
    }
    else {

      // HACK: Cache the location of the error.  Don't emit the same
      // warning for the same error type that occurs at the same program
      // location but along a different path.
      void* p = GetLocation(I).getRawData();

      if (CachedErrors.count(p))
        continue;

      CachedErrors.insert(p);
    }

    EmitDiag(Diag, SrcMgr, ErrorDiag, I);
  }
}

unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
                         Diagnostic& Diag, bool Visualize, bool TrimGraph) {

  if (Diag.hasErrorOccurred())
    return 0;

  GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
  GRExprEngine* CheckerState = &Engine.getCheckerState();
  GRSimpleVals GRSV;
  CheckerState->setTransferFunctions(GRSV);

  // Execute the worklist algorithm.
  Engine.ExecuteWorkList(50000);

  SourceManager& SrcMgr = Ctx.getSourceManager();

  EmitWarning(Diag, SrcMgr,
              CheckerState->null_derefs_begin(),
              CheckerState->null_derefs_end(),
              "NULL pointer is dereferenced after it is checked for NULL.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->explicit_bad_divides_begin(),
              CheckerState->explicit_bad_divides_end(),
              "Division by zero/undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_results_begin(),
              CheckerState->undef_results_end(),
              "Result of operation is undefined.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->bad_calls_begin(),
              CheckerState->bad_calls_end(),
              "Call using a NULL or undefined function pointer value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_arg_begin(),
              CheckerState->undef_arg_end(),
      "Pass-by-value argument in function or message expression is undefined.");

#ifndef NDEBUG
  if (Visualize) CheckerState->ViewGraph(TrimGraph);
#endif

  return Engine.getGraph().size();
}

} // end clang namespace

//===----------------------------------------------------------------------===//
// Transfer function for Casts.
//===----------------------------------------------------------------------===//

RVal GRSimpleVals::EvalCast(BasicValueFactory& BasicVals, NonLVal X, QualType T) {

  if (!isa<nonlval::ConcreteInt>(X))
    return UnknownVal();

  llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(BasicVals.getContext().getTypeSize(T));

  if (T->isPointerType())
    return lval::ConcreteInt(BasicVals.getValue(V));
  else
    return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Casts.

RVal GRSimpleVals::EvalCast(BasicValueFactory& BasicVals, LVal X, QualType T) {

  if (T->isPointerType() || T->isReferenceType())
    return X;

  assert (T->isIntegerType());

  if (!isa<lval::ConcreteInt>(X))
    return UnknownVal();

  llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(BasicVals.getContext().getTypeSize(T));

  return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Unary operators.

RVal GRSimpleVals::EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U, NonLVal X){

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalMinus(BasicVals, U);

    default:
      return UnknownVal();
  }
}

RVal GRSimpleVals::EvalComplement(BasicValueFactory& BasicVals, NonLVal X) {

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalComplement(BasicVals);

    default:
      return UnknownVal();
  }
}

// Binary operators.

RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                             NonLVal L, NonLVal R)  {
  while (1) {

    switch (L.getSubKind()) {
      default:
        return UnknownVal();

      case nonlval::ConcreteIntKind:

        if (isa<nonlval::ConcreteInt>(R)) {
          const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
          const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
          return L_CI.EvalBinOp(BasicVals, Op, R_CI);
        }
        else {
          NonLVal tmp = R;
          R = L;
          L = tmp;
          continue;
        }

      case nonlval::SymbolValKind: {

        if (isa<nonlval::ConcreteInt>(R)) {
          const SymIntConstraint& C =
            BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
                                 cast<nonlval::ConcreteInt>(R).getValue());

          return nonlval::SymIntConstraintVal(C);
        }
        else
          return UnknownVal();
      }
    }
  }
}

// Binary Operators (except assignments and comma).

RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                             LVal L, LVal R) {

  switch (Op) {

    default:
      return UnknownVal();

    case BinaryOperator::EQ:
      return EvalEQ(BasicVals, L, R);

    case BinaryOperator::NE:
      return EvalNE(BasicVals, L, R);
  }
}

// Pointer arithmetic.

RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
                             LVal L, NonLVal R) {
  return UnknownVal();
}

// Equality operators for LVals.

RVal GRSimpleVals::EvalEQ(BasicValueFactory& BasicVals, LVal L, LVal R) {

  switch (L.getSubKind()) {

    default:
      assert(false && "EQ not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() ==
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {

        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {

      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement == for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L == R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, false);
}

RVal GRSimpleVals::EvalNE(BasicValueFactory& BasicVals, LVal L, LVal R) {

  switch (L.getSubKind()) {

    default:
      assert(false && "NE not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() !=
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                               BinaryOperator::NE,
                               cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {
      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                               BinaryOperator::NE,
                               cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement != for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();

      break;
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L != R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, true);
}

//===----------------------------------------------------------------------===//
// Transfer function for Function Calls.
//===----------------------------------------------------------------------===//

void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
                            ValueStateManager& StateMgr,
                            GRStmtNodeBuilder<ValueState>& Builder,
                            BasicValueFactory& BasicVals,
                            CallExpr* CE, LVal L,
                            ExplodedNode<ValueState>* Pred) {

  ValueState* St = Pred->getState();

  // Invalidate all arguments passed in by reference (LVals).

  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
        I != E; ++I) {

    RVal V = StateMgr.GetRVal(St, *I);

    if (isa<LVal>(V))
      St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
  }

  Builder.Nodify(Dst, CE, Pred, St);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013 libwallet developers (see AUTHORS)
 *
 * This file is part of libwallet.
 *
 * libwallet is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <wallet/define.hpp>
#include <wallet/hd_keys.hpp>

#ifdef USE_OPENSSL_EC
#include <openssl/ec.h>
#endif
#ifdef USE_OPENSSL_HM
#include <openssl/hmac.h>
#endif
#ifdef USE_OPENSSL_BN
#include <openssl/bn.h>
#endif

#include <algorithm>
#include <bitcoin/bitcoin.hpp>

namespace libwallet {

template<typename T, void destroy(T* p)>
class auto_free
{
public:
    auto_free(T* p)
      : ptr(p)
    {
    }
    ~auto_free()
    {
        destroy(ptr);
    }
    operator T*()
    {
        return ptr;
    }
    T* ptr;
};

typedef auto_free<BIGNUM, BN_free> ssl_bignum;
typedef auto_free<BN_CTX, BN_CTX_free> ssl_bn_ctx;

// ****************************************************************************
typedef auto_free<EC_GROUP, EC_GROUP_free> ssl_ec_group;
typedef auto_free<EC_POINT, EC_POINT_free> ssl_ec_point;

secret_parameter secp256k1_n
{
    {
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
        0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
        0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
    }
};
// ****************************************************************************

constexpr uint32_t mainnet_private_prefix = 0x0488ADE4;
constexpr uint32_t mainnet_public_prefix = 0x0488B21E;
constexpr uint32_t testnet_private_prefix = 0x04358394;
constexpr uint32_t testnet_public_prefix = 0x043587CF;

static data_chunk secret_to_public_key(const secret_parameter& secret)
{
    elliptic_curve_key key;
    key.set_compressed(true);
    key.set_secret(secret);
    return key.public_key();
}

/**
 * Corresponds to a split HMAC-SHA256 result, as used in BIP 32.
 */

// long_hash is used for hmac_sha512 in libbitcoin
constexpr size_t half_hmac_sha512_size = long_hash_size / 2;
typedef std::array<uint8_t, half_hmac_sha512_size> half_long_hash;

struct split_long_hash
{
    half_long_hash left;
    half_long_hash right;
};

static split_long_hash split(long_hash& hmac)
{
    split_long_hash split;

    std::copy(hmac.begin(), hmac.begin() + half_hmac_sha512_size,
        split.left.begin());

    std::copy(hmac.begin() + half_hmac_sha512_size, hmac.end(),
        split.right.begin());

    return split;
}

static long_hash hmac_sha512(
    const uint8_t* key, size_t key_length, const data_chunk& data)
{
    // TODO: determine if this should be key_data(key, key + key_length - 1)
    data_chunk key_data(key, key + key_length);
    return libbitcoin::hmac_sha512_hash(data, key_data);
}

static ser32_type ser32(uint32_t i)
{
    ser32_type out;
    out[0] = 0xff & (i >> 24);
    out[1] = 0xff & (i >> 16);
    out[2] = 0xff & (i >> 8);
    out[3] = 0xff & i;
    return out;
}

BCW_API hd_public_key::hd_public_key()
  : valid_(false)
{
}

BCW_API hd_public_key::hd_public_key(const data_chunk& public_key,
    const chain_code_type& chain_code, hd_key_lineage lineage)
  : valid_(true), K_(public_key), c_(chain_code), lineage_(lineage)
{
}

BCW_API bool hd_public_key::valid() const
{
    return valid_;
}

BCW_API const data_chunk& hd_public_key::public_key() const
{
    return K_;
}

BCW_API const chain_code_type& hd_public_key::chain_code() const
{
    return c_;
}

BCW_API const hd_key_lineage& hd_public_key::lineage() const
{
    return lineage_;
}

BCW_API std::string hd_public_key::serialize() const
{
    data_chunk data;
    data.reserve(4 + 1 + 4 + 4 + 32 + 33 + 4);

    extend_data(data, ser32(lineage_.testnet ? testnet_public_prefix :
        mainnet_public_prefix));
    data.push_back(lineage_.depth);
    extend_data(data, lineage_.parent_fingerprint);
    extend_data(data, ser32(lineage_.child_number));
    extend_data(data, c_);
    extend_data(data, K_);

    extend_data(data, uncast_type(bitcoin_checksum(data)));
    return encode_base58(data);
}

BCW_API ser32_type hd_public_key::fingerprint() const
{
    short_hash md = bitcoin_short_hash(K_);
    return ser32_type{ { md[0], md[1], md[2], md[3] } };
}

BCW_API payment_address hd_public_key::address() const
{
    payment_address address;
    set_public_key(address, K_);
    return address;
}

BCW_API hd_public_key hd_public_key::generate_public_key(uint32_t i)
{
    if (!valid_)
        return hd_private_key();
    if (first_hardened_key <= i)
        return hd_public_key();

    data_chunk data;
    data.reserve(33 + 4);
    extend_data(data, K_);
    extend_data(data, ser32(i));
    auto I = split(hmac_sha512(c_.data(), (int)c_.size(), data));

    // ************************************************************************
    // The returned child key Ki is point(parse256(IL)) + Kpar.
    ssl_ec_group group = EC_GROUP_new_by_curve_name(NID_secp256k1);

    if (!group)
        return hd_public_key();

    ssl_bn_ctx ctx = BN_CTX_new();
    ssl_ec_point Ki = EC_POINT_new(group);
    ssl_ec_point Kpar = EC_POINT_new(group);
    ssl_ec_point IL = EC_POINT_new(group);

    ssl_bignum il = BN_bin2bn(I.left.data(), (int)I.left.size(), nullptr);
    ssl_bignum n = BN_bin2bn(secp256k1_n.data(), (int)secp256k1_n.size(),
        nullptr);

    if (!ctx || !Ki || !Kpar || !IL || !il || !n)
        return hd_public_key();

    if (!EC_POINT_oct2point(group, Kpar, K_.data(), K_.size(), ctx))
        return hd_public_key();
    if (!EC_POINT_mul(group, IL, il, nullptr, nullptr, ctx))
        return hd_public_key();
    if (!EC_POINT_add(group, Ki, IL, Kpar, ctx))
        return hd_public_key();

    // The key is invalid if parse256(IL) >= n or Ki is at infinity:
    if (0 <= BN_cmp(il, n) || EC_POINT_is_at_infinity(group, Ki))
        return hd_private_key();

    size_t Ki_size = EC_POINT_point2oct(group, Ki, POINT_CONVERSION_COMPRESSED,
        NULL, 0, ctx);

    data_chunk out(Ki_size);
    if (!EC_POINT_point2oct(group, Ki, POINT_CONVERSION_COMPRESSED, out.data(),
        out.size(), ctx))
        return hd_public_key();
    // ************************************************************************

    hd_key_lineage lineage = hd_key_lineage{ lineage_.testnet,
        static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i };

    return hd_public_key(out, I.right, lineage);
}

BCW_API hd_private_key::hd_private_key()
  : hd_public_key()
{
}

BCW_API hd_private_key::hd_private_key(const secret_parameter& private_key,
    const chain_code_type& chain_code, hd_key_lineage lineage)
  : hd_public_key(secret_to_public_key(private_key), chain_code, lineage),
    k_(private_key)
{
}

BCW_API hd_private_key::hd_private_key(const data_chunk& seed, bool testnet)
  : hd_public_key()
{
    constexpr uint32_t key_length = 13;
    const uint8_t hmac_key[key_length] = "Bitcoin seed";

    split_long_hash I = split(hmac_sha512(hmac_key, key_length, seed));
    ssl_bignum il = BN_bin2bn(I.left.data(), (int)I.left.size(), nullptr);

    // ************************************************************************
    ssl_bignum n = BN_bin2bn(secp256k1_n.data(), (int)secp256k1_n.size(),
        nullptr);
    // ************************************************************************

    // The key is invalid if parse256(IL) >= n or 0:
    if (0 <= BN_cmp(il, n) || BN_is_zero(il.ptr))
        return;

    hd_key_lineage null_seed = hd_key_lineage{ testnet, 0, { { 0 } }, 0 };

    *this = hd_private_key(I.left, I.right, null_seed);
}

BCW_API const secret_parameter& hd_private_key::private_key() const
{
    return k_;
}

BCW_API std::string hd_private_key::serialize() const
{
    data_chunk data;
    data.reserve(4 + 1 + 4 + 4 + 32 + 33 + 4);

    extend_data(data, ser32(lineage_.testnet ? testnet_private_prefix :
        mainnet_private_prefix));
    data.push_back(lineage_.depth);
    extend_data(data, lineage_.parent_fingerprint);
    extend_data(data, ser32(lineage_.child_number));
    extend_data(data, c_);
    data.push_back(0x00);
    extend_data(data, k_);

    extend_data(data, uncast_type(bitcoin_checksum(data)));
    return encode_base58(data);
}

BCW_API hd_private_key hd_private_key::generate_private_key(uint32_t i)
{
    if (!valid_)
        return hd_private_key();

    data_chunk data;
    data.reserve(33 + 4);
    if (first_hardened_key <= i)
    {
        data.push_back(0x00);
        extend_data(data, k_);
        extend_data(data, ser32(i));
    }
    else
    {
        extend_data(data, K_);
        extend_data(data, ser32(i));
    }

    auto I = split(hmac_sha512(c_.data(), (int)c_.size(), data));

    // The child key ki is (parse256(IL) + kpar) mod n:
    ssl_bn_ctx ctx = BN_CTX_new();
    ssl_bignum ki = BN_new();
    ssl_bignum kpar = BN_bin2bn(k_.data(), (int)k_.size(), nullptr);
    ssl_bignum il = BN_bin2bn(I.left.data(), (int)I.left.size(), nullptr);

    // ************************************************************************
    ssl_bignum n = BN_bin2bn(secp256k1_n.data(), (int)secp256k1_n.size(),
        nullptr);
    // ************************************************************************

    if (!ctx || !ki || !kpar || !il || !n)
        return hd_private_key();

    if (!BN_mod_add(ki, kpar, il, n, ctx))
        return hd_private_key();

    // The key is invalid if parse256(IL) >= n or ki == 0:
    if (0 <= BN_cmp(il, n) || BN_is_zero(ki.ptr))
        return hd_private_key();

    secret_parameter out{ { 0 } };
    int ki_size = BN_num_bytes(ki);
    if (ki_size != BN_bn2bin(ki, &out[out.size() - ki_size]))
        return hd_private_key();

    hd_key_lineage lineage = hd_key_lineage
    {
        lineage_.testnet,
        static_cast<uint8_t>(lineage_.depth + 1),
        fingerprint(),
        i
    };

    return hd_private_key(out, I.right, lineage);
}

BCW_API hd_public_key hd_private_key::generate_public_key(uint32_t i)
{
    return generate_private_key(i);
}

} // libwallet

<commit_msg>change parameter to const<commit_after>/*
 * Copyright (c) 2011-2013 libwallet developers (see AUTHORS)
 *
 * This file is part of libwallet.
 *
 * libwallet is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <wallet/define.hpp>
#include <wallet/hd_keys.hpp>

#ifdef USE_OPENSSL_EC
#include <openssl/ec.h>
#endif
#ifdef USE_OPENSSL_HM
#include <openssl/hmac.h>
#endif
#ifdef USE_OPENSSL_BN
#include <openssl/bn.h>
#endif

#include <algorithm>
#include <bitcoin/bitcoin.hpp>

namespace libwallet {

template<typename T, void destroy(T* p)>
class auto_free
{
public:
    auto_free(T* p)
      : ptr(p)
    {
    }
    ~auto_free()
    {
        destroy(ptr);
    }
    operator T*()
    {
        return ptr;
    }
    T* ptr;
};

typedef auto_free<BIGNUM, BN_free> ssl_bignum;
typedef auto_free<BN_CTX, BN_CTX_free> ssl_bn_ctx;

// ****************************************************************************
typedef auto_free<EC_GROUP, EC_GROUP_free> ssl_ec_group;
typedef auto_free<EC_POINT, EC_POINT_free> ssl_ec_point;

secret_parameter secp256k1_n
{
    {
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
        0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
        0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
    }
};
// ****************************************************************************

constexpr uint32_t mainnet_private_prefix = 0x0488ADE4;
constexpr uint32_t mainnet_public_prefix = 0x0488B21E;
constexpr uint32_t testnet_private_prefix = 0x04358394;
constexpr uint32_t testnet_public_prefix = 0x043587CF;

static data_chunk secret_to_public_key(const secret_parameter& secret)
{
    elliptic_curve_key key;
    key.set_compressed(true);
    key.set_secret(secret);
    return key.public_key();
}

/**
 * Corresponds to a split HMAC-SHA256 result, as used in BIP 32.
 */

// long_hash is used for hmac_sha512 in libbitcoin
constexpr size_t half_hmac_sha512_size = long_hash_size / 2;
typedef std::array<uint8_t, half_hmac_sha512_size> half_long_hash;

struct split_long_hash
{
    half_long_hash left;
    half_long_hash right;
};

static split_long_hash split(const long_hash& hmac)
{
    split_long_hash split;

    std::copy(hmac.begin(), hmac.begin() + half_hmac_sha512_size,
        split.left.begin());

    std::copy(hmac.begin() + half_hmac_sha512_size, hmac.end(),
        split.right.begin());

    return split;
}

static long_hash hmac_sha512(const uint8_t* key, size_t key_length,
    const data_chunk& data)
{
    // TODO: determine if this should be key_data(key, key + key_length - 1)
    data_chunk key_data(key, key + key_length);
    return libbitcoin::hmac_sha512_hash(data, key_data);
}

static ser32_type ser32(uint32_t i)
{
    ser32_type out;
    out[0] = 0xff & (i >> 24);
    out[1] = 0xff & (i >> 16);
    out[2] = 0xff & (i >> 8);
    out[3] = 0xff & i;
    return out;
}

BCW_API hd_public_key::hd_public_key()
  : valid_(false)
{
}

BCW_API hd_public_key::hd_public_key(const data_chunk& public_key,
    const chain_code_type& chain_code, hd_key_lineage lineage)
  : valid_(true), K_(public_key), c_(chain_code), lineage_(lineage)
{
}

BCW_API bool hd_public_key::valid() const
{
    return valid_;
}

BCW_API const data_chunk& hd_public_key::public_key() const
{
    return K_;
}

BCW_API const chain_code_type& hd_public_key::chain_code() const
{
    return c_;
}

BCW_API const hd_key_lineage& hd_public_key::lineage() const
{
    return lineage_;
}

BCW_API std::string hd_public_key::serialize() const
{
    data_chunk data;
    data.reserve(4 + 1 + 4 + 4 + 32 + 33 + 4);

    extend_data(data, ser32(lineage_.testnet ? testnet_public_prefix :
        mainnet_public_prefix));
    data.push_back(lineage_.depth);
    extend_data(data, lineage_.parent_fingerprint);
    extend_data(data, ser32(lineage_.child_number));
    extend_data(data, c_);
    extend_data(data, K_);

    extend_data(data, uncast_type(bitcoin_checksum(data)));
    return encode_base58(data);
}

BCW_API ser32_type hd_public_key::fingerprint() const
{
    short_hash md = bitcoin_short_hash(K_);
    return ser32_type{ { md[0], md[1], md[2], md[3] } };
}

BCW_API payment_address hd_public_key::address() const
{
    payment_address address;
    set_public_key(address, K_);
    return address;
}

BCW_API hd_public_key hd_public_key::generate_public_key(uint32_t i)
{
    if (!valid_)
        return hd_private_key();
    if (first_hardened_key <= i)
        return hd_public_key();

    data_chunk data;
    data.reserve(33 + 4);
    extend_data(data, K_);
    extend_data(data, ser32(i));
    auto I = split(hmac_sha512(c_.data(), (int)c_.size(), data));

    // ************************************************************************
    // The returned child key Ki is point(parse256(IL)) + Kpar.
    ssl_ec_group group = EC_GROUP_new_by_curve_name(NID_secp256k1);

    if (!group)
        return hd_public_key();

    ssl_bn_ctx ctx = BN_CTX_new();
    ssl_ec_point Ki = EC_POINT_new(group);
    ssl_ec_point Kpar = EC_POINT_new(group);
    ssl_ec_point IL = EC_POINT_new(group);

    ssl_bignum il = BN_bin2bn(I.left.data(), (int)I.left.size(), nullptr);
    ssl_bignum n = BN_bin2bn(secp256k1_n.data(), (int)secp256k1_n.size(),
        nullptr);

    if (!ctx || !Ki || !Kpar || !IL || !il || !n)
        return hd_public_key();

    if (!EC_POINT_oct2point(group, Kpar, K_.data(), K_.size(), ctx))
        return hd_public_key();
    if (!EC_POINT_mul(group, IL, il, nullptr, nullptr, ctx))
        return hd_public_key();
    if (!EC_POINT_add(group, Ki, IL, Kpar, ctx))
        return hd_public_key();

    // The key is invalid if parse256(IL) >= n or Ki is at infinity:
    if (0 <= BN_cmp(il, n) || EC_POINT_is_at_infinity(group, Ki))
        return hd_private_key();

    size_t Ki_size = EC_POINT_point2oct(group, Ki, POINT_CONVERSION_COMPRESSED,
        NULL, 0, ctx);

    data_chunk out(Ki_size);
    if (!EC_POINT_point2oct(group, Ki, POINT_CONVERSION_COMPRESSED, out.data(),
        out.size(), ctx))
        return hd_public_key();
    // ************************************************************************

    hd_key_lineage lineage = hd_key_lineage{ lineage_.testnet,
        static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i };

    return hd_public_key(out, I.right, lineage);
}

BCW_API hd_private_key::hd_private_key()
  : hd_public_key()
{
}

BCW_API hd_private_key::hd_private_key(const secret_parameter& private_key,
    const chain_code_type& chain_code, hd_key_lineage lineage)
  : hd_public_key(secret_to_public_key(private_key), chain_code, lineage),
    k_(private_key)
{
}

BCW_API hd_private_key::hd_private_key(const data_chunk& seed, bool testnet)
  : hd_public_key()
{
    constexpr uint32_t key_length = 13;
    const uint8_t hmac_key[key_length] = "Bitcoin seed";

    split_long_hash I = split(hmac_sha512(hmac_key, key_length, seed));
    ssl_bignum il = BN_bin2bn(I.left.data(), (int)I.left.size(), nullptr);

    // ************************************************************************
    ssl_bignum n = BN_bin2bn(secp256k1_n.data(), (int)secp256k1_n.size(),
        nullptr);
    // ************************************************************************

    // The key is invalid if parse256(IL) >= n or 0:
    if (0 <= BN_cmp(il, n) || BN_is_zero(il.ptr))
        return;

    hd_key_lineage null_seed = hd_key_lineage{ testnet, 0, { { 0 } }, 0 };

    *this = hd_private_key(I.left, I.right, null_seed);
}

BCW_API const secret_parameter& hd_private_key::private_key() const
{
    return k_;
}

BCW_API std::string hd_private_key::serialize() const
{
    data_chunk data;
    data.reserve(4 + 1 + 4 + 4 + 32 + 33 + 4);

    extend_data(data, ser32(lineage_.testnet ? testnet_private_prefix :
        mainnet_private_prefix));
    data.push_back(lineage_.depth);
    extend_data(data, lineage_.parent_fingerprint);
    extend_data(data, ser32(lineage_.child_number));
    extend_data(data, c_);
    data.push_back(0x00);
    extend_data(data, k_);

    extend_data(data, uncast_type(bitcoin_checksum(data)));
    return encode_base58(data);
}

BCW_API hd_private_key hd_private_key::generate_private_key(uint32_t i)
{
    if (!valid_)
        return hd_private_key();

    data_chunk data;
    data.reserve(33 + 4);
    if (first_hardened_key <= i)
    {
        data.push_back(0x00);
        extend_data(data, k_);
        extend_data(data, ser32(i));
    }
    else
    {
        extend_data(data, K_);
        extend_data(data, ser32(i));
    }

    auto I = split(hmac_sha512(c_.data(), (int)c_.size(), data));

    // The child key ki is (parse256(IL) + kpar) mod n:
    ssl_bn_ctx ctx = BN_CTX_new();
    ssl_bignum ki = BN_new();
    ssl_bignum kpar = BN_bin2bn(k_.data(), (int)k_.size(), nullptr);
    ssl_bignum il = BN_bin2bn(I.left.data(), (int)I.left.size(), nullptr);

    // ************************************************************************
    ssl_bignum n = BN_bin2bn(secp256k1_n.data(), (int)secp256k1_n.size(),
        nullptr);
    // ************************************************************************

    if (!ctx || !ki || !kpar || !il || !n)
        return hd_private_key();

    if (!BN_mod_add(ki, kpar, il, n, ctx))
        return hd_private_key();

    // The key is invalid if parse256(IL) >= n or ki == 0:
    if (0 <= BN_cmp(il, n) || BN_is_zero(ki.ptr))
        return hd_private_key();

    secret_parameter out{ { 0 } };
    int ki_size = BN_num_bytes(ki);
    if (ki_size != BN_bn2bin(ki, &out[out.size() - ki_size]))
        return hd_private_key();

    hd_key_lineage lineage = hd_key_lineage
    {
        lineage_.testnet,
        static_cast<uint8_t>(lineage_.depth + 1),
        fingerprint(),
        i
    };

    return hd_private_key(out, I.right, lineage);
}

BCW_API hd_public_key hd_private_key::generate_public_key(uint32_t i)
{
    return generate_private_key(i);
}

} // libwallet

<|endoftext|>


<commit_before>#ifndef __ENVIRE_CORE_BOUNDING_VOLUME__
#define __ENVIRE_CORE_BOUNDING_VOLUME__

#include <Eigen/Geometry>
#include <boost/intrusive_ptr.hpp>

namespace envire { namespace core
{

    /**@class BoundingVolume
    *
    * BoundingVolume class
    */
    class BoundingVolume
    {
    protected:

        BoundingVolume() {};

        long ref_count; /** Reference counter of the smart pointer */

    protected:

        friend void intrusive_ptr_add_ref( BoundingVolume* bv );
        friend void intrusive_ptr_release( BoundingVolume* bv );

    public:

        virtual void extend(const Eigen::Vector3d& point) = 0;
        virtual bool contains(const Eigen::Vector3d& point) const = 0;
        virtual double exteriorDistance(const Eigen::Vector3d& point) const = 0;
        virtual Eigen::Vector3d center() const = 0;
        virtual void extend(const boost::intrusive_ptr<BoundingVolume>& bv) = 0;
        virtual bool intersects(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual boost::intrusive_ptr<BoundingVolume> intersection(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual bool contains(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual double exteriorDistance(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual void clear() = 0;

    protected:

        template<class T>
        bool cast(const boost::intrusive_ptr< BoundingVolume >& bv, boost::intrusive_ptr< T >& derived_type) const
        {
            T* derived_volume = dynamic_cast<T*>(bv.get());
            if(derived_volume != NULL)
            {
                derived_type.reset(derived_volume);
                return true;
            }
            return false;
        }

    };

    void intrusive_ptr_add_ref( BoundingVolume* bv );
    void intrusive_ptr_release( BoundingVolume* bv );

}}
#endif<commit_msg>added missing virtual destructor<commit_after>#ifndef __ENVIRE_CORE_BOUNDING_VOLUME__
#define __ENVIRE_CORE_BOUNDING_VOLUME__

#include <Eigen/Geometry>
#include <boost/intrusive_ptr.hpp>

namespace envire { namespace core
{

    /**@class BoundingVolume
    *
    * BoundingVolume class
    */
    class BoundingVolume
    {
    protected:

        BoundingVolume() {};

        long ref_count; /** Reference counter of the smart pointer */

    protected:

        friend void intrusive_ptr_add_ref( BoundingVolume* bv );
        friend void intrusive_ptr_release( BoundingVolume* bv );

    public:

        virtual ~BoundingVolume() {};
        virtual void extend(const Eigen::Vector3d& point) = 0;
        virtual bool contains(const Eigen::Vector3d& point) const = 0;
        virtual double exteriorDistance(const Eigen::Vector3d& point) const = 0;
        virtual Eigen::Vector3d center() const = 0;
        virtual void extend(const boost::intrusive_ptr<BoundingVolume>& bv) = 0;
        virtual bool intersects(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual boost::intrusive_ptr<BoundingVolume> intersection(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual bool contains(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual double exteriorDistance(const boost::intrusive_ptr<BoundingVolume>& bv) const = 0;
        virtual void clear() = 0;

    protected:

        template<class T>
        bool cast(const boost::intrusive_ptr< BoundingVolume >& bv, boost::intrusive_ptr< T >& derived_type) const
        {
            T* derived_volume = dynamic_cast<T*>(bv.get());
            if(derived_volume != NULL)
            {
                derived_type.reset(derived_volume);
                return true;
            }
            return false;
        }

    };

    void intrusive_ptr_add_ref( BoundingVolume* bv );
    void intrusive_ptr_release( BoundingVolume* bv );

}}
#endif<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
//     Free Software Foundation, Inc.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <time.h>

#include <Context.h>
#include <Directory.h>
#include <File.h>
#include <Date.h>
#include <Duration.h>
#include <ViewText.h>
#include <text.h>
#include <util.h>
#include <main.h>

static void countTasks (const std::vector <Task>&, const std::string&, const std::vector <Task>&, int&, int&);

extern Context context;

///////////////////////////////////////////////////////////////////////////////
std::string getFullDescription (Task& task, const std::string& report)
{
  std::string desc = task.get ("description");
  std::string annotationDetails;

  std::map <std::string, std::string> annotations;
  task.getAnnotations (annotations);

  if (annotations.size () != 0)
  {
    std::string annotationDetails = context.config.get ("report." + report + ".annotations");
    if (annotationDetails == "")
      annotationDetails = context.config.get ("annotations");
    if (report == "info")
      annotationDetails = "full";

    if (annotationDetails == "none")
    {
      desc = "+" + desc;
    }
    else if (annotationDetails == "sparse")
    {
      if (annotations.size () > 1)
        desc = "+" + desc;

      std::map <std::string, std::string>::iterator i = annotations.begin ();

      Date dt (strtol (i->first.substr (11).c_str (), NULL, 10));
      std::string format = context.config.get ("dateformat.annotation");
      if (format == "")
        format = context.config.get ("dateformat");
      std::string when = dt.toString (format);
      desc += "\n" + when + " " + i->second;
    }
    else
    {
      std::map <std::string, std::string>::iterator anno;
      for (anno = annotations.begin (); anno != annotations.end (); ++anno)
      {
        Date dt (strtol (anno->first.substr (11).c_str (), NULL, 10));
        std::string format = context.config.get ("dateformat.annotation");
        if (format == "")
          format = context.config.get ("dateformat");
        std::string when = dt.toString (format);
        desc += "\n" + when + " " + anno->second;
      }
    }
  }

  return desc;
}

///////////////////////////////////////////////////////////////////////////////
std::string getDueDate (Task& task, const std::string& format)
{
  std::string due = task.get ("due");
  if (due.length ())
  {
    Date d (atoi (due.c_str ()));
    due = d.toString (format);
  }

  return due;
}

///////////////////////////////////////////////////////////////////////////////
std::string onProjectChange (Task& task, bool scope /* = true */)
{
  std::stringstream msg;
  std::string project = task.get ("project");

  if (project != "")
  {
    if (scope)
      msg << "The project '"
          << project
          << "' has changed.  ";

    // Count pending and done tasks, for this project.
    int count_pending = 0;
    int count_done = 0;

    std::vector <Task> all;
    std::vector <Task> none;
    context.tdb.load (all);

    countTasks (all,                           project, context.tdb.getAllModified (), count_pending, count_done);
    countTasks (context.tdb.getAllModified (), project, none,                          count_pending, count_done);

    // count_done  count_pending  percentage
    // ----------  -------------  ----------
    //          0              0          0%
    //         >0              0        100%
    //          0             >0          0%
    //         >0             >0  calculated
    int percentage = 0;
    if (count_done == 0)
      percentage = 0;
    else if (count_pending == 0)
      percentage = 100;
    else
      percentage = (count_done * 100 / (count_done + count_pending));

    msg << "Project '"
        << project
        << "' is "
        << percentage
        << "% complete ("
        << count_pending
        << " of "
        << (count_pending + count_done)
        << " tasks remaining).\n";
  }

  return msg.str ();
}

///////////////////////////////////////////////////////////////////////////////
std::string onProjectChange (Task& task1, Task& task2)
{
  std::string messages = onProjectChange (task1);
  messages            += onProjectChange (task2);

  return messages;
}

///////////////////////////////////////////////////////////////////////////////
static void countTasks (
  const std::vector <Task>& all,
  const std::string& project,
  const std::vector <Task>& skipTasks,
  int& count_pending,
  int& count_done)
{
  std::vector <Task>::const_iterator it;
  for (it = all.begin (); it != all.end (); ++it)
  {
    bool skip = 0;

    if (it->get ("project") == project)
    {
      std::vector <Task>::const_iterator itSkipTasks;
      for (itSkipTasks = skipTasks.begin (); itSkipTasks != skipTasks.end (); ++itSkipTasks)
      {
        if (it->get("uuid") == itSkipTasks->get("uuid"))
        {
          skip = 1;
          break;
        }
      }

      if (skip == 0)
      {
        switch (it->getStatus ())
        {
        case Task::pending:
        case Task::waiting:
          ++count_pending;
          break;

        case Task::completed:
          ++count_done;
          break;

        default:
          break;
        }
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>TDB2<commit_after>////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
//     Free Software Foundation, Inc.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <time.h>

#include <Context.h>
#include <Directory.h>
#include <File.h>
#include <Date.h>
#include <Duration.h>
#include <ViewText.h>
#include <text.h>
#include <util.h>
#include <main.h>

static void countTasks (const std::vector <Task>&, const std::string&, const std::vector <Task>&, int&, int&);

extern Context context;

///////////////////////////////////////////////////////////////////////////////
std::string getFullDescription (Task& task, const std::string& report)
{
  std::string desc = task.get ("description");
  std::string annotationDetails;

  std::map <std::string, std::string> annotations;
  task.getAnnotations (annotations);

  if (annotations.size () != 0)
  {
    std::string annotationDetails = context.config.get ("report." + report + ".annotations");
    if (annotationDetails == "")
      annotationDetails = context.config.get ("annotations");
    if (report == "info")
      annotationDetails = "full";

    if (annotationDetails == "none")
    {
      desc = "+" + desc;
    }
    else if (annotationDetails == "sparse")
    {
      if (annotations.size () > 1)
        desc = "+" + desc;

      std::map <std::string, std::string>::iterator i = annotations.begin ();

      Date dt (strtol (i->first.substr (11).c_str (), NULL, 10));
      std::string format = context.config.get ("dateformat.annotation");
      if (format == "")
        format = context.config.get ("dateformat");
      std::string when = dt.toString (format);
      desc += "\n" + when + " " + i->second;
    }
    else
    {
      std::map <std::string, std::string>::iterator anno;
      for (anno = annotations.begin (); anno != annotations.end (); ++anno)
      {
        Date dt (strtol (anno->first.substr (11).c_str (), NULL, 10));
        std::string format = context.config.get ("dateformat.annotation");
        if (format == "")
          format = context.config.get ("dateformat");
        std::string when = dt.toString (format);
        desc += "\n" + when + " " + anno->second;
      }
    }
  }

  return desc;
}

///////////////////////////////////////////////////////////////////////////////
std::string getDueDate (Task& task, const std::string& format)
{
  std::string due = task.get ("due");
  if (due.length ())
  {
    Date d (atoi (due.c_str ()));
    due = d.toString (format);
  }

  return due;
}

///////////////////////////////////////////////////////////////////////////////
std::string onProjectChange (Task& task, bool scope /* = true */)
{
  std::stringstream msg;
  std::string project = task.get ("project");

  if (project != "")
  {
    if (scope)
      msg << "The project '"
          << project
          << "' has changed.  ";

    // Count pending and done tasks, for this project.
    int count_pending = 0;
    int count_done = 0;

    std::vector <Task> all;
    std::vector <Task> none;
// TODO Fix.
//    context.tdb.load (all);
//
//    countTasks (all,                           project, context.tdb.getAllModified (), count_pending, count_done);
//    countTasks (context.tdb.getAllModified (), project, none,                          count_pending, count_done);

    // count_done  count_pending  percentage
    // ----------  -------------  ----------
    //          0              0          0%
    //         >0              0        100%
    //          0             >0          0%
    //         >0             >0  calculated
    int percentage = 0;
    if (count_done == 0)
      percentage = 0;
    else if (count_pending == 0)
      percentage = 100;
    else
      percentage = (count_done * 100 / (count_done + count_pending));

    msg << "Project '"
        << project
        << "' is "
        << percentage
        << "% complete ("
        << count_pending
        << " of "
        << (count_pending + count_done)
        << " tasks remaining).\n";
  }

  return msg.str ();
}

///////////////////////////////////////////////////////////////////////////////
std::string onProjectChange (Task& task1, Task& task2)
{
  std::string messages = onProjectChange (task1);
  messages            += onProjectChange (task2);

  return messages;
}

///////////////////////////////////////////////////////////////////////////////
static void countTasks (
  const std::vector <Task>& all,
  const std::string& project,
  const std::vector <Task>& skipTasks,
  int& count_pending,
  int& count_done)
{
  std::vector <Task>::const_iterator it;
  for (it = all.begin (); it != all.end (); ++it)
  {
    bool skip = 0;

    if (it->get ("project") == project)
    {
      std::vector <Task>::const_iterator itSkipTasks;
      for (itSkipTasks = skipTasks.begin (); itSkipTasks != skipTasks.end (); ++itSkipTasks)
      {
        if (it->get("uuid") == itSkipTasks->get("uuid"))
        {
          skip = 1;
          break;
        }
      }

      if (skip == 0)
      {
        switch (it->getStatus ())
        {
        case Task::pending:
        case Task::waiting:
          ++count_pending;
          break;

        case Task::completed:
          ++count_done;
          break;

        default:
          break;
        }
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>