--- /dev/null
+cmake_minimum_required (VERSION 2.6)
+
+
+# ==================
+# Define Our Project
+# ==================
+
+set (My_Project_Title "Some Project")
+set (My_Project_Author "Somebody")
+set (My_Project_Revised_Date "2015-06-05")
+set (My_Project_Version_Major 1)
+set (My_Project_Version_Minor 0)
+set (My_Project_Version_Patch 0)
+
+set (My_Project_Copyright_Date "2015")
+set (My_Project_Copyright "Copyright © ${My_Project_Copyright_Date} ${My_Project_Author}.")
+
+project (${My_Project_Title})
+
+
+# Search for included files here
+include_directories( ${PROJECT_SOURCE_DIR}/src )
+include_directories( ${PROJECT_SOURCE_DIR}/test )
+
+
+string(TOUPPER ${My_Project_Title} My_Project_Title_Caps )
+string(REGEX REPLACE " " "_" My_Project_Title_Caps ${My_Project_Title_Caps} )
+
+
+# ======================
+# Process Template Files
+# ======================
+
+file(READ ${PROJECT_SOURCE_DIR}/LICENSE.txt My_Project_License)
+
+string(REGEX REPLACE "\n" "\n\t" My_Project_License_Indent ${My_Project_License})
+
+configure_file (
+ "${PROJECT_SOURCE_DIR}/templates/template.c.in"
+ "${PROJECT_BINARY_DIR}/template.c"
+)
+
+configure_file (
+ "${PROJECT_SOURCE_DIR}/templates/template.h.in"
+ "${PROJECT_BINARY_DIR}/template.h"
+)
+
+configure_file (
+ "${PROJECT_SOURCE_DIR}/templates/README.md.in"
+ "${PROJECT_BINARY_DIR}/README.md"
+)
+
+
+# =============
+# Build Targets
+# =============
+
+set(src_files
+# src/file.c
+)
+
+set(header_files
+# src/file.h
+)
+
+# Create a library?
+# add_library(libFOO STATIC
+# ${src_files}
+# ${header_files}
+# )
+
+# remove the extra "lib" from "liblibFOO"
+# SET_TARGET_PROPERTIES(libFOO PROPERTIES PREFIX "")
+
+# Create a command-line app?
+# if (NOT DEFINED TEST)
+# add_executable(main
+# src/main.c
+# src/GLibFacade.c
+# src/GLibFacade.h
+# ${header_files}
+# )
+#
+# Link the library to the app?
+# target_link_libraries(main libFOO)
+# endif()
+
+
+# ===========================================
+# Build Test Suite with CuTest (unit testing)
+# ===========================================
+
+set(test_files
+ test/CuTest.c
+ test/CuTest.h
+ ${PROJECT_BINARY_DIR}/AllTests.c
+)
+
+if (DEFINED TEST)
+ add_definitions(-DTEST)
+
+ add_executable(run_tests
+ ${test_files}
+ ${src_files}
+ ${header_files}
+ )
+
+ # Process source files to look for tests to run
+ add_custom_command (
+ OUTPUT ${PROJECT_BINARY_DIR}/AllTests.c
+ COMMAND sh ${PROJECT_SOURCE_DIR}/test/make-tests.sh ${PROJECT_SOURCE_DIR}/src/*.c > ${PROJECT_BINARY_DIR}/AllTests.c
+ )
+
+ enable_testing()
+
+ add_test( test ${PROJECT_BINARY_DIR}/run_tests)
+
+endif()
+
+
+# ==========================
+# Build Installer with CPack
+# ==========================
+
+# You're on your own here
--- /dev/null
+This project is designed for use with cmake.
+
+The Makefile controls the overall build:
+
+ make
+ make release
+
+Build a version optimized for performance.
+
+ make debug
+
+Faster compile, but not as high performance.
+
+ make xcode
+
+Create an Xcode project for use on OS X.
+
+ make windows
+
+Used for cross-compiling for Windows using MinGW.
+
+ make clean
+
+Clean up the `build` directory.
+
+These commands control the `build` directory. Everything in this directory is
+auto-generated. You should not manually change these files or put anything
+else in there.
+
+
+The setup is designed to support unit testing with CuTest. Functions along
+the lines of `void Test*` will be located automatically and used to create the
+test suite, which is run by:
+
+ ./run_tests
+
+Or
+
+ make test
+
+(The `run_tests` approach will probably give more useful feedback if a test fails.)
+
+
+Integration testing must be handled separately.
+
+You can configure the `CMakeLists.txt` to support creating installers.
--- /dev/null
+The `new-project` project is released under the MIT License.
+
+GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
+
+ https://github.com/fletcher/MultiMarkdown-4/
+
+MMD 4 is released under both the MIT License and GPL.
+
+
+CuTest is released under the zlib/libpng license. See CuTest.c for the text
+of the license.
+
+
+## The MIT License ##
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
--- /dev/null
+BUILD_DIR = build
+
+$(BUILD_DIR_):
+ -mkdir $(BUILD_DIR_) 2>/dev/null
+ -cd $(BUILD_DIR); rm -rf *
+
+# The release target will perform additional optimization
+release: $(BUILD_DIR)
+ cd $(BUILD_DIR); \
+ cmake -DCMAKE_BUILD_TYPE=Release ..
+
+# Enables CuTest unit testing
+debug: $(BUILD_DIR)
+ cd $(BUILD_DIR); \
+ cmake -DTEST=1 ..
+
+# For Mac only
+xcode: $(BUILD_DIR)
+ cd $(BUILD_DIR); \
+ cmake -G Xcode ..
+
+# Cross-compile for Windows
+windows: $(BUILD_DIR)
+ cd $(BUILD_DIR); \
+ cmake -DCMAKE_TOOLCHAIN_FILE=../tools/Toolchain-mingw32.cmake -DCMAKE_BUILD_TYPE=Release ..
+
+# Clean out the build directory
+clean:
+ rm -rf $(BUILD_DIR)/*
--- /dev/null
+Title: Some Project
+Author: Fletcher T. Penney
+Date: 2015-06-05
+Copyright: Copyright © 2015 Fletcher T. Penney.
+Version: 1.0.0
+
+# Introduction #
+
+This template was created out of a desire to simplify some of the setup and
+configuration that I was doing over and over each time I started a new project.
+Additionally, I wanted to try to start encouraging some "better practices"
+(though not necessarily "best practices"):
+
+1. [Test-driven development][tdd] -- My development of MultiMarkdown
+ focused on integration testing, but really had no unit testing to
+ speak of. Some newer projects I began working on were a bit math-
+ heavy, and ensuring that each piece works properly became even more
+ important. It was also nice to be able to actually develop code that
+ could do *something* (via the test suite), even though the project as
+ a whole was nowhere near complete.) To accomplish this, I include the
+ [CuTest] project to support writing tests for your code.
+
+2. Use of the [cmake] build system. `cmake` is not perfect by any
+ means, but it does offer some very useful features and a means for
+ better integrating the compilation and packaging/installation aspects
+ of development. Rather than reinventing the wheel each time, this
+ setup incorporates basic `cmake` functionality to make it easy to
+ control how your project is compiled, and includes automated generation
+ of the test command.
+
+3. Templates -- `cmake` has a reasonable templating system, so that you
+ can define basic variables (e.g. author, project name, etc.) and allow
+ `cmake` to combine those elements to ensure consistency across source
+ code and README files.
+
+
+
+[tdd]: https://en.wikipedia.org/wiki/Test-driven_development
+[cmake]: http://www.cmake.org/
+[CuTest]: http://cutest.sourceforge.net
+
+
+# How do I use it? #
+
+You can download the source from [github] and get to work. The file "IMPORTANT"
+contains instructions on the various build commands you can use.
+
+
+I recommend using the following script to automatically create a new git repo,
+pull in the default project template, and configure git-flow. You simply have
+to rename your project from `new-project` to whatever you desire:
+
+
+ #!/bin/sh
+
+ git init new-project
+
+ cd new-project
+
+ git remote add "template" https://github.com/fletcher/c-template.git
+
+ git pull template master
+
+ git flow init -d
+
+ git checkout develop
+
+
+Using this approach, you can define your own "origin" remote if you like, but
+the "template" remote can be used to update the core project files should any
+improvements come about:
+
+ git checkout develop
+ git merge template master
+
+**NOTE**: `cmake` is a complex suite of utilities, and if you have trouble you
+will need to get support elsewhere. If you find errors in this template, by
+all means I want to hear about them and fix them, but this is just a basic
+framework to get you started. In all likelihood, all but the most basic
+projects will need some customization.
+
+
+# License #
+
+## The MIT License ##
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
--- /dev/null
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
--- /dev/null
+/*
+ * GLibFacade.c
+ * MultiMarkdown
+ *
+ * https://github.com/fletcher/MultiMarkdown-4/
+ *
+ * Created by Daniel Jalkut on 7/26/11.
+ * Modified by Fletcher T. Penney on 9/15/11.
+ * Modified by Dan Lowe on 1/3/12.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ */
+
+#include "GLibFacade.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+/*
+ * The following section came from:
+ *
+ * http://lists-archives.org/mingw-users/12649-asprintf-missing-vsnprintf-
+ * behaving-differently-and-_vsncprintf-undefined.html
+ *
+ * and
+ *
+ * http://groups.google.com/group/jansson-users/browse_thread/thread/
+ * 76a88d63d9519978/041a7d0570de2d48?lnk=raot
+ */
+
+/* Solaris and Windows do not provide vasprintf() or asprintf(). */
+#if defined(__WIN32) || (defined(__SVR4) && defined(__sun))
+int vasprintf( char **sptr, char *fmt, va_list argv )
+{
+ int wanted = vsnprintf( *sptr = NULL, 0, fmt, argv );
+ if( (wanted > 0) && ((*sptr = malloc( 1 + wanted )) != NULL) )
+ return vsprintf( *sptr, fmt, argv );
+
+ return wanted;
+}
+
+int asprintf( char **sptr, char *fmt, ... )
+{
+ int retval;
+ va_list argv;
+ va_start( argv, fmt );
+ retval = vasprintf( sptr, fmt, argv );
+ va_end( argv );
+ return retval;
+}
+#endif
+
+
+/* GString */
+
+#define kStringBufferStartingSize 1024
+#define kStringBufferGrowthMultiplier 2
+
+GString* g_string_new(char *startingString)
+{
+ GString* newString = malloc(sizeof(GString));
+
+ if (startingString == NULL) startingString = "";
+
+ size_t startingBufferSize = kStringBufferStartingSize;
+ size_t startingStringSize = strlen(startingString);
+ while (startingBufferSize < (startingStringSize + 1))
+ {
+ startingBufferSize *= kStringBufferGrowthMultiplier;
+ }
+
+ newString->str = malloc(startingBufferSize);
+ newString->currentStringBufferSize = startingBufferSize;
+ strncpy(newString->str, startingString, startingStringSize);
+ newString->str[startingStringSize] = '\0';
+ newString->currentStringLength = startingStringSize;
+
+ return newString;
+}
+
+char* g_string_free(GString* ripString, bool freeCharacterData)
+{
+ char* returnedString = ripString->str;
+ if (freeCharacterData)
+ {
+ if (ripString->str != NULL)
+ {
+ free(ripString->str);
+ }
+ returnedString = NULL;
+ }
+
+ free(ripString);
+
+ return returnedString;
+}
+
+static void ensureStringBufferCanHold(GString* baseString, size_t newStringSize)
+{
+ size_t newBufferSizeNeeded = newStringSize + 1;
+ if (newBufferSizeNeeded > baseString->currentStringBufferSize)
+ {
+ size_t newBufferSize = baseString->currentStringBufferSize;
+
+ while (newBufferSizeNeeded > newBufferSize)
+ {
+ newBufferSize *= kStringBufferGrowthMultiplier;
+ }
+
+ baseString->str = realloc(baseString->str, newBufferSize);
+ baseString->currentStringBufferSize = newBufferSize;
+ }
+}
+
+void g_string_append(GString* baseString, char* appendedString)
+{
+ if ((appendedString != NULL) && (strlen(appendedString) > 0))
+ {
+ size_t appendedStringLength = strlen(appendedString);
+ size_t newStringLength = baseString->currentStringLength + appendedStringLength;
+ ensureStringBufferCanHold(baseString, newStringLength);
+
+ /* We already know where the current string ends, so pass that as the starting address for strncat */
+ strncat(baseString->str + baseString->currentStringLength, appendedString, appendedStringLength);
+ baseString->currentStringLength = newStringLength;
+ }
+}
+
+void g_string_append_c(GString* baseString, char appendedCharacter)
+{
+ size_t newSizeNeeded = baseString->currentStringLength + 1;
+ ensureStringBufferCanHold(baseString, newSizeNeeded);
+
+ baseString->str[baseString->currentStringLength] = appendedCharacter;
+ baseString->currentStringLength++;
+ baseString->str[baseString->currentStringLength] = '\0';
+}
+
+void g_string_append_printf(GString* baseString, char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ char* formattedString = NULL;
+ vasprintf(&formattedString, format, args);
+ if (formattedString != NULL)
+ {
+ g_string_append(baseString, formattedString);
+ free(formattedString);
+ }
+ va_end(args);
+}
+
+void g_string_prepend(GString* baseString, char* prependedString)
+{
+ if ((prependedString != NULL) && (strlen(prependedString) > 0))
+ {
+ size_t prependedStringLength = strlen(prependedString);
+ size_t newStringLength = baseString->currentStringLength + prependedStringLength;
+ ensureStringBufferCanHold(baseString, newStringLength);
+
+ memmove(baseString->str + prependedStringLength, baseString->str, baseString->currentStringLength);
+ strncpy(baseString->str, prependedString, prependedStringLength);
+ baseString->currentStringLength = newStringLength;
+ baseString->str[baseString->currentStringLength] = '\0';
+ }
+}
+
+/* GSList */
+
+void g_slist_free(GSList* ripList)
+{
+ GSList* thisListItem = ripList;
+ while (thisListItem != NULL)
+ {
+ GSList* nextItem = thisListItem->next;
+
+ /* I guess we don't release the data? Non-retained memory management is hard... let's figure it out later. */
+ free(thisListItem);
+
+ thisListItem = nextItem;
+ }
+}
+
+/* Currently only used for markdown_output.c endnotes printing */
+GSList* g_slist_reverse(GSList* theList)
+{
+ GSList* lastNodeSeen = NULL;
+
+ /* Iterate the list items, tacking them on to our new reversed List as we find them */
+ GSList* listWalker = theList;
+ while (listWalker != NULL)
+ {
+ GSList* nextNode = listWalker->next;
+ listWalker->next = lastNodeSeen;
+ lastNodeSeen = listWalker;
+ listWalker = nextNode;
+ }
+
+ return lastNodeSeen;
+}
+
+GSList* g_slist_prepend(GSList* targetElement, void* newElementData)
+{
+ GSList* newElement = malloc(sizeof(GSList));
+ newElement->data = newElementData;
+ newElement->next = targetElement;
+ return newElement;
+}
--- /dev/null
+/*
+ * GLibFacade.h
+ * MultiMarkdown
+ *
+ * https://github.com/fletcher/MultiMarkdown-4/
+ *
+ * Created by Daniel Jalkut on 7/26/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ */
+
+#ifndef __MARKDOWN_GLIB_FACADE__
+#define __MARKDOWN_GLIB_FACADE__
+
+/* peg_markdown uses the link symbol for its own purposes */
+#define link MARKDOWN_LINK_IGNORED
+#include <unistd.h>
+#undef link
+
+#include <stdbool.h>
+#include <ctype.h>
+
+typedef int gboolean;
+typedef char gchar;
+
+/* This style of bool is used in shared source code */
+#define FALSE false
+#define TRUE true
+
+/* WE implement minimal mirror implementations of GLib's GString and GSList
+ * sufficient to cover the functionality required by MultiMarkdown.
+ *
+ * NOTE: THese are 100% clean, from-scratch implementations using only the
+ * GLib function prototype as guide for behavior.
+ */
+
+typedef struct
+{
+ /* Current UTF8 byte stream this string represents */
+ char* str;
+
+ /* Where in the str buffer will we add new characters */
+ /* or append new strings? */
+ int currentStringBufferSize;
+ int currentStringLength;
+} GString;
+
+GString* g_string_new(char *startingString);
+char* g_string_free(GString* ripString, bool freeCharacterData);
+
+void g_string_append_c(GString* baseString, char appendedCharacter);
+void g_string_append(GString* baseString, char *appendedString);
+
+void g_string_prepend(GString* baseString, char* prependedString);
+
+void g_string_append_printf(GString* baseString, char* format, ...);
+
+/* Just implement a very simple singly linked list. */
+
+typedef struct _GSList
+{
+ void* data;
+ struct _GSList* next;
+} GSList;
+
+void g_slist_free(GSList* ripList);
+GSList* g_slist_prepend(GSList* targetElement, void* newElementData);
+GSList* g_slist_reverse(GSList* theList);
+
+#endif
--- /dev/null
+/*
+
+ main.c -- Template main()
+
+ Copyright © 2015 Fletcher T. Penney.
+
+
+ This program is free software you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "GLibFacade.h"
+
+char * stdin_buffer() {
+ /* Read from stdin and return a char *
+ `result` will need to be freed elsewhere */
+
+ GString * buffer = g_string_new("");
+ char curchar;
+ char * result;
+
+ while ((curchar = fgetc(stdin)) != EOF)
+ g_string_append_c(buffer, curchar);
+
+ fclose(stdin);
+
+ result = buffer->str;
+
+ g_string_free(buffer, false);
+
+ return result;
+}
+
+int main( int argc, char** argv ) {
+ /* Make your program do whatever you want */
+}
--- /dev/null
+Title: @My_Project_Title@
+Author: @My_Project_Author@
+Date: @My_Project_Revised_Date@
+Copyright: @My_Project_Copyright@
+Version: @My_Project_Version_Major@.@My_Project_Version_Minor@.@My_Project_Version_Patch@
+
+# Introduction #
+
+
+
+# License #
+
+@My_Project_License@
--- /dev/null
+/*
+
+ file.c -- @My_Project_Title@
+
+ @My_Project_Copyright@
+
+
+ @My_Project_License_Indent@
+
+*/
+
+#include "file.h"
+
+int void_function(void) {
+ return 0;
+}
+
+#ifdef TEST
+void Test_void_function(CuTest* tc) {
+ int test = void_function();
+
+ CuAssertIntEquals(tc, 0, test);
+}
+#endif
--- /dev/null
+/*
+
+ file.h -- @My_Project_Title@
+
+ @My_Project_Copyright@
+
+
+ @My_Project_License_Indent@
+
+*/
+
+#ifndef FILE_@My_Project_Title_Caps@_H
+#define FILE_@My_Project_Title_Caps@_H
+
+#ifdef TEST
+#include "CuTest.h"
+#endif
+
+
+#endif
--- /dev/null
+/*
+
+CuTest
+
+ http://cutest.sourceforge.net/
+
+NOTE
+
+The license is based on the zlib/libpng license. For more details see
+http://www.opensource.org/licenses/zlib-license.html. The intent of the
+license is to:
+
+- keep the license as simple as possible
+- encourage the use of CuTest in both free and commercial applications
+ and libraries
+- keep the source code together
+- give credit to the CuTest contributors for their work
+
+If you ship CuTest in source form with your source distribution, the
+following license document must be included with it in unaltered form.
+If you find CuTest useful we would like to hear about it.
+
+LICENSE
+
+Copyright (c) 2003 Asim Jalis
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in
+a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+*/
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "CuTest.h"
+
+/*-------------------------------------------------------------------------*
+ * CuStr
+ *-------------------------------------------------------------------------*/
+
+char* CuStrAlloc(int size)
+{
+ char* newStr = (char*) malloc( sizeof(char) * (size) );
+ return newStr;
+}
+
+char* CuStrCopy(const char* old)
+{
+ int len = strlen(old);
+ char* newStr = CuStrAlloc(len + 1);
+ strcpy(newStr, old);
+ return newStr;
+}
+
+/*-------------------------------------------------------------------------*
+ * CuString
+ *-------------------------------------------------------------------------*/
+
+void CuStringInit(CuString* str)
+{
+ str->length = 0;
+ str->size = STRING_MAX;
+ str->buffer = (char*) malloc(sizeof(char) * str->size);
+ str->buffer[0] = '\0';
+}
+
+CuString* CuStringNew(void)
+{
+ CuString* str = (CuString*) malloc(sizeof(CuString));
+ str->length = 0;
+ str->size = STRING_MAX;
+ str->buffer = (char*) malloc(sizeof(char) * str->size);
+ str->buffer[0] = '\0';
+ return str;
+}
+
+void CuStringDelete(CuString *str)
+{
+ if (!str) return;
+ free(str->buffer);
+ free(str);
+}
+
+void CuStringResize(CuString* str, int newSize)
+{
+ str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
+ str->size = newSize;
+}
+
+void CuStringAppend(CuString* str, const char* text)
+{
+ int length;
+
+ if (text == NULL) {
+ text = "NULL";
+ }
+
+ length = strlen(text);
+ if (str->length + length + 1 >= str->size)
+ CuStringResize(str, str->length + length + 1 + STRING_INC);
+ str->length += length;
+ strcat(str->buffer, text);
+}
+
+void CuStringAppendChar(CuString* str, char ch)
+{
+ char text[2];
+ text[0] = ch;
+ text[1] = '\0';
+ CuStringAppend(str, text);
+}
+
+void CuStringAppendFormat(CuString* str, const char* format, ...)
+{
+ va_list argp;
+ char buf[HUGE_STRING_LEN];
+ va_start(argp, format);
+ vsprintf(buf, format, argp);
+ va_end(argp);
+ CuStringAppend(str, buf);
+}
+
+void CuStringInsert(CuString* str, const char* text, int pos)
+{
+ int length = strlen(text);
+ if (pos > str->length)
+ pos = str->length;
+ if (str->length + length + 1 >= str->size)
+ CuStringResize(str, str->length + length + 1 + STRING_INC);
+ memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
+ str->length += length;
+ memcpy(str->buffer + pos, text, length);
+}
+
+/*-------------------------------------------------------------------------*
+ * CuTest
+ *-------------------------------------------------------------------------*/
+
+void CuTestInit(CuTest* t, const char* name, TestFunction function)
+{
+ t->name = CuStrCopy(name);
+ t->failed = 0;
+ t->ran = 0;
+ t->message = NULL;
+ t->function = function;
+ t->jumpBuf = NULL;
+}
+
+CuTest* CuTestNew(const char* name, TestFunction function)
+{
+ CuTest* tc = CU_ALLOC(CuTest);
+ CuTestInit(tc, name, function);
+ return tc;
+}
+
+void CuTestDelete(CuTest *t)
+{
+ if (!t) return;
+ free(t->name);
+ free(t);
+}
+
+void CuTestRun(CuTest* tc)
+{
+ jmp_buf buf;
+ tc->jumpBuf = &buf;
+ if (setjmp(buf) == 0)
+ {
+ tc->ran = 1;
+ (tc->function)(tc);
+ }
+ tc->jumpBuf = 0;
+}
+
+static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
+{
+ char buf[HUGE_STRING_LEN];
+
+ sprintf(buf, "%s:%d: ", file, line);
+ CuStringInsert(string, buf, 0);
+
+ tc->failed = 1;
+ tc->message = string->buffer;
+ if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
+}
+
+void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message)
+{
+ CuString string;
+
+ CuStringInit(&string);
+ if (message2 != NULL)
+ {
+ CuStringAppend(&string, message2);
+ CuStringAppend(&string, ": ");
+ }
+ CuStringAppend(&string, message);
+ CuFailInternal(tc, file, line, &string);
+}
+
+void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition)
+{
+ if (condition) return;
+ CuFail_Line(tc, file, line, NULL, message);
+}
+
+void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ const char* expected, const char* actual)
+{
+ CuString string;
+ if ((expected == NULL && actual == NULL) ||
+ (expected != NULL && actual != NULL &&
+ strcmp(expected, actual) == 0))
+ {
+ return;
+ }
+
+ CuStringInit(&string);
+ if (message != NULL)
+ {
+ CuStringAppend(&string, message);
+ CuStringAppend(&string, ": ");
+ }
+ CuStringAppend(&string, "expected <");
+ CuStringAppend(&string, expected);
+ CuStringAppend(&string, "> but was <");
+ CuStringAppend(&string, actual);
+ CuStringAppend(&string, ">");
+ CuFailInternal(tc, file, line, &string);
+}
+
+void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ int expected, int actual)
+{
+ char buf[STRING_MAX];
+ if (expected == actual) return;
+ sprintf(buf, "expected <%d> but was <%d>", expected, actual);
+ CuFail_Line(tc, file, line, message, buf);
+}
+
+void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ double expected, double actual, double delta)
+{
+ char buf[STRING_MAX];
+ if (fabs(expected - actual) <= delta) return;
+ sprintf(buf, "expected <%f> but was <%f>", expected, actual);
+
+ CuFail_Line(tc, file, line, message, buf);
+}
+
+void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ void* expected, void* actual)
+{
+ char buf[STRING_MAX];
+ if (expected == actual) return;
+ sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
+ CuFail_Line(tc, file, line, message, buf);
+}
+
+
+/*-------------------------------------------------------------------------*
+ * CuSuite
+ *-------------------------------------------------------------------------*/
+
+void CuSuiteInit(CuSuite* testSuite)
+{
+ testSuite->count = 0;
+ testSuite->failCount = 0;
+ memset(testSuite->list, 0, sizeof(testSuite->list));
+}
+
+CuSuite* CuSuiteNew(void)
+{
+ CuSuite* testSuite = CU_ALLOC(CuSuite);
+ CuSuiteInit(testSuite);
+ return testSuite;
+}
+
+void CuSuiteDelete(CuSuite *testSuite)
+{
+ unsigned int n;
+ for (n=0; n < MAX_TEST_CASES; n++)
+ {
+ if (testSuite->list[n])
+ {
+ CuTestDelete(testSuite->list[n]);
+ }
+ }
+ free(testSuite);
+
+}
+
+void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
+{
+ assert(testSuite->count < MAX_TEST_CASES);
+ testSuite->list[testSuite->count] = testCase;
+ testSuite->count++;
+}
+
+void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2)
+{
+ int i;
+ for (i = 0 ; i < testSuite2->count ; ++i)
+ {
+ CuTest* testCase = testSuite2->list[i];
+ CuSuiteAdd(testSuite, testCase);
+ }
+}
+
+void CuSuiteRun(CuSuite* testSuite)
+{
+ int i;
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ CuTestRun(testCase);
+ if (testCase->failed) { testSuite->failCount += 1; }
+ }
+}
+
+void CuSuiteSummary(CuSuite* testSuite, CuString* summary)
+{
+ int i;
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ CuStringAppend(summary, testCase->failed ? "F" : ".");
+ }
+ CuStringAppend(summary, "\n\n");
+}
+
+void CuSuiteDetails(CuSuite* testSuite, CuString* details)
+{
+ int i;
+ int failCount = 0;
+
+ if (testSuite->failCount == 0)
+ {
+ int passCount = testSuite->count - testSuite->failCount;
+ const char* testWord = passCount == 1 ? "test" : "tests";
+ CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
+ }
+ else
+ {
+ if (testSuite->failCount == 1)
+ CuStringAppend(details, "There was 1 failure:\n");
+ else
+ CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
+
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ if (testCase->failed)
+ {
+ failCount++;
+ CuStringAppendFormat(details, "%d) %s: %s\n",
+ failCount, testCase->name, testCase->message);
+ }
+ }
+ CuStringAppend(details, "\n!!!FAILURES!!!\n");
+
+ CuStringAppendFormat(details, "Runs: %d ", testSuite->count);
+ CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
+ CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount);
+ }
+}
--- /dev/null
+/*
+
+CuTest
+
+ http://cutest.sourceforge.net/
+
+NOTE
+
+The license is based on the zlib/libpng license. For more details see
+http://www.opensource.org/licenses/zlib-license.html. The intent of the
+license is to:
+
+- keep the license as simple as possible
+- encourage the use of CuTest in both free and commercial applications
+ and libraries
+- keep the source code together
+- give credit to the CuTest contributors for their work
+
+If you ship CuTest in source form with your source distribution, the
+following license document must be included with it in unaltered form.
+If you find CuTest useful we would like to hear about it.
+
+LICENSE
+
+Copyright (c) 2003 Asim Jalis
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in
+a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+*/
+
+#ifndef CU_TEST_H
+#define CU_TEST_H
+
+#include <setjmp.h>
+#include <stdarg.h>
+
+#define CUTEST_VERSION "CuTest 1.5"
+
+/* CuString */
+
+char* CuStrAlloc(int size);
+char* CuStrCopy(const char* old);
+
+#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE)))
+
+#define HUGE_STRING_LEN 8192
+#define STRING_MAX 256
+#define STRING_INC 256
+
+typedef struct
+{
+ int length;
+ int size;
+ char* buffer;
+} CuString;
+
+void CuStringInit(CuString* str);
+CuString* CuStringNew(void);
+void CuStringRead(CuString* str, const char* path);
+void CuStringAppend(CuString* str, const char* text);
+void CuStringAppendChar(CuString* str, char ch);
+void CuStringAppendFormat(CuString* str, const char* format, ...);
+void CuStringInsert(CuString* str, const char* text, int pos);
+void CuStringResize(CuString* str, int newSize);
+void CuStringDelete(CuString* str);
+
+/* CuTest */
+
+typedef struct CuTest CuTest;
+
+typedef void (*TestFunction)(CuTest *);
+
+struct CuTest
+{
+ char* name;
+ TestFunction function;
+ int failed;
+ int ran;
+ const char* message;
+ jmp_buf *jumpBuf;
+};
+
+void CuTestInit(CuTest* t, const char* name, TestFunction function);
+CuTest* CuTestNew(const char* name, TestFunction function);
+void CuTestRun(CuTest* tc);
+void CuTestDelete(CuTest *t);
+
+/* Internal versions of assert functions -- use the public versions */
+void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message);
+void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition);
+void CuAssertStrEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ const char* expected, const char* actual);
+void CuAssertIntEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ int expected, int actual);
+void CuAssertDblEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ double expected, double actual, double delta);
+void CuAssertPtrEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ void* expected, void* actual);
+
+/* public assert functions */
+
+#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms))
+#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond))
+#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond))
+
+#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
+#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
+#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl))
+#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl))
+#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
+#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+
+#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL))
+#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL))
+
+/* CuSuite */
+
+#define MAX_TEST_CASES 1024
+
+#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST))
+
+typedef struct
+{
+ int count;
+ CuTest* list[MAX_TEST_CASES];
+ int failCount;
+
+} CuSuite;
+
+
+void CuSuiteInit(CuSuite* testSuite);
+CuSuite* CuSuiteNew(void);
+void CuSuiteDelete(CuSuite *testSuite);
+void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase);
+void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2);
+void CuSuiteRun(CuSuite* testSuite);
+void CuSuiteSummary(CuSuite* testSuite, CuString* summary);
+void CuSuiteDetails(CuSuite* testSuite, CuString* details);
+
+#endif /* CU_TEST_H */
--- /dev/null
+#!/usr/bin/env bash
+
+# Auto generate single AllTests file for CuTest.
+# Searches through all *.c files in the current directory.
+# Prints to stdout.
+# Author: Asim Jalis
+# Date: 01/08/2003
+
+if test $# -eq 0 ; then FILES=*.c ; else FILES=$* ; fi
+
+echo '
+
+/* This is auto-generated code. Edit at your own peril. */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "CuTest.h"
+
+'
+
+cat $FILES | grep '^void Test' |
+ sed -e 's/(.*$//' \
+ -e 's/$/(CuTest*);/' \
+ -e 's/^/extern /'
+
+echo \
+'
+
+void RunAllTests(void)
+{
+ CuString *output = CuStringNew();
+ CuSuite* suite = CuSuiteNew();
+
+'
+cat $FILES | grep '^void Test' |
+ sed -e 's/^void //' \
+ -e 's/(.*$//' \
+ -e 's/^/ SUITE_ADD_TEST(suite, /' \
+ -e 's/$/);/'
+
+echo \
+'
+ CuSuiteRun(suite);
+ CuSuiteSummary(suite, output);
+ CuSuiteDetails(suite, output);
+ printf("%s\\n", output->buffer);
+ CuStringDelete(output);
+ CuSuiteDelete(suite);
+}
+
+int main(void)
+{
+ RunAllTests();
+}
+'
--- /dev/null
+# Settings for compiling under MinGW32
+
+set (CMAKE_SYSTEM_NAME Windows)
+
+set (CMAKE_C_COMPILER i586-mingw32msvc-gcc)
+set (CMAKE_CXX_COMPILER i586-mingw32msvc-g++)
+set (CMAKE_RC_COMPILER i586-mingw32msvc-windres)
+
+set (CMAKE_FIND_ROOT_PATH /usr/bin)