Shell - A script I use to rapidly create a new C project skeleton.
#include "../src/minunit.h"
#include "../src/dbg.h"
#include "../src/myutil.h"
#include "../src/array_util.h"
char *test_util(void)
{
int err = 0;
/* put tests here */
mu_assert(err == 0, "test util error!");
return NULL;
}
char *all_tests() {
mu_suite_start();
mu_run_test(test_util);
return NULL;
}
RUN_TESTS(all_tests);
echo "Running unit tests:"
for i in tests/*_tests
do
if test -f $i
then
if $VALGRIND ./$i 2>> tests/tests.log
then
echo $i PASS
else
echo "ERROR in test $i: here's tests/tests.log"
echo "------"
tail tests/tests.log
fi
fi
done
echo ""
/**
* @file myutil.h
* @author Joseph Pan <cs.wzpan@gmail.com>
* @date
*
* @brief for rapidly drafting programs
*
*/
#ifndef MY_UTIL_H
#define MY_UTIL_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dbg.h"
#include "array_util.h"
/* Put definitions of functions here */
#endif
/**
* @file myutil.c
* @author Joseph Pan <cs.wzpan@gmail.com>
* @date
*
* @brief for rapidly drafting programs
*
*
*/
#include "myutil.h"
/* Put declarations of functions here. */
/**
* @file minunit.h
* @author Zed A.Shaw, Jera Design
* @date Thu Sep 19 19:48:35 2013
*
* @brief A minimal unit testing framework for C
*
*/
#undef NDEBUG
#ifndef MINUNIT_H
#define MINUNIT_H
#include <stdio.h>
#include "dbg.h"
#include <stdlib.h>
#define mu_suite_start() char *message = NULL
#define mu_assert(test, message) if (!(test)) { log_err(message); return message; }
#define mu_run_test(test) debug("\n-----%s", " " #test); \
message = test(); tests_run++; if (message) return message;
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
argc = 1; \
debug("----- RUNNING: %s", argv[0]);\
printf("----\nRUNNING: %s\n", argv[0]);\
char *result = name();\
if (result != 0) {\
printf("FAILED: %s\n", result);\
}\
else {\
printf("ALL TESTS PASSED\n");\
}\
printf("Tests run: %d\n", tests_run);\
exit(result != 0);\
}
int tests_run;
#endif
#/bin/bash
if [[ $# -eq 0 ]]
then
echo "Type the project name you want to create: "
read project_name
else
project_name=$1
fi
if [[ ! -d $project_name ]]
then
mkdir -p $project_name
fi
for i in src bin build tests
do
if [[ ! -d $i ]]
then
mkdir $project_name/$i
fi
done
# download Makefile and test scripts
mkdir /tmp/fast-project
cd /tmp/fast-project
wget https://gist.github.com/wzpan/6778981/download
tar -xf /tmp/fast-project/download
cd -
cp /tmp/fast-project/gist*/Makefile $project_name/
cp /tmp/fast-project/gist*/*.h $project_name/src/
cp /tmp/fast-project/gist*/*util.c $project_name/src/
cp /tmp/fast-project/gist*/*_tests.* $project_name/tests/
cp /tmp/fast-project/gist*/runtests.sh $project_name/tests/
touch $project_name/README.md
touch $project_name/LICENSE
rm -r /tmp/fast-project
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s:) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif
/**
* @file array_util.h
* @author Joseph Pan <cs.wzpan@gmail.com>
* @date Thu Sep 19 19:44:33 2013
*
* @brief useful functions to manage arrays
*
*/
#ifndef ARRAY_H
#define ARRAY_H
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define MAX 10
/* For input a integer. */
extern int read_num(void);
/* For input and output arrays. */
extern void print_array(int *array, int length);
extern void read_array(int *array, int length);
extern void generate_array(int *array, int length); // randomly generate array
/* For input and output matrix. */
extern void read_matrix2(int matrix[MAX][MAX], int m, int n);
extern void print_matrix2(int matrix[MAX][MAX], int m, int n);
#endif
/**
* @file array_util.c
* @author Joseph Pan <cs.wzpan@gmail.com>
* @date Thu Sep 19 19:46:26 2013
*
* @brief useful functions to manage arrays
*
*/
#include "array_util.h"
/**
* read_num - input a number
* Input an integer number.
* @return the integer number
*
*/
extern int read_num(void)
{
int i;
const int SIZE = 5;
char input[SIZE];
int sum = 0;
int success = 0;
while (0 == success){ // loop unless input a valid number
i = 0;
sum = 0;
scanf("%s", input);
while (TRUE){
if (input[i] < '0' || input[i] > '9') {
printf("Invalid input! Please input again: ");
sum = -1;
break;
}
sum = sum*10 + input[i] - '0';
i++;
if (input[i] == '\0') {
success = 1;
break;
}
}
}
return sum;
}
/**
* read_array - input an array
* @param array the array to be printed
* @param length the length of the array
*
* Input an integers array.
*/
extern void read_array(int *array, int length)
{
int i = 0;
for (i = 0; i < length; i++){
*(array + i) = read_num();
}
return;
}
/**
* print_array - print all the elements from an array
* @param array the array to be printed
* @param length the length of the array
*/
extern void print_array(int *array, int length)
{
int i = 0;
for (i = 0; i < length; i++){
printf("%d ", array[i]);
}
printf("\n");
return;
}
/**
* generate_array - randomly generate an integer array
* @param array the expected array
* @param length the length of the array
*
*/
extern void generate_array(int *array, int length)
{
srand((unsigned)time(NULL));
int i;
for (i = 0; i < length; i++){
*(array + i) = random() % 100;
}
return;
}
/**
* read_matrix - input a matrix
* @param matrix the required matrix
* @param m rows of the matrix
* @param n cols of the matrix
*
*/
extern void read_matrix2(int matrix[MAX][MAX], int m, int n)
{
int i, j, temp;
printf("Input elements of Matrix(%d*%d):\n", m, n);
for(i = 0; i < m; i++)
for(j = 0; j < n; j++){
scanf("%d", &temp);
matrix[i][j] = temp;
}
return;
}
/**
* print_matrix - print a matrix
* @param matrix the required matrix
* @param m rows of the matrix
* @param n cols of the matrix
*
*/
extern void print_matrix2(int matrix[MAX][MAX], int m, int n)
{
int i, j;
for(i = 0; i < 2*n; i++)
printf("-");
putchar('\n');
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
printf("%d ", matrix[i][j]);
}
putchar('\n');
}
for(i = 0; i < 2*n; i++)
printf("-");
putchar('\n');
return;
}
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libmyutil.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: CFLAGS += $(TARGET)
$(TESTS): %: %.c
$(CC) $(CFLAGS) $< -o $@ -Lbuild -lmyutil -static
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions.
@egrep $(BADFUNCS) $(SOURCES) || true