From ebacc3d0ee00212a20cb33b8f660ae73ecd5b95a Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Fri, 12 Jul 2019 22:11:16 -0400 Subject: Move to www/text.causal.agency --- .gitignore | 2 - 001-make.7 | 159 ------------------------------ 002-writing-mdoc.7 | 138 -------------------------- 003-pleasant-c.7 | 120 ---------------------- 004-uloc.7 | 64 ------------ 005-testing-c.7 | 79 --------------- Makefile | 23 ----- feed.sh | 29 ------ www/text.causal.agency/.gitignore | 2 + www/text.causal.agency/001-make.7 | 159 ++++++++++++++++++++++++++++++ www/text.causal.agency/002-writing-mdoc.7 | 138 ++++++++++++++++++++++++++ www/text.causal.agency/003-pleasant-c.7 | 120 ++++++++++++++++++++++ www/text.causal.agency/004-uloc.7 | 64 ++++++++++++ www/text.causal.agency/005-testing-c.7 | 79 +++++++++++++++ www/text.causal.agency/Makefile | 23 +++++ www/text.causal.agency/feed.sh | 29 ++++++ 16 files changed, 614 insertions(+), 614 deletions(-) delete mode 100644 .gitignore delete mode 100644 001-make.7 delete mode 100644 002-writing-mdoc.7 delete mode 100644 003-pleasant-c.7 delete mode 100644 004-uloc.7 delete mode 100644 005-testing-c.7 delete mode 100644 Makefile delete mode 100755 feed.sh create mode 100644 www/text.causal.agency/.gitignore create mode 100644 www/text.causal.agency/001-make.7 create mode 100644 www/text.causal.agency/002-writing-mdoc.7 create mode 100644 www/text.causal.agency/003-pleasant-c.7 create mode 100644 www/text.causal.agency/004-uloc.7 create mode 100644 www/text.causal.agency/005-testing-c.7 create mode 100644 www/text.causal.agency/Makefile create mode 100755 www/text.causal.agency/feed.sh diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 37dd51ef..00000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.txt -feed.atom diff --git a/001-make.7 b/001-make.7 deleted file mode 100644 index a96ba6f2..00000000 --- a/001-make.7 +++ /dev/null @@ -1,159 +0,0 @@ -.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/002-writing-mdoc.7 b/002-writing-mdoc.7 deleted file mode 100644 index 92c2fc05..00000000 --- a/002-writing-mdoc.7 +++ /dev/null @@ -1,138 +0,0 @@ -.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/003-pleasant-c.7 b/003-pleasant-c.7 deleted file mode 100644 index bfa29b9b..00000000 --- a/003-pleasant-c.7 +++ /dev/null @@ -1,120 +0,0 @@ -.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/004-uloc.7 b/004-uloc.7 deleted file mode 100644 index 909a0d1c..00000000 --- a/004-uloc.7 +++ /dev/null @@ -1,64 +0,0 @@ -.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/005-testing-c.7 b/005-testing-c.7 deleted file mode 100644 index c3a47c12..00000000 --- a/005-testing-c.7 +++ /dev/null @@ -1,79 +0,0 @@ -.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 - -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/Makefile b/Makefile deleted file mode 100644 index 8f2a55a1..00000000 --- a/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -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/feed.sh b/feed.sh deleted file mode 100755 index 3c6e6589..00000000 --- a/feed.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -set -e -u - -updated=$(date -u '+%FT%TZ') -cat < - -Causal Agency -Junejune@causal.agency - -https://text.causal.agency/ -${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 < - ${title} - ${summary} - - ${url} - ${updated} - -EOF -done -echo '' 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 + +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 < + +Causal Agency +Junejune@causal.agency + +https://text.causal.agency/ +${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 < + ${title} + ${summary} + + ${url} + ${updated} + +EOF +done +echo '' -- cgit 1.4.1