diff options
-rwxr-xr-x | acprep | 58 | ||||
-rw-r--r-- | lib/Makefile | 17 | ||||
-rw-r--r-- | lib/sha1.cpp | 1178 | ||||
-rw-r--r-- | lib/sha1.h | 178 | ||||
-rw-r--r-- | lisp/ledger.el | 18 | ||||
-rw-r--r-- | src/expr.h | 6 | ||||
-rw-r--r-- | src/parser.cc | 4 | ||||
-rw-r--r-- | src/parser.h | 8 | ||||
-rw-r--r-- | src/query.cc | 55 | ||||
-rw-r--r-- | src/query.h | 6 | ||||
-rw-r--r-- | src/report.h | 2 | ||||
-rw-r--r-- | src/token.cc | 108 | ||||
-rw-r--r-- | src/token.h | 9 |
13 files changed, 892 insertions, 755 deletions
@@ -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)); +} @@ -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 @@ -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 |