summary refs log tree commit diff
path: root/www/text.causal.agency
diff options
context:
space:
mode:
Diffstat (limited to 'www/text.causal.agency')
-rw-r--r--www/text.causal.agency/.gitignore2
-rw-r--r--www/text.causal.agency/001-make.7159
-rw-r--r--www/text.causal.agency/002-writing-mdoc.7138
-rw-r--r--www/text.causal.agency/003-pleasant-c.7120
-rw-r--r--www/text.causal.agency/004-uloc.764
-rw-r--r--www/text.causal.agency/005-testing-c.779
-rw-r--r--www/text.causal.agency/Makefile23
-rwxr-xr-xwww/text.causal.agency/feed.sh29
8 files changed, 614 insertions, 0 deletions
diff --git a/www/text.causal.agency/.gitignore b/www/text.causal.agency/.gitignore
new file mode 100644
index 00000000..37dd51ef
--- /dev/null
+++ b/www/text.causal.agency/.gitignore
@@ -0,0 +1,2 @@
+*.txt
+feed.atom
diff --git a/www/text.causal.agency/001-make.7 b/www/text.causal.agency/001-make.7
new file mode 100644
index 00000000..a96ba6f2
--- /dev/null
+++ b/www/text.causal.agency/001-make.7
@@ -0,0 +1,159 @@
+.Dd September 17, 2018
+.Dt MAKE 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Using Make
+.Nd writing less Makefile
+.
+.Sh DESCRIPTION
+Let's talk about
+.Xr make 1 .
+I think an important thing to know about
+.Xr make 1
+is that you don't need to write a
+.Pa Makefile
+to use it.
+There are default rules
+for C, C++ and probably Fortran.
+To build
+.Pa foo
+from
+.Pa foo.c ,
+just run:
+.
+.Pp
+.Dl make foo
+.
+.Pp
+The default rule for C files uses the
+.Ev CFLAGS
+variable,
+so you can set that in the environment
+to pass flags to the C compiler:
+.
+.Pp
+.Dl CFLAGS=-Wall make foo
+.
+.Pp
+It also uses
+.Ev LDLIBS
+for linking,
+so you can add libraries with:
+.
+.Pp
+.Dl LDLIBS=-lcurses make foo
+.
+.Pp
+Obviously writing this every time
+would become tedious,
+so it might be time to write a
+.Pa Makefile .
+But it really doesn't need much:
+.
+.Bd -literal -offset indent
+CFLAGS += -Wall -Wextra
+LDLIBS = -lcurses
+
+foo:
+.Ed
+.
+.Pp
+Assigning
+.Ev CFLAGS
+with
+.Ql +=
+preserves the system default
+or anything passed in the environment.
+Declaring
+.Pa foo
+as the first rule
+makes it the default when
+.Ql make
+is run without a target.
+Note that the rule doesn't need a definition;
+the default will still be used.
+.
+.Pp
+If
+.Pa foo
+is built from serveral source files,
+unfortunately a rule definition is required:
+.
+.Bd -literal -offset indent
+OBJS = foo.o bar.o baz.o
+
+foo: $(OBJS)
+	$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
+.Ed
+.
+.Pp
+This rule uses
+.Ev LDFLAGS
+for passing linker flags,
+which is what the default rule does.
+The
+.Ql $@
+variable here expands to
+.Ql foo ,
+so this rule can be copied easily
+for other binary targets.
+.
+.Pp
+If some sources depend on a header file,
+they can be automatically rebuilt
+when the header changes
+by declaring a dependency rule:
+.
+.Pp
+.Dl foo.o bar.o: foo.h
+.
+.Pp
+Note that several files can appear
+either side of the
+.Ql ":" .
+.
+.Pp
+Lastly,
+it's always nice to add a
+.Cm clean
+target:
+.
+.Bd -literal -offset indent
+clean:
+	rm -f $(OBJS) foo
+.Ed
+.
+.Pp
+I hope this helps getting started with
+.Xr make 1
+without writing too much
+.Pa Makefile !
+.
+.Sh EXAMPLES
+The example
+.Pa Makefile
+in its entirety:
+.
+.Bd -literal -offset indent
+CFLAGS += -Wall -Wextra
+LDLIBS = -lcurses
+OBJS = foo.o bar.o baz.o
+
+foo: $(OBJS)
+	$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
+
+foo.o bar.o: foo.h
+
+clean:
+	rm -f $(OBJS) foo
+.Ed
+.
+.Sh AUTHORS
+.An June Aq Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://code.causal.agency/june/text.causal.agency "Code Toilet"
diff --git a/www/text.causal.agency/002-writing-mdoc.7 b/www/text.causal.agency/002-writing-mdoc.7
new file mode 100644
index 00000000..92c2fc05
--- /dev/null
+++ b/www/text.causal.agency/002-writing-mdoc.7
@@ -0,0 +1,138 @@
+.Dd September 27, 2018
+.Dt WRITING-MDOC 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Writing mdoc
+.Nd semantic markup
+.
+.Sh DESCRIPTION
+I recently learned how to write man pages
+so that I could document
+a bunch of little programs I've written.
+Modern man pages are written in
+.Xr mdoc 7 ,
+whose documentation is also available from
+.Lk http://mandoc.bsd.lv .
+.
+.Pp
+.Xr mdoc 7
+differs from many other markup languages
+by providing
+.Dq semantic markup
+rather than just
+.Dq physical markup.
+What this means is that
+the markup indicates what something is,
+not how to format it.
+For example,
+the
+.Ql \&Ar
+macro is used to indicate
+command-line arguments
+rather than one of the macros
+for bold, italic or underline.
+This frees each author of having to choose
+and enables consistent presentation
+across different man pages.
+.
+.Pp
+Another advantage of semantic markup
+is that information can be extracted from it.
+For example,
+.Xr makewhatis 8
+can easily extract the name and short description
+from each man page
+thanks to the
+.Ql \&Nm
+and
+.Ql \&Nd
+macros.
+I use the same information
+to generate an Atom feed for these documents,
+though in admittedly a much less robust way than
+.Xr mandoc 1 .
+.
+.Pp
+When it comes to actually writing
+.Xr mdoc 7 ,
+it can take some getting used to.
+The language is of
+.Xr roff 7
+lineage
+so its syntax is very particular.
+Macros cannot appear inline,
+but must start on new lines
+beginning with
+.Ql \&. .
+Sentences should likewise
+always start on a new line.
+Since I'm in the habit of writing with
+semantic line breaks,
+I actually find these requirements
+fit in well.
+.
+.Pp
+The more frustrating syntax limitation to me
+is the rule against empty lines.
+Without them,
+it can be quite difficult to edit a lengthy document.
+Thankfully,
+lines with only a
+.Ql \&.
+on them are allowed,
+but this still causes visual noise.
+To alleviate that,
+I have a
+.Xr vim 1
+syntax file for
+.Xr mdoc 7
+which conceals the lone dots:
+.
+.Bd -literal -offset indent
+if exists("b:current_syntax")
+	finish
+endif
+
+runtime! syntax/nroff.vim
+unlet! b:current_syntax
+
+setlocal sections+=ShSs
+syntax match mdocBlank /^\\.$/ conceal
+setlocal conceallevel=2
+
+let b:current_syntax = "mdoc"
+.Ed
+.
+.Pp
+It also adds the
+.Xr mdoc 7
+section header and subsection header macros to the
+.Cm sections
+option to make
+.Xr vim 1 Ap s
+.Ic {
+and
+.Ic }
+motions
+aware of them.
+.
+.Pp
+With that,
+I've found writing man pages pleasant and rewarding.
+I've started writing other documents with
+.Xr mdoc 7
+as well,
+as you can see here.
+.
+.Sh SEE ALSO
+.Lk http://rhodesmill.org/brandon/2012/one-sentence-per-line/ "Semantic Linefeeds"
+.
+.Sh AUTHORS
+.An June Aq Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://code.causal.agency/june/text.causal.agency "Code Toilet"
diff --git a/www/text.causal.agency/003-pleasant-c.7 b/www/text.causal.agency/003-pleasant-c.7
new file mode 100644
index 00000000..bfa29b9b
--- /dev/null
+++ b/www/text.causal.agency/003-pleasant-c.7
@@ -0,0 +1,120 @@
+.Dd September 30, 2018
+.Dt PLEASANT-C 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Pleasant C
+.Nd it's good, actually
+.
+.Sh DESCRIPTION
+I've been writing a lot of C lately
+and actually find it very pleasant.
+I want to talk about some of its ergonomic features.
+These are C99 features unless otherwise noted.
+.
+.Ss Initializer syntax
+Struct and union initializer syntax
+is well generalized.
+Designators can be chained,
+making initializing nested structs easy,
+and all uninitialized fields are zeroed.
+.
+.Bd -literal -offset indent
+struct {
+	struct pollfd fds[2];
+} loop = {
+	.fds[0].fd = STDIN_FILENO,
+	.fds[1].fd = STDOUT_FILENO,
+	.fds[0].events = POLLIN,
+	.fds[1].events = POLLOUT,
+};
+.Ed
+.
+.Ss Variable-length arrays
+VLAs can be multi-dimensional,
+which can avoid manual stride multiplications
+needed to index a flat
+.Xr malloc 3 Ap d
+array.
+.
+.Bd -literal -offset indent
+uint8_t glyphs[len][height][width];
+fread(glyphs, height * width, len, stdin);
+.Ed
+.
+.Ss Incomplete array types
+The last field of a struct can be an
+.Dq incomplete
+array type,
+which means it doesn't have a length.
+A variable amount of space for the struct can be
+.Xr malloc 3 Ap d ,
+or the struct can be used as
+a sort of pointer with fields.
+.
+.Bd -literal -offset indent
+struct Line {
+	enum Filter type;
+	uint8_t data[];
+} *line = &png.data[1 + lineSize()];
+.Ed
+.
+.Ss Anonymous struct and union fields (C11)
+Members of structs or unions
+which are themselves structs or unions
+can be unnamed.
+In that case,
+each of the inner fields
+is treated as a member of the outer struct or union.
+This makes working with tagged unions nicer.
+.
+.Bd -literal -offset indent
+struct Message {
+	enum { Foo, Bar } type;
+	union {
+		uint8_t foo;
+		uint32_t bar;
+	};
+} msg = { .type = Foo, .foo = 0xFF };
+.Ed
+.
+.Ss Static assert (C11)
+Assertions can be made at compile time.
+Most useful for checking sizes of structs.
+.
+.Bd -literal -offset indent
+static_assert(13 == sizeof(struct PNGHeader), "PNG IHDR size");
+.Ed
+.
+.Ss Leading-break switch
+This one is just an odd style choice
+I came across that C happens to allow.
+To prevent accidental fall-through
+in switch statements,
+you can put breaks before the case labels.
+.
+.Bd -literal -offset indent
+while (0 < (opt = getopt(argc, argv, "h:w:"))) {
+	switch (opt) {
+		break; case 'h': height = optarg;
+		break; case 'w': width = optarg;
+		break; default:  return EX_USAGE;
+	}
+}
+.Ed
+.
+.Sh AUTHORS
+.An June Aq Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://code.causal.agency/june/text.causal.agency "Code Toilet"
+.
+.Sh CAVEATS
+This isn't meant to be advice.
+It's just how I like to write C,
+and I don't
+.Dq ship
+software in C.
diff --git a/www/text.causal.agency/004-uloc.7 b/www/text.causal.agency/004-uloc.7
new file mode 100644
index 00000000..909a0d1c
--- /dev/null
+++ b/www/text.causal.agency/004-uloc.7
@@ -0,0 +1,64 @@
+.Dd December 14, 2018
+.Dt ULOC 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm ULOC
+.Nd unique lines of code
+.
+.Sh DESCRIPTION
+There are many tools available
+which measure SLOC: source lines of code.
+These tools are strangely complex
+for what they intend to do,
+which is to estimate the relative sizes of projects.
+They perform some amount of parsing
+in order to discount comments in various languages,
+and for reasons unknown each format their ouput
+in some oddly encumbered way.
+.
+.Pp
+I propose a much simpler method
+of estimating relative sizes of projects:
+unique lines of code.
+ULOC can be calculated with standard tools as follows:
+.
+.Bd -literal -offset indent
+sort -u *.h *.c | wc -l
+.Ed
+.
+.Pp
+In my opinion,
+the number this produces
+should be a better estimate of
+the complexity of a project.
+Compared to SLOC,
+not only are blank lines discounted,
+but so are close-brace lines
+and other repetitive code
+such as common includes.
+On the other hand,
+ULOC counts comments,
+which require just as much maintenance
+as the code around them does,
+while avoiding inflating the result
+with license headers which appear in every file,
+for example.
+.
+.Pp
+It can also be amusing
+to read all of your code sorted alphabetically.
+.
+.Sh AUTHORS
+.An C. McEnroe Aq Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://code.causal.agency/june/text.causal.agency "Code Toilet"
+.
+.Sh CAVEATS
+Estimates such as these
+should not be used for decision making
+as if they were data.
diff --git a/www/text.causal.agency/005-testing-c.7 b/www/text.causal.agency/005-testing-c.7
new file mode 100644
index 00000000..c3a47c12
--- /dev/null
+++ b/www/text.causal.agency/005-testing-c.7
@@ -0,0 +1,79 @@
+.Dd December 21, 2018
+.Dt TESTING-C 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Testing C
+.Nd a simple unit testing setup
+.
+.Sh DESCRIPTION
+This is a simple approach
+to unit testing in C
+that I've used in a couple projects.
+At the bottom of a C file
+with some code I want to test,
+I add:
+.
+.Bd -literal -offset indent
+#ifdef TEST
+#include <assert.h>
+
+int main(void) {
+	assert(...);
+	assert(...);
+}
+
+#endif
+.Ed
+.
+.Pp
+This file normally produces a
+.Pa .o
+to be linked into the main binary.
+For testing,
+I produce separate binaries
+and run them with
+.Xr make 1 :
+.
+.Bd -literal -offset indent
+TESTS = foo.t bar.t
+
+\&.SUFFIXES: .t
+
+\&.c.t:
+	$(CC) $(CFLAGS) -DTEST $(LDFLAGS) $< $(LDLIBS) -o $@
+
+test: $(TESTS)
+	set -e; $(TESTS:%=./%;)
+.Ed
+.
+.Pp
+Note that the test binaries
+aren't linked with the rest of the code,
+so there is potential for simple stubbing or mocking.
+.
+.Pp
+To get the best output
+from C's simple
+.Xr assert 3 ,
+it's best to assert the result
+of a helper function
+which takes the expected output
+and the test input,
+rather than calling
+.Xr assert 3
+inside the helper function.
+This way,
+the message printed by the assert failure
+contains a useful line number
+and the expected output
+rather than just variable names.
+.
+.Pp
+For a real example,
+check
+.Lk https://code.causal.agency/june/catgirl/src/branch/master/term.c term.c
+from my IRC client project.
+.
+.Sh AUTHORS
+.An C. McEnroe Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/Makefile b/www/text.causal.agency/Makefile
new file mode 100644
index 00000000..8f2a55a1
--- /dev/null
+++ b/www/text.causal.agency/Makefile
@@ -0,0 +1,23 @@
+WEBROOT = /usr/local/www/text.causal.agency
+
+TXTS += 001-make.txt
+TXTS += 002-writing-mdoc.txt
+TXTS += 003-pleasant-c.txt
+TXTS += 004-uloc.txt
+TXTS += 005-testing-c.txt
+
+all: $(TXTS)
+
+.SUFFIXES: .7 .txt
+
+.7.txt:
+	mandoc $< | col -b -x > $@
+
+feed.atom: $(TXTS)
+	./feed.sh > feed.atom
+
+clean:
+	rm -f $(TXTS) feed.atom
+
+install: $(TXTS) feed.atom
+	install -p -m 644 $(TXTS) feed.atom $(WEBROOT)
diff --git a/www/text.causal.agency/feed.sh b/www/text.causal.agency/feed.sh
new file mode 100755
index 00000000..3c6e6589
--- /dev/null
+++ b/www/text.causal.agency/feed.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e -u
+
+updated=$(date -u '+%FT%TZ')
+cat <<EOF
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>Causal Agency</title>
+<author><name>June</name><email>june@causal.agency</email></author>
+<link href="https://text.causal.agency"/>
+<id>https://text.causal.agency/</id>
+<updated>${updated}</updated>
+EOF
+for entry in *.7; do
+	url="https://text.causal.agency/${entry%.7}.txt"
+	title=$(grep '^\.Nm' "$entry" | cut -c 5-)
+	summary=$(grep '^\.Nd' "$entry" | cut -c 5-)
+	updated=$(date -j -u -f '%s' "$(stat -f '%m' "$entry")" '+%FT%TZ')
+	cat <<EOF
+	<entry>
+	<title>${title}</title>
+	<summary>${summary}</summary>
+	<link href="${url}"/>
+	<id>${url}</id>
+	<updated>${updated}</updated>
+	</entry>
+EOF
+done
+echo '</feed>'