summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-01-13 21:37:15 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-01-13 21:37:15 -0800
commit4f2a724e0ec9d4f4b6145a2c83e5a44a28e8acc8 (patch)
tree6476edff61a0bb69ba6d799bcb834b9d51aafc60
downloadhalt3-4f2a724e0ec9d4f4b6145a2c83e5a44a28e8acc8.tar.gz
halt3-4f2a724e0ec9d4f4b6145a2c83e5a44a28e8acc8.tar.bz2
halt3-4f2a724e0ec9d4f4b6145a2c83e5a44a28e8acc8.zip
Initial revision.halt3-1.0
-rw-r--r--example-error-decider.c4
-rw-r--r--example-halting-decider.c6
-rwxr-xr-xgenprog.sh123
-rw-r--r--lib.sh13
-rw-r--r--ternary.h6
5 files changed, 152 insertions, 0 deletions
diff --git a/example-error-decider.c b/example-error-decider.c
new file mode 100644
index 0000000..89a2e3e
--- /dev/null
+++ b/example-error-decider.c
@@ -0,0 +1,4 @@
+int error_decider(const char *hdecider, const char *program, const char *input)
+{
+ return 1;
+}
diff --git a/example-halting-decider.c b/example-halting-decider.c
new file mode 100644
index 0000000..101bf05
--- /dev/null
+++ b/example-halting-decider.c
@@ -0,0 +1,6 @@
+#include "ternary.h"
+
+ternary halting_decider(const char *program, const char *input)
+{
+ return ERROR;
+}
diff --git a/genprog.sh b/genprog.sh
new file mode 100755
index 0000000..b3d4d3f
--- /dev/null
+++ b/genprog.sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+#
+# This script requires two arguments which are file names:
+#
+# 1. The name of a C source file which defines a three-valued halting
+# decider function, whose prototype is:
+#
+# ternary halting_decider(const char *program, const char *input);
+#
+# This function tries to answer the question: does the program,
+# when given the specified input, halt? It can return TRUE, or FALSE.
+# It can also return ERROR when, for whatever reason, it deems
+# that neither TRUE nor FALSE is the correct answer.
+#
+# 2. The name of a C source file which defines the following boolean
+# function, which returns 0 or 1:
+#
+# int error_decider(const char *hdecider, const char *program,
+# const char *input);
+#
+# Error decider functions try to answer the question: does the given
+# program, when operating on the given input, behave in such
+# a way that the given decider must return ERROR for that program?
+#
+
+set -e # stop on any errors
+
+MYDIR=$(dirname "$0")
+
+. "$MYDIR"/lib.sh
+
+if [ $# != 2 ] ; then
+ printf "usage: $0 <halting_decider>.c <error_decider.c>\n"
+ exit 1
+fi
+
+ORIG_HALTING_DECIDER=$1
+ORIG_ERROR_DECIDER=$2
+
+HD_FULL_HASH=$(file_hash $ORIG_HALTING_DECIDER)
+ED_FULL_HASH=$(file_hash $ORIG_ERROR_DECIDER)
+HD_HASH=$(short_hash $HD_FULL_HASH)
+ED_HASH=$(short_hash $ED_FULL_HASH)
+
+HALTING_DECIDER=hd-${HD_HASH}.c
+ERROR_DECIDER=ed-${ED_HASH}.c
+
+cp $ORIG_HALTING_DECIDER $HALTING_DECIDER
+cp $ORIG_ERROR_DECIDER $ERROR_DECIDER
+
+PROGRAM_BASENAME=pg-${HD_HASH}-${ED_HASH}
+
+printf "halting decider: %s\n" $HALTING_DECIDER
+printf "error decider: %s\n" $ERROR_DECIDER
+printf "\n"
+printf "generating program %s from these deciders\n" $PROGRAM_BASENAME.c
+
+cat > ${PROGRAM_BASENAME}.c <<!
+#include <stdio.h>
+#include <stdlib.h>
+#include "ternary.h"
+
+#define HD_HASH "$HD_HASH"
+#define ED_HASH "$ED_HASH"
+#define PG_BASE "$PROGRAM_BASENAME"
+#define PG_SELF PG_BASE ".c"
+#define HD_NAME "$HALTING_DECIDER"
+
+#include "$ERROR_DECIDER"
+#include "$HALTING_DECIDER"
+
+int main(int argc, char **argv)
+{
+ const char *input;
+
+ if (argc != 2) {
+ fprintf(stderr, "this program test case requires input\n");
+ return EXIT_FAILURE;
+ }
+
+ input = argv[1];
+
+ if (error_decider(HD_NAME, PG_SELF, input)) {
+ switch (halting_decider(PG_SELF, input)) {
+ case FALSE:
+ printf("decider %s RIGHT: %s/%s does not halt\n", HD_NAME, PG_SELF, input);
+ for(;;);
+ case TRUE:
+ printf("decider %s RIGHT: %s/%s halts\n", HD_NAME, PG_SELF, input);
+ return EXIT_SUCCESS;
+ case ERROR:
+ printf("decider %s WRONG: TRUE and FALSE are viable answers for %s/%s\n",
+ HD_NAME, PG_SELF, input);
+ abort();
+ }
+ } else {
+ switch (halting_decider(PG_SELF, input)) {
+ case FALSE:
+ printf("decider %s WRONG: %s/%s does not halt\n", HD_NAME, PG_SELF, input);
+ return EXIT_SUCCESS;
+ case TRUE:
+ printf("decider %s WRONG: %s/%s halts\n", HD_NAME, PG_SELF, input);
+ for(;;);
+ case ERROR:
+ printf("decider %s RIGHT: neither TRUE nor FALSE is correct for %s/%s\n",
+ HD_NAME, PG_SELF, input);
+ abort();
+ }
+ }
+ /* notreached */
+ puts("internal error");
+ abort();
+}
+!
+
+printf "compiling %s to %s\n" $PROGRAM_BASENAME.c $PROGRAM_BASENAME
+gcc $PROGRAM_BASENAME.c -o $PROGRAM_BASENAME
+
+printf "\n"
+
+printf "executing test case %s %s\n" ./$PROGRAM_BASENAME $PROGRAM_BASENAME
+./$PROGRAM_BASENAME $PROGRAM_BASENAME
diff --git a/lib.sh b/lib.sh
new file mode 100644
index 0000000..08da993
--- /dev/null
+++ b/lib.sh
@@ -0,0 +1,13 @@
+#
+# Library of functions
+#
+
+file_hash()
+{
+ sha256sum $1 | awk '{ print $1 }'
+}
+
+short_hash()
+{
+ awk "BEGIN { print substr(\"$1\", 1, 7) }"
+}
diff --git a/ternary.h b/ternary.h
new file mode 100644
index 0000000..0711fec
--- /dev/null
+++ b/ternary.h
@@ -0,0 +1,6 @@
+#ifndef TERNARY_H
+#define TERNARY_H
+
+typedef enum { FALSE, TRUE, ERROR } ternary;
+
+#endif