summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xacprep58
-rw-r--r--lib/Makefile17
-rw-r--r--lib/sha1.cpp1178
-rw-r--r--lib/sha1.h178
-rw-r--r--lisp/ledger.el18
-rw-r--r--src/expr.h6
-rw-r--r--src/parser.cc4
-rw-r--r--src/parser.h8
-rw-r--r--src/query.cc55
-rw-r--r--src/query.h6
-rw-r--r--src/report.h2
-rw-r--r--src/token.cc108
-rw-r--r--src/token.h9
13 files changed, 892 insertions, 755 deletions
diff --git a/acprep b/acprep
index f260edcb..e7d8b6d4 100755
--- a/acprep
+++ b/acprep
@@ -254,8 +254,8 @@ class CommandLineApp(object):
force_exit = True # If true, always ends run() with sys.exit()
log_handler = None
darwin_gcc = False
- boost_version = "1_47_0"
- boost_major = "1_47"
+ boost_version = "1_48_0"
+ boost_major = "1_48"
options = {
'debug': False,
@@ -484,9 +484,9 @@ class PrepareBuild(CommandLineApp):
op.add_option('', '--clang', action='store_true',
dest='use_clang', default=False,
help='Use the Clang C++ compiler')
- op.add_option('', '--glibcxx-debug', action='store_true',
- dest='use_glibcxx_debug', default=False,
- help='Define _GLIBCXX_DEBUG=1 during compilation')
+ #op.add_option('', '--glibcxx-debug', action='store_true',
+ # dest='use_glibcxx_debug', default=False,
+ # help='Define _GLIBCXX_DEBUG=1 during compilation')
op.add_option('', '--help', action="callback",
callback=self.option_help,
help='Show this help text')
@@ -523,9 +523,12 @@ class PrepareBuild(CommandLineApp):
op.add_option('', '--gcc46', action='store_true',
dest='gcc46', default=False,
help='Require the use of gcc 4.6')
+ op.add_option('', '--gcc47', action='store_true',
+ dest='gcc47', default=False,
+ help='Require the use of gcc 4.7')
op.add_option('', '--cpp0x', action='store_true',
dest='cpp0x', default=False,
- help='Use C++0x extensions (requires Clang or gcc 4.6)')
+ help='Use C++0x extensions (requires Clang or gcc 4.6/7)')
op.add_option('', '--output', metavar='DIR', action="callback",
callback=self.option_output,
help='Build in the specified directory')
@@ -709,9 +712,9 @@ class PrepareBuild(CommandLineApp):
self.log.info("Build directory => " + self.build_directory())
self.log.info("Need to run configure => " +
str(self.need_to_run_configure()))
- self.log.info("Use _GLIBCXX_DEBUG => " +
- str(self.options.use_glibcxx_debug
- and not self.options.use_clang))
+ #self.log.info("Use _GLIBCXX_DEBUG => " +
+ # str(self.options.use_glibcxx_debug
+ # and not self.options.use_clang))
self.log.info("Use pre-compiled headers => " +
str('--enable-pch' in conf_args))
@@ -1025,8 +1028,8 @@ class PrepareBuild(CommandLineApp):
self.log.debug('Using Boost ident: %s/%s' %
(self.boost_inc_ident, self.boost_lib_ident))
- if self.boost_lib_ident != "xgcc42":
- self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
+ #if self.boost_lib_ident != "xgcc42":
+ # self.CPPFLAGS.append('-D_GLIBCXX_FULLY_DYNAMIC_STRING=1')
if self.current_flavor == 'debug':
if exists('/usr/local/stow/icu-%s/include' % self.boost_inc_ident):
@@ -1077,26 +1080,31 @@ class PrepareBuild(CommandLineApp):
self.current_flavor == 'default') and \
not self.options.gcc45 and \
not self.options.gcc46 and \
+ not self.options.gcc47 and \
exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2'
self.envvars['CXX'] = '/usr/bin/g++-4.2'
self.envvars['LD'] = '/usr/bin/g++-4.2'
self.darwin_gcc = True
+ elif exists('/usr/local/bin/g++-mp-4.7') and \
+ self.options.gcc47:
+ self.envvars['CC'] = '/usr/local/bin/gcc-mp-4.7'
+ self.envvars['CXX'] = '/usr/local/bin/g++-mp-4.7'
+ self.envvars['LD'] = '/usr/local/bin/g++-mp-4.7'
+ elif exists('/opt/local/bin/g++-mp-4.7') and \
+ self.options.gcc47:
+ self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.7'
+ self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.7'
+ self.envvars['LD'] = '/opt/local/bin/g++-mp-4.7'
elif exists('/opt/local/bin/g++-mp-4.6') and \
self.options.gcc46:
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.6'
- #if exists('/Users/johnw/bin/gfilt'):
- # self.envvars['CXX'] = '/Users/johnw/bin/gfilt'
- #else:
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.6'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.6'
elif exists('/opt/local/bin/g++-mp-4.5') and \
self.options.gcc45:
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.5'
- if exists('/Users/johnw/bin/gfilt'):
- self.envvars['CXX'] = '/Users/johnw/bin/gfilt'
- else:
- self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.5'
+ self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.5'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.5'
elif exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2'
@@ -1280,9 +1288,10 @@ class PrepareBuild(CommandLineApp):
def locate_darwin_libraries(self):
if self.current_flavor == 'debug':
- if self.options.use_glibcxx_debug and not self.options.use_clang:
- self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
- self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
+ #if self.options.use_glibcxx_debug and not self.options.use_clang:
+ # self.log.debug('We are using GLIBCXX_DEBUG, so setting up flags')
+ # self.CPPFLAGS.append('-D_GLIBCXX_DEBUG=1')
+ # pass
if self.boost_info.configure(
home_path = '/usr/local/stow/boost_%s-%s' % \
@@ -1330,7 +1339,7 @@ class PrepareBuild(CommandLineApp):
def setup_flavor_debug(self):
self.configure_args.append('--enable-debug')
- if self.options.gcc45 or self.options.gcc46:
+ if self.options.gcc45 or self.options.gcc46 or self.options.gcc47:
self.CXXFLAGS.append('-g2')
self.CXXFLAGS.append('-ggdb')
self.LDFLAGS.append('-g2')
@@ -1355,6 +1364,11 @@ class PrepareBuild(CommandLineApp):
# self.CXXFLAGS.append(i)
# self.CFLAGS.append(i)
# self.LDFLAGS.append(i)
+ #if self.options.gcc47:
+ # for i in ['-flto']:
+ # self.CXXFLAGS.append(i)
+ # self.CFLAGS.append(i)
+ # self.LDFLAGS.append(i)
if self.darwin_gcc:
self.option_no_pch()
if '--disable-shared' in self.configure_args:
diff --git a/lib/Makefile b/lib/Makefile
index bc9611f0..d7b1071b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -6,7 +6,7 @@ STOW_ROOT = /usr/local/stow
PRODUCTS = $(HOME)/Products
GCC_VERSION = 4.6
-BOOST_VERSION = 1_47_0
+BOOST_VERSION = 1_48_0
CC = gcc-mp-$(GCC_VERSION)
ifeq ($(CC),clang)
@@ -20,20 +20,20 @@ LD = gcc-mp-$(GCC_VERSION)
DIR_SUFFIX = gcc$(subst .,,$(GCC_VERSION))
OPTJ = #-j8
endif
-CPPFLAGS = -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
-ifneq ($(CC),clang)
-CPPFLAGS += -D_GLIBCXX_DEBUG=1
-endif
+#CPPFLAGS = -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
+#ifneq ($(CC),clang)
+#CPPFLAGS += -D_GLIBCXX_DEBUG=1
+#endif
CFLAGS = $(CPPFLAGS) -g2 -ggdb
LDFLAGS = -g2 -ggdb
BOOST_SOURCE = boost-release
-BOOST_DEFINES = define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
+#BOOST_DEFINES = define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
ifeq ($(CC),clang)
BOOST_TOOLSET = clang
else
BOOST_TOOLSET = darwin
-BOOST_DEFINES += define=_GLIBCXX_DEBUG=1
+#BOOST_DEFINES += define=_GLIBCXX_DEBUG=1
endif
#BOOST_FLAGS = --architecture=x86 --address_model=32_64
BOOST_FLAGS = toolset=$(BOOST_TOOLSET) --layout=versioned \
@@ -56,8 +56,7 @@ boost-build: prepare-boost
(cd $(BOOST_SOURCE) && \
sh bootstrap.sh && \
./b2 $(OPTJ) debug --prefix=$(BOOST_STOW) \
- --build-dir=$(BOOST_BUILD) \
- $(BOOST_FLAGS) install)
+ --build-dir=$(BOOST_BUILD) $(BOOST_FLAGS) install)
icu-build:
-(cd icu/source; make distclean)
diff --git a/lib/sha1.cpp b/lib/sha1.cpp
index 8689d711..5610cd44 100644
--- a/lib/sha1.cpp
+++ b/lib/sha1.cpp
@@ -1,589 +1,589 @@
-/*
- * 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((unsigned 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((unsigned 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<char>((Length_High >> 24) & 0xFF);
- Message_Block[57] = static_cast<char>((Length_High >> 16) & 0xFF);
- Message_Block[58] = static_cast<char>((Length_High >> 8) & 0xFF);
- Message_Block[59] = static_cast<char>((Length_High) & 0xFF);
- Message_Block[60] = static_cast<char>((Length_Low >> 24) & 0xFF);
- Message_Block[61] = static_cast<char>((Length_Low >> 16) & 0xFF);
- Message_Block[62] = static_cast<char>((Length_Low >> 8) & 0xFF);
- Message_Block[63] = static_cast<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));
-}
+/*
+ * 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<char>((Length_High >> 24) & 0xFF);
+ Message_Block[57] = static_cast<char>((Length_High >> 16) & 0xFF);
+ Message_Block[58] = static_cast<char>((Length_High >> 8) & 0xFF);
+ Message_Block[59] = static_cast<char>((Length_High) & 0xFF);
+ Message_Block[60] = static_cast<char>((Length_Low >> 24) & 0xFF);
+ Message_Block[61] = static_cast<char>((Length_Low >> 16) & 0xFF);
+ Message_Block[62] = static_cast<char>((Length_Low >> 8) & 0xFF);
+ Message_Block[63] = static_cast<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));
+}
diff --git a/lib/sha1.h b/lib/sha1.h
index de28bbf0..0a12d0f3 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -1,89 +1,89 @@
-/*
- * 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
+/*
+ * 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
diff --git a/lisp/ledger.el b/lisp/ledger.el
index 2d15f090..56bc33cd 100644
--- a/lisp/ledger.el
+++ b/lisp/ledger.el
@@ -1316,6 +1316,24 @@ end of a ledger file which is included in some other file."
(expand-file-name ledger-master-file)
(buffer-file-name)))
+(easy-menu-define ledger-menu ledger-mode-map
+ "Ledger menu"
+ '("Ledger"
+ ["New entry" ledger-add-entry t]
+ ["Toggle cleared status of current entry" ledger-toggle-current-entry t]
+ ["Set default year for entry" ledger-set-year t]
+ ["Set default month for entry" ledger-set-month t]
+ "--"
+ ["Reconcile uncleared entries for account" ledger-reconcile t]
+ "--"
+ "Reports"
+ ["Run a report" ledger-report t]
+ ["Go to report buffer" ledger-report-goto t]
+ ["Edit defined reports" ledger-report-edit t]
+ ["Save report definition" ledger-report-save t]
+ ["Re-run ledger report" ledger-report-redo t]
+ ["Kill report buffer" ledger-report-kill t]))
+
(provide 'ledger)
;;; ledger.el ends here
diff --git a/src/expr.h b/src/expr.h
index a3ae5669..c4cd5dc5 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -49,15 +49,15 @@ namespace ledger {
class expr_t : public expr_base_t<value_t>
{
- struct token_t;
- class parser_t;
-
+ class parser_t;
typedef expr_base_t<value_t> base_type;
public:
+ struct token_t;
class op_t;
typedef intrusive_ptr<op_t> ptr_op_t;
typedef intrusive_ptr<const op_t> const_ptr_op_t;
+
protected:
ptr_op_t ptr;
diff --git a/src/parser.cc b/src/parser.cc
index f0085295..a18fa552 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -74,7 +74,7 @@ expr_t::parser_t::parse_value_term(std::istream& in,
case token_t::LPAREN:
node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL)
.minus_flags(PARSE_SINGLE));
- tok = next_token(in, tflags, ')');
+ tok = next_token(in, tflags, token_t::RPAREN);
break;
default:
@@ -367,7 +367,7 @@ expr_t::parser_t::parse_querycolon_expr(std::istream& in,
throw_(parse_error,
_("%1 operator not followed by argument") << tok.symbol);
- next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT), ':');
+ next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT), token_t::COLON);
prev = node->right();
ptr_op_t subnode = new op_t(op_t::O_COLON);
subnode->set_left(prev);
diff --git a/src/parser.h b/src/parser.h
index 9a65765d..09e12d95 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -53,11 +53,15 @@ class expr_t::parser_t : public noncopyable
mutable bool use_lookahead;
token_t& next_token(std::istream& in, const parse_flags_t& tflags,
- const char expecting = '\0') const {
+ const optional<token_t::kind_t>& expecting = none) const {
if (use_lookahead)
use_lookahead = false;
else
- lookahead.next(in, tflags, expecting);
+ lookahead.next(in, tflags);
+
+ if (expecting && lookahead.kind != *expecting)
+ lookahead.expected(*expecting);
+
return lookahead;
}
diff --git a/src/query.cc b/src/query.cc
index 5c11add5..b0f8d691 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -36,7 +36,8 @@
namespace ledger {
-query_t::lexer_t::token_t query_t::lexer_t::next_token()
+query_t::lexer_t::token_t
+query_t::lexer_t::next_token(query_t::lexer_t::token_t::kind_t tok_context)
{
if (token_cache.kind != token_t::UNKNOWN) {
token_t tok = token_cache;
@@ -105,11 +106,19 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token()
case '\r':
case '\n':
if (++arg_i == arg_end)
- return next_token();
+ return next_token(tok_context);
goto resume;
- case '(': ++arg_i; return token_t(token_t::LPAREN);
- case ')': ++arg_i; return token_t(token_t::RPAREN);
+ case '(':
+ ++arg_i;
+ if (tok_context == token_t::TOK_EXPR)
+ consume_whitespace = true;
+ return token_t(token_t::LPAREN);
+ case ')':
+ ++arg_i;
+ if (tok_context == token_t::TOK_EXPR)
+ consume_whitespace = false;
+ return token_t(token_t::RPAREN);
case '&': ++arg_i; return token_t(token_t::TOK_AND);
case '|': ++arg_i; return token_t(token_t::TOK_OR);
case '!': ++arg_i; return token_t(token_t::TOK_NOT);
@@ -118,7 +127,7 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token()
case '%': ++arg_i; return token_t(token_t::TOK_META);
case '=':
++arg_i;
- consume_next_arg = true;
+ consume_next = true;
return token_t(token_t::TOK_EQ);
case '\\':
@@ -143,8 +152,10 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token()
ident.push_back(*arg_i);
break;
- case '(':
case ')':
+ if (! consume_next && tok_context == token_t::TOK_EXPR)
+ goto test_ident;
+ case '(':
case '&':
case '|':
case '!':
@@ -152,7 +163,7 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token()
case '#':
case '%':
case '=':
- if (! consume_next)
+ if (! consume_next && tok_context != token_t::TOK_EXPR)
goto test_ident;
// fall through...
default:
@@ -247,7 +258,7 @@ query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_contex
{
expr_t::ptr_op_t node;
- lexer_t::token_t tok = lexer.next_token();
+ lexer_t::token_t tok = lexer.next_token(tok_context);
switch (tok.kind) {
case lexer_t::token_t::TOK_SHOW:
case lexer_t::token_t::TOK_ONLY:
@@ -288,10 +299,10 @@ query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_contex
expr_t::ptr_op_t arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
arg1->set_value(mask_t(*tok.value));
- tok = lexer.peek_token();
+ tok = lexer.peek_token(tok_context);
if (tok.kind == lexer_t::token_t::TOK_EQ) {
- tok = lexer.next_token();
- tok = lexer.next_token();
+ tok = lexer.next_token(tok_context);
+ tok = lexer.next_token(tok_context);
if (tok.kind != lexer_t::token_t::TERM)
throw_(parse_error,
_("Metadata equality operator not followed by term"));
@@ -340,7 +351,7 @@ query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_contex
case lexer_t::token_t::LPAREN:
node = parse_query_expr(tok_context, true);
- tok = lexer.next_token();
+ tok = lexer.next_token(tok_context);
if (tok.kind != lexer_t::token_t::RPAREN)
tok.expected(')');
break;
@@ -358,7 +369,7 @@ query_t::parser_t::parse_unary_expr(lexer_t::token_t::kind_t tok_context)
{
expr_t::ptr_op_t node;
- lexer_t::token_t tok = lexer.next_token();
+ lexer_t::token_t tok = lexer.next_token(tok_context);
switch (tok.kind) {
case lexer_t::token_t::TOK_NOT: {
expr_t::ptr_op_t term(parse_query_term(tok_context));
@@ -385,7 +396,7 @@ query_t::parser_t::parse_and_expr(lexer_t::token_t::kind_t tok_context)
{
if (expr_t::ptr_op_t node = parse_unary_expr(tok_context)) {
while (true) {
- lexer_t::token_t tok = lexer.next_token();
+ lexer_t::token_t tok = lexer.next_token(tok_context);
if (tok.kind == lexer_t::token_t::TOK_AND) {
expr_t::ptr_op_t prev(node);
node = new expr_t::op_t(expr_t::op_t::O_AND);
@@ -409,7 +420,7 @@ query_t::parser_t::parse_or_expr(lexer_t::token_t::kind_t tok_context)
{
if (expr_t::ptr_op_t node = parse_and_expr(tok_context)) {
while (true) {
- lexer_t::token_t tok = lexer.next_token();
+ lexer_t::token_t tok = lexer.next_token(tok_context);
if (tok.kind == lexer_t::token_t::TOK_OR) {
expr_t::ptr_op_t prev(node);
node = new expr_t::op_t(expr_t::op_t::O_OR);
@@ -451,13 +462,13 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
(query_map_t::value_type
(QUERY_LIMIT, predicate_t(limiter, what_to_keep).print_to_str()));
- lexer_t::token_t tok = lexer.peek_token();
+ lexer_t::token_t tok = lexer.peek_token(tok_context);
while (tok.kind != lexer_t::token_t::END_REACHED) {
switch (tok.kind) {
case lexer_t::token_t::TOK_SHOW:
case lexer_t::token_t::TOK_ONLY:
case lexer_t::token_t::TOK_BOLD: {
- lexer.next_token();
+ lexer.next_token(tok_context);
kind_t kind;
switch (tok.kind) {
@@ -496,7 +507,7 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
case lexer_t::token_t::TOK_FOR:
case lexer_t::token_t::TOK_SINCE:
case lexer_t::token_t::TOK_UNTIL: {
- tok = lexer.next_token();
+ tok = lexer.next_token(tok_context);
string for_string;
@@ -506,10 +517,10 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
for_string = "until";
lexer.consume_next_arg = true;
- tok = lexer.peek_token();
+ tok = lexer.peek_token(tok_context);
while (tok.kind != lexer_t::token_t::END_REACHED) {
- tok = lexer.next_token();
+ tok = lexer.next_token(tok_context);
assert(tok.kind == lexer_t::token_t::TERM);
if (*tok.value == "show" || *tok.value == "bold" ||
@@ -526,7 +537,7 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
for_string += *tok.value;
lexer.consume_next_arg = true;
- tok = lexer.peek_token();
+ tok = lexer.peek_token(tok_context);
}
if (! for_string.empty())
@@ -538,7 +549,7 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
goto done;
}
- tok = lexer.peek_token();
+ tok = lexer.peek_token(tok_context);
}
done:
;
diff --git a/src/query.h b/src/query.h
index b5b3b0fc..aca31b61 100644
--- a/src/query.h
+++ b/src/query.h
@@ -222,14 +222,14 @@ public:
TRACE_DTOR(query_t::lexer_t);
}
- token_t next_token();
+ token_t next_token(token_t::kind_t tok_context = token_t::UNKNOWN);
void push_token(token_t tok) {
assert(token_cache.kind == token_t::UNKNOWN);
token_cache = tok;
}
- token_t peek_token() {
+ token_t peek_token(token_t::kind_t tok_context = token_t::UNKNOWN) {
if (token_cache.kind == token_t::UNKNOWN)
- token_cache = next_token();
+ token_cache = next_token(tok_context);
return token_cache;
}
};
diff --git a/src/report.h b/src/report.h
index 58c12f24..5b403205 100644
--- a/src/report.h
+++ b/src/report.h
@@ -770,7 +770,7 @@ public:
parent->HANDLER(total_)
.set_expr(string("--percent"),
"((is_account&parent&parent.total)?"
- " percent(scrub(total), scrub(parent.total)):0");
+ " percent(scrub(total), scrub(parent.total)):0)");
});
OPTION__
diff --git a/src/token.cc b/src/token.cc
index 735f5825..fe7ce7cd 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -137,8 +137,7 @@ void expr_t::token_t::parse_ident(std::istream& in)
value.set_string(buf);
}
-void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
- const char expecting)
+void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags)
{
if (in.eof()) {
kind = TOK_EOF;
@@ -230,7 +229,6 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
break;
}
-#if 0
case '{': {
in.get(c);
amount_t temp;
@@ -243,7 +241,6 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
value = temp;
break;
}
-#endif
case '!':
in.get(c);
@@ -427,7 +424,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
throw_(parse_error, _("Failed to reset input stream"));
c = static_cast<char>(in.peek());
- if (std::isdigit(c) || c == '.')
+ if (! std::isalpha(c))
expected('\0', c);
parse_ident(in);
@@ -436,7 +433,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
kind = ERROR;
symbol[0] = c;
symbol[1] = '\0';
- unexpected(expecting);
+ throw_(parse_error, _("Failed to parse identifier"));
}
} else {
if (! in.good()) {
@@ -505,10 +502,8 @@ void expr_t::token_t::unexpected(const char wanted)
}
}
-void expr_t::token_t::expected(char wanted, char c)
+void expr_t::token_t::expected(const char wanted, char c)
{
- kind = ERROR;
-
if (c == '\0' || c == -1) {
if (wanted == '\0' || wanted == -1)
throw_(parse_error, _("Unexpected end"));
@@ -518,8 +513,101 @@ void expr_t::token_t::expected(char wanted, char c)
if (wanted == '\0' || wanted == -1)
throw_(parse_error, _("Invalid char '%1'") << c);
else
- throw_(parse_error, _("Invalid char '%1' (wanted '%2')") << c << wanted);
+ throw_(parse_error,
+ _("Invalid char '%1' (wanted '%2')") << c << wanted);
+ }
+}
+
+void expr_t::token_t::expected(const kind_t wanted)
+{
+ try {
+ if (wanted == '\0' || wanted == -1)
+ throw_(parse_error, _("Invalid token '%1'") << *this);
+ else
+ throw_(parse_error,
+ _("Invalid token '%1' (wanted '%2')") << *this << wanted);
+ }
+ catch (...) {
+ kind = ERROR;
+ throw;
}
}
+std::ostream& operator<<(std::ostream& out, const expr_t::token_t::kind_t& kind)
+{
+ switch (kind) {
+ case expr_t::token_t::ERROR: out << "<error token>"; break;
+ case expr_t::token_t::VALUE: out << "<value>"; break;
+ case expr_t::token_t::IDENT: out << "<identifier>"; break;
+ case expr_t::token_t::MASK: out << "<regex mask>"; break;
+
+ case expr_t::token_t::LPAREN: out << "("; break;
+ case expr_t::token_t::RPAREN: out << ")"; break;
+ case expr_t::token_t::LBRACE: out << "{"; break;
+ case expr_t::token_t::RBRACE: out << "}"; break;
+
+ case expr_t::token_t::EQUAL: out << "=="; break;
+ case expr_t::token_t::NEQUAL: out << "!="; break;
+ case expr_t::token_t::LESS: out << "<"; break;
+ case expr_t::token_t::LESSEQ: out << "<="; break;
+ case expr_t::token_t::GREATER: out << ">"; break;
+ case expr_t::token_t::GREATEREQ: out << ">="; break;
+
+ case expr_t::token_t::ASSIGN: out << "="; break;
+ case expr_t::token_t::MATCH: out << "=~"; break;
+ case expr_t::token_t::NMATCH: out << "!~"; break;
+ case expr_t::token_t::MINUS: out << "-"; break;
+ case expr_t::token_t::PLUS: out << "+"; break;
+ case expr_t::token_t::STAR: out << "*"; break;
+ case expr_t::token_t::SLASH: out << "/"; break;
+ case expr_t::token_t::ARROW: out << "->"; break;
+ case expr_t::token_t::KW_DIV: out << "div"; break;
+
+ case expr_t::token_t::EXCLAM: out << "!"; break;
+ case expr_t::token_t::KW_AND: out << "and"; break;
+ case expr_t::token_t::KW_OR: out << "or"; break;
+ case expr_t::token_t::KW_MOD: out << "mod"; break;
+
+ case expr_t::token_t::KW_IF: out << "if"; break;
+ case expr_t::token_t::KW_ELSE: out << "else"; break;
+
+ case expr_t::token_t::QUERY: out << "?"; break;
+ case expr_t::token_t::COLON: out << ":"; break;
+
+ case expr_t::token_t::DOT: out << "."; break;
+ case expr_t::token_t::COMMA: out << ","; break;
+ case expr_t::token_t::SEMI: out << ";"; break;
+
+ case expr_t::token_t::TOK_EOF: out << "<end of input>"; break;
+ case expr_t::token_t::UNKNOWN: out << "<unknown>"; break;
+
+ default:
+ assert(false);
+ break;
+ }
+
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const expr_t::token_t& token)
+{
+ switch (token.kind) {
+ case expr_t::token_t::VALUE:
+ out << "<value '" << token.value << "'>";
+ break;
+ case expr_t::token_t::IDENT:
+ out << "<ident '" << token.value << "'>";
+ break;
+ case expr_t::token_t::MASK:
+ out << "<mask '" << token.value << "'>";
+ break;
+
+ default:
+ out << token.kind;
+ break;
+ }
+
+ return out;
+}
+
} // namespace ledger
diff --git a/src/token.h b/src/token.h
index 13a799cb..cbdf1258 100644
--- a/src/token.h
+++ b/src/token.h
@@ -123,13 +123,16 @@ struct expr_t::token_t : public noncopyable
int parse_reserved_word(std::istream& in);
void parse_ident(std::istream& in);
- void next(std::istream& in, const parse_flags_t& flags,
- const char expecting = '\0');
+ void next(std::istream& in, const parse_flags_t& flags);
void rewind(std::istream& in);
void unexpected(const char wanted = '\0');
- void expected(const char wanted, char c = '\0');
+ void expected(const char wanted, const char c = '\0');
+ void expected(const kind_t wanted);
};
+std::ostream& operator<<(std::ostream& out, const expr_t::token_t::kind_t& kind);
+std::ostream& operator<<(std::ostream& out, const expr_t::token_t& token);
+
} // namespace ledger
#endif // _TOKEN_H