Merge commit 'a0c5addbbdaf472d26ae25c86ff826e509b3ee17'
This commit is contained in:
commit
fd18f58392
21 changed files with 286 additions and 791 deletions
10
.travis.yml
10
.travis.yml
|
|
@ -2,8 +2,14 @@ language: cpp
|
||||||
compiler:
|
compiler:
|
||||||
- clang
|
- clang
|
||||||
- gcc
|
- gcc
|
||||||
install: "./acprep dependencies"
|
install:
|
||||||
before_script: "./acprep opt make --python"
|
- "./acprep dependencies"
|
||||||
|
- wget http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.tar.bz2/download
|
||||||
|
- tar jxf download
|
||||||
|
- mv boost_1_55_0 $HOME/boost-trunk
|
||||||
|
before_script:
|
||||||
|
- BOOST="$HOME/boost-trunk"
|
||||||
|
- "./acprep opt make --python"
|
||||||
script:
|
script:
|
||||||
- "./acprep check -- --output-on-failure"
|
- "./acprep check -- --output-on-failure"
|
||||||
- "PYTHONPATH=. python python/demo.py"
|
- "PYTHONPATH=. python python/demo.py"
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@ PROJECT(ledger)
|
||||||
|
|
||||||
set(Ledger_VERSION_MAJOR 3)
|
set(Ledger_VERSION_MAJOR 3)
|
||||||
set(Ledger_VERSION_MINOR 0)
|
set(Ledger_VERSION_MINOR 0)
|
||||||
set(Ledger_VERSION_PATCH 1)
|
set(Ledger_VERSION_PATCH 2)
|
||||||
set(Ledger_VERSION_DATE 20140327)
|
set(Ledger_VERSION_DATE 20140417)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
add_definitions(-std=c++11)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
option(USE_PYTHON "Build support for the Python scripting bridge" OFF)
|
option(USE_PYTHON "Build support for the Python scripting bridge" OFF)
|
||||||
|
|
@ -65,7 +67,7 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set BOOST_ROOT to help CMake to find the right Boost version
|
# Set BOOST_ROOT to help CMake to find the right Boost version
|
||||||
find_package(Boost 1.46.0
|
find_package(Boost 1.55.0
|
||||||
REQUIRED date_time filesystem system iostreams regex unit_test_framework
|
REQUIRED date_time filesystem system iostreams regex unit_test_framework
|
||||||
${BOOST_PYTHON})
|
${BOOST_PYTHON})
|
||||||
|
|
||||||
|
|
@ -148,37 +150,6 @@ endif()
|
||||||
|
|
||||||
cmake_pop_check_state()
|
cmake_pop_check_state()
|
||||||
|
|
||||||
#cmake_push_check_state()
|
|
||||||
#
|
|
||||||
#set(CMAKE_REQUIRED_FLAGS -std=c++11)
|
|
||||||
#set(CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH})
|
|
||||||
#
|
|
||||||
#check_cxx_source_runs("
|
|
||||||
##include <regex>
|
|
||||||
##include <vector>
|
|
||||||
##include <iostream>
|
|
||||||
#
|
|
||||||
#int main() {
|
|
||||||
# std::vector<int> x {0, 1, 2, 3, 4};
|
|
||||||
# for (auto i : x)
|
|
||||||
# std::cout << i << std::endl;
|
|
||||||
#
|
|
||||||
# std::regex r(\"foo\");
|
|
||||||
# std::cout << std::regex_match(\"foobar\", r) << std::endl;
|
|
||||||
# return 0;
|
|
||||||
#}" CXX11_RUNS)
|
|
||||||
#
|
|
||||||
#cmake_pop_check_state()
|
|
||||||
#
|
|
||||||
#if(CXX11_RUNS)
|
|
||||||
# set(HAVE_CXX11 1)
|
|
||||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
#else()
|
|
||||||
set(HAVE_CXX11 0)
|
|
||||||
#endif()
|
|
||||||
#
|
|
||||||
#cmake_pop_check_state()
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
include_directories(${CMAKE_INCLUDE_PATH})
|
include_directories(${CMAKE_INCLUDE_PATH})
|
||||||
|
|
|
||||||
39
default.nix
Normal file
39
default.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{ stdenv, fetchgit, cmake, boost, gmp, mpfr, libedit, python
|
||||||
|
, texinfo, gnused }:
|
||||||
|
|
||||||
|
let
|
||||||
|
rev = "20140417";
|
||||||
|
in
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "ledger-3.0.2.${rev}";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
buildInputs = [ cmake boost gmp mpfr libedit python texinfo gnused ];
|
||||||
|
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
|
# Skip byte-compiling of emacs-lisp files because this is currently
|
||||||
|
# broken in ledger...
|
||||||
|
postInstall = ''
|
||||||
|
mkdir -p $out/share/emacs/site-lisp/
|
||||||
|
cp -v $src/lisp/*.el $out/share/emacs/site-lisp/
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
homepage = "http://ledger-cli.org/";
|
||||||
|
description = "A double-entry accounting system with a command-line reporting interface";
|
||||||
|
license = "BSD";
|
||||||
|
|
||||||
|
longDescription = ''
|
||||||
|
Ledger is a powerful, double-entry accounting system that is accessed
|
||||||
|
from the UNIX command-line. This may put off some users, as there is
|
||||||
|
no flashy UI, but for those who want unparalleled reporting access to
|
||||||
|
their data, there really is no alternative.
|
||||||
|
'';
|
||||||
|
|
||||||
|
platforms = stdenv.lib.platforms.all;
|
||||||
|
maintainers = with stdenv.lib.maintainers; [ simons the-kenny jwiegley ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
Copyright (C) 1998
|
|
||||||
Paul E. Jones <paulej@arid.us>
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
This software is licensed as "freeware." Permission to distribute
|
|
||||||
this software in source and binary forms is hereby granted without
|
|
||||||
a fee. THIS SOFTWARE IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED
|
|
||||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
THE AUTHOR SHALL NOT BE HELD LIABLE FOR ANY DAMAGES RESULTING
|
|
||||||
FROM THE USE OF THIS SOFTWARE, EITHER DIRECTLY OR INDIRECTLY, INCLUDING,
|
|
||||||
BUT NOT LIMITED TO, LOSS OF DATA OR DATA BEING RENDERED INACCURATE.
|
|
||||||
|
|
||||||
589
lib/sha1.cpp
589
lib/sha1.cpp
|
|
@ -1,589 +0,0 @@
|
||||||
/*
|
|
||||||
* sha1.cpp
|
|
||||||
*
|
|
||||||
* Copyright (C) 1998
|
|
||||||
* Paul E. Jones <paulej@arid.us>
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
*****************************************************************************
|
|
||||||
* $Id: sha1.cpp,v 1.9 2004/03/27 18:02:20 paulej Exp $
|
|
||||||
*****************************************************************************
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This class implements the Secure Hashing Standard as defined
|
|
||||||
* in FIPS PUB 180-1 published April 17, 1995.
|
|
||||||
*
|
|
||||||
* The Secure Hashing Standard, which uses the Secure Hashing
|
|
||||||
* Algorithm (SHA), produces a 160-bit message digest for a
|
|
||||||
* given data stream. In theory, it is highly improbable that
|
|
||||||
* two messages will produce the same message digest. Therefore,
|
|
||||||
* this algorithm can serve as a means of providing a "fingerprint"
|
|
||||||
* for a message.
|
|
||||||
*
|
|
||||||
* Portability Issues:
|
|
||||||
* SHA-1 is defined in terms of 32-bit "words". This code was
|
|
||||||
* written with the expectation that the processor has at least
|
|
||||||
* a 32-bit machine word size. If the machine word size is larger,
|
|
||||||
* the code should still function properly. One caveat to that
|
|
||||||
* is that the input functions taking characters and character arrays
|
|
||||||
* assume that only 8 bits of information are stored in each character.
|
|
||||||
*
|
|
||||||
* Caveats:
|
|
||||||
* SHA-1 is designed to work with messages less than 2^64 bits long.
|
|
||||||
* Although SHA-1 allows a message digest to be generated for
|
|
||||||
* messages of any number of bits less than 2^64, this implementation
|
|
||||||
* only works with messages with a length that is a multiple of 8
|
|
||||||
* bits.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "sha1.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SHA1
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This is the constructor for the sha1 class.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
SHA1::SHA1()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ~SHA1
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This is the destructor for the sha1 class
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
SHA1::~SHA1()
|
|
||||||
{
|
|
||||||
// The destructor does nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function will initialize the sha1 class member variables
|
|
||||||
* in preparation for computing a new message digest.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::Reset()
|
|
||||||
{
|
|
||||||
Length_Low = 0;
|
|
||||||
Length_High = 0;
|
|
||||||
Message_Block_Index = 0;
|
|
||||||
|
|
||||||
H[0] = 0x67452301;
|
|
||||||
H[1] = 0xEFCDAB89;
|
|
||||||
H[2] = 0x98BADCFE;
|
|
||||||
H[3] = 0x10325476;
|
|
||||||
H[4] = 0xC3D2E1F0;
|
|
||||||
|
|
||||||
Computed = false;
|
|
||||||
Corrupted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Result
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function will return the 160-bit message digest into the
|
|
||||||
* array provided.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_digest_array: [out]
|
|
||||||
* This is an array of five unsigned integers which will be filled
|
|
||||||
* with the message digest that has been computed.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* True if successful, false if it failed.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool SHA1::Result(unsigned *message_digest_array)
|
|
||||||
{
|
|
||||||
int i; // Counter
|
|
||||||
|
|
||||||
if (Corrupted)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Computed)
|
|
||||||
{
|
|
||||||
PadMessage();
|
|
||||||
Computed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
message_digest_array[i] = H[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function accepts an array of octets as the next portion of
|
|
||||||
* the message.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_array: [in]
|
|
||||||
* An array of characters representing the next portion of the
|
|
||||||
* message.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::Input( const unsigned char *message_array,
|
|
||||||
unsigned length)
|
|
||||||
{
|
|
||||||
if (!length)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Computed || Corrupted)
|
|
||||||
{
|
|
||||||
Corrupted = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(length-- && !Corrupted)
|
|
||||||
{
|
|
||||||
Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
|
|
||||||
|
|
||||||
Length_Low += 8;
|
|
||||||
Length_Low &= 0xFFFFFFFF; // Force it to 32 bits
|
|
||||||
if (Length_Low == 0)
|
|
||||||
{
|
|
||||||
Length_High++;
|
|
||||||
Length_High &= 0xFFFFFFFF; // Force it to 32 bits
|
|
||||||
if (Length_High == 0)
|
|
||||||
{
|
|
||||||
Corrupted = true; // Message is too long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Message_Block_Index == 64)
|
|
||||||
{
|
|
||||||
ProcessMessageBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
message_array++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function accepts an array of octets as the next portion of
|
|
||||||
* the message.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_array: [in]
|
|
||||||
* An array of characters representing the next portion of the
|
|
||||||
* message.
|
|
||||||
* length: [in]
|
|
||||||
* The length of the message_array
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::Input( const char *message_array,
|
|
||||||
unsigned length)
|
|
||||||
{
|
|
||||||
Input(reinterpret_cast<unsigned char *>(const_cast<char *>(message_array)), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function accepts a single octets as the next message element.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_element: [in]
|
|
||||||
* The next octet in the message.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::Input(unsigned char message_element)
|
|
||||||
{
|
|
||||||
Input(&message_element, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function accepts a single octet as the next message element.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_element: [in]
|
|
||||||
* The next octet in the message.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::Input(char message_element)
|
|
||||||
{
|
|
||||||
Input((unsigned char *) &message_element, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* operator<<
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This operator makes it convenient to provide character strings to
|
|
||||||
* the SHA1 object for processing.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_array: [in]
|
|
||||||
* The character array to take as input.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* A reference to the SHA1 object.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
* Each character is assumed to hold 8 bits of information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
SHA1& SHA1::operator<<(const char *message_array)
|
|
||||||
{
|
|
||||||
const char *p = message_array;
|
|
||||||
|
|
||||||
while(*p)
|
|
||||||
{
|
|
||||||
Input(*p);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* operator<<
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This operator makes it convenient to provide character strings to
|
|
||||||
* the SHA1 object for processing.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_array: [in]
|
|
||||||
* The character array to take as input.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* A reference to the SHA1 object.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
* Each character is assumed to hold 8 bits of information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
SHA1& SHA1::operator<<(const unsigned char *message_array)
|
|
||||||
{
|
|
||||||
const unsigned char *p = message_array;
|
|
||||||
|
|
||||||
while(*p)
|
|
||||||
{
|
|
||||||
Input(*p);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* operator<<
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function provides the next octet in the message.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_element: [in]
|
|
||||||
* The next octet in the message
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* A reference to the SHA1 object.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
* The character is assumed to hold 8 bits of information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
SHA1& SHA1::operator<<(const char message_element)
|
|
||||||
{
|
|
||||||
Input(reinterpret_cast<unsigned char *>(const_cast<char *>(&message_element)), 1);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* operator<<
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function provides the next octet in the message.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* message_element: [in]
|
|
||||||
* The next octet in the message
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* A reference to the SHA1 object.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
* The character is assumed to hold 8 bits of information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
SHA1& SHA1::operator<<(const unsigned char message_element)
|
|
||||||
{
|
|
||||||
Input(&message_element, 1);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ProcessMessageBlock
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function will process the next 512 bits of the message
|
|
||||||
* stored in the Message_Block array.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
* Many of the variable names in this function, especially the single
|
|
||||||
* character names, were used because those were the names used
|
|
||||||
* in the publication.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::ProcessMessageBlock()
|
|
||||||
{
|
|
||||||
const unsigned K[] = { // Constants defined for SHA-1
|
|
||||||
0x5A827999,
|
|
||||||
0x6ED9EBA1,
|
|
||||||
0x8F1BBCDC,
|
|
||||||
0xCA62C1D6
|
|
||||||
};
|
|
||||||
int t; // Loop counter
|
|
||||||
unsigned temp; // Temporary word value
|
|
||||||
unsigned W[80]; // Word sequence
|
|
||||||
unsigned A, B, C, D, E; // Word buffers
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the first 16 words in the array W
|
|
||||||
*/
|
|
||||||
for(t = 0; t < 16; t++)
|
|
||||||
{
|
|
||||||
W[t] = ((unsigned) Message_Block[t * 4]) << 24;
|
|
||||||
W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
|
|
||||||
W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
|
|
||||||
W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(t = 16; t < 80; t++)
|
|
||||||
{
|
|
||||||
W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
|
|
||||||
}
|
|
||||||
|
|
||||||
A = H[0];
|
|
||||||
B = H[1];
|
|
||||||
C = H[2];
|
|
||||||
D = H[3];
|
|
||||||
E = H[4];
|
|
||||||
|
|
||||||
for(t = 0; t < 20; t++)
|
|
||||||
{
|
|
||||||
temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
|
|
||||||
temp &= 0xFFFFFFFF;
|
|
||||||
E = D;
|
|
||||||
D = C;
|
|
||||||
C = CircularShift(30,B);
|
|
||||||
B = A;
|
|
||||||
A = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(t = 20; t < 40; t++)
|
|
||||||
{
|
|
||||||
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
|
|
||||||
temp &= 0xFFFFFFFF;
|
|
||||||
E = D;
|
|
||||||
D = C;
|
|
||||||
C = CircularShift(30,B);
|
|
||||||
B = A;
|
|
||||||
A = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(t = 40; t < 60; t++)
|
|
||||||
{
|
|
||||||
temp = CircularShift(5,A) +
|
|
||||||
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
|
|
||||||
temp &= 0xFFFFFFFF;
|
|
||||||
E = D;
|
|
||||||
D = C;
|
|
||||||
C = CircularShift(30,B);
|
|
||||||
B = A;
|
|
||||||
A = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(t = 60; t < 80; t++)
|
|
||||||
{
|
|
||||||
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
|
|
||||||
temp &= 0xFFFFFFFF;
|
|
||||||
E = D;
|
|
||||||
D = C;
|
|
||||||
C = CircularShift(30,B);
|
|
||||||
B = A;
|
|
||||||
A = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
H[0] = (H[0] + A) & 0xFFFFFFFF;
|
|
||||||
H[1] = (H[1] + B) & 0xFFFFFFFF;
|
|
||||||
H[2] = (H[2] + C) & 0xFFFFFFFF;
|
|
||||||
H[3] = (H[3] + D) & 0xFFFFFFFF;
|
|
||||||
H[4] = (H[4] + E) & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
Message_Block_Index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PadMessage
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* According to the standard, the message must be padded to an even
|
|
||||||
* 512 bits. The first padding bit must be a '1'. The last 64 bits
|
|
||||||
* represent the length of the original message. All bits in between
|
|
||||||
* should be 0. This function will pad the message according to those
|
|
||||||
* rules by filling the message_block array accordingly. It will also
|
|
||||||
* call ProcessMessageBlock() appropriately. When it returns, it
|
|
||||||
* can be assumed that the message digest has been computed.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Nothing.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SHA1::PadMessage()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Check to see if the current message block is too small to hold
|
|
||||||
* the initial padding bits and length. If so, we will pad the
|
|
||||||
* block, process it, and then continue padding into a second block.
|
|
||||||
*/
|
|
||||||
if (Message_Block_Index > 55)
|
|
||||||
{
|
|
||||||
Message_Block[Message_Block_Index++] = 0x80;
|
|
||||||
while(Message_Block_Index < 64)
|
|
||||||
{
|
|
||||||
Message_Block[Message_Block_Index++] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessMessageBlock();
|
|
||||||
|
|
||||||
while(Message_Block_Index < 56)
|
|
||||||
{
|
|
||||||
Message_Block[Message_Block_Index++] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Message_Block[Message_Block_Index++] = 0x80;
|
|
||||||
while(Message_Block_Index < 56)
|
|
||||||
{
|
|
||||||
Message_Block[Message_Block_Index++] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Store the message length as the last 8 octets
|
|
||||||
*/
|
|
||||||
Message_Block[56] = static_cast<unsigned char>((Length_High >> 24) & 0xFF);
|
|
||||||
Message_Block[57] = static_cast<unsigned char>((Length_High >> 16) & 0xFF);
|
|
||||||
Message_Block[58] = static_cast<unsigned char>((Length_High >> 8) & 0xFF);
|
|
||||||
Message_Block[59] = static_cast<unsigned char>((Length_High) & 0xFF);
|
|
||||||
Message_Block[60] = static_cast<unsigned char>((Length_Low >> 24) & 0xFF);
|
|
||||||
Message_Block[61] = static_cast<unsigned char>((Length_Low >> 16) & 0xFF);
|
|
||||||
Message_Block[62] = static_cast<unsigned char>((Length_Low >> 8) & 0xFF);
|
|
||||||
Message_Block[63] = static_cast<unsigned char>((Length_Low) & 0xFF);
|
|
||||||
|
|
||||||
ProcessMessageBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CircularShift
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This member function will perform a circular shifting operation.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* bits: [in]
|
|
||||||
* The number of bits to shift (1-31)
|
|
||||||
* word: [in]
|
|
||||||
* The value to shift (assumes a 32-bit integer)
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* The shifted value.
|
|
||||||
*
|
|
||||||
* Comments:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
unsigned SHA1::CircularShift(int bits, unsigned word)
|
|
||||||
{
|
|
||||||
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
|
|
||||||
}
|
|
||||||
89
lib/sha1.h
89
lib/sha1.h
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* sha1.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 1998
|
|
||||||
* Paul E. Jones <paulej@arid.us>
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
*****************************************************************************
|
|
||||||
* $Id: sha1.h,v 1.6 2004/03/27 18:02:26 paulej Exp $
|
|
||||||
*****************************************************************************
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This class implements the Secure Hashing Standard as defined
|
|
||||||
* in FIPS PUB 180-1 published April 17, 1995.
|
|
||||||
*
|
|
||||||
* Many of the variable names in this class, especially the single
|
|
||||||
* character names, were used because those were the names used
|
|
||||||
* in the publication.
|
|
||||||
*
|
|
||||||
* Please read the file sha1.cpp for more information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SHA1_H_
|
|
||||||
#define _SHA1_H_
|
|
||||||
|
|
||||||
class SHA1
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SHA1();
|
|
||||||
virtual ~SHA1();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Re-initialize the class
|
|
||||||
*/
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the message digest
|
|
||||||
*/
|
|
||||||
bool Result(unsigned *message_digest_array);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provide input to SHA1
|
|
||||||
*/
|
|
||||||
void Input( const unsigned char *message_array,
|
|
||||||
unsigned length);
|
|
||||||
void Input( const char *message_array,
|
|
||||||
unsigned length);
|
|
||||||
void Input(unsigned char message_element);
|
|
||||||
void Input(char message_element);
|
|
||||||
SHA1& operator<<(const char *message_array);
|
|
||||||
SHA1& operator<<(const unsigned char *message_array);
|
|
||||||
SHA1& operator<<(const char message_element);
|
|
||||||
SHA1& operator<<(const unsigned char message_element);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process the next 512 bits of the message
|
|
||||||
*/
|
|
||||||
void ProcessMessageBlock();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pads the current message block to 512 bits
|
|
||||||
*/
|
|
||||||
void PadMessage();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Performs a circular left shift operation
|
|
||||||
*/
|
|
||||||
inline unsigned CircularShift(int bits, unsigned word);
|
|
||||||
|
|
||||||
unsigned H[5]; // Message digest buffers
|
|
||||||
|
|
||||||
unsigned Length_Low; // Message length in bits
|
|
||||||
unsigned Length_High; // Message length in bits
|
|
||||||
|
|
||||||
unsigned char Message_Block[64]; // 512-bit message blocks
|
|
||||||
int Message_Block_Index; // Index into message block array
|
|
||||||
|
|
||||||
bool Computed; // Is the digest computed?
|
|
||||||
bool Corrupted; // Is the message digest corruped?
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -254,7 +254,7 @@ include(GNUInstallDirs)
|
||||||
|
|
||||||
if(BUILD_LIBRARY)
|
if(BUILD_LIBRARY)
|
||||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||||
add_library(libledger SHARED ${LEDGER_SOURCES} ${PROJECT_SOURCE_DIR}/lib/sha1.cpp)
|
add_library(libledger SHARED ${LEDGER_SOURCES})
|
||||||
add_ledger_library_dependencies(libledger)
|
add_ledger_library_dependencies(libledger)
|
||||||
set_target_properties(libledger PROPERTIES
|
set_target_properties(libledger PROPERTIES
|
||||||
PREFIX ""
|
PREFIX ""
|
||||||
|
|
@ -267,11 +267,9 @@ if(BUILD_LIBRARY)
|
||||||
|
|
||||||
install(TARGETS libledger DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(TARGETS libledger DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
install(FILES ${LEDGER_INCLUDES}
|
install(FILES ${LEDGER_INCLUDES}
|
||||||
${PROJECT_SOURCE_DIR}/lib/sha1.h
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ledger)
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ledger)
|
||||||
else()
|
else()
|
||||||
add_executable(ledger
|
add_executable(ledger ${LEDGER_SOURCES} main.cc global.cc)
|
||||||
${LEDGER_SOURCES} ${PROJECT_SOURCE_DIR}/lib/sha1.cpp main.cc global.cc)
|
|
||||||
add_ledger_library_dependencies(ledger)
|
add_ledger_library_dependencies(ledger)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,36 @@ void account_t::add_post(post_t * post)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void account_t::add_deferred_post(const string& uuid, post_t * post)
|
||||||
|
{
|
||||||
|
if (! deferred_posts)
|
||||||
|
deferred_posts = deferred_posts_map_t();
|
||||||
|
|
||||||
|
deferred_posts_map_t::iterator i = deferred_posts->find(uuid);
|
||||||
|
if (i == deferred_posts->end()) {
|
||||||
|
posts_list lst;
|
||||||
|
lst.push_back(post);
|
||||||
|
deferred_posts->insert(deferred_posts_map_t::value_type(uuid, lst));
|
||||||
|
} else {
|
||||||
|
(*i).second.push_back(post);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void account_t::apply_deferred_posts()
|
||||||
|
{
|
||||||
|
if (deferred_posts) {
|
||||||
|
foreach (deferred_posts_map_t::value_type& pair, *deferred_posts) {
|
||||||
|
foreach (post_t * post, pair.second)
|
||||||
|
post->account->add_post(post);
|
||||||
|
}
|
||||||
|
deferred_posts = none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also apply in child accounts
|
||||||
|
foreach (const accounts_map::value_type& pair, accounts)
|
||||||
|
pair.second->apply_deferred_posts();
|
||||||
|
}
|
||||||
|
|
||||||
bool account_t::remove_post(post_t * post)
|
bool account_t::remove_post(post_t * post)
|
||||||
{
|
{
|
||||||
// It's possible that 'post' wasn't yet in this account, but try to
|
// It's possible that 'post' wasn't yet in this account, but try to
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class post_t;
|
||||||
|
|
||||||
typedef std::list<post_t *> posts_list;
|
typedef std::list<post_t *> posts_list;
|
||||||
typedef std::map<string, account_t *> accounts_map;
|
typedef std::map<string, account_t *> accounts_map;
|
||||||
|
typedef std::map<string, posts_list> deferred_posts_map_t;
|
||||||
|
|
||||||
class account_t : public supports_flags<>, public scope_t
|
class account_t : public supports_flags<>, public scope_t
|
||||||
{
|
{
|
||||||
|
|
@ -61,13 +62,14 @@ class account_t : public supports_flags<>, public scope_t
|
||||||
#define ACCOUNT_GENERATED 0x04 // account never actually existed
|
#define ACCOUNT_GENERATED 0x04 // account never actually existed
|
||||||
|
|
||||||
public:
|
public:
|
||||||
account_t * parent;
|
account_t * parent;
|
||||||
string name;
|
string name;
|
||||||
optional<string> note;
|
optional<string> note;
|
||||||
unsigned short depth;
|
unsigned short depth;
|
||||||
accounts_map accounts;
|
accounts_map accounts;
|
||||||
posts_list posts;
|
posts_list posts;
|
||||||
optional<expr_t> value_expr;
|
optional<deferred_posts_map_t> deferred_posts;
|
||||||
|
optional<expr_t> value_expr;
|
||||||
|
|
||||||
mutable string _fullname;
|
mutable string _fullname;
|
||||||
#if DOCUMENT_MODEL
|
#if DOCUMENT_MODEL
|
||||||
|
|
@ -136,6 +138,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_post(post_t * post);
|
void add_post(post_t * post);
|
||||||
|
void add_deferred_post(const string& uuid, post_t * post);
|
||||||
|
void apply_deferred_posts();
|
||||||
bool remove_post(post_t * post);
|
bool remove_post(post_t * post);
|
||||||
|
|
||||||
posts_list::iterator posts_begin() {
|
posts_list::iterator posts_begin() {
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ void anonymize_posts::render_commodity(amount_t& amt)
|
||||||
|
|
||||||
void anonymize_posts::operator()(post_t& post)
|
void anonymize_posts::operator()(post_t& post)
|
||||||
{
|
{
|
||||||
SHA1 sha;
|
boost::uuids::detail::sha1 sha;
|
||||||
unsigned int message_digest[5];
|
unsigned int message_digest[5];
|
||||||
bool copy_xact_details = false;
|
bool copy_xact_details = false;
|
||||||
|
|
||||||
|
|
@ -256,9 +256,9 @@ void anonymize_posts::operator()(post_t& post)
|
||||||
buf << reinterpret_cast<uintmax_t>(post.xact->payee.c_str())
|
buf << reinterpret_cast<uintmax_t>(post.xact->payee.c_str())
|
||||||
<< integer_gen() << post.xact->payee.c_str();
|
<< integer_gen() << post.xact->payee.c_str();
|
||||||
|
|
||||||
sha.Reset();
|
sha.reset();
|
||||||
sha << buf.str().c_str();
|
sha.process_bytes(buf.str().c_str(), buf.str().length());
|
||||||
sha.Result(message_digest);
|
sha.get_digest(message_digest);
|
||||||
|
|
||||||
xact.payee = to_hex(message_digest);
|
xact.payee = to_hex(message_digest);
|
||||||
xact.note = none;
|
xact.note = none;
|
||||||
|
|
@ -274,9 +274,9 @@ void anonymize_posts::operator()(post_t& post)
|
||||||
std::ostringstream buf;
|
std::ostringstream buf;
|
||||||
buf << integer_gen() << acct << acct->fullname();
|
buf << integer_gen() << acct << acct->fullname();
|
||||||
|
|
||||||
sha.Reset();
|
sha.reset();
|
||||||
sha << buf.str().c_str();
|
sha.process_bytes(buf.str().c_str(), buf.str().length());
|
||||||
sha.Result(message_digest);
|
sha.get_digest(message_digest);
|
||||||
|
|
||||||
account_names.push_front(to_hex(message_digest));
|
account_names.push_front(to_hex(message_digest));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ void journal_t::initialize()
|
||||||
force_checking = false;
|
force_checking = false;
|
||||||
check_payees = false;
|
check_payees = false;
|
||||||
day_break = false;
|
day_break = false;
|
||||||
checking_style = CHECK_PERMISSIVE;
|
checking_style = CHECK_NORMAL;
|
||||||
recursive_aliases = false;
|
recursive_aliases = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,6 +363,21 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lt_posting_account(post_t * left, post_t * right) {
|
||||||
|
return left->account < right->account;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_equivalent_posting(post_t * left, post_t * right)
|
||||||
|
{
|
||||||
|
if (left->account != right->account)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (left->amount != right->amount)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool journal_t::add_xact(xact_t * xact)
|
bool journal_t::add_xact(xact_t * xact)
|
||||||
{
|
{
|
||||||
xact->journal = this;
|
xact->journal = this;
|
||||||
|
|
@ -385,12 +400,54 @@ bool journal_t::add_xact(xact_t * xact)
|
||||||
// will have been performed by extend_xact, so asserts can still be
|
// will have been performed by extend_xact, so asserts can still be
|
||||||
// applied to it.
|
// applied to it.
|
||||||
if (optional<value_t> ref = xact->get_tag(_("UUID"))) {
|
if (optional<value_t> ref = xact->get_tag(_("UUID"))) {
|
||||||
|
std::string uuid = ref->to_string();
|
||||||
std::pair<checksum_map_t::iterator, bool> result
|
std::pair<checksum_map_t::iterator, bool> result
|
||||||
= checksum_map.insert(checksum_map_t::value_type(ref->to_string(), xact));
|
= checksum_map.insert(checksum_map_t::value_type(uuid, xact));
|
||||||
if (! result.second) {
|
if (! result.second) {
|
||||||
// jww (2012-02-27): Confirm that the xact in
|
// This UUID has been seen before; apply any postings which the
|
||||||
// (*result.first).second is exact match in its significant
|
// earlier version may have deferred.
|
||||||
// details to xact.
|
foreach (post_t * post, xact->posts) {
|
||||||
|
account_t * acct = post->account;
|
||||||
|
if (acct->deferred_posts) {
|
||||||
|
auto i = acct->deferred_posts->find(uuid);
|
||||||
|
if (i != acct->deferred_posts->end()) {
|
||||||
|
for (post_t * rpost : (*i).second)
|
||||||
|
if (acct == rpost->account)
|
||||||
|
acct->add_post(rpost);
|
||||||
|
acct->deferred_posts->erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xact_t * other = (*result.first).second;
|
||||||
|
|
||||||
|
// Copy the two lists of postings (which should be relatively
|
||||||
|
// short), and make sure that the intersection is the empty set
|
||||||
|
// (i.e., that they are the same list).
|
||||||
|
std::vector<post_t *> this_posts(xact->posts.begin(),
|
||||||
|
xact->posts.end());
|
||||||
|
std::sort(this_posts.begin(), this_posts.end(),
|
||||||
|
lt_posting_account);
|
||||||
|
std::vector<post_t *> other_posts(other->posts.begin(),
|
||||||
|
other->posts.end());
|
||||||
|
std::sort(other_posts.begin(), other_posts.end(),
|
||||||
|
lt_posting_account);
|
||||||
|
bool match = std::equal(this_posts.begin(), this_posts.end(),
|
||||||
|
other_posts.begin(), is_equivalent_posting);
|
||||||
|
|
||||||
|
if (! match || this_posts.size() != other_posts.size()) {
|
||||||
|
add_error_context(_("While comparing this previously seen transaction:"));
|
||||||
|
add_error_context(source_context(other->pos->pathname,
|
||||||
|
other->pos->beg_pos,
|
||||||
|
other->pos->end_pos, "> "));
|
||||||
|
add_error_context(_("to this later transaction:"));
|
||||||
|
add_error_context(source_context(xact->pos->pathname,
|
||||||
|
xact->pos->beg_pos,
|
||||||
|
xact->pos->end_pos, "> "));
|
||||||
|
throw_(std::runtime_error,
|
||||||
|
_f("Transactions with the same UUID must have equivalent postings"));
|
||||||
|
}
|
||||||
|
|
||||||
xact->journal = NULL;
|
xact->journal = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ public:
|
||||||
|
|
||||||
enum checking_style_t {
|
enum checking_style_t {
|
||||||
CHECK_PERMISSIVE,
|
CHECK_PERMISSIVE,
|
||||||
|
CHECK_NORMAL,
|
||||||
CHECK_WARNING,
|
CHECK_WARNING,
|
||||||
CHECK_ERROR
|
CHECK_ERROR
|
||||||
} checking_style;
|
} checking_style;
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public:
|
||||||
#define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator
|
#define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator
|
||||||
#define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@)
|
#define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@)
|
||||||
#define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting
|
#define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting
|
||||||
|
#define POST_DEFERRED 0x1000 // the account was specified with <angles>
|
||||||
|
|
||||||
xact_t * xact; // only set for posts of regular xacts
|
xact_t * xact; // only set for posts of regular xacts
|
||||||
account_t * account;
|
account_t * account;
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,6 @@ std::size_t session_t::read_data(const string& master_account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HANDLED(explicit))
|
|
||||||
journal->force_checking = true;
|
|
||||||
if (HANDLED(check_payees))
|
|
||||||
journal->check_payees = true;
|
|
||||||
if (HANDLED(day_break))
|
if (HANDLED(day_break))
|
||||||
journal->day_break = true;
|
journal->day_break = true;
|
||||||
|
|
||||||
|
|
@ -118,14 +114,20 @@ std::size_t session_t::read_data(const string& master_account)
|
||||||
if (HANDLED(no_aliases))
|
if (HANDLED(no_aliases))
|
||||||
journal->no_aliases = true;
|
journal->no_aliases = true;
|
||||||
|
|
||||||
|
if (HANDLED(explicit))
|
||||||
|
journal->force_checking = true;
|
||||||
|
if (HANDLED(check_payees))
|
||||||
|
journal->check_payees = true;
|
||||||
|
|
||||||
if (HANDLED(permissive))
|
if (HANDLED(permissive))
|
||||||
journal->checking_style = journal_t::CHECK_PERMISSIVE;
|
journal->checking_style = journal_t::CHECK_PERMISSIVE;
|
||||||
else if (HANDLED(pedantic))
|
else if (HANDLED(pedantic))
|
||||||
journal->checking_style = journal_t::CHECK_ERROR;
|
journal->checking_style = journal_t::CHECK_ERROR;
|
||||||
else if (HANDLED(strict))
|
else if (HANDLED(strict))
|
||||||
journal->checking_style = journal_t::CHECK_WARNING;
|
journal->checking_style = journal_t::CHECK_WARNING;
|
||||||
else if (HANDLED(value_expr_))
|
|
||||||
journal->value_expr = HANDLER(value_expr_).str();
|
if (HANDLED(value_expr_))
|
||||||
|
journal->value_expr = HANDLER(value_expr_).str();
|
||||||
|
|
||||||
#if HAVE_BOOST_SERIALIZATION
|
#if HAVE_BOOST_SERIALIZATION
|
||||||
optional<archive_t> cache;
|
optional<archive_t> cache;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,6 @@
|
||||||
#define Ledger_VERSION_PATCH @Ledger_VERSION_PATCH@
|
#define Ledger_VERSION_PATCH @Ledger_VERSION_PATCH@
|
||||||
#define Ledger_VERSION_DATE @Ledger_VERSION_DATE@
|
#define Ledger_VERSION_DATE @Ledger_VERSION_DATE@
|
||||||
|
|
||||||
#define HAVE_CXX11 @HAVE_CXX11@
|
|
||||||
|
|
||||||
#define HAVE_EDIT @HAVE_EDIT@
|
#define HAVE_EDIT @HAVE_EDIT@
|
||||||
#define HAVE_GETTEXT @HAVE_GETTEXT@
|
#define HAVE_GETTEXT @HAVE_GETTEXT@
|
||||||
|
|
||||||
|
|
@ -160,7 +158,6 @@ typedef std::ostream::pos_type ostream_pos_type;
|
||||||
|
|
||||||
#include <gmp.h>
|
#include <gmp.h>
|
||||||
#include <mpfr.h>
|
#include <mpfr.h>
|
||||||
#include "sha1.h"
|
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
|
||||||
#if HAVE_EDIT
|
#if HAVE_EDIT
|
||||||
|
|
|
||||||
|
|
@ -77,16 +77,18 @@ namespace {
|
||||||
std::istream& in;
|
std::istream& in;
|
||||||
instance_t * parent;
|
instance_t * parent;
|
||||||
std::list<application_t> apply_stack;
|
std::list<application_t> apply_stack;
|
||||||
|
bool no_assertions;
|
||||||
#if defined(TIMELOG_SUPPORT)
|
#if defined(TIMELOG_SUPPORT)
|
||||||
time_log_t timelog;
|
time_log_t timelog;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
instance_t(parse_context_stack_t& _context_stack,
|
instance_t(parse_context_stack_t& _context_stack,
|
||||||
parse_context_t& _context,
|
parse_context_t& _context,
|
||||||
instance_t * _parent = NULL)
|
instance_t * _parent = NULL,
|
||||||
|
const bool _no_assertions = false)
|
||||||
: context_stack(_context_stack), context(_context),
|
: context_stack(_context_stack), context(_context),
|
||||||
in(*context.stream.get()), parent(_parent),
|
in(*context.stream.get()), parent(_parent),
|
||||||
timelog(context) {}
|
no_assertions(_no_assertions), timelog(context) {}
|
||||||
|
|
||||||
virtual string description() {
|
virtual string description() {
|
||||||
return _("textual parser");
|
return _("textual parser");
|
||||||
|
|
@ -779,8 +781,8 @@ void instance_t::include_directive(char * line)
|
||||||
context_stack.get_current().master = master;
|
context_stack.get_current().master = master;
|
||||||
context_stack.get_current().scope = scope;
|
context_stack.get_current().scope = scope;
|
||||||
try {
|
try {
|
||||||
instance_t instance(context_stack,
|
instance_t instance(context_stack, context_stack.get_current(),
|
||||||
context_stack.get_current(), this);
|
this, no_assertions);
|
||||||
instance.apply_stack.push_front(application_t("account", master));
|
instance.apply_stack.push_front(application_t("account", master));
|
||||||
instance.parse();
|
instance.parse();
|
||||||
}
|
}
|
||||||
|
|
@ -1430,6 +1432,12 @@ post_t * instance_t::parse_post(char * line,
|
||||||
}
|
}
|
||||||
p++; e--;
|
p++; e--;
|
||||||
}
|
}
|
||||||
|
else if (*p == '<' && *(e - 1) == '>') {
|
||||||
|
post->add_flags(POST_DEFERRED);
|
||||||
|
DEBUG("textual.parse", "line " << context.linenum << ": "
|
||||||
|
<< "Parsed a deferred account name");
|
||||||
|
p++; e--;
|
||||||
|
}
|
||||||
|
|
||||||
string name(p, static_cast<string::size_type>(e - p));
|
string name(p, static_cast<string::size_type>(e - p));
|
||||||
DEBUG("textual.parse", "line " << context.linenum << ": "
|
DEBUG("textual.parse", "line " << context.linenum << ": "
|
||||||
|
|
@ -1601,22 +1609,25 @@ post_t * instance_t::parse_post(char * line,
|
||||||
"line " << context.linenum << ": " << "post amount = " << amt);
|
"line " << context.linenum << ": " << "post amount = " << amt);
|
||||||
|
|
||||||
amount_t diff = amt;
|
amount_t diff = amt;
|
||||||
|
amount_t tot;
|
||||||
|
|
||||||
switch (account_total.type()) {
|
switch (account_total.type()) {
|
||||||
case value_t::AMOUNT:
|
case value_t::AMOUNT:
|
||||||
diff -= account_total.as_amount();
|
tot = account_total.as_amount();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case value_t::BALANCE:
|
case value_t::BALANCE:
|
||||||
if (optional<amount_t> comm_bal =
|
if (optional<amount_t> comm_bal =
|
||||||
account_total.as_balance().commodity_amount(amt.commodity()))
|
account_total.as_balance().commodity_amount(amt.commodity()))
|
||||||
diff -= *comm_bal;
|
tot = *comm_bal;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diff -= tot;
|
||||||
|
|
||||||
DEBUG("post.assign",
|
DEBUG("post.assign",
|
||||||
"line " << context.linenum << ": " << "diff = " << diff);
|
"line " << context.linenum << ": " << "diff = " << diff);
|
||||||
DEBUG("textual.parse", "line " << context.linenum << ": "
|
DEBUG("textual.parse", "line " << context.linenum << ": "
|
||||||
|
|
@ -1625,8 +1636,10 @@ post_t * instance_t::parse_post(char * line,
|
||||||
if (! diff.is_zero()) {
|
if (! diff.is_zero()) {
|
||||||
if (! post->amount.is_null()) {
|
if (! post->amount.is_null()) {
|
||||||
diff -= post->amount;
|
diff -= post->amount;
|
||||||
if (! diff.is_zero())
|
if (! no_assertions && ! diff.is_zero())
|
||||||
throw_(parse_error, _f("Balance assertion off by %1%") % diff);
|
throw_(parse_error,
|
||||||
|
_f("Balance assertion off by %1% (expected to see %2%)")
|
||||||
|
% diff % tot);
|
||||||
} else {
|
} else {
|
||||||
post->amount = diff;
|
post->amount = diff;
|
||||||
DEBUG("textual.parse", "line " << context.linenum << ": "
|
DEBUG("textual.parse", "line " << context.linenum << ": "
|
||||||
|
|
@ -1909,13 +1922,17 @@ std::size_t journal_t::read_textual(parse_context_stack_t& context_stack)
|
||||||
{
|
{
|
||||||
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
|
||||||
{
|
{
|
||||||
instance_t instance(context_stack, context_stack.get_current());
|
instance_t instance(context_stack, context_stack.get_current(), NULL,
|
||||||
|
checking_style == journal_t::CHECK_PERMISSIVE);
|
||||||
instance.apply_stack.push_front
|
instance.apply_stack.push_front
|
||||||
(application_t("account", context_stack.get_current().master));
|
(application_t("account", context_stack.get_current().master));
|
||||||
instance.parse();
|
instance.parse();
|
||||||
}
|
}
|
||||||
TRACE_STOP(parsing_total, 1);
|
TRACE_STOP(parsing_total, 1);
|
||||||
|
|
||||||
|
// Apply any deferred postings at this time
|
||||||
|
master->apply_deferred_posts();
|
||||||
|
|
||||||
// These tracers were started in textual.cc
|
// These tracers were started in textual.cc
|
||||||
TRACE_FINISH(xact_text, 1);
|
TRACE_FINISH(xact_text, 1);
|
||||||
TRACE_FINISH(xact_details, 1);
|
TRACE_FINISH(xact_details, 1);
|
||||||
|
|
|
||||||
15
src/utils.h
15
src/utils.h
|
|
@ -44,6 +44,8 @@
|
||||||
#ifndef _UTILS_H
|
#ifndef _UTILS_H
|
||||||
#define _UTILS_H
|
#define _UTILS_H
|
||||||
|
|
||||||
|
#include <boost/uuid/sha1.hpp>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Default values
|
* @name Default values
|
||||||
*/
|
*/
|
||||||
|
|
@ -483,11 +485,7 @@ inline void check_for_signal() {
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
#define foreach BOOST_FOREACH
|
#define foreach BOOST_FOREACH
|
||||||
#if HAVE_CXX11
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
#else
|
|
||||||
#define unique_ptr std::auto_ptr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
|
@ -625,11 +623,12 @@ inline string to_hex(unsigned int * message_digest, const int len = 1)
|
||||||
|
|
||||||
inline string sha1sum(const string& str)
|
inline string sha1sum(const string& str)
|
||||||
{
|
{
|
||||||
SHA1 sha;
|
boost::uuids::detail::sha1 sha;
|
||||||
sha.Reset();
|
|
||||||
sha << str.c_str();
|
sha.process_bytes(str.c_str(), str.length());
|
||||||
|
|
||||||
unsigned int message_digest[5];
|
unsigned int message_digest[5];
|
||||||
sha.Result(message_digest);
|
sha.get_digest(message_digest);
|
||||||
return to_hex(message_digest, 5);
|
return to_hex(message_digest, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,10 @@ bool xact_base_t::finalize()
|
||||||
some_null = true;
|
some_null = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
post->account->add_post(post);
|
if (post->has_flags(POST_DEFERRED))
|
||||||
|
post->account->add_deferred_post(id(), post);
|
||||||
|
else
|
||||||
|
post->account->add_post(post);
|
||||||
|
|
||||||
post->xdata().add_flags(POST_EXT_VISITED);
|
post->xdata().add_flags(POST_EXT_VISITED);
|
||||||
post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
|
post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,17 @@ add_subdirectory(manual)
|
||||||
add_subdirectory(baseline)
|
add_subdirectory(baseline)
|
||||||
add_subdirectory(regress)
|
add_subdirectory(regress)
|
||||||
|
|
||||||
if(PYTHONINTERP_FOUND)
|
# jww (2014-04-17): This is temporary until we find a fix.
|
||||||
set(_class DocTests)
|
#if(PYTHONINTERP_FOUND)
|
||||||
file(GLOB ${_class}_TESTS ${PROJECT_SOURCE_DIR}/doc/*.texi)
|
# set(_class DocTests)
|
||||||
foreach(TestFile ${${_class}_TESTS})
|
# file(GLOB ${_class}_TESTS ${PROJECT_SOURCE_DIR}/doc/*.texi)
|
||||||
get_filename_component(TestFile_Name ${TestFile} NAME_WE)
|
# foreach(TestFile ${${_class}_TESTS})
|
||||||
add_test(${_class}Test_${TestFile_Name}
|
# get_filename_component(TestFile_Name ${TestFile} NAME_WE)
|
||||||
${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/test/DocTests.py
|
# add_test(${_class}Test_${TestFile_Name}
|
||||||
--ledger ${LEDGER_LOCATION} --file ${TestFile})
|
# ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/test/DocTests.py
|
||||||
set_target_properties(check PROPERTIES DEPENDS ${_class}Test_${TestFile_Name})
|
# --ledger ${LEDGER_LOCATION} --file ${TestFile})
|
||||||
endforeach()
|
# set_target_properties(check PROPERTIES DEPENDS ${_class}Test_${TestFile_Name})
|
||||||
endif()
|
# endforeach()
|
||||||
|
#endif()
|
||||||
|
|
||||||
### CMakeLists.txt ends here
|
### CMakeLists.txt ends here
|
||||||
|
|
|
||||||
60
test/baseline/feat-balance_assert_split.test
Normal file
60
test/baseline/feat-balance_assert_split.test
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
;; a.dat
|
||||||
|
|
||||||
|
2012-01-01 Test
|
||||||
|
Expenses:Unknown $100.00
|
||||||
|
Liabilities:MasterCard
|
||||||
|
|
||||||
|
2012-01-02 Test
|
||||||
|
Expenses:Unknown $100.00
|
||||||
|
Liabilities:MasterCard
|
||||||
|
|
||||||
|
2012-01-03 Test
|
||||||
|
Expenses:Unknown $100.00
|
||||||
|
Liabilities:MasterCard
|
||||||
|
|
||||||
|
2012-01-04 Test
|
||||||
|
; UUID: foo
|
||||||
|
Liabilities:MasterCard $150.00 = $-300
|
||||||
|
<Assets:Checking>
|
||||||
|
|
||||||
|
2012-01-04 Test
|
||||||
|
; UUID: bar
|
||||||
|
Liabilities:MasterCard $150.00 = $0
|
||||||
|
<Assets:Checking>
|
||||||
|
|
||||||
|
2012-01-04 Test
|
||||||
|
; UUID: baz
|
||||||
|
Liabilities:MasterCard $150.00 = $0
|
||||||
|
<Assets:Checking>
|
||||||
|
|
||||||
|
;; b.dat
|
||||||
|
|
||||||
|
2012-01-01 Test
|
||||||
|
Assets:Checking $150.00
|
||||||
|
Income
|
||||||
|
|
||||||
|
2012-01-02 Test
|
||||||
|
Assets:Checking $150.00
|
||||||
|
Income
|
||||||
|
|
||||||
|
2012-01-03 Test
|
||||||
|
Assets:Checking $150.00
|
||||||
|
Income
|
||||||
|
|
||||||
|
2012-01-04 Test
|
||||||
|
; UUID: foo
|
||||||
|
Liabilities:MasterCard $150.00
|
||||||
|
Assets:Checking $-150.00 = $300.00
|
||||||
|
|
||||||
|
2012-01-04 Test
|
||||||
|
; UUID: bar
|
||||||
|
Liabilities:MasterCard $150.00
|
||||||
|
Assets:Checking $-150.00 = $150.00
|
||||||
|
|
||||||
|
test balance
|
||||||
|
$300.00 Expenses:Unknown
|
||||||
|
$-450.00 Income
|
||||||
|
$150.00 Liabilities:MasterCard
|
||||||
|
--------------------
|
||||||
|
0
|
||||||
|
end test
|
||||||
|
|
@ -4,8 +4,8 @@ flavor=$1
|
||||||
shift 1
|
shift 1
|
||||||
|
|
||||||
JOBS=-j$(sysctl -n hw.activecpu)
|
JOBS=-j$(sysctl -n hw.activecpu)
|
||||||
OPTIONS="$flavor --debug --python --ninja --doxygen $JOBS"
|
#OPTIONS="$flavor --debug --python --ninja --doxygen $JOBS"
|
||||||
OPTIONS="$OPTIONS --prefix /usr/local/Cellar/ledger/HEAD"
|
OPTIONS="$flavor --debug --ninja $JOBS"
|
||||||
|
|
||||||
time ( \
|
time ( \
|
||||||
cd ~/src/ledger ; \
|
cd ~/src/ledger ; \
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue