changeset 734:d4edcc124e64

added Torture capabilities
author thomask
date Fri, 11 Nov 2005 21:15:57 +0000
parents 476575c64be3
children 4704970e47ad
files dstress.c
diffstat 1 files changed, 502 insertions(+), 248 deletions(-) [+]
line wrap: on
line diff
--- a/dstress.c	Mon Nov 07 04:26:11 2005 +0000
+++ b/dstress.c	Fri Nov 11 21:15:57 2005 +0000
@@ -32,21 +32,22 @@
 #include <errno.h>
 #include <ctype.h>
 
-#define RUN		1
-#define NORUN		2
-#define COMPILE		4
-#define NOCOMPILE	8
+/* number's choice: XOR and printf :) */
+#define MODE_RUN	(0x10000)
+#define MODE_NORUN	(0x1000)
+#define MODE_COMPILE	(0x100)
+#define MODE_NOCOMPILE	(0x10)
+#define MODE_TORTURE	(0x2)
 
-/* secure malloc */
-void *xmalloc(size_t size){
-	void *p = malloc(size);
-	if (p == NULL){
-		fprintf(stderr,"Failed to allocate %zd bytes!\n", size);
-		exit(EXIT_FAILURE);
-	}
-	return p;
-}
-#define malloc xmalloc
+#define RES_BASE_MASK	(0xFFFFFF0)
+#define RES_PASS	(0x1000000)
+#define RES_XFAIL	(0x100000)
+#define RES_XPASS	(0x10000)
+#define RES_FAIL	(0x1000)
+#define RES_ERROR	(0x100)
+#define RES_UNTESTED	(0x10)
+#define RES_BAD_GDB	(0x4)
+#define RES_BAD_MSG	(0x2)
 
 #if defined(__GNU_LIBRARY__) || defined(__GLIBC__)
 #define USE_POSIX 1
@@ -72,7 +73,23 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <regex.h>
+#include <stdint.h>
+#include <limits.h>
 
+/* not every STDLIB supports C99's "%z" for printf formating */
+#if PTRDIFF_MAX == INT_MAX
+#define ZU "%u"
+#else
+#if PTRDIFF_MAX == LONG_MAX
+#define ZU "%lu"
+#else
+#if PTRDIFF_MAX == SHRT_MAX
+#define ZU "%hu"
+#else
+#error what is the size of a pointer?
+#endif
+#endif
+#endif
 #else
 #ifdef USE_WINDOWS
 
@@ -80,6 +97,18 @@
 #define snprintf _snprintf
 #ifndef INVALID_FILE_SIZE
 #define INVALID_FILE_SIZE (-1)
+
+/* not every STDLIB supports C99's "%z" for printf formating */
+#ifdef win32
+#define ZU "%u"
+#else
+#ifdef win64
+#define ZU "%llu"
+#else
+#error what is the size of a pointer?
+#endif
+#endif
+
 #endif
 
 #else
@@ -87,28 +116,88 @@
 #endif /* USE_WINDOWS else */
 #endif /* USE_POSIX else */
 
-#define OBJ			"obj "
+#define TORTURE_PREFIX		"torture-"
 
 #ifdef USE_POSIX
-#define		TLOG		"./obj/log.tmp"
 #define		CRASH_RUN	"./crashRun"
-#define		GDB_SCRIPTER	"./obj/gdb.tmp"
+#define		TMP_DIR		"./obj"
 #else
 #ifdef USE_WINDOWS
-#define		TLOG		".\\obj\\log.tmp"
 #define		CRASH_RUN	".\\crashRun"
-#define		GDB_SCRIPTER	".\\obj\\gdb.tmp"
+#define		TMP_DIR		".\\obj"
 #else
 #error OS dependent file names not defined
 #endif
 #endif
 
-char* errorMsg(int good_error){
-	return (good_error) ? ("") : " [bad error message]";
+const char* torture[] = {
+	"",
+	
+	"-g", "-inline", "-fPIC", "-O", "-release",
+	
+	"-g -inline", "-g -fPIC", "-g -O", "-g -release",
+	"-inline -fPIC", "-inline -O", "-inline -release",
+	"-fPIC -O", "-fPIC -release",
+	"-O -release",
+	
+	"-g -inline -fPIC", "-g -inline -O", "-g -inline -release",
+	"-g -fPIC -O", "-g -fPIC -release", "-g -O -release",
+	"-inline -fPIC -O", "-inline -fPIC -release", "-inline -O -release",
+	"-fPIC -O -release",
+
+	"-g -inline -fPIC -O", "-g -inline -fPIC -release",
+	"-g -fPIC -O -release",
+	"-inline -fPIC -O -release",
+
+	"-g -inline -fPIC -O -release"
+};
+
+/* secure malloc */
+void *xmalloc(size_t size){
+	void *p = malloc(size);
+	if (p == NULL){
+		fprintf(stderr, "Failed to allocate " ZU " bytes!\n", size);
+		exit(EXIT_FAILURE);
+	}
+	return p;
 }
+#define malloc xmalloc
 
-char* gdbMsg(int good_gdb){
-	return (good_gdb) ? ("") : " [bad debugger message]";
+/* secure calloc */
+void* xcalloc(size_t members, size_t size){
+	void* ptr = calloc(members, size);
+	if(ptr == NULL){
+		fprintf(stderr, "Failed to allocate " ZU " elements"
+			"(" ZU " bytes each)!\n", members, size);
+		exit(EXIT_FAILURE);
+	}
+	return ptr;
+}
+#define calloc xcalloc
+
+
+void printResult(int result, int modus, char* case_file, FILE* stream){
+	char* msg = NULL;
+#ifdef DEBUG
+	fprintf(stderr, "case: %s, modus: %x, result: %x\n", case_file, modus,
+			result);
+#endif
+
+	if(result & RES_PASS){
+		msg = "PASS: ";
+	}else if(result & RES_XFAIL){
+		msg = "XFAIL:";
+	}else if(result & RES_XPASS){
+		msg = "XPASS:";
+	}else if(result & RES_FAIL){
+		msg = "FAIL: ";
+	}else if(result & RES_ERROR){
+		msg = "ERROR:";
+	}
+
+	fprintf(stream, "%s\t%s%s%s\n", msg, case_file,
+			(result & RES_BAD_MSG) ? " [bad error message]" : "",
+			(result & RES_BAD_GDB) ? " [bad debugger message]" : "");
 }
 
 char* strip(char* buffer){
@@ -126,6 +215,19 @@
 	return buffer;
 }
 
+unsigned int genTempFileNameCount;
+char* genTempFileName(){
+	char* back;
+	size_t len;
+
+	len = strlen(TMP_DIR) + 128;
+	back = malloc(len);
+	
+	snprintf(back, len, "%s/t%x-%x-%x.tmp", TMP_DIR, getpid(), rand(), ++genTempFileNameCount);
+
+	return back;
+}
+
 /* cleanup "/" versus "\" in filenames */
 char* cleanPathSeperator(char* filename){
 	char* pos = NULL;
@@ -171,15 +273,12 @@
 	if(back){
 		return back;
 	}
-	if(0==strcmp(filename, TLOG)){
-		return calloc(1,sizeof(char));
-	}
 
 	fprintf(stderr, "File not found \"%s\" (%s)\n", filename, strerror(errno));
 	exit(EXIT_FAILURE);
 #else /* USE_POSIX */
 #ifdef USE_WINDOWS
-	// @todo@ check for 32bit/64bit
+	/* @todo@ check for 32bit/64bit */
 	char* back;
 	DWORD size, numread;
 	HANDLE file=CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
@@ -247,11 +346,6 @@
 char* getCompiler(void){
 	char* back = getenv("DMD");
 
-#ifdef USE_WINDOWS
-	if(back == NULL){
-		back = getenv("dmd");
-	}
-#endif
 	if(back==NULL){
 		back = "dmd";
 	}
@@ -263,11 +357,6 @@
 char* getGDB(void){
 	char* back = getenv("GDB");
 
-#ifdef USE_WINDOWS
-	if(back == NULL){
-		back = getenv("gdb");
-	}
-#endif
 	if(back==NULL){
 		back = "gdb";
 	}
@@ -275,6 +364,19 @@
 	return strip(cleanPathSeperator(back));
 }
 
+char* getTortureBlock(void){
+	char* back = getenv("DSTRESS_TORTURE_BLOCK");
+
+	if(back!=NULL){
+		back = strip(back);
+		if(strlen(back)<1){
+			back = NULL;
+		}
+	}
+
+	return back;
+}
+
 /* extract the FIRST occurance of a given TAG until the next linebreak */
 char* getCaseFlag(const char* data, const char* tag){
 	char* begin;
@@ -502,18 +604,20 @@
 }
 
 /* system call with time-out */
-int crashRun(const char* cmd){
+int crashRun(const char* cmd, char** logFile){
 #ifdef USE_POSIX
 	size_t len;
 	char* buffer;
 
-	len = 4 + strlen(CRASH_RUN) + strlen(cmd);
+	*logFile = genTempFileName();
+
+	len = 20 + strlen(CRASH_RUN) + strlen(cmd) + strlen(*logFile);
 	buffer = malloc(len);
 
-	snprintf(buffer, len, "\"%s\" %s", CRASH_RUN, cmd);
+	snprintf(buffer, len, "\"%s\" %s > %s 2>&1", CRASH_RUN, cmd, *logFile);
 
 	system(buffer);
-	buffer=loadFile(TLOG);
+	buffer=loadFile(*logFile);
 
 	if(strstr(buffer, "EXIT CODE: 0")){
 		return EXIT_SUCCESS;
@@ -534,43 +638,277 @@
 #endif /* USE_POSIX else */
 }
 
+int target_compile(int modus, char* compiler, char* arguments, char* case_file,
+		char* error_file, char* error_line)
+{
+	size_t bufferLen;
+	char* buffer;
+	int res;
+	int testResult;
+	int good_error;
+	char* logFile;
+
+	bufferLen = 0;
+	buffer = NULL;
+	res = -1;
+	testResult = -1;
+	good_error = 0;
+	logFile = NULL;
+
+	if(!(modus & MODE_COMPILE) && !(modus & MODE_NOCOMPILE)){
+		fprintf(stderr, "BUG: badly handled mode %i (->compile)\n",
+			modus);
+		exit(EXIT_FAILURE);
+	}
+
+	/* gen command */
+	bufferLen = strlen(compiler) + strlen(arguments) + strlen(TMP_DIR)
+		+ strlen(case_file) + 21;
+	buffer = malloc(bufferLen);
+	snprintf(buffer, bufferLen, "%s %s ", compiler, arguments);
+
+	if(NULL == strstr(buffer, "-od")){
+		snprintf(buffer, bufferLen, "%s %s -od%s -c %s",
+			compiler, arguments, TMP_DIR, case_file);
+	}else{
+		snprintf(buffer, bufferLen, "%s %s -c %s",
+			compiler, arguments, case_file);
+	}
+
+	/* test */
+	if(modus & MODE_COMPILE){
+		fprintf(stderr, "compile: %s\n", buffer);
+	}else{
+		fprintf(stderr, "nocompile: %s\n", buffer);
+	}
+	res = crashRun(buffer, &logFile);
+
+	/* diagnostic */
+	buffer = loadFile(logFile);
+	fprintf(stderr, "%s\n", buffer);
+	remove(logFile);
+	good_error = checkErrorMessage(error_file, error_line, buffer);
+
+	if(hadExecCrash(buffer)){
+		testResult = RES_ERROR;
+	}else if(modus & MODE_COMPILE){
+		if(res == EXIT_SUCCESS){
+			testResult = RES_PASS;
+		}else if(res == EXIT_FAILURE){
+			testResult = RES_FAIL | (good_error ? 0 : RES_BAD_MSG);
+		}else{
+			testResult = RES_ERROR | (good_error ? 0 : RES_BAD_MSG);
+		}
+	}else{
+		if(res == EXIT_FAILURE){
+			if(good_error){
+				testResult = RES_XFAIL;
+			}else{
+				testResult = RES_FAIL | RES_BAD_MSG;
+			}
+		}else if(res == EXIT_SUCCESS){
+			testResult = RES_XPASS;
+		}else{
+			testResult = RES_ERROR;
+		}
+	}
+
+	return testResult;
+}
+
+int target_run(int modus, char* compiler, char* arguments, char* case_file,
+	char* error_file, char* error_line
+#ifdef REG_EXTENDED
+	, char* gdb, char* gdb_script, regex_t* gdb_pattern
+#endif
+	)
+{
+	size_t bufferLen;
+	char* buffer;
+	int res;
+	int testResult;
+	int good_error;
+	char* logFile;
+	char* gdb_scripter;
+	int good_gdb;
+
+	bufferLen = 0;
+	buffer = NULL;
+	res = -1;
+	testResult = -1;
+	good_error = 0;
+	logFile = NULL;
+	good_gdb = 0;
+	gdb_scripter = NULL;
+
+	if(!(modus & MODE_RUN) && !(modus & MODE_NORUN)){
+		fprintf(stderr, "BUG: badly handled mode %i (->run)\n", modus);
+		exit(EXIT_FAILURE);
+	}
+	
+	/* gen command */
+
+	bufferLen = strlen(compiler) + strlen(arguments) + strlen(TMP_DIR)
+			+ strlen(case_file) * 2 + 64;
+	buffer = malloc(bufferLen);
+	snprintf(buffer, bufferLen, "%s %s ", compiler, arguments);
+
+	if(NULL == strstr(buffer, "-od")){
+		if(NULL == strstr(buffer, "-of")){
+			snprintf(buffer, bufferLen,
+				"%s %s -od%s -of%s.exe %s",
+				compiler, arguments, TMP_DIR, case_file,
+				case_file);
+		}else{
+			snprintf(buffer, bufferLen,
+				"%s %s -od%s %s",
+				compiler, arguments, TMP_DIR, case_file);
+		}
+	}else if(NULL == strstr(buffer, "-of")){
+		snprintf(buffer, bufferLen,
+			"%s %s -of%s.exe %s",
+			compiler, arguments, case_file, case_file);
+	}else{
+		snprintf(buffer, bufferLen, "%s %s %s",
+			compiler, arguments, case_file);
+	}
+
+	/* test 1/3 - compile */
+	if(modus & MODE_RUN){
+		fprintf(stderr, "run: %s\n", buffer);
+	}else{
+		fprintf(stderr, "norun: %s\n", buffer);
+	}
+	res = crashRun(buffer, &logFile);
+
+	/* diagnostic 1/3 */
+	buffer = loadFile(logFile);
+	fprintf(stderr, "%s", buffer);
+	remove(logFile);
+	
+	if(modus & MODE_RUN){
+		good_error = checkErrorMessage(error_file, error_line,
+			buffer);
+	}else{
+		good_error = 1;
+	}
+
+	if(hadExecCrash(buffer)){
+		return RES_ERROR;
+	}else if((res == EXIT_FAILURE) && good_error){
+		return RES_FAIL;
+	}else if(res!=EXIT_SUCCESS){
+		return RES_ERROR | (good_error ? 0 : RES_BAD_MSG);
+	}
+
+	/* test 2/3 - run */
+	bufferLen = strlen(case_file) + 30;
+	buffer = malloc(bufferLen);
+	snprintf(buffer, bufferLen, "%s.exe", case_file);
+	fprintf(stderr, "%s\n", buffer);
+	res=crashRun(buffer, &logFile);
+
+	/* diagnostic 2/3 */
+	buffer = loadFile(logFile);
+	fprintf(stderr, "%s\n", buffer);
+	remove(logFile);
+
+	if(modus & MODE_NORUN){
+		good_error = checkRuntimeErrorMessage(error_file, error_line,
+				buffer);
+	}else{
+		good_error = 1;
+	}
+
+#ifdef REG_EXTENDED
+	if(gdb_script != NULL){
+		good_gdb = 0;
+		/* test 3/3 - gdb */
+		gdb_scripter = genTempFileName();
+		writeFile(gdb_scripter, gdb_script);
+		bufferLen = strlen(gdb) + strlen(case_file)
+			+ strlen(gdb_scripter) + 20;
+		snprintf(buffer, bufferLen, "%s %s.exe < %s",
+			gdb, case_file, gdb_scripter);
+		fprintf(stderr, "%s\n", buffer);
+		if(EXIT_SUCCESS==crashRun(buffer, &logFile)){
+			/* diagnostic 3/3 */
+			buffer = loadFile(logFile);
+			fprintf(stderr, "%s\n", buffer);
+			good_gdb = (regexec(gdb_pattern, buffer, 0, NULL, 0)==0);
+		}
+		remove(logFile);
+		remove(gdb_scripter);
+	}else{
+		good_gdb = 1;
+	}
+#endif /* REG_EXTENDED */
+
+	if(modus & MODE_RUN){
+		if(hadExecCrash(buffer)){
+			testResult = RES_ERROR;	
+		}else if((res==EXIT_SUCCESS) && good_gdb){
+			testResult = RES_PASS;
+		}else if((res==EXIT_FAILURE) && good_error && good_gdb){
+			testResult = RES_FAIL;
+		}else{
+			testResult = RES_ERROR | (good_error ? 0 : RES_BAD_MSG)
+				| (good_gdb ? 0 : RES_BAD_GDB);
+		}
+	}else{
+		if(res==EXIT_SUCCESS){
+			testResult = RES_XPASS;
+		}else if(good_error && good_gdb){
+			testResult = RES_XFAIL;
+		}else{
+			testResult = RES_FAIL | (good_error ? 0 : RES_BAD_MSG)
+				| (good_gdb ? 0 : RES_BAD_GDB);
+		}
+	}
+
+	return testResult;
+}
 
 int main(int argc, char* arg[]){
+	
 	char* compiler;		/* the compiler - from enviroment flag "DMD" */
 	char* cmd_arg_case;	/* additional arguments - from the testcase file */
 	char* buffer;		/* general purpose buffer */
 	size_t bufferLen;
+	int index;
 	int modus;		/* test modus: RUN NORUN COMPILE NOCOMPILE */
-	int res;		/* return code from external executions */
 	char* case_file;
+	int case_result;
+	int torture_result[sizeof(torture)/sizeof(char*)];
+	char* torture_block_global;
+	char* torture_block_case;
+	char* torture_require;
 	char* error_file;	/* expected sourcefile containing the error */
 	char* error_line;	/* expected error line */
-	int good_error;		/* error contained file and line and matched the expectations */
 	char* gdb;		/* the debugger - from environment flag "GDB" */
 	char* gdb_script;	/* gdb command sequence */
 	char* gdb_pattern_raw;	/* POSIX regexp expected in GDB's output */
 #ifdef REG_EXTENDED
 	regex_t* gdb_pattern;
 #endif
-	int good_gdb;		/* (gdb test and positive) or (no gdb test)*/
 
 	compiler	= NULL;
 	cmd_arg_case	= NULL;
 	buffer		= NULL;
 	bufferLen 	= 0;
 	modus 		= -1;
-	res 		= -1;
 	case_file 	= NULL;
+	torture_block_global	= NULL;
+	torture_block_case	= NULL;
+	torture_require	= NULL;
 	error_file 	= NULL;
 	error_line 	= NULL;
-	good_error 	= -1;
 	gdb		= NULL;
 	gdb_script	= NULL;
 	gdb_pattern_raw = NULL;
 #ifdef REG_EXTENDED
 	gdb_pattern 	= NULL;
 #endif
-	good_gdb 	= -1;
 
 	/* check arguments */
 	if(argc != 3){
@@ -579,32 +917,34 @@
 			"Copyright by Thomas Kuehne <thomas@kuehne.cn> 2005\n"
 			"\n");
 
-		if(argc!=0)
+		if(argc!=0){
 			fprintf(stderr,
 				"%s <run|norun|compile|nocompile> <source>\n",
 				arg[0]);
-		else
+		}else{
 			fprintf(stderr,
 				"dstress <run|norun|compile|nocompile>"
 				" <source>\n");
+		}
 
-		fprintf(stderr,
-		"\n"
+		fprintf(stderr, "\n"
 		"== eniroment settings (usually $NAME or %%NAME%%)  ==\n"
 		"* DMD                - compiler (including standard arguments)\n"
-		"* GDB                - debugger (including standard arguments)\n"
-		"\n"
+		"* GDB                - debugger (including standard arguments)\n");
+		fprintf(stderr, "\n"
 		"== case setting (line in the case source) ==\n"
 		"* __DSTRESS_DFLAGS__ - additional compiler arguments\n"
 		"only evaluated if it is a \"nocompile\" or \"norun\" test:\n"
 		"* __DSTRESS_ELINE__  - expected source line to throw an error message\n"
 		"* __DSTRESS_EFILE__  - expected source file to throw an error message\n"
-		"                       (defaults to the case file)\n"
+		"                       (defaults to the case file)\n");
+		fprintf(stderr,
 		"only evaluated if it is a \"run\" or \"norun\" test:\n"
 		"* __GDB_SCRIPT__     - command sequence to feed to the debugger\n"
 		"                       (use \\n to encode a line break)\n"
 		"* __GDB_PATTERN__    - expected regular expression in the debugger's\n"
-		"                       output\n"
+		"                       output\n");
+		fprintf(stderr, "\n"
 		"== note ==\n"
 		"* the current directory is required to contain the sub-directory \"obj\"\n"
 		"  (used for temporary files)\n"
@@ -612,14 +952,19 @@
 		exit(EXIT_FAILURE);
 	}
 
+	modus = 0;
+	if(0==strncmp(arg[1], TORTURE_PREFIX, strlen(TORTURE_PREFIX))){
+		modus |= MODE_TORTURE;
+		arg[1] += strlen(TORTURE_PREFIX);
+	}
 	if(0==strcmp(arg[1], "run")){
-		modus = RUN;
+		modus |= MODE_RUN;
 	}else if(0==strcmp(arg[1], "norun")){
-		modus = NORUN;
+		modus |= MODE_NORUN;
 	}else if(0==strcmp(arg[1], "compile")){
-		modus = COMPILE;
+		modus |= MODE_COMPILE;
 	}else if(0==strcmp(arg[1], "nocompile")){
-		modus = NOCOMPILE;
+		modus |= MODE_NOCOMPILE;
 	}else{
 		goto err;
 	}
@@ -628,6 +973,7 @@
 	case_file = cleanPathSeperator(strdup(arg[2]));
 	compiler = getCompiler();
 	gdb = getGDB();
+	torture_block_global = getTortureBlock();
 	buffer = loadFile(case_file);
 
 	cmd_arg_case = getCaseFlag(buffer, "__DSTRESS_DFLAGS__");
@@ -635,7 +981,8 @@
 	error_file = getCaseFlag(buffer, "__DSTRESS_EFILE__");
 	gdb_script = getCaseFlag(buffer, "__GDB_SCRIPT__");
 	gdb_pattern_raw = getCaseFlag(buffer, "__GDB_PATTERN__");
-
+	torture_block_case = getCaseFlag(buffer, "__DSTRESS_TORTURE_BLOCK__");
+	torture_require = getCaseFlag(buffer, "__DSTRESS_TORTURE_REQUIRE__");
 
 	/* set implicit source file */
 	if(strcmp(error_line, "")!=0 && strcmp(error_file, "")==0){
@@ -680,9 +1027,7 @@
 		buffer=malloc(bufferLen);
 		snprintf(buffer, bufferLen, "%s\n\nquit\ny\n\n", gdb_script);
 		gdb_script=buffer;
-		good_gdb = 0;
 	}else{
-	    good_gdb = 1;
 	    gdb_script = NULL;
 	}
 
@@ -690,223 +1035,132 @@
 
 	if(gdb_script && strlen(gdb_script)){
 		if(gdb_pattern_raw && strlen(gdb_pattern_raw)){
-			fprintf(stderr, "WARNING: debugger/regex support inactive\n");
+			fprintf(stderr, "WARNING: GDB/regex support inactive\n");
 		}else{
-			fprintf(stderr, "debugger script without debugger pattern\n");
+			fprintf(stderr, "GDB script without GDB pattern\n");
 			exit(EXIT_FAILURE);
 		}
 	}else if(gdb_pattern_raw && strlen(gdb_pattern_raw)){
-		fprintf(stderr, "debugger pattern without debugger script\n");
+		fprintf(stderr, "GDB pattern without GDB script\n");
 		exit(EXIT_FAILURE);
 	}
 
 #endif /* REG_EXTENDED else */
 
-
-
 #ifdef DEBUG
 	fprintf(stderr, "case:     \"%s\"\n", case_file);
 	fprintf(stderr, "compiler: \"%s\"\n", compiler);
 	fprintf(stderr, "DFLAGS C: \"%s\"\n", cmd_arg_case);
 	fprintf(stderr, "ELINE   : \"%s\"\n", error_line);
 	fprintf(stderr, "EFILE   : \"%s\"\n", error_file);
+#ifdef REG_EXTENDED
 	fprintf(stderr, "GDB Scri: \"%s\"\n", gdb_script);
 	fprintf(stderr, "GDB Patt: \"%s\"\n", gdb_pattern_raw);
 #endif
-
-	/* start working */
-	if(modus==COMPILE || modus==NOCOMPILE){
-		/* gen command */
-		bufferLen = strlen(compiler)+strlen(cmd_arg_case)
-			+strlen(OBJ)+strlen(case_file)+strlen(TLOG)+21;
-		buffer = malloc(bufferLen);
-		snprintf(buffer, bufferLen, "%s %s ", compiler, cmd_arg_case);
+	fprintf(stderr, "block G : \"%s\"\n", torture_block_global);
+	fprintf(stderr, "block C : \"%s\"\n", torture_block_case);
+	fprintf(stderr, "modus   : %x\n", modus);
+#endif
 
-		if(NULL==strstr(buffer, "-od")){
-			snprintf(buffer, bufferLen,
-				"%s %s -od%s -c %s 1> %s 2>&1",
-				compiler, cmd_arg_case, OBJ, case_file, TLOG);
-		}else{
-			snprintf(buffer, bufferLen, "%s %s -c %s 1> %s 2>&1",
-				compiler, cmd_arg_case, case_file, TLOG);
-		}
 
-		/* test */
-		if(modus==COMPILE){
-			fprintf(stderr, "compile: %s\n", buffer);
-		}else{
-			fprintf(stderr, "nocompile: %s\n", buffer);
-		}
-		res = crashRun(buffer);
-
-		/* diagnostic */
-		buffer = loadFile(TLOG);
-		fprintf(stderr, "%s\n", buffer);
-		good_error = checkErrorMessage(error_file, error_line, buffer);
+	/* let's get serious */
 
-		if(hadExecCrash(buffer)){
-			printf("ERROR:\t%s [internal compiler error]\n",
-				case_file);
-		}else if(modus==COMPILE){
-			if(res==EXIT_SUCCESS){
-				printf("PASS: \t%s\n", case_file);
-			}else if(res==EXIT_FAILURE && good_error){
-				if(checkErrorMessage(case_file, "", buffer)){
-					printf("FAIL: \t%s\n", case_file);
-				}else{
-					printf("ERROR:\t%s%s\n", case_file,
-						errorMsg(good_error));
-				}
-			}else{
-				printf("ERROR:\t%s%s\n", case_file,
-					errorMsg(good_error));
-			}
-		}else{
-			if(res==EXIT_FAILURE){
-				if(good_error){
-					printf("XFAIL:\t%s\n", case_file);
-				}else{
-					printf("FAIL: \t%s%s\n", case_file,
-						errorMsg(good_error));
-				}
-			}else if(res==EXIT_SUCCESS){
-				printf("XPASS:\t%s\n", case_file);
-			}else{
-				printf("ERROR:\t%s\n", case_file);
-			}
-		}
-		fprintf(stderr,"--------\n");
-	}else if(modus==RUN || modus==NORUN){
-		/* gen command */
-
-		bufferLen = strlen(compiler)+strlen(cmd_arg_case)
-			+strlen(OBJ)
-			+strlen(case_file)*2+strlen(TLOG)+64;
-		buffer = malloc(bufferLen);
-		snprintf(buffer, bufferLen, "%s %s ", compiler, cmd_arg_case);
-
-		if(NULL==strstr(buffer, "-od")){
-			if(NULL==strstr(buffer, "-of")){
-				snprintf(buffer, bufferLen,
-					"%s %s -od%s -of%s.exe %s 1> %s 2>&1",
-					compiler, cmd_arg_case, OBJ, case_file,
-					case_file, TLOG);
-			}else{
-				snprintf(buffer, bufferLen,
-					"%s %s -od%s %s 1> %s 2>&1",
-					compiler, cmd_arg_case, OBJ, case_file,
-					TLOG);
-			}
-		}else if(NULL==strstr(buffer, "-of")){
-			snprintf(buffer, bufferLen,
-				"%s %s -of%s.exe %s 1> %s 2>&1",
-				compiler, cmd_arg_case, case_file, case_file,
-				TLOG);
-		}else{
-			snprintf(buffer, bufferLen, "%s %s %s 1> %s 2>&1",
-				compiler, cmd_arg_case, case_file, TLOG);
+	if(modus & MODE_TORTURE){
+		if((modus & (MODE_COMPILE | MODE_NOCOMPILE)) 
+			&& (modus & (MODE_RUN | MODE_NORUN)))
+		{
+			fprintf(stderr, "BUG: unhandled torture modus %x\n", modus);
+		}else if(!(modus & (MODE_COMPILE | MODE_NOCOMPILE | MODE_RUN | MODE_NORUN))){
+			fprintf(stderr, "BUG: unhandled torture modus %x\n", modus);
 		}
 
-		/* test 1/3 - compile */
-		if(modus==RUN){
-			fprintf(stderr, "run: %s\n", buffer);
-		}else{
-			fprintf(stderr, "norun: %s\n", buffer);
-		}
-		res = crashRun(buffer);
-
-		/* diagnostic 1/3 */
-		buffer = loadFile(TLOG);
-		fprintf(stderr, "%s", buffer);
-
-		if(modus==RUN){
-			good_error = checkErrorMessage(error_file, error_line,
-				buffer);
-		}else{
-			good_error = 1;
+		bufferLen = strlen(torture[(sizeof(torture) / sizeof(char*))-1])
+			+ strlen(cmd_arg_case) + 3;
+		
+		if(torture_block_case!=NULL && strlen(torture_block_case)<1){
+			torture_block_case=NULL;
 		}
-		if(hadExecCrash(buffer)){
-			printf("ERROR:\t%s [internal compiler error]\n",
-				case_file);
-			fprintf(stderr, "\n--------\n");
-			return  EXIT_SUCCESS;
-		}else if(res==EXIT_FAILURE && good_error){
-			printf("FAIL: \t%s\n", case_file);
-			fprintf(stderr, "\n--------\n");
-			return  EXIT_SUCCESS;
-		}else if(res!=EXIT_SUCCESS){
-			printf("ERROR:\t%s%s\n", case_file,
-				errorMsg(good_error));
-			fprintf(stderr, "\n--------\n");
-			return  EXIT_SUCCESS;
-		}
+		
+		buffer = malloc(bufferLen);
+		for(index=0; index < sizeof(torture)/sizeof(char*); index++){
+			if((torture_block_global && strstr(torture[index], torture_block_global))
+				|| (torture_block_case && strstr(torture[index], torture_block_case))
+				|| (torture_block_case && !strstr(torture[index], torture_require)))
+			{
+				torture_result[index]=RES_UNTESTED;
+				continue;
+			}
+			
+			buffer[0]=0;
+			snprintf(buffer, bufferLen, "%s %s", torture[index], cmd_arg_case);
+		
+			if(modus & (MODE_COMPILE | MODE_NOCOMPILE)){
+				torture_result[index] = target_compile(modus,
+					compiler, buffer, case_file,
+					error_file, error_line);
+			}else if(modus & (MODE_RUN | MODE_NORUN)){
+				torture_result[index] = target_run(modus,
+					compiler, buffer, case_file,
+					error_file, error_line
+#ifdef REG_EXTENDED
+					, gdb, gdb_script, gdb_pattern
+#endif
+				);
+			}
 
-		/* test 2/3 - run */
-		bufferLen = strlen(case_file) + strlen(TLOG) + 30;
-		buffer = malloc(bufferLen);
-		snprintf(buffer, bufferLen, "%s.exe 1> %s 2>&1\n", case_file,
-			TLOG);
-		fprintf(stderr, "%s\n", buffer);
-		res=crashRun(buffer);
-
-		/* diagnostic 2/3 */
-		buffer = loadFile(TLOG);
-		fprintf(stderr, "%s\n", buffer);
-		if(modus==NORUN){
-			good_error = checkRuntimeErrorMessage(error_file,
-				error_line, buffer);
-		}else{
-			good_error = 1;
+			fprintf(stderr, "Torture-Sub-%i/" ZU "-", index+1,
+					sizeof(torture)/sizeof(char*));
+			printResult(torture_result[index], modus, case_file,
+					stderr);
+			fprintf(stderr, "--------\n");
 		}
 
-#ifdef REG_EXTENDED
-		if(!good_gdb){
-			/* test 3/3 - gdb */
-			writeFile(GDB_SCRIPTER, gdb_script);
-			bufferLen = strlen(gdb) + strlen(case_file)
-				+ strlen(GDB_SCRIPTER) + strlen(TLOG) + 20;
-			snprintf(buffer, bufferLen, "%s %s.exe < %s > %s 2>&1",
-				gdb, case_file, GDB_SCRIPTER, TLOG);
-			fprintf(stderr, "%s\n", buffer);
-			if(EXIT_SUCCESS==crashRun(buffer)){
-				/* diagnostic 3/3 */
-				buffer = loadFile(TLOG);
-				fprintf(stderr, "%s\n", buffer);
-				good_gdb = (regexec(
-						gdb_pattern, buffer, 0, NULL, 0
-					)==0);
+		printf("Torture:\t%s\t{", case_file);
+		for(index=0; index < sizeof(torture)/sizeof(char*); index++){
+			case_result = 0;
+			switch(torture_result[index] & RES_BASE_MASK){
+				case RES_UNTESTED: case_result = 0; break;
+				case RES_PASS: case_result = 1 << 2; break;
+				case RES_XFAIL: case_result = 2 << 2; break;
+				case RES_XPASS: case_result = 3 << 2; break;
+				case RES_FAIL: case_result = 4 << 2; break;
+				case RES_ERROR: case_result = 5 << 2; break;
+				default:
+					fprintf(stderr, "BUG: unexpected case result %i\n",
+							torture_result[index]);
+					exit(EXIT_FAILURE);
 			}
-		}
-#endif /* REG_EXTENDED */
+			
+			if(torture_result[index] & RES_BAD_MSG){
+				case_result |= 1;
+			}
+			if(torture_result[index] & RES_BAD_GDB){
+				case_result |= 2;
+			}
 
-		if(modus==RUN){
-			if(hadExecCrash(buffer)){
-				printf("ERROR:\t%s [test case crash]%s%s",
-					case_file, errorMsg(good_error),
-					gdbMsg(good_gdb));
-			}else if(res==EXIT_SUCCESS && good_gdb){
-				printf("PASS: \t%s\n", case_file);
-			}else if(res==EXIT_FAILURE && good_error && good_gdb){
-				printf("FAIL: \t%s\n", case_file);
-			}else{
-				printf("ERROR:\t%s%s%s\n", case_file,
-					errorMsg(good_error), gdbMsg(good_gdb));
-			}
-		}else{
-			if(res==EXIT_SUCCESS && good_gdb){
-				printf("XPASS:\t%s%s\n", case_file, gdbMsg(good_gdb));
-			}else if(good_error && good_gdb){
-				printf("XFAIL:\t%s%s%s\n", case_file,
-					errorMsg(good_error), gdbMsg(good_gdb));
-			}else{
-				printf("FAIL:\t%s%s%s\n", case_file,
-					errorMsg(good_error), gdbMsg(good_gdb));
-			}
+			printf("%c", 'A' + case_result);
 		}
-		fprintf(stderr, "--------\n");
+		printf("}\n");
 	}else{
-		printf("@bug@ %d (%s)\n", modus, case_file);
-		return EXIT_FAILURE;
+		/* start working */
+		if(modus & (MODE_RUN | MODE_NORUN)){
+			case_result = target_run(modus, compiler, cmd_arg_case,
+					case_file, error_file, error_line
+#ifdef REG_EXTENDED
+					, gdb, gdb_script, gdb_pattern
+#endif
+					);
+			printResult(case_result, modus, case_file, stdout);
+		}
+
+		if(modus & (MODE_COMPILE | MODE_NOCOMPILE)){
+			case_result = target_compile(modus, compiler,
+					cmd_arg_case, case_file, error_file,
+					error_line);
+			printResult(case_result, modus, case_file, stdout);
+		}
 	}
+
+	
 	return EXIT_SUCCESS;
 }