Sunday, August 31, 2014

C++ Smart Pointers

C++ smart pointers are not a feature of the C++ language put a utilization of the language.  Consider the function below, which is translation of the C way of handling allocated resources:
bool function()
{
    Class *a {new Class};
    // ... do some work ...
    if (error)
    {
        delete a1;
        return false;
    }
    Class *b {new Class};
    // ... do some more work ...
    if (error)
    {
        delete b;
        delete a;
        return false;
    }
    // ... do final work ...
    delete b;
    delete a;
    return true;
}
Care must be taken to release the resources that were allocated to prevent memory leaks.  This puts the burden on the programmer to make sure resources are released.  Consider that if the class instances were local variables, their destructors would be called automatically when they go out of scope.  This is the basic idea of a smart pointer, consider this simple smart pointer class:
class SmartPtr
{
    Class *ptr;    // hold pointer to allocated resources
public:
    SmartPtr(Class *p) : ptr {p} {}
    ~SmartPtr() { delete ptr; }
    const Class *pointer() const { return ptr; }
};
The class holds the pointer to the allocated resource.  When the smart pointer instance goes out of scope, its destructor will release the resource it is holding.  The smart pointer provides access to the pointer it is holding.  This class can be made more elaborate and convenient (for example, allowing the pointer to be replaced, allowing the pointer to be cleared, providing the indirection and arrow operators so that it behaves like a pointer, etc.), but this definition is sufficient to show the basic concept of smart pointers.  The original function can be rewritten as:
bool function()
{
    SmartPtr a {new Class};
    // ... do some work ...
    if (error)
    {
        return false;
    }
    SmartPtr b {new Class};
    //
... do some more work ...
    if (error)
    {
        return false;
    }
    //
... do final work ...
    return true;
}
Note that it is no longer necessary to release the resources.  The new calls in the first function are known as naked, each of which requires a corresponding naked delete.  In the second function, the smart pointers hold the allocated resources (the new is enclosed).  When the smart pointer goes out of scope, it destructor is called releasing the resource.

Fortunately, very elaborate smart pointer classes have already been implemented.  In the C++11 version of the STL, there is the std::unique_ptr class, which is a more elaborate implementation of the class above.  Qt has the similar QScopedPointer class.

The C++11 STL also has the std::shared_ptr class, which is a smart pointer that can be shared.  These have a use count, which is incremented each time the pointer is copied (for example, put into a different list or stack).  When one of the copies is deleted, the use count is decremented.  When the use count reaches zero, the resource is automatically released.  Qt has the similar QSharePointer class.  These shared smart pointers will be used for the tokens, which get shared (in the RPN output list, done stack, holding stack, pending parentheses token, etc.).

Saturday, August 30, 2014

Memory Testing Issues

The next step is to start using C++ smart pointers (described in the next post).  One use for smart pointers will be to replace the complicated code used to track the handling of tokens and the reporting of various errors (for example, memory leaks for tokens not freed).  Smart pointers will make this code unnecessary.  Before starting I thought it was a good idea to make sure the memory test scripts still worked.

There were no memory errors reported when using Qt 4.8.1 (installed with Mint13 or Ubuntu 12.04) or Qt 4.8.2 (installed with the kubuntu backports to get the latest KDE).  However, when building the application with Qt 4.8.6 (the latest Qt 4.8 that was installed from source), memory errors were reported.  The CMake build file was set up to generate the error suppression file from a template using the detected version and directory of Qt.  This file was not tested with newer versions of Qt.

It appeared that with Qt 4.8.6, memory errors were reported differently (which was also the case with Qt 4.8.4, also built from source).  After examining the output for each version of Qt, a common error suppressions file template was created that works with each of these four versions of Qt (other versions were not tested).

As with GDB, valgrind (the memory testing utility) only supports the new debug symbols output from GCC 4.8.1 starting with version 3.8.0 (3.7.0 is installed in Mint13).  Version 3.9.0 is the latest available from source code.  However, version 3.7.0 appears to work fine, including within Qt Creator.  The new errors suppressions file also works with valgrind 3.9.0.  Click Continue... for details on installing 3.9.0 from source, but this shouldn't be necessary on Mint 13 (Unbuntu 12.04).  The valgrind 3.10.0.SVN installed on Mint 17 (Ubuntu 14.04) reports errors differently and does not work with this error suppression file (for now 3.9.0 would have to be installed from source).

[branch cpp11 commit a2069aae24]

Sunday, August 24, 2014

Qt Creator (GDB) No Watch Variables With GCC 4.8

The next set of changes are rather complicated and required debugging.  Upon reaching the first breakpoint, no variables were displayed in the Locals and Expressions debugging window in Qt Creator.  After a little research, the problem was determined to be with GCC 4.8.1, which is using a new format (named DWARF-4) to write debugging symbols to the executable.

The problem is that GDB (debugger) does not support this newer format, at least older versions prior to GDB 7.5.  Mint 13 (Ubuntu 12.04) has only version 7.4.  This problem does not affect Windows with the programs installed as recently described (see the Windows tagged posts).  The latest MSYS with MinGW has GDB 7.6.1 and MinGW-w64 has GDB 7.7.  Mint 17 (Ubuntu 14.04) is also fine with GDB 7.7.

There are two ways to solve this problem.  The GCC compiler has an option for generating the older DWARF-3 format debugging symbols.  Instead of permanently adding this option to the CMake build file, the following option can be added to the CMake command line or in Arguments field in the Run CMake wizard within Qt Creator:
-DCMAKE_CXX_FLAGS_DEBUG='-g -gdwarf-3'
The other solution is to build and install GDB from source code.  Click Continue... for details on the procedure for this.

Thursday, August 21, 2014

Token – Status As Enumeration Class

I misinterpreted how the compiler generates code for switch statements (caused by looking at disassembled output instead of assembler output of the compiler).  The compiler does not generate an if-elseif chain in circumstances where it doesn't simplify a switch statement to an array of return values (when the return values are simple types as previously described).

The compiler still generates an array for a switch statement, but instead of an array of return values (of simple types), it generates an array of pointers.  Each pointer is the address to the code for the case.  During run-time, the processor indexes on the expression of the switch into this array and jumps to the address.  While this is not space efficient, it is run-time efficient.

Unfortunately, for the token status enumeration, a single C style string constants cannot be used because each must be the result of the tr() translation function.  This was not necessary for the other enumeration to string functions because these are only used for testing (translation is not necessary).

The switch statement for converting a token status enumerator was put into the message function of the Token class.  This function previously returned an element from the static message array (which was removed).  The status enumeration was put into the Token class as an enumeration class therefore requiring the Token::Status:: scoping prefix on the status enumerators.  The _TokenStatus suffix was removed from each (the bug statuses did not have this prefix, but now require the scoping prefix).

The generation of the token status enumeration was removed from the auto-generation awk script and the token source file was removed as a dependency to the auto-generated enumerations header file.  Several of the token status enumerators were not being used and were removed.  The only auto-generated code remaining is for the code enumeration and the code enumerator to code name array.  These will be handled later when the Table class is redesigned.

[branch cpp11 commit cfed68f09b]

Wednesday, August 20, 2014

Token – Type As Enumeration Class

A series of changes were made to change the token type enumeration to an enumeration class because its size of enumerator was used to dimension several arrays.  The changes were put into several individual commits on a work branch, which were later combined (squashed using the interactive git rebase command) into a single commit and merged back to the cpp11 branch before pushing to GitHub.  Details of these changes follow.

1) Unrelated to the token type enumeration, the Table class convert code function was moved to the Token class.  This function contained arguments for a token with a data type and the desired data type to convert to.  It returned a conversion code.  However, it did not actually access the table.  Since codes are not part of the table (the table is only indexed by codes) and this function took a token pointer, it made more sense for this to be a Token member function.

2) Also unrelated to the token type enumeration, the auto-generated data type to string map was changed to a brute force static function with a switch statement in the test source file as described in the previous post(The compiler in-lined this function when set to release build.)  The generate map function was removed from the test names awk script and the dependency on the main header file was removed from the auto-generated test names source file from the CMake build file.

3) Two of the uses of the token type enumerator was the static has parentheses flag and precedence arrays used to determine if the token type has a parentheses and the precedence of the token type.  These arrays were initialized by the static initialize function.  These arrays were changed to unordered maps with initializer lists for their values.  Note that the maps do not contain values for all the token types.  When the map is accessed for one of these other token types, a new element will be added with the correct default values (false for the flag, zero for the precedence).  Since these maps are initialized, the initialize function was no longer needed and was removed.

4) The token type enumeration was changed to an enumeration class and was moved into the Token class where it belongs.  Outside of the Token class, the token type enumerators need a double scope as in the Constant_TokenType enumerator becomes Token::Type::Constant.

5) The auto-generated token type to string array was changed to a brute force function also.  (The compiler also in-lined this function.)  The find enumeration function in the test names awk script was now no longer used and so was removed and the dependency on the token header file was removed from the auto-generated test names source file from the CMake build file.

[branch cpp11 commit e7dc6a964a]

Tuesday, August 19, 2014

Better Enumerators To Strings Solution

Several enumerations need to be converted to strings for output during testing.  This was accomplished with an awk script that scanned source files for the enumerations and automatically generated a source file that contained C style string arrays of the enumerator names, which were indexed by an enumerator.  With enumeration classes, the enumerators can not be used as indexes to arrays.  Another solution was to generate an unordered map that can be indexed by the enumerators provided that a generic hash is defined for enumeration classes.

The method of automatically generating source code from source code is kludgy and should be eliminated.  Also, changing a source file read by an awk script forces the entire project to be rebuilt since all the source files are generally dependent on the auto-generated source file.  A different solution was needed.

Another solution is using a function that takes an enumerator value as input and returns the string using the brute force method with switch statement and returning a string for each case, for example:
const char *enumName(Enum value)
{
    switch (value)
    {
    case Enum::Value1:
        return "Value1";
    case Enum::Value2:
        return "Value2":
    ...
    case Enum::ValueN:
        return "ValueN":
    }
}
A good optimizing compiler will convert this switch statement to an array instead of a series of an if-elseif chain, which the GCC compiler does at the higher optimization levels.  However, there are some conditions that are required.  First, the compiler will only generate a look up array if the function is static (local to the source file where used).  Also, the return values need to be relatively simply types.

However, if the return type is QString and each return value is QString("Value1"), the compiler no longer generates an array, but instead an if-elseif chain.  Though note that the actual return value can still be a C style string where the QString constructor is called to create the QString return value.  (This information was acquired by looking at the assembly code generated.)

On the other hand, if the return value is a standard string (STL std::string), then the compiler does generate an array.  This probably has something to do with the fact that the standard string class supports move constructors (a C++11 addition not discussed here).  The QString class does not support these (at least Qt4 classes no not, but Qt5 classes do).  The problem with using standard strings is that the return values of these functions are used with Qt stream classes, which do not support standard strings.  Therefore, C style strings will be used for now.

Functions like the example above will be used.  These functions could be auto-generated, but again this practice will no longer be used.  The nice thing about auto-generation is that it eliminates the mistake of missing an enumerator, because with all warnings enabled (and as errors), if an enumerator is missing, a compiler warning is issued for the switch statement that not values are handled (provided no default case is included).  This is not a perfect solution, but probably the best within the limits of the C++ language.

There is one final issue with the function above.  The compiler sees that there is no return value at the end of the function and issues a warning (error).  The compiler is apparently not smart enough to realize that execution does not get past the switch statement since all cases return.  To silence this warning, a return ""; statement is needed at the end of the function.

Sunday, August 17, 2014

More Enumeration Classes

Several more enumerations were changed to enumeration classes.  While more of these included a size of enumerator, they were not being used.  This included the translator test mode, translator reference type, dictionary entry type, error list type, program model operation type, and the table multiple enumerations.  Two instances where the enum keyword was in front of the enumeration name were removed (this is something required for C but not C++).

This leaves several enumerations that are not as easy as adding the class keyword and renaming the enumerators like those changed above.  These include the code (auto-generated), token status (auto-generated), sub-code (bit masks), table flag (bit masks), table search type, token type, and test option enumerations.

The auto-generated enumerations need a good C++ solution and not the current kludgy C solution using an external awk script.  The bit mask enumerations will need operator functions implemented (bit-wise OR and AND), which will require using type casting.  For the others, the size of enumerators are used for either dimensioning arrays or for looping over the enumerators.

[branch cpp11 commit e71fe6f0fe]

Data Type As Enumeration Class

Now that the number of and size of enumerators of the data type enumeration have been removed, there was one more enumerator left that needed to be removed if possible, specifically the No_DataType enumerator that was assigned to a -1, which was used to indicate an unset data type.  If this enumerator was left in place, then switch statements would need to have a case for it or would need a blank default.

C++11 allows a default enumerator in the form EnumName{} just like for any other type.  For user types, it calls the default constructor (if there is one, else a compile error is reported).  For built in types, the value is assigned a zero.  And so is the case for a default enumerator, which also has the equivalent value of zero.  For unscoped enumerations, the value is zero, but for an enumeration class, the value can't be used as an integer without a cast.

Therefore, the No_DataType enumerator was replaced with the default enumerator DataType{}.  In addition, the first enumerator can't have the default value of zero, so was assigned to the value of one.  This is not an issue since data type enumerators are no longer used as indexes to array (only as keys to maps).  All of the Xx_DataType enumerators were changed to just Xx in the class enumeration definition and to DataType::Xx for all uses in the code since the enumerators are now scoped.

There was one remaining issue.  The test names awk script scanned the header file for the data type enumeration and created an array of C style strings with the names of the enumerator. As the string  This awk script generates the test names header file used in the test source file for converting enumerators to strings for test output.  The awk script was modified to instead look for the enumeration class and to generate an unordered map.  This code was put into a new function in the script.  This script also generates C style string arrays for the code and token type enumerations.  These will also be changed at some point.

[branch cpp11 commit 06ef6f17c5]

Size of Data Types Enumerator

The size of enumerator was removed but it was used for the dimension of two arrays.  Both of these arrays were two dimensional, so some sort of compound map would have been needed.  Instead, simple switch statements and conditional operators were used.  This should be nearly as efficient as an array as the compiler may generate a lookup table for a switch and this is not in highly critical code so absolute efficiency is not required.

The first array was used to obtain a conversion code needed to convert the data type in a token to the desired data type.  The conversion code obtained could be a null code representing no conversion needed or an invalid code representing a data type that can't be converted.

This array was used by the convert code and find code functions in the Table class.  The convert code function was modified to process the two data types directly using compound switch statements (the first on the token data type, and the second on the needed data type).  The find code function used the array for a data type in a token with the needed data type and so was changed to simply call the convert code function instead.

The second used of the size of enumerator was to dimension the an array used in the expected error status function of the Translator class.  This array was dimensioned for the number of data types and the number of reference types (none, variable, variable or defined function, or all) and used to obtain a token error status when a reference is expected but not found.  This function was changed to use a compound switch statement (the first on the data type, and the second on the reference type or the tertiary operator was used where a second switch was overkill).  The size of enumerator for the reference enumerator was only used for this array and was also removed.

[branch cpp11 commit 4183a87f74]

Saturday, August 16, 2014

Number of Data Types Enumerator

Not only does the data type enumerator have the size of enumerator (which needs to be removed before changing to an enumeration class), it also has a number of enumerator, which was placed after the three main data types (double, integer and string).  This enumerator was removed, but is was used to dimension two arrays that needed to be changed.

In the Table constructor, there is a section that scans the secondary associated codes of a main code, the purpose of which is to set the expected data type for the main code.  If the main code has associated codes for both doubles and integers, the expected data type is set to number (for example, the minus operator); and if there are associated codes for all three types (numbers and string), the expected data type is set to any (for example, the plus operator).

This is accomplished by using bit masks where there is a bit for each type (double, integer and string).  For each associated code, the data type of the code is bit-wise ORed together.  After all the associated codes are scanned, the final value is checked to see if it as the two number bits set or all three bits set to determine the expected data type.

Originally, an array of three elements was defined with the bit masks for the three data types.  The number of enumerator was used to dimension this array.  With the number of enumerator removed, this array was replaced with an unordered map, with an initializer list to set the bit masks for each data type enumerator.

The other use of the number of enumerator was in the equivalent data type function of the Table class, which contained an array from data type to equivalent data type, but when the sub-string and temporary string data types were removed, this function ended up essentially just returning the data type passed to it.  In other words, this function is no longer does anything, so it was removed and the one use of it was replaced with the data type (in the LET translator routine).

[branch cpp11 commit 8f56e1117a]

Enumeration Class Hash

In order to use the STL unordered map class, a hash function is required for the key of the map.  Hash functions are provided for all the built in types plus some of the other STL classes (like std::string), but unfortunately, not for enumeration classes.  For the built in types (integers), the number itself is used as the hash.  However, enumeration class enumerator values can't be because they can't be used as integers even though there values are just numbers.  The solution is to use a generic (template) function type that will work for all enumeration classes that converts the enumerators to integers:
struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};
This works for any enumeration class by returning an integer for an enumerator (a size_t is an integer that is large enough to cover any enumeration) using a static cast (hopefully the only place a cast will be needed).  An unordered map to use an enumeration class with an initializer list to assign values to the enumerators would be defined as:
std::unordered_map<EnumName, QString, EnumClassHash> names {
    {First_EnumName, "First"},
    {Second_EnumName, "Second"},
    {Third_EnumName, "Third"}
};
The name of the map does not need to be repeated for an assignment of each value (which could be tedious for a long name or with a lot of enumerators).  This does not resolve the issue of forgotten values, but hopefully when an undefined enumerator value is accessed, the default value (in this case a blank string) would be detected or identified easily.

QMap vs. Standard Map (Initializer Lists)

Using enumeration classes will require using an associated array container class (like QMap or QHash) since the size of the enumeration (the number of enumerators) is not obtainable (without kludgy type casting) to dimension an C style array.  As mentioned in the previous post, to use a associated array container class requires run-time assignments to fill the container.

C++11 provides a solution with initialize lists.  Unfortunately, the Qt containers do no support C++11 initializer lists (specifically Qt4 doesn't because Qt5 does contain support for initializer lists).  The Standard Template Library (STL) containers does support initializer lists.  Therefore, the STL containers will be used as needed until the inevitable change to Qt5.  STL containers are technically already available since the various Qt containers have method functions for converting STL containers to and from Qt containers.

For an associated array, either the QMap or std::map container could be used.  Both of these containers order the keys of the elements.  Ordering of the keys is not required in this case.  Qt provides the QHash class for an associated array not requiring ordered keys.  Similarly, STL provides std::unordered_map, which will be the class used.

Enumerators As Indexes – Using A Map

The first enumeration that will be changed to an enumeration class will be the data type enumeration.  One of the differences with enumerations is that unscoped enumerators can be used as integers.  One of the other things I preferred to do when defining an enumeration was add a size of enumerator at the end:
enum EnumName {
    First_EnumName,
    Second_EnumName,
    Third_EnumName,
    sizeof_EnumName
};
This size of enumerator can then be used to dimension an array, like to hold a conversion to another value (another enumeration, string, etc.).  This will not work with enumeration classes because the enumerators can't be used as integers without resorting to kludgy type casting (something I prefer to avoid if possible).  Plus, once this size of enumerator is added, then any switch statement using the enumeration will generate a warning since there is no case statement for this enumerator.  Adding a blank default statement is also kludgy.

Alternatively, using an associated array (map) instead of a C style array solves the issue of needing to know the size of the enumeration.  Compare the array solution to the map solution:
QString names[sizeof_EnumName] = {    QMap<EnumName, QString> names;
    "First",                          names[First_EnumName] = "First";
    "Second",                         names[Second_EnumName] = "Second";
    "Third"                           names[Third_EnumName] = "Third";
};
The array method is error-prone and care must be taken to make sure the right values (strings in this case) are applied to the right elements in the array.  This could be solved by using assignments that would look identical to the map assignments, though may not be as efficient because the assignments are done at run-time instead of at compile time, and the array still needs to be dimensioned.

The map method method of using assignments (same for the array method using assignments) can also be error-prone because it is easy to miss an assignment of one of the values.  In the array case, a null pointer would be returned, which will probably cause a segmentation fault unless it is checked for.

For the map method, however, accessing a value that doesn't exist simply adds a new element to the map with a default value (in this case a blank string).  This is still a problem, but much less fatal.  Alternatively, in the case of QMap, the value method function could be used instead of the [] operator, which doesn't add an element for a non-existing element and allows a default value to be returned for the non-existing element (for example, in this case a default value like "BUG" could be used).

C++11 – New Enumeration Class

With original implementation of C/C++ enumerations (enum), I preferred to add a suffix to each of the enumerators to associate them to the enumeration so that when one appears in the code, it is easy to identify it to the enumeration:
enum EnumName {
    First_EnumName,
    Second_EnumName,
    Third_EnumName
};
Without this suffix, it is difficult to see which enumeration the value is associated to.  (Though using an IDE like Qt Creator, there is a command to go right to the definition.)  In addition, obviously the same name can't be used for two different enumerations.  A suffix (a prefix could have been used instead) solves this issue.

C++11 introduces a new enum class where the enumerators are scoped inside the enumeration.  The enumerators for these are also more strongly typed then the normal enumerations (which represent integers and can be used as such).  As an enumeration class, the above enumeration becomes:
enum class EnumName {
    First,
    Second,
    Third
};
In order to use these enumerations, they must be scoped, so to refer to the second enumerator, the name EnumName::Second would be used.  This is similar to my solution of using suffix (in this case it is a prefix).  An example of an enumeration class was added to the try compile test program.  The intention is to change the enumerations used in the project to enumeration classes.

[branch cpp11 commit 2a8e3899ee]

Thursday, August 14, 2014

Project – Enable C++11 Compiling

By default, GCC C++ compiles for the corrected C++98 standard (C++03) with GNU extensions (there is no option for compiling for the uncorrected original C++98 standard).  There are two options for compiling C++11, one for the standard and one with GNU extensions.  The option for the standard C++11 will be used and was added to the CMake build file.

Though not necessary, I decided that it was a reasonable idea to validate that C++11 compiling was enabled and that C++11 was supported while generating the make file.  This meant adding a try_compile command to the CMake build file for a simple C++11 program.  If compiling of the simple program fails, an error is reported and CMake aborts.

The initial simple C++11 program tests two C++11 features.  As more C++11 features are used in the project, this simple program will be expanded to test those features also.  The two initial features tested are the new universal initializer syntax and the new null pointer.  Click Continue... for details of these two features.

I discovered something about CMake syntax, namely else and endif statements no longer require repeating the expression in the if statement (as of CMake 2.6.0).  The expression may now be left empty.  Repeating the expression can sometimes be misleading, for example:
if (NOT ${SOMETHING})
   
... <not something processing here> ...
else  (NOT ${SOMETHING})
   
... <something procession here> ...
endif (NOT ${SOMETHING})
Which makes it seem like the else part is for handling the "not something" condition.  Leaving the expression blank, as in else() and endif(), is much less confusing.  The rest of the if-else-endif statements in the CMake file will be updated to this style at some point.  (This syntax was already used for handling issues with Windows.)

There was also a statement in the CMake build file that obtained the GCC version for checking, but statements that were checking the version have been since removed, so this statement was also removed.  Work is now taking place on a new cpp11 branch.

[branch cpp11 commit 18ed38e9af]

Wednesday, August 13, 2014

Project – Compiler Warnings

In [Stroustrup, 2013], he frequently mentions that for questionably formed C++ statements that the compiler should issue a warning.  This made me realize that only the default warnings in the compiler were being used.  To possibly catch more problems, all of the warnings were enabled using the following GCC compiler options:
-Wall       enable all (well actually most) warnings
-Wextra     enable warnings not enabled by -Wall
-pedantic   enable warnings demanded by strict ISO C++ standard
-Werrors    cause compiler to treat warnings as errors
The last option causes the compiler to abort after issuing a warning instead of proceeding, which will require the warning to be corrected; however, this does not affect warnings from pedantic option, therefore the -pendantic-errors was used instead, which has the same affect.  After adding these options, several warnings were reported, which were of six different types.  Click Continue... for details of these warning types that were corrected.  Since this commit is development related and not specific to any topic, the commit was just made to the develop branch.

[commit bb0124444f]

Tuesday, August 12, 2014

Transitioning to the New Branching Model

The current topic in development was integrating the program model with recreator into the edit box, which has been going well, but there is at least one issue remaining.  When the text for a line entered in the edit box is recreated line replaced back into the edit box, extra undo commands are added to the undo stack.  So upon undoing the line, it firsts undoes the recreation and then undoes the change.  This issue will probably not be trivial to correct.

I want to start working on improving the C++ usage including using features that are part of the C++11 standard.  This implies a new topic branch for this work.  A topic branch is also needed for the recreator to edit box integration, somewhere on the current branch0.6 branch.  Finally for the new branching model, the develop branch is needed somewhere.

Since v0.6.1 was the last tag, the develop branch should go at this tag.  For the new C++11 branch, it should branch off of the develop branch (at this tag).  However, a lot of improvements are on the current branch0.6 branch, so I've decided to split branches further on from the last tag.

Therefore, the new develop branch was created at branch0.6.  The current branch0.6 was dead ended with an appropriate abandoned commit.  There will be no more of these branches.  Normally, git does not allow an empty commit with just a message, but this can be circumvented by using the --allow-empty option on the commit command.

A new recreator-editbox topic branch was placed at where the failing encoder test expected results were corrected before the latest two commits where the various Windows build issues were corrected since these commits have nothing to with this topic.  When work commences on this topic, changes can be merged from the develop branch.

[commit d3bb314f24] [commit 727f7d223f]

Monday, August 11, 2014

Project – New Git Branching Model

I found a better Git branching model.  Currently, a branch is created for the development release series.  For example, branch0.5 was created for all the 0.5.x versions (0.5.0 through 0.5.3).  Once this development series was completed, the branch was merged back to the master branch.  Since there were no other changes on the master branch, the pointer to master was simply moved from 0.4.6 (the last of the 0.4 development series) to 0.5.3 - what is known as a fast-forward merge.  In the end though, the repository is just a long row of linear commits.

The new Git branch model is detailed in this blog post.  I'm going to adopt this branching model.  The main development branch will be named develop, which will replace the branchX.X branches that has been used for development.  When development is ready for a release, a releaseX.X branch will be created from the develop branch.  There will be at least one commit used for updating the version number, and possibly another to do minor clean up (like fixing comments), plus any for possible platform related bug fixes discovered during testing.  This will replace the "updated files for release X.X.X" commits just before a release.  If testing goes well (on all platforms), then this branch will be merged to master and tagged for the release (as vX.X.X).

When a new feature, function or change is being added (what is called a "topic"), a topic branch will be created off of the develop branch and will be named for the topic.  This will more clearly state what is being developed (branchX.X states nothing except the release series).  When the topic is complete, it will be merged back to the develop branch.  If for some reason the topic doesn't work out, then the branch will abandoned and an empty commit will be made with the reason for the abandonment.  These topic branches will allow more when one topic to be worked on at a given time.

This model also allows for hit fixes to the master branch, where a hotfix-X.X.X branch will be created for the fix (which includes the proposed hot fix version number).  Once complete, the hot fix branch will be merged backed to the master branch, and it can be merged to the develop branch as needed.

As the blog post explains, all merges will use the no-fast-forward option (--no-ff), meaning that Git will make a merge commit showing the branch being merged instead of just moving the branch pointer.  Using this option will allow it to be cleary seen where the branch started and where it was merged.  With the current model, there is no way to see where the branch originally started, only where it ended up (assuming it isn't deleted, which is why the older development branches were not deleted).

Sunday, August 10, 2014

Building and Running on Windows 8.1 – Command Line

The application can also be built using the command line, either from the Windows Command Prompt or from the BASH shell that comes with Git for Windows named Git Bash in the menu or start screen.  However, the procedure is slightly different between the two.  The procedures below include cloning the IBCP Git repository.  Here are the steps for using Git Bash:
  1. cd Documents
  2. git clone https://github.com/thunder422/ibcp
  3. cd ibcp                               (shows master is the current branch)
  4. git checkout branch0.6                (now shows branch0.6 is the current branch)
  5. cd ..
  6. mkdir ibcp-build
  7. cd ibcp-build
  8. cmake -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make ../ibcp
  9. mingw32-make
  10. regtest                               (runs the Linux regression test script)
In step 8, the MSYS generator looks for the make command, which it will not find because it is named ming32-make with the MinGW-w64 installation.  Therefore the make program needs to be identified on the command line.

Here are the steps for using the Command Prompt:
  1. cd Documents
  2. git clone https://github.com/thunder422/ibcp
  3. cd ibcp
  4. git checkout branch0.6
  5. cd ..
  6. md ibcp-build
  7. cd ibcp-build
  8. cmake -G "MinGW Makefiles" ../ibcp    (produces errors - see below)
  9. cmake -G "MinGW Makefiles" ../ibcp
  10. mingw32-make
  11. regtest                               (runs Windows regression test batch file)
In steps 8 and 9, unlike the MSYS generator, the MinGW generator does look for the mingw32-make command, so the make program does not need to be specified.  In step 8 like Qt Creator, there are a bunch of errors, one screaming about sh.exe being in the path and that MinGW make won't work correctly.  This does not appear to actually affect the build however.  In step 9 again like with Qt Creator, the second time no errors are reported.

In step 11, the batch file will run all the tests and then it will compare the first set of results (parser tests).  If the tests are successful it will say OK for each file.  Answer N for comparing more files.  The next set of results will be compared.  Answer N after each comparison (otherwise it will prompt for more files to compare).

In step 8 for Git Bash and steps 8 and 9 for the Command Prompt, add -DCMAKE_BUILD_TYPE=Debug before the source directory to do a debug build.

Building and Running on Windows 8.1 – Qt Creator

To obtain the project Git repository, start the Git GUI, either from the Start Menu (Programs, Git, Git GUI), from the Start Screen Git GUI icon or by typing "Git GUI" on the Start Screen (and there are probably other ways).  For Windows 8, it probably dumped the Git GUI icon right on the Start Screen.  For Windows 8.1, click the Down Arrow at the bottom-left and find the Git GUI under Git (pin to the Start screen if desired).

In the opening dialog of Git GUI, click on Clone Existing Repository.  Enter https://github.com/thunder422/ibcp in the Source Location and set to Target Directory by clicking the Browse button.  Find the Documents folder (or another folder), and click the OK button.  To the Target Directory, add /ibcp (it must be a non-existing folder or and error will occur) and click the Clone button.  After a few moments, the repository will be cloned.  The next time the Git GUI is started, the same dialog appears, however, the Git GUI remembers the repositories that have been opened previously.  Select the Repository menu and the recent repositories are listed.

The main Git GUI will be started indicating it is on the master branch.  Check out the latest branch by Branch, Create..., click the Matching Tracking Branch Name option, click the Tracking Branch option, select origin/branch0.6 (or another branch) and click the Create button.  This will create a local branch.  Now the project can be opened in Qt Creator so start Qt Creator and select File and Open File or Project...  and navigate to the Documents and then ibcp folder.  Select the CMakeLists file (the .txt is not displayed unless file extensions are enabled) and click the Open button.  

The CMake Wizard dialog appears with the build directory set to ...\Documents\ibcp-build,  click the Next button.  For a debug build (optional) add -DCMAKE_BUILD_TYPE=Debug into the Arguments field and then click the Run CMake button.  For some reason, there are a bunch of errors the first time.  Just click the Run CMake button again and it should complete successfully.  Click the Finish button and the application is ready to be built.

To start the build, click the Hammer icon (lower left, or type Ctrl+B or use the Build menu).  The run the program, click the Run/Play icon (lower left, or type Ctrl+R or use the Build menu).  For a debug build use the Debug/Play icon (lower left, or type F5 or use the Debug menu).  The application should start in GUI mode.

[commit ec787762b9] [commit 3285823de0]

CMake Problems Windows 8.1 – Part 3

The final build problem found with the awk script used to auto-generate the automatic enumerations header file and the codes reference text file.  The problem was that when building with Qt Creator (procedure will be provided in the next post), the build aborted with a strange error message after running this script.  It correctly built the output files, and telling it to build again allowed it to successfully complete the build.

The problem was in the part of the script that generates the codes.txt reference file that lists all the codes by code index and by code name.  This information is helpful to aid debugging, but otherwise it is not used.  To sort by code names, it pipes the code name output through the sort command.  It was desired that names like Asc_Code and Asc2_Code be sorted like this, but it was reversing these because the underscore sorts after the 2 character.

An attempt to correct this issue was made be adding the "-d" option (dictionary order) to the sort command which tells it to only recognize letters and digits ignoring underscore characters.  When building under Windows, it was calling the Windows sort command.  This sort command did not recognize this option and reported an error, which caused the build to fail.

Unfortunately, adding this option did not work as desired anyway.  The problem was that with the underscores removed, the above names become AscCode and Asc2Code and the 2 character still sorted before the C character.  This was not noticed when this option was added.  Anyway, once this option was removed, the build no longer failed on Windows.  (Curiously, the Windows sort command does sort the names as desired.)

Saturday, August 9, 2014

CMake Problems Windows 8.1 – Part 2

The second problem was with the paths to the test files generated in the make file.  When CMake generates a custom command for making the test directory and copying a test file, it uses the Unix style path forward slash separator regardless of the generator being used.  While cmd.exe on Windows does support these style paths, the md and copy commands do not (in fact the forward slash indicates an option like the minus does for Linux and MSYS commands).  This obviously causes problems with the custom commands.

In CMake, the file command supports a TO_NATIVE_PATH option, but when used, this command didn't work as expected (didn't do anything).  Apparently this is a known issue and according to what I read, this is not the purpose of this command anyway.  So instead, a ConvertPath function was added to the CMake build file, which if the MinGW generator is being used, changes forward slashes to back slashes and surrounds that path with double quotes to deal with paths that may have spaces in them (which doesn't occur with the MinGW generator like with the MSYS generator).  For any other generator, the path is not changed.

Another build problem was found with the awk program required for building.  When using MSYS with MinGW, MSYS included many of the Unix utilities including the awk program.  Fortunately, Git for Windows includes many of the MSYS utilities.  However, the gawk program is included instead (stands for GNU awk).  Also included is an awk script, but this shell script is meant to be run by the sh.exe command that is part of MSYS, which just calls gawk.  When run from cmd.exe the script doesn't work.

When looking for the awk program, CMake found this awk script and so an error occurred from the make command running under cmd.exe.  To make CMake find gawk.exe instead of this script, the CMake build file was modified to look for gawk first, and if this is not found, then looks for awk.  In fact, on Linux, awk is also called gawk, but there is an awk file that soft links to it, so that either can be used.

While testing a minor mismatch was found with encoder test #2 with recreator testing.  The issue was that lines with error now store the text of the line, which is recreated.  This change was made in the last commit but the expect results were not updated.

[commit 727f7d223f]

Build Problems on Windows 8.1 – Part 1

Several problems were discovered when attempting to build and run on Windows 8.1 using Qt Creator.  The first problem that occurred was with the copying of the test files from the source directory to the build (binary) directory.  This is accomplished by creating custom commands for each test file.  These custom commands generate a mkdir -p command to make the test directory if not already there and the cp command to copy the file.  Both of these commands are available on Linux and with MSYS on Windows.

When building on the command line on Windows using MSYS to create the make file or using the CMake GUI to generator the make file, the "MSYS Makefiles" generator is used.  This creates the make file assuming that the make command will be run using a Unix shell (specifically bash or the Bourne Again SHell).

On Windows when running CMake from Qt Creator, it uses the "MinGW Makefiles" generator to generator the make file.  This generator assumes that the make command is going to be run using cmd.exe, the Windows command prompt program, which Qt Creator uses cmd.exe to run the make command.  The make command uses the program under which it is run to execute commands in the make file like for custom commands.

The CMake build file needed to be modified to detect when the MinGW generator was being used and use the appropriate make directory and copy commands for cmd.exe.  Fortunately, the CMake CMAKE_GENERATOR variable is set to the generator is being used.  So, if the generator is MinGW Makefiles, the md and copy commands are used, otherwise the mkdir -p and cp and used.

Another problem with the md command is that if the directory already exists, the command returns an error and the make command aborts.  With Linux/MSYS, the -p option solves this problem.  With cmd.exe, the md command has no similar option.  The only solution that worked was using an if not exist command (so the md command is only performed when the test directory doesn't exist):
if not exist test-directory md test-directory
When the generator is not MinGW, CMake adds double quotes about each component of an individual command in the custom command if the component has a space in it, because otherwise the shell parse a path with a space incorrectly as two arguments and not one.  For this reason, the command variable could not be set to mkdir -p because it would create the command "mkdir -p" and this is not a valid command.  Therefore, the mkdir and -p had to be put into two separate variables.  This does not occur with the MinGW generator.

Installing QtCreator on Windows 8.1

Downloading Qt Creator was described a few posts ago.  The latest version of Qt Creator at the time is 3.1.2.  Open the qt‑creator‑opensource‑windows‑x86‑3.1.2.exe download file and click through, accepting the recommended Installation Folder, the license, and Start Menu shortcuts.  Accept the User Access Control if asked.  At the end go ahead and Launch Qt Creator as some post install configuration is needed.

Qt Creator should be able to find the various utilities and Qt 4.8.6 since these are on the path, but it does not appear to actually look for some of these, so these need to be configured manually.  In Qt Creator selected Tools and Options...  Click the Build & Run page.

On the Qt Versions tab, if Qt 4.8.6 was not auto-detected, it needs to be set manually.  Click the Add button and browse to the C:\Qt\4.8.6\bin directory and select the qmake.exe (just qmake if extensions are not displayed).  Click the Apply button.

On the Compilers tab, if MinGW was not auto-detected, it needs to be set manually.   as MinGW (x86 32bit in C:\mingw32\bin).  Click the Add button and select MinGW (from the drop down menu).  On the Compiler path field, click the Browse button and navigate to the C:\mingw32\bin directory and select g++.  Click the Apply button.

On the Debuggers tab, it GDB was not auto-detected, it needs to be set manually.  Click the Add and replace the default New Debugger name with something like GDB 7.7 (which is the version installed with MinGW).  Click the Browse... button and browse to This PC, Local Disk (C:) (or whatever it may be called), mingw32, bin, gdb and click the Open button.  Click the Apply button.

On the CMake tab, click the Browse... button and navigate to This PC, Local Disk (C:), Program Files (x86), Cmake 2.8, bin, cmake and click the Open button.  Click the Apply button.

Finally on the Kits tab, select the Desktop (default) under manual, which is italicized with a yellow triangle warning indicating it is not configured properly.  Under the Debugger field, select GDB 7.7 on the drop down (only debugger listed).  The warning should go away since the Compiler and Qt Version fields are already set.  Click the OK button.

The configuration can be testing by compiling one of the Examples.  On the Welcome page (icon on upper-left), select Examples.  I selected the first example: 2D Painting Example.  On the Configure Project page that appears next, click the Configure Project button.  Test building by clicking the Hammer icon (lower-left or type Ctrl+B).  After a few moments it should finish.  Click the Run/Play icon (or type Ctrl+R) to run the program.  It should present two rotating patterns.  Qt and Qt Creator have been successfully installed.

Installing Git on Windows 8.1

Finally, to obtain this project from this project's Git repository on GitHub, the Git utility is required.  The latest Git for Windows can be obtained from their home page (which has changed since I previously described how to install Git).  Click the Download button to download the latest version.

Open the download file (Git‑1.9.4‑preview20140611) and accept the User Control Access if asked.  Click through and accept the license.  On the Select Components dialog, select additional icons if desired and click through accepting the defaults.  It's not necessary to view the release notes, so disable and click Finish.

The paths to these programs along with Qt needs to be added to Windows.  From Windows Explorer, select This PC, right-click and select Properties, Advanced system settings, and on the Advanced tab, click Environment Variables...  Under System variables, scroll down to Path and add:
;C:\mingw32\bin;C:\Qt\4.8.6\bin;C:\Program Files (x86)\Git\bin
Select Path, click Edit..., add the string above to the end of Variable value, and click OK (the whole way out).  This will allow the utilities git, g++ (compiler), gdb (debugger) and qmake (how it is determined where Qt is installed) to be found on the command line or by a program that is started under Windows.  The path to the CMake directory should already have been added during CMake installation.

Installing CMake on Windows 8.1

Building project requires the CMake utility.  CMake can be obtained from the CMake download page.  For now I suggest installing the latest 2.8 version, which is 2.8.12.2.  There is a newer version (3.0.1 at this time), but Linux only has 2.8.7 (Linux Mint 13/Ubuntu 12.04) or 2.8.12.2 (with kubuntu backports or Linux Mint 17/Ubuntu 14.04).  This project only requires 2.8, so 2.8.12.2 for Windows is sufficient.

Open the cmake‑2.8.12.2‑win32‑x86.exe download file and accept the User Control Access if asked.  Click through and accept the license.  On the Install Options dialog, select the Add CMake to the system PATH for all users or current user as desired, and the Create CMake Desktop Icon if desired.   Continue clicking through and finally click Finish.

Installing Qt For MinGW on Windows 8.1

Download the latest Qt4 for Windows with MinGW at the Qt Project's download page.  Upon first opening this page, only the latest Qt5 version is shown (which at this time is 5.3.1).  To see more versions, click the Show Downloads button and scroll down to Qt 4.8 (4.8.6 at this moment).  Download the one for MinGW with GCC 4.8.2 (note that this download does not actually include MinGW).  While here, the latest version of Qt Creator can also be downloaded (3.1.2 at this moment).

For now, I plan to continue using Qt4 even though Qt5 has been out for a while.  I will describe installing the current latest Qt4.  The version present on Linux Mint 13 (Ubuntu 12.04) is 4.8.1 unless the kubuntu backports are being used to get the latest version of KDE, in which case 4.8.2 is present.  Linux Mint 17 (Ubuntu 14.04) has version 4.8.5.  These versions are sufficient so there is no need to install 4.8.6 for Linux.  (I don't know enough about Qt5, which is something that may be revisited some time in the future.)

Now Qt4 can be installed.  Open the qt-opensource-windows-x86-mingw482-4.8.6-1.exe download file and accept the User Account Control if asked.  Click though, accept license, continue clicking through, accept the default C:\Qt\4.8.6 installation location, and continue clicking through.  It will ask where the MinGW installation is located.  If MinGW was installed as previously described, the default C:\mingw32 can be accepted, so click Install.

At the end of the install process, the setup program will ask to Run Examples and Demos and Show Documentation.  This is not necessary, so disable these before clicking Finish.  These can be accessed by the Start Menu (Classic Shell) by Programs, Qt by Digia v4.8.6 (MinGW 4.8.2 OpenSource), Examples and Demos and Assistant.  From the Start Screen on Windows 8 I'm guessing the install throws all the programs on the Start Screen itself.  However, on Windows 8.1, click the Down Arrow (lower left where it says new apps installed), and scroll right to where the Qt by Digia v4.8.6 (MinGW 4.8.2 OpenS... programs are listed where Assistant and Examples and Demos will be.  These can be pinned to the Start Screen if desired (Pin to Start on right-click menu).

Installing MinGW on Windows 8.1

The procedure for installing MinGW (that came with GCC 4.6.2 at the time) was previously described.  Later once Qt was being utilized, the procedure for installing the QtSDK with MinGW (that came with the older GCC 4.4) was given, and then it was detailed how to connect the MinGW with GCC 4.6.2 to QtCreator since 4.4 was too old.

The Qt Project team no longer provides the QtSDK (that included the Qt library development files, MinGW and QtCreator).  Therefore, the Qt4 libraries and QtCreator now need to be installed separately.  The latest Qt4 (4.8.6) for MinGW does not actually come with MinGW, which needs to be install separately beforehand.  They suggest installing MinGW-w64 first (which includes GCC 4.8.2) and give a specific version to install.

MinGW-w64 can be downloaded from here.  This is revision 3 and there is now a revision 4 (they don't detail very well what was changed in revision 4), but I installed the recommended revision 3.  The download file is in 7-Zip format, which Windows 8.1 does not have native support for.   To install 7-Zip, go to the 7-Zip website and click the Download .msi (for 64-bit Windows 8 or Download .exe if using 32-bit Windows 8).  Once downloaded open the program.  (Don't install the 7z922.exe program, the default program on their SourceForge page, as it doesn't connect into Windows Explorer.)

MinGW can now be installed by extracting the i686-4.8.2-release-posix-dwarf-rt_v3-rev3.7z download file.  Right-click on this file, select 7-Zip, and Extract files...  Set the Extract to directory to C:\ and click OK.  This will install MinGW at C:\mingw32, which is the location Qt expects to find it.  Next post will describe installing Qt.

Wednesday, August 6, 2014

Upgrading MinGW on Windows

Upgrading GCC in MinGW to the latest version is easily accomplished.  Simply start the MSYS Shell and run the following commands (this worked on the MinGW installs on both Windows XP and 7):
mingw-get update
mingw-get upgrade
Use the command g++ --version to verify that GCC 4.8.1 has been installed.  Installing MinGW with the Qt libraries has been previously covered (see the Windows tagged posts).  However, it is probably be a good idea to update the procedure and repeat for Window 8 since only Windows XP and 7 were covered previously.  Plus, there are newer versions of Qt and MinGW.  Specifically I will provide the installation procedure for Windows 8.1 update 1, which I have running in a virtual machine.  All the tools necessary will be covered, including MinGW, Qt for MinGW, CMake and git in the following posts.

I obtained Windows 8 Pro via their $40 upgrade offer, otherwise I would not have bothered.  On my Windows 8.1 installation, I have Classic Shell installed.  This is not necessarily because I don't like the Modern (AKA Metro) UI, but it's just contrary works to the way I like to work.  In Classic Shell, I use the Classic start menu style as I don't like the Window 7 start menu style (I use the Classic Shell on Windows 7 for the same purpose).  Procedures for the classic start menu style and the start screen will be provided when appropriate.

Tuesday, August 5, 2014

Upgrading GCC on Linux Mint 13/Ubuntu 12.04

GCC on Linux Mint 13/Ubuntu 12.04 can be upgraded from the default GCC 4.6.3 by adding the tool chains repository.  Instructions can be found around the Internet, but I will briefly provide procedure that I used.  First, the python‑software‑properties package needs to be installed (it was already installed on my system):
sudo apt-get install python-software-properties
Now the tool chain repository can be added with these commands:
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
With this repository, the current GCC 4.6.3 can be upgraded to the most recent of the 4.6 series to 4.6.4.  However, the goal is to get a more recent version.  For this the g++-4.8 package needs to be installed:
sudo apt-get install g++-4.8
This should also bring the other required packages (gcc-4.8-base, gcc-4.8, cpp-4.8 and libstdc++-4.8-dev).  Once the 4.8 packages are installed, they need to be selected, otherwise the 4.6 commands will still be executed.  This is accomplished with the following commands:
sudo update-alternatives --remove-all gcc
sudo update-alternatives --remove-all g++
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

For the first time, the first two commands are not needed.  I put these lines into a script file (named usegcc48), and created and second script identical to this except with the "4.8" changed to "4.6" to select the 4.6 commands (named usegcc46).  This way, it is easy to switch between the two versions (the execute bit needs to set on these scripts using the command chmod +x usegcc4*).

Monday, August 4, 2014

Project – C++11 Standard

Part of learning to use C++ more effectively should include the latest C++ standard, which at the moment is C++11.  Support for C++11 is being or has been implemented in compilers.  This project uses GCC (The GNU Compiler Collection), which is standard on Linux systems and can be installed on Windows systems (the MinGW program is the one recommended).  Sorry MAC OS-X users, I do not have access to MAC system to figure what is needed to build and run this project on OS-X even though OS-X is Linux like and shouldn't be much different than Linux.

Even though many of the recent GCC versions support various features of C++11 (which was previously known as C++0X before the standard was finalized) starting with GCC 4.3, all the C++11 features highlighted in the  The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup require and more recent version of GCC, specifically GCC 4.8 or later.  Fortunately, this version is available both on Linux (the current Mint/Ubuntu LTS or Long-Term-Support versions) and MinGW (Windows).

The current version of GCC on Mint 13 LTS (Ubuntu 12.04 LTS) is only GCC 4.6.3.  Fortunately there is a way to update to GCC 4.8.1 by adding the tool chains repository.  On Mint 17 LTS (Ubuntu 14.04 LTS) GCC 4.8.2 is available.  The latest version installed with MinGW is also GCC 4.8.1.  However, since Qt is also required, it is easier to install Qt that includes MinGW, which happens to have GCC 4.8.2  GCC 4.8 should be sufficient for using the major C++11 features.  Details for upgrading and installing the necessary versions and tools will be provided in subsequent posts.

Sunday, August 3, 2014

Project – Better C++

The primary goals for this project was to get back to C++ programming, to learn using it more effectively after more than a decade doing only C programming, and to learn GUI programming.  Creating an incremental (interactive) BASIC compiler seemed to be an ideal way to accomplish this.  The GUI programming came later with the selection and use of the Qt toolkit.  Learning about the CMake build system and the git distributed revision control also came along the way.

After reading the book API Design For C++ by Martin Reddy recommended by a coworker, I started to get more of a taste for what C++ is capable of.  Even though this project is not an API (Application Programming Interface), when you think about it, any C++ class is an like API for other code that uses it.

I then picked up an old C++ book I purchased over two decodes ago when I was first learning C++, but couldn't get past the first chapter at the time.  I won't bother mentioning the title since this 1989 book is way out of date now (for example, C++ did not even have templates or the delete[] operator when the book was written).  Any way, I read the book and it wasn't really that bad, so I decided to pick up a more up to date book on C++.

I selected the book The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup (the creator of C++).  I never liked older editions of this book, but decided to give this book a try since it includes the new C++11 standard.  I've picked up quite a bit that I did not previously know about C++ and I'm barely into the book at this point.  What I have realized that parts of what has been implemented in the project fails at being good C++ code.

One example is the memory management of tokens.  A lot of work went into tracking tokens.  There were two separate implementations in the attempt to make sure the ownership of the tokens and allocation of tokens worked properly - and to report any errors upon termination of the application.  The C++ facility of overloading the new and delete operators was used to accomplish this.  There is a better C++ facility using existing library classes that can be used to drastically simplify this.

Another example is the code table that holds information for all the BASIC program elements (commands, operators, functions, etc.).  The current solution is very much a straight C solution with C++ wrapped around it.  The current method on how code IDs are assigned is very kludgy (via an awk script that scans for special comments in a source file).  The method of how  associated codes are setup is also very kludgy (via elaborate C macros).  As a result, it is very easy to setup table entries incorrectly.  There must be a better way to accomplish this with C++ (though I'm not sure what that is yet).