From f6b8e76789e428ac264a393fbd60d77499b9abfd Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Fri, 25 Oct 2019 18:37:26 -0300 Subject: Add doc/test framework. --- src/.gitignore | 12 ++++++++++ src/Makefile | 50 ++++++++++++++++++++++++++++++++++++++++ src/chatprotocol.c | 15 ++++++++++++ src/doc.c | 32 ++++++++++++++++++++++++++ src/doctest.a | Bin 0 -> 1580 bytes src/doctest.c | 9 ++++++++ src/doctest.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 184 insertions(+) create mode 100644 src/.gitignore create mode 100644 src/Makefile create mode 100644 src/chatprotocol.c create mode 100644 src/doc.c create mode 100644 src/doctest.a create mode 100644 src/doctest.c create mode 100644 src/doctest.h 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 + +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 + +#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 Binary files /dev/null and b/src/doctest.a differ diff --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 -- cgit v1.2.3