diff --git a/.cproject b/.cproject
new file mode 100644
index 0000000..7f2148c
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..f649d94
--- /dev/null
+++ b/.project
@@ -0,0 +1,26 @@
+
+
+ stubi
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs
new file mode 100644
index 0000000..f925dfa
--- /dev/null
+++ b/.settings/org.eclipse.cdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/delimiter=;
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/operation=replace
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/value=C\:\\cygwin
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/append=true
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/appendContributed=true
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/delimiter=;
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/operation=replace
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/value=C\:\\cygwin
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/append=true
+environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/appendContributed=true
diff --git a/src/stubi.c b/src/stubi.c
new file mode 100644
index 0000000..69e9c60
--- /dev/null
+++ b/src/stubi.c
@@ -0,0 +1,271 @@
+/*!
+ Name : stubi.c
+ Author : Martin Winkler
+ Version :
+ Copyright :
+ Description : Scan a folder for .c files and generate stubs from function definitions
+
+ @todo complete function dissection
+ @todo output stub header and function
+ @attention Using regular expressions to scan c files for function definitions. No 100%
+ success rate and should be seen as helper. Result must be reviewed manually.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#define STUBI_FUNCTION_REGEX "^[ \\t]*([ _\\*[:alnum:]]*) ([_\\*[:alnum:]]*)[ \\t]*\\(([^\\)]*)"
+#define STUBI_FUNCTION_MULTI "[ \\t]*(.*)"
+#define STUBI_FUNCTION_MULTI_END "[ \\t]*(.*)\\)[ \\t\\{;]*"
+
+static int one(const struct dirent *unused)
+{
+ return 1;
+}
+
+static char *gnu_basename(char *path)
+{
+ char *base = strrchr(path, '/');
+ return base ? base + 1 : path;
+}
+
+/*!
+ * @brief Process a string (e.g. from getline()) if it is a single or multiple line function definition
+ * @todo closing parenthesis within parameter list will break the detection
+ * @retval -1 Invalid regula expressions
+ * @retval -2 Given String not a function
+ * @retval 0 function evaluated
+ */
+static int matchFunction(char *aLine)
+{
+ const size_t maxGroup = 10;
+ regmatch_t matchGroup[maxGroup];
+ const char *pattern =
+ STUBI_FUNCTION_REGEX;
+ const char *patternend =
+ STUBI_FUNCTION_REGEX "\\)";
+ regex_t regX;
+ regex_t regXEnd;
+ regex_t regXMulti;
+ regex_t regXMultiEnd;
+ uint8_t i = 0;
+ char funPrefix[256] =
+ { 0 };
+ static uint8_t multiParamFlag = 0;
+ uint8_t multiParamEndFlag = 0;
+
+ if (0 > regcomp(®X, pattern, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regex\n");
+ return -1;
+ }
+
+ if (0 > regcomp(®XEnd, patternend, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regexend\n");
+ return -1;
+ }
+
+ if (0 > regcomp(®XMulti, STUBI_FUNCTION_MULTI, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regXMulti\n");
+ return -1;
+ }
+
+ if (0 > regcomp(®XMultiEnd, STUBI_FUNCTION_MULTI_END, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regXMultiEnd\n");
+ return -1;
+ }
+
+ if (multiParamFlag)
+ {
+ if (0 == regexec(®XMultiEnd, aLine, maxGroup, matchGroup, 0))
+ {
+ // end of multi line function
+ ++multiParamFlag;
+ multiParamEndFlag = 1;
+ }
+ else
+ {
+ // continuation of multi line function
+ (void) regexec(®XMulti, aLine, maxGroup, matchGroup, 0);
+ ++multiParamFlag;
+ }
+ }
+ else if (0 == regexec(®XEnd, aLine, maxGroup, matchGroup, 0))
+ {
+ // single line function
+ multiParamFlag = 0;
+ }
+ else if (0 == regexec(®X, aLine, maxGroup, matchGroup, 0))
+ {
+ // start of multi line function
+ ++multiParamFlag;
+ printf("[ mls][%d]:", multiParamFlag);
+ }
+ else
+ {
+ // no fit
+ return -2;
+ }
+
+ switch (multiParamFlag)
+ {
+ case 0: // single line function definition
+ case 1: // first line of multi line function definition
+ {
+ (void) strlcpy(funPrefix, &aLine[matchGroup[1].rm_so], (size_t) (matchGroup[1].rm_eo - matchGroup[1].rm_so) + 1);
+
+ if ( //
+ NULL == strstr(funPrefix, "extern") //
+ && NULL == strstr(funPrefix, "EXTERN") //
+ && NULL == strstr(funPrefix, "static") //
+ && NULL == strstr(funPrefix, "STATIC") //
+ && matchGroup[2].rm_so < matchGroup[2].rm_eo)
+ {
+ printf("[ sl ]:%s", funPrefix);
+ for (i = 2; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i)
+ {
+ printf(" (%.3ld - %.3ld): ", matchGroup[i].rm_so, matchGroup[i].rm_eo);
+ printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]);
+ }
+ printf("\n");
+ }
+ // TODO special handling for static functions (as extern in stub header)
+ else if (NULL != strstr(funPrefix, "static") || NULL != strstr(funPrefix, "STATIC"))
+ {
+ printf("[todo] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]);
+ }
+ // ignore functions declared as extern
+ else if (NULL != strstr(funPrefix, "extern") || NULL != strstr(funPrefix, "EXTERN"))
+ {
+ printf("[ nu ] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]);
+ }
+ break;
+ }
+ default: // further lines
+ {
+ if (multiParamEndFlag)
+ {
+ printf("[ mle][%d]:", multiParamFlag);
+ }
+ else
+ {
+ printf("[ ml ][%d]:", multiParamFlag);
+ }
+
+ if (matchGroup[1].rm_so < matchGroup[1].rm_eo)
+ {
+ for (i = 1; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i)
+ {
+ printf("(%.3ld-%.3ld):", matchGroup[i].rm_so, matchGroup[i].rm_eo);
+ printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]);
+ }
+ printf("\n");
+ }
+
+ if (multiParamEndFlag)
+ {
+ multiParamFlag = 0;
+ multiParamEndFlag = 0;
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * @brief Opens given file for line by line function matching
+ * @param *path file path
+ * @retval 0 matching complete
+ * @retval -1 error opening file
+ */
+static int scanFile(char *path)
+{
+ FILE *fdesc;
+ ssize_t charRead = 0;
+ size_t lineSize = 0;
+ char *fileLine = NULL; // will be allocated by getline(); must be freed
+
+ fdesc = fopen(path, "r");
+ if (NULL == fdesc)
+ {
+ perror("Error open file");
+ return -1;
+ }
+
+ do
+ {
+ charRead = getline(&fileLine, &lineSize, fdesc);
+ if (0 <= charRead)
+ {
+ (void) matchFunction(fileLine);
+ }
+ } while (0 <= charRead);
+
+ free(fileLine);
+ (void) fclose(fdesc);
+ return 0;
+}
+
+/*
+ * @brief Scan given folder for .c files
+ * @param argc amount of command line arguments
+ * @param **argv array of argments separated by spaces
+ * @retval -1 Directory not found or regex compilation error
+ * @retval 0 Direcotry scanned successfully
+ * @details
+ * see printf for usage
+ */
+int main(int argc, char **argv)
+{
+ struct dirent **eps;
+ int n;
+ regex_t regX;
+ char filePath[256] =
+ { 0 };
+ const char *pattern = "^.*\\.[cC]";
+
+ printf("%s %s\n\n", argv[1], argv[2]);
+
+ if (3 != argc)
+ {
+ printf("Usage:\n");
+ printf(" %s \n", gnu_basename(argv[0]));
+ return -1;
+ }
+
+ if (regcomp(®X, pattern, REG_NEWLINE))
+ {
+ fprintf(stderr, "bad pattern: '%s'\n", pattern);
+ return -1;
+ }
+
+ n = scandir(argv[1], &eps, one, alphasort);
+ if (n >= 0)
+ {
+ int cnt;
+ for (cnt = 0; cnt < n; ++cnt)
+ {
+ if (0 == regexec(®X, eps[cnt]->d_name, 0, NULL, 0) //
+ && DT_REG == eps[cnt]->d_type)
+ {
+ sprintf(filePath, "%s/%s", argv[1], eps[cnt]->d_name);
+ printf("%s (%d)\n", filePath, eps[cnt]->d_type);
+ scanFile(filePath);
+ }
+ }
+ }
+ else
+ perror("Couldn't open the directory");
+
+ return 0;
+}
+