]> granicus.if.org Git - multimarkdown/commitdiff
Initialize project
authorFletcher T. Penney <fletcher@fletcherpenney.net>
Sat, 13 Jun 2015 18:59:00 +0000 (14:59 -0400)
committerFletcher T. Penney <fletcher@fletcherpenney.net>
Sat, 13 Jun 2015 18:59:00 +0000 (14:59 -0400)
16 files changed:
CMakeLists.txt [new file with mode: 0644]
IMPORTANT [new file with mode: 0644]
LICENSE.txt [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
build/.gitignore [new file with mode: 0644]
src/GLibFacade.c [new file with mode: 0644]
src/GLibFacade.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]
templates/README.md.in [new file with mode: 0644]
templates/template.c.in [new file with mode: 0644]
templates/template.h.in [new file with mode: 0644]
test/CuTest.c [new file with mode: 0644]
test/CuTest.h [new file with mode: 0644]
test/make-tests.sh [new file with mode: 0644]
tools/Toolchain-mingw32.cmake [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0129aa2
--- /dev/null
@@ -0,0 +1,125 @@
+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
diff --git a/IMPORTANT b/IMPORTANT
new file mode 100644 (file)
index 0000000..a332193
--- /dev/null
+++ b/IMPORTANT
@@ -0,0 +1,46 @@
+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.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644 (file)
index 0000000..a89ea09
--- /dev/null
@@ -0,0 +1,32 @@
+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
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c132a5e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+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)/*
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..a003f3b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,104 @@
+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.
+
diff --git a/build/.gitignore b/build/.gitignore
new file mode 100644 (file)
index 0000000..5e7d273
--- /dev/null
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/src/GLibFacade.c b/src/GLibFacade.c
new file mode 100644 (file)
index 0000000..552d066
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *     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;
+}
diff --git a/src/GLibFacade.h b/src/GLibFacade.h
new file mode 100644 (file)
index 0000000..035d97b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *     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
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..22d0ff2
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+
+       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 */
+}
diff --git a/templates/README.md.in b/templates/README.md.in
new file mode 100644 (file)
index 0000000..bf2b25e
--- /dev/null
@@ -0,0 +1,13 @@
+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@
diff --git a/templates/template.c.in b/templates/template.c.in
new file mode 100644 (file)
index 0000000..d11d1e6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+
+       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
diff --git a/templates/template.h.in b/templates/template.h.in
new file mode 100644 (file)
index 0000000..e135985
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+
+       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
diff --git a/test/CuTest.c b/test/CuTest.c
new file mode 100644 (file)
index 0000000..f5e142a
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+
+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);
+       }
+}
diff --git a/test/CuTest.h b/test/CuTest.h
new file mode 100644 (file)
index 0000000..e293fd0
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+
+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 */
diff --git a/test/make-tests.sh b/test/make-tests.sh
new file mode 100644 (file)
index 0000000..9d41dab
--- /dev/null
@@ -0,0 +1,55 @@
+#!/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();
+}
+'
diff --git a/tools/Toolchain-mingw32.cmake b/tools/Toolchain-mingw32.cmake
new file mode 100644 (file)
index 0000000..f529580
--- /dev/null
@@ -0,0 +1,9 @@
+# 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)