summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2019-10-25 18:37:26 -0300
committerSoniEx2 <endermoneymod@gmail.com>2019-10-25 18:37:26 -0300
commitf6b8e76789e428ac264a393fbd60d77499b9abfd (patch)
tree00071db51e3ceb86e2fbce81c55ee136b5ae7ff8 /src
parent9d4e28d4265a6a293b18a68ec4d51a4b086b20fa (diff)
Add doc/test framework. HEAD default
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore12
-rw-r--r--src/Makefile50
-rw-r--r--src/chatprotocol.c15
-rw-r--r--src/doc.c32
-rw-r--r--src/doctest.abin0 -> 1580 bytes
-rw-r--r--src/doctest.c9
-rw-r--r--src/doctest.h66
7 files changed, 184 insertions, 0 deletions
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..c1c7f87
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,12 @@
+# compilation results
+*.o
+*.doctest
+*.code
+/doctest.include
+/doctest.declare
+/doctestobj/
+
+# binaries
+/doc
+/doctest
+/chatprotocol
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..de6a9e7
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,50 @@
+.POSIX:
+
+# by default we use system nm but make does not provide nm
+NM= nm
+MKDIR= mkdir -p
+
+ALL_DOCTEST_O= chatprotocol.doctest
+ALL_CODE_O= chatprotocol.code
+
+.SUFFIXES:
+
+default: all
+
+all: chatprotocol doc doctest
+
+chatprotocol: $(ALL_CODE_O)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o chatprotocol $(ALL_CODE_O)
+
+doc: doc.o doctest.a
+	$(CC) $(CFLAGS) $(LDFLAGS) -o doc doc.o doctest.a
+
+doctest: doctest.o doctest.a
+	$(CC) $(CFLAGS) $(LDFLAGS) -o doctest doctest.o doctest.a
+
+doc.o: doc.c doctest.h doctest.declare doctest.include
+	$(CC) $(CFLAGS) -DDOCS -UDOCTEST -c doc.c
+
+doctest.o: doctest.c doc.c doctest.h doctest.declare doctest.include
+	$(CC) $(CFLAGS) -DDOCTEST -c doctest.c
+
+doctest.declare: doctest.a
+	$(NM) -P -g $? | sed -n -e 's/^\([^[:blank:]]*_mkdocs\)[[:blank:]]..*/extern void \1(struct docs *doc);/p' > $@
+
+doctest.include: doctest.a
+	$(NM) -P -g $? | sed -n -e 's/^\([^[:blank:]]*_mkdocs\)[[:blank:]]..*/\1(\&doc);/p' > $@
+
+doctest.a: $(ALL_DOCTEST_O)
+	$(MKDIR) $(@D)/doctestobj
+	for file in $(?:.doctest=); do cp -p $$file.doctest $(@D)/doctestobj/$$(basename $$file).o; done
+	cd $(@D)/doctestobj && $(AR) $(ARFLAGS) -u ../$(@F) $(ALL_DOCTEST_O:.doctest=.o)
+
+.SUFFIXES: .c .doctest .code
+
+.c.doctest:
+	$(CC) $(CFLAGS) -DDOCTEST -c $<
+	mv $*.o $*.doctest
+
+.c.code:
+	$(CC) $(CFLAGS) -UDOCS -UDOCTEST -c $<
+	mv $*.o $*.code
diff --git a/src/chatprotocol.c b/src/chatprotocol.c
new file mode 100644
index 0000000..f4725fc
--- /dev/null
+++ b/src/chatprotocol.c
@@ -0,0 +1,15 @@
+#include "doctest.h"
+#include <stdio.h>
+
+DOCF(int, main, int argc, char *argv[]) {
+#ifdef DOCS
+	D("Prints \"Hello, World!\" and args.");
+#else
+	int i = 0;
+	printf("Hello, World!\n");
+	for (i = 0; i < argc; i++) {
+		printf("%d: %s\n", i, argv[i]);
+	}
+#endif
+	DOCF_END;
+}
diff --git a/src/doc.c b/src/doc.c
new file mode 100644
index 0000000..33a283e
--- /dev/null
+++ b/src/doc.c
@@ -0,0 +1,32 @@
+/*
+ * Doc/test generation. See doctest.h for more information.
+ */
+#include "doctest.h"
+
+#ifdef DOCS
+#include <stdio.h>
+
+#include "doctest.declare"
+
+struct docs {
+	int dummy;
+};
+
+void docs_for( struct docs *doc, char *sig, char *name, char *params ) {
+	printf("docs_for: %s %s (%s)\n", sig, name, params);
+}
+
+void docs_line( struct docs *doc, char *s ) {
+	printf("docs_line: %s\n", s);
+}
+
+void docs_testline( struct docs *doc, int lineno, char *file, char *s) {
+	printf("docs_testline: %s:%d: %s\n", file, lineno, s);
+}
+
+int main(int argc, char *argv[]) {
+	struct docs doc = {0};
+#include "doctest.include"
+	return 0;
+}
+#endif
diff --git a/src/doctest.a b/src/doctest.a
new file mode 100644
index 0000000..3c80dbf
--- /dev/null
+++ b/src/doctest.a
Binary files differdiff --git a/src/doctest.c b/src/doctest.c
new file mode 100644
index 0000000..34646c1
--- /dev/null
+++ b/src/doctest.c
@@ -0,0 +1,9 @@
+/*
+ * Doctest generation. See doctest.h for more information.
+ */
+#include "doctest.h"
+
+/* This is unusual, but it works. */
+#ifdef DOCTEST
+#include "doc.c"
+#endif
diff --git a/src/doctest.h b/src/doctest.h
new file mode 100644
index 0000000..7c5403b
--- /dev/null
+++ b/src/doctest.h
@@ -0,0 +1,66 @@
+/**
+ * Doc/testing Utilities
+ * Help I can't document my documentation tool with my documentation tool.
+ *
+ *   Basics: All to-be-documented functions must be defined with DOCF/DOCF_END.
+ * Additionally, one needs to put #ifdef DOCS/else/endif around their code and docs:
+ *
+ *     DOCF(void, foo, void) {
+ *     #ifdef DOCS
+ *         docs go here
+ *     #else
+ *         code goes here
+ *     #endif
+ *     DOCF_END;
+ *     }
+ *
+ *   D("...") is used for doc lines, DT("...") for doctest lines.
+ *
+ *   Internal (static) functions cannot currently be documented, but support for them is planned.
+ *
+ *   You must also put your main within #ifndef DOCS/#endif, if you don't wish to document it:
+ *
+ *     #ifndef DOCS
+ *     int main(int argc, char *argv[]) {
+ *     }
+ *     #endif
+ *
+ *     // or (preferred)
+ *
+ *     DOCF(int, main, int argc, char *argv[]) {
+ *     #ifdef DOCS
+ *         docs go here
+ *     #else
+ *         code goes here
+ *     #endif
+ *     DOCF_END;
+ *     }
+ */
+
+#ifdef DOCTEST
+#define DOCS
+#endif
+
+#ifdef DOCS
+
+/* docs enabled */
+struct docs;
+
+extern void docs_for( struct docs *doc, char *sig, char *name, char *params );
+extern void docs_line( struct docs *doc, char *s );
+extern void docs_testline( struct docs *doc, int lineno, char *file, char *s);
+
+#define DOCF(sig, name, ...) extern void name##_mkdocs ( struct docs *doc ) { docs_for( doc , #sig , #name , #__VA_ARGS__ ); do 
+#define DOCF_END }while(0)
+#define D(s) docs_line(doc, s)
+/* enabled unconditionally as doctests are part of and embedded into docs */
+#define DT(s) docs_testline(doc, __LINE__, __FILE__, s)
+
+#else
+
+/* docs not enabled */
+#define DOCF(sig, name, ...) sig name ( __VA_ARGS__ )
+/* for the sake of semicolon */
+#define DOCF_END do{}while(0)
+
+#endif