<?xml version='1.0' encoding='utf-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <atom:link href="https://www.davidpriver.com/feed.xml" rel="self" type="application/rss+xml" />
    <title>DavidsBlog</title>
    <link>https://www.davidpriver.com</link>
    <description>David's Blog</description>
    <language>en-us</language>
  <item><title>Templates in C</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;Templates in C&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
body {
  max-width: 44em !important;
}
pre .type {
  color: #ff8105 !important;
}
/*endcss*/
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#generics-in-c"&gt;Generics in C&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#void-pointers"&gt;Void Pointers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#function-pointers"&gt;Function pointers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#inline-macros"&gt;Inline Macros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#code-generating-macros"&gt;Code Generating Macros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#source-code-generation"&gt;Source Code Generation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#copy-paste"&gt;Copy Paste&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#template-headers-with-multiple-inclusion"&gt;Template Headers with Multiple Inclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#template-headers"&gt;Template Headers&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#example-usage"&gt;Example Usage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#copyright"&gt;Copyright&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;&lt;h1 id="templates-in-c"&gt;Templates in C&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, July 22nd, 2022&lt;/i&gt;
&lt;/p&gt;
&lt;article&gt;

&lt;p&gt;
Sometimes I see people on the internet sharing their generic libraries in C.
More often than not, they turn out to use some giant macro that generates a huge
amount of code on a single source line. I thought I would show a better way of
doing it if you need to write some C and don't want to copy-paste yet another
dynamic array or hash table.
&lt;/p&gt;
&lt;p&gt;
None of these ideas are new &amp;mdash; I am sure people were doing this in the 80s &amp;mdash;
but not everyone is aware of them.
&lt;/p&gt;
&lt;p&gt;
Note, &lt;tt&gt;_Generic&lt;/tt&gt; has nothing to do with this (althought you could use it
to simulate overloads if you generate a lot of code).
&lt;/p&gt;
&lt;div&gt;
&lt;h2 id="generics-in-c"&gt;Generics in C&lt;/h2&gt;
&lt;p&gt;
There are a few ways of creating generic data structures or algorithms in C:
&lt;/p&gt;
&lt;dt id="void-pointers"&gt;Void Pointers&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
If the data you are working with can be coerced to a void pointer, you can
side step the problem by writing a single implementation that only works
with void pointers or only with raw bytes. When the user actually uses it
they have to cast back to the original type and to be careful not to get
confused about which data structure is which.
&lt;/p&gt;
&lt;p&gt;
This is easy to implement, but is error-prone and type-unsafe to use. If you
require all data to be pointers the user is encouraged to heap allocate a
large number of individual items, which is bad for performance.
&lt;/p&gt;
&lt;/dd&gt;
&lt;dt id="function-pointers"&gt;Function pointers&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
You write your library or algorithm to work with opaque types and when you
need type-specific functionality, you call a function pointer given by the
user.
&lt;/p&gt;
&lt;p&gt;
A good example of this in the standard C library is the &lt;tt&gt;qsort&lt;/tt&gt;
function. For moving things it just &lt;tt&gt;memcpy&lt;/tt&gt;'s a void pointer, but
for the actual comparison it calls the comparison function given by the
user.
&lt;/p&gt;
&lt;p&gt;
The advantage of this approach is that it takes up very little code space -
there is just one &lt;tt&gt;qsort&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
The disadvantages are that it is type unsafe &amp;mdash; there is no way to check
that the user's function pointer is the right one and it is annoying to use.
The user has to define a (probably trivial) global function just to sort
some data.
&lt;/p&gt;
&lt;/dd&gt;
&lt;dt id="inline-macros"&gt;Inline Macros&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
Another approach is to not define a function at all and just do the work in
a macro. The classic K&amp;amp;R definition of max is an example of this:
&lt;/p&gt;
&lt;div class="C"&gt;
&lt;pre&gt;
#define max(a, b) ((a) &amp;gt; (b)? (a) : (b))
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Ignoring the multiple evaluation problem (a or b is evaluated twice, which
can be expensive or surprising if it involves side-effects), this is not
adequate for more advanced operations. Sans extensions, you can't really
define or use local variables, you can't use recursion, you can't get the
normal compiler errors when you pass the wrong type to the "function" and
this forcibly inlines the code at every usage site.
&lt;/p&gt;
&lt;p&gt;
It is very easy to use though (it looks like a function).
&lt;/p&gt;
&lt;/dd&gt;
&lt;dt id="code-generating-macros"&gt;Code Generating Macros&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
Another approach is to actually generate a function with the actual types
and call that generated function. To avoid having to actually copy-paste,
you generate the function via a macro.
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-combine"&gt;COMBINE&lt;/span&gt;(a, b) a##b
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-make-max"&gt;MAKE_MAX&lt;/span&gt;(&lt;span class="type"&gt;T&lt;/span&gt;, prefix) \
  &lt;span class="keyword"&gt;static&lt;/span&gt; &lt;span class="keyword"&gt;inline&lt;/span&gt; \
  &lt;span class="type"&gt;T&lt;/span&gt; &lt;span class="macro"&gt;COMBINE&lt;/span&gt;(prefix, max)(&lt;span class="type"&gt;T&lt;/span&gt; a, &lt;span class="type"&gt;T&lt;/span&gt; b){ \
      &lt;span class="keyword"&gt;if&lt;/span&gt;(a &amp;gt; b) &lt;span class="keyword"&gt;return&lt;/span&gt; a; \
      &lt;span class="keyword"&gt;return&lt;/span&gt; b; \
  }
&lt;span class="macro"&gt;MAKE_MAX&lt;/span&gt;(&lt;span class="type"&gt;int&lt;/span&gt;, int_)

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt;
&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;int&lt;/span&gt; x = &lt;span class="func"&gt;int_max&lt;/span&gt;(&lt;span class="literal"&gt;1&lt;/span&gt;, &lt;span class="literal"&gt;2&lt;/span&gt;);
    assert(x == &lt;span class="literal"&gt;2&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;

&lt;p&gt;
This is type safe and you get the benefits of functions (separating
implementation details from usage, local variables, early returns, etc.),
but it becomes impossible to debug if you need to step through the generated
code &amp;mdash; the nature of C macros is everything will be on a single line.
Checking the result of the macro expansion is also more difficult.
&lt;/p&gt;
&lt;p&gt;
Additionally, customizing the expanded code is difficult: you either need a
large number of arguments to the macro or just forgo customization of things
like prefixes to function names.
&lt;/p&gt;
&lt;p&gt;
Finally, just writing it is annoying. You need a &lt;tt&gt;\&lt;/tt&gt; on every line,
most editors give up on syntax highlighting it properly, etc.
&lt;/p&gt;
&lt;/dd&gt;
&lt;dt id="source-code-generation"&gt;Source Code Generation&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
Another alternative is to generate extra source files that then are compiled
into your program. The issue with this is that it greatly complicates the
building and compiling of your code. Suddenly you need a build system that
is aware of the need to generate the code instead of just leveraging the C
compiler that you already have. You step farther away from the ideal of just
compiling with &lt;tt&gt;cc *.c -o program&lt;/tt&gt;.
&lt;/p&gt;
&lt;/dd&gt;
&lt;dt id="copy-paste"&gt;Copy Paste&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
The manual version of source code generation is copy-pasting the data
structure and functions every time you need a new one. This is a nightmare
for maintainability &amp;mdash; a bug copy-pasted 100 times might never get fixed,
especially if that code is then altered and diverges.
&lt;/p&gt;
&lt;/dd&gt;
&lt;dt id="template-headers-with-multiple-inclusion"&gt;Template Headers with Multiple Inclusion&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
This approach is very similar to Code Generating Macros, but with the
benefit of it being easy to check the expanded code, it is possible to debug
and customization is much more straightforward thanks to &lt;tt&gt;#ifdef&lt;/tt&gt;.
The rest of this article will explain how they work.
&lt;/p&gt;
&lt;/dd&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="template-headers"&gt;Template Headers&lt;/h2&gt;
&lt;p&gt;
The idea of a template header is that you have a file that's meant to be
included multiple times. Each time the file is included, it generates a new
data structure or new functions, specialized to a given type or types, or
really on anything you can imagine.
&lt;/p&gt;
&lt;p&gt;
The easiest way to explain this is via an example:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// Darray.h&lt;/span&gt;
&lt;span class="comment"&gt;// Include this header multiple times to implement a&lt;/span&gt;
&lt;span class="comment"&gt;// simplistic dynamic array.  Before inclusion define at&lt;/span&gt;
&lt;span class="comment"&gt;// least DARRAY_T to the type the dynamic array can hold.&lt;/span&gt;
&lt;span class="comment"&gt;// See DARRAY_NAME, DARRAY_PREFIX and DARRAY_LINKAGE for&lt;/span&gt;
&lt;span class="comment"&gt;// other customization points.&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;
&lt;span class="comment"&gt;// If you define DARRAY_DECLS_ONLY, only the declarations&lt;/span&gt;
&lt;span class="comment"&gt;// of the type and its function will be declared.&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifndef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_HEADER_H&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_HEADER_H&lt;/span&gt;
&lt;span class="comment"&gt;// Inline functions, #defines and includes that will be&lt;/span&gt;
&lt;span class="comment"&gt;// needed for all instantiations can go up here.&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt; &lt;span class="comment"&gt;// realloc, size_t&lt;/span&gt;

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-impl"&gt;DARRAY_IMPL&lt;/span&gt;(word) &lt;span class="macro"&gt;DARRAY_COMB1&lt;/span&gt;(&lt;span class="macro"&gt;DARRAY_PREFIX&lt;/span&gt;,word)
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-comb1"&gt;DARRAY_COMB1&lt;/span&gt;(pre, word) &lt;span class="macro"&gt;DARRAY_COMB2&lt;/span&gt;(pre, word)
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-comb2"&gt;DARRAY_COMB2&lt;/span&gt;(pre, word) pre##word

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt; &lt;span class="comment"&gt;// DARRAY_HEADER_H&lt;/span&gt;

&lt;span class="comment"&gt;// NOTE: this section is *not* guarded as it is intended&lt;/span&gt;
&lt;span class="comment"&gt;// to be included multiple times.&lt;/span&gt;

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifndef&lt;/span&gt; &lt;span class="type"&gt;DARRAY_T&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;error&lt;/span&gt; &lt;span class="literal"&gt;"DARRAY_T must be defined"&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt;

&lt;span class="comment"&gt;// The name of the data type to be generated.&lt;/span&gt;
&lt;span class="comment"&gt;// If not given, will expand to something like&lt;/span&gt;
&lt;span class="comment"&gt;// `darray_int` for an `int`.&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifndef&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_COMB1&lt;/span&gt;(&lt;span class="macro"&gt;DARRAY_COMB1&lt;/span&gt;(darray,_), &lt;span class="type"&gt;DARRAY_T&lt;/span&gt;)
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt;

&lt;span class="comment"&gt;// Prefix for generated functions.&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifndef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_PREFIX&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-prefix"&gt;DARRAY_PREFIX&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_COMB1&lt;/span&gt;(&lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt;, _)
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt;

&lt;span class="comment"&gt;// Customize the linkage of the function.&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifndef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_LINKAGE&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-linkage"&gt;DARRAY_LINKAGE&lt;/span&gt; &lt;span class="keyword"&gt;static&lt;/span&gt; &lt;span class="keyword"&gt;inline&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt;

&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt;;
&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt; {
    &lt;span class="type"&gt;DARRAY_T&lt;/span&gt;* items;
    &lt;span class="type"&gt;size_t&lt;/span&gt; count;
    &lt;span class="type"&gt;size_t&lt;/span&gt; capacity;
};

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-push"&gt;DARRAY_push&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_IMPL&lt;/span&gt;(push)

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifdef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_DECLS_ONLY&lt;/span&gt;

&lt;span class="macro"&gt;DARRAY_LINKAGE&lt;/span&gt;
&lt;span class="type"&gt;void&lt;/span&gt;
&lt;span class="macro"&gt;DARRAY_push&lt;/span&gt;(&lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt;* array, &lt;span class="type"&gt;DARRAY_T&lt;/span&gt; item);

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;else&lt;/span&gt;

&lt;span class="macro"&gt;DARRAY_LINKAGE&lt;/span&gt;
&lt;span class="type"&gt;void&lt;/span&gt;
&lt;span class="macro"&gt;DARRAY_push&lt;/span&gt;(&lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt;* array, &lt;span class="type"&gt;DARRAY_T&lt;/span&gt; item){
    &lt;span class="keyword"&gt;if&lt;/span&gt;(array-&amp;gt;count &amp;gt;= array-&amp;gt;capacity){
        &lt;span class="type"&gt;size_t&lt;/span&gt; old_cap = array-&amp;gt;capacity;
        &lt;span class="type"&gt;size_t&lt;/span&gt; new_cap = old_cap?old_cap*&lt;span class="literal"&gt;2&lt;/span&gt;:&lt;span class="literal"&gt;4&lt;/span&gt;;
        &lt;span class="type"&gt;size_t&lt;/span&gt; new_size = new_cap * &lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;DARRAY_T&lt;/span&gt;);
        array-&amp;gt;items = &lt;span class="func"&gt;realloc&lt;/span&gt;(array-&amp;gt;items, new_size);
        array-&amp;gt;capacity = new_cap;
    }
    array-&amp;gt;items[array-&amp;gt;count++] = item;
}
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt;

&lt;span class="comment"&gt;// Cleanup&lt;/span&gt;
&lt;span class="comment"&gt;// These need to be undef'ed so they can be redefined the&lt;/span&gt;
&lt;span class="comment"&gt;// next time you need to instantiate this template.&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;undef&lt;/span&gt; &lt;span class="type"&gt;DARRAY_T&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;undef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_PREFIX&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;undef&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;undef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_LINKAGE&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;undef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_push&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifdef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_DECLS_ONLY&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;undef&lt;/span&gt; &lt;span class="macro"&gt;DARRAY_DECLS_ONLY&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt;
&lt;/pre&gt;
&lt;div&gt;
&lt;h3 id="example-usage"&gt;Example Usage&lt;/h3&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// example.c&lt;/span&gt;

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="type"&gt;DARRAY_T&lt;/span&gt; &lt;span class="type"&gt;int&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-darray-prefix"&gt;DARRAY_PREFIX&lt;/span&gt; i
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="type"&gt;DARRAY_NAME&lt;/span&gt; &lt;span class="type"&gt;IntArray&lt;/span&gt;
&lt;span class="comment"&gt;// Must be manually instantiated by #including the file&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"darray.h"&lt;/span&gt;

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;IntArray&lt;/span&gt; ints = {&lt;span class="literal"&gt;0&lt;/span&gt;};
    &lt;span class="func"&gt;ipush&lt;/span&gt;(&amp;amp;ints, &lt;span class="literal"&gt;1&lt;/span&gt;);
    &lt;span class="func"&gt;ipush&lt;/span&gt;(&amp;amp;ints, &lt;span class="literal"&gt;2&lt;/span&gt;);
    &lt;span class="func"&gt;ipush&lt;/span&gt;(&amp;amp;ints, &lt;span class="literal"&gt;3&lt;/span&gt;);
    &lt;span class="func"&gt;ipush&lt;/span&gt;(&amp;amp;ints, &lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="func"&gt;ipush&lt;/span&gt;(&amp;amp;ints, &lt;span class="literal"&gt;5&lt;/span&gt;);
    &lt;span class="func"&gt;ipush&lt;/span&gt;(&amp;amp;ints, &lt;span class="literal"&gt;6&lt;/span&gt;);
    assert(ints.count == &lt;span class="literal"&gt;6&lt;/span&gt;);
    assert(ints.items[&lt;span class="literal"&gt;0&lt;/span&gt;] == &lt;span class="literal"&gt;1&lt;/span&gt;);
    assert(ints.items[&lt;span class="literal"&gt;1&lt;/span&gt;] == &lt;span class="literal"&gt;2&lt;/span&gt;);
    assert(ints.items[&lt;span class="literal"&gt;2&lt;/span&gt;] == &lt;span class="literal"&gt;3&lt;/span&gt;);
    assert(ints.items[&lt;span class="literal"&gt;3&lt;/span&gt;] == &lt;span class="literal"&gt;4&lt;/span&gt;);
    assert(ints.items[&lt;span class="literal"&gt;4&lt;/span&gt;] == &lt;span class="literal"&gt;5&lt;/span&gt;);
    assert(ints.items[&lt;span class="literal"&gt;5&lt;/span&gt;] == &lt;span class="literal"&gt;6&lt;/span&gt;);
    assert(ints.capacity == &lt;span class="literal"&gt;8&lt;/span&gt;);
    &lt;span class="keyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; i = &lt;span class="literal"&gt;0&lt;/span&gt;; i &amp;lt; ints.count; i++){
        &lt;span class="func"&gt;printf&lt;/span&gt;(&lt;span class="literal"&gt;"[%zu] = %d\n"&lt;/span&gt;, i, ints.items[i]);
    }
    &lt;span class="func"&gt;free&lt;/span&gt;(ints.items);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
One reason this approach shines is that it is simple to debug the generation of
the code. For example, you can simply see what the code expands to by a command
like:
&lt;/p&gt;
&lt;div class="sh"&gt;
&lt;pre&gt;
$ cc -DDARRAY_T=int darray.h -E -P
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
(assuming a gcc or clang-like cc).
&lt;/p&gt;
&lt;p&gt;
If you tried to do a similar thing with a Code Generating Macro, it would be a
giant mess on a single line.
&lt;/p&gt;
&lt;p&gt;
The biggest benefit though is that if you have a bug in your generated code and
an assertion fails or address-sanitizer complains &amp;mdash; you have a real source
file with a real location. You can step through the code in a debugger and it is
readable and reasonable.
&lt;/p&gt;
&lt;p&gt;
The final benefit is that it is simple to implement customization points: check
for a macro to be defined and if not use some default behavior. This can get
pretty ugly, but it is better than a huge number of arguments to a Code
Generating Macro.
&lt;/p&gt;
&lt;div&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
By leveraging the ability of the preprocessor to include files multiple times
and the limited amount of introspection it provides, you can generate
efficient, specialized code without resorting to generating external files,
giving up type safety or copy-pasting code around.
&lt;/p&gt;
&lt;p&gt;
Newer languages than C have better solutions to this problem, but there are
many situations you still want to write some C and need things like type safe
dynamic arrays, hashtables or even sorting functions (this approach can easily
be used to specialize a quicksort).
&lt;/p&gt;
&lt;/div&gt;
&lt;/article&gt;

&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description>
<pubDate>Sun, 24 Jul 2022 03:48:51 GMT</pubDate>
<link>https://www.davidpriver.com/ctemplates.html</link>
<author>david@davidpriver.com</author>
</item>
<item><title>run(**vars(args))</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;run(**vars(args))&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
h1, #runvarsargs {
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
}
/*endcss*/
.python .control {
  color: rgb(200, 100, 0);
}
.python .comment {
  color: grey;
}
.python .None {
  color: purple;
}
.python .string {
  color: rgb(220, 0, 0);
}
.python .number {
  color: teal;
}
.python .import {
  color: purple;
}
/*endcss*/
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#runvarsargs"&gt;run(**vars(args))&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#copyright"&gt;Copyright&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;&lt;article&gt;
&lt;div&gt;
&lt;h2 id="runvarsargs"&gt;run(**vars(args))&lt;/h2&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, July 27th, 2022&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
Python has the pretty decent argument parsing module &lt;tt&gt;&lt;a href="https://docs.python.org/3/library/argparse.html"&gt;argparse&lt;/a&gt;&lt;/tt&gt; as part
of the standard library. It offers a procedural API for building up a parser
for a program's command line arguments. After calling &lt;tt&gt;parse_args&lt;/tt&gt;, you
get back a simple namespace object that contains the values as defined by your
parser (which I'll refer to as &lt;tt&gt;args&lt;/tt&gt;.)
&lt;/p&gt;
&lt;pre class="python"&gt;
&lt;span class="comment"&gt;# some_script.py&lt;/span&gt;
&lt;span class="import"&gt;import&lt;/span&gt; argparse

&lt;span class="keyword"&gt;def&lt;/span&gt; main() -&amp;gt; &lt;span class="None"&gt;None&lt;/span&gt;:
    parser = argparse.ArgumentParser()
    parser.add_argument(&lt;span class="string"&gt;'N'&lt;/span&gt;, type=&lt;span class="type"&gt;int&lt;/span&gt;)
    parser.add_argument(&lt;span class="string"&gt;'pid'&lt;/span&gt;, type=&lt;span class="type"&gt;int&lt;/span&gt;)
    parser.add_argument(&lt;span class="string"&gt;'--with-candles'&lt;/span&gt;, action=&lt;span class="string"&gt;'store_true'&lt;/span&gt;)

    args = parser.parse_args()
    ...

&lt;span class="control"&gt;if&lt;/span&gt; __name__ == &lt;span class="string"&gt;'__main__'&lt;/span&gt;:
    main()
&lt;/pre&gt;
&lt;p&gt;
There's just one problem: the only way to tell what is in this returned
&lt;tt&gt;args&lt;/tt&gt; is by reading the code that builds up the parser.
&lt;/p&gt;
&lt;p&gt;
What I've found to be an effective way to help with that problem is to
immediately grab the attributes off of the &lt;tt&gt;args&lt;/tt&gt; and pass them to a
function that actually does the work (normally named &lt;tt&gt;run&lt;/tt&gt;). You want
to spend as little time as possible with this dynamic, unstructured
&lt;tt&gt;args&lt;/tt&gt;.
&lt;/p&gt;
&lt;pre class="python"&gt;
&lt;span class="comment"&gt;# some_script.py&lt;/span&gt;
&lt;span class="import"&gt;import&lt;/span&gt; argparse

&lt;span class="keyword"&gt;def&lt;/span&gt; main() -&amp;gt; &lt;span class="None"&gt;None&lt;/span&gt;:
    parser = argparse.ArgumentParser()
    parser.add_argument(&lt;span class="string"&gt;'N'&lt;/span&gt;, type=&lt;span class="type"&gt;int&lt;/span&gt;)
    parser.add_argument(&lt;span class="string"&gt;'pid'&lt;/span&gt;, type=&lt;span class="type"&gt;int&lt;/span&gt;)
    parser.add_argument(&lt;span class="string"&gt;'--with-candles'&lt;/span&gt;, action=&lt;span class="string"&gt;'store_true'&lt;/span&gt;)

    args = parser.parse_args()
    run(args.N, args.pid, args.with_candles)


&lt;span class="keyword"&gt;def&lt;/span&gt; run(N:&lt;span class="type"&gt;int&lt;/span&gt;, pid:&lt;span class="type"&gt;int&lt;/span&gt;, with_candles:&lt;span class="type"&gt;bool&lt;/span&gt;=&lt;span class="None"&gt;False&lt;/span&gt;) -&amp;gt; &lt;span class="None"&gt;None&lt;/span&gt;:
    ...

&lt;span class="control"&gt;if&lt;/span&gt; __name__ == &lt;span class="string"&gt;'__main__'&lt;/span&gt;:
    main()
&lt;/pre&gt;
&lt;p&gt;
Having a separate &lt;tt&gt;run&lt;/tt&gt; function is nice anyway, as it means you can
write scripts that import your script and just call the &lt;tt&gt;run&lt;/tt&gt; function:
&lt;/p&gt;
&lt;pre class="python"&gt;
&lt;span class="comment"&gt;# myscript.py&lt;/span&gt;
&lt;span class="import"&gt;import&lt;/span&gt; some_script
&lt;span class="import"&gt;import&lt;/span&gt; another_script

some_script.run(&lt;span class="number"&gt;1&lt;/span&gt;, &lt;span class="number"&gt;2&lt;/span&gt;, with_candles=&lt;span class="None"&gt;True&lt;/span&gt;)
another_script.run(&lt;span class="string"&gt;'big'&lt;/span&gt;, &lt;span class="number"&gt;1&lt;/span&gt;, &lt;span class="string"&gt;'hello.txt'&lt;/span&gt;)
&lt;/pre&gt;
&lt;p&gt;
However, this &lt;tt&gt;run&lt;/tt&gt; function poses its own problem. It's tedious to
grab all of the attributes off of &lt;tt&gt;args&lt;/tt&gt;, which tempts you to the dark
side of just passing the &lt;tt&gt;args&lt;/tt&gt; object around in your application,
making it very hard to understand what's going on.
&lt;/p&gt;
&lt;p&gt;
Luckily, there is a relatively obscure builtin function in python called
&lt;tt&gt;&lt;a href="https://docs.python.org/3/library/functions.html#vars"&gt;vars&lt;/a&gt;&lt;/tt&gt;. &lt;tt&gt;vars&lt;/tt&gt; (when given an argument) basically grabs all of
the attributes off of an object and puts them into a &lt;tt&gt;dict&lt;/tt&gt;. Coupling
that with python's convenient &lt;tt&gt;**&lt;/tt&gt; for dictionary unpacking, you are
saved the trouble of manually peeling the attributes off yourself. Thus the
title of this article: you use the incantation &lt;tt&gt;run(**vars(args))&lt;/tt&gt;
immediately after parsing command-line arguments.
&lt;/p&gt;
&lt;pre class="python"&gt;
&lt;span class="comment"&gt;# some_script.py&lt;/span&gt;
&lt;span class="import"&gt;import&lt;/span&gt; argparse

&lt;span class="keyword"&gt;def&lt;/span&gt; main() -&amp;gt; &lt;span class="None"&gt;None&lt;/span&gt;:
    parser = argparse.ArgumentParser()
    parser.add_argument(&lt;span class="string"&gt;'N'&lt;/span&gt;, type=&lt;span class="type"&gt;int&lt;/span&gt;)
    parser.add_argument(&lt;span class="string"&gt;'pid'&lt;/span&gt;, type=&lt;span class="type"&gt;int&lt;/span&gt;)
    parser.add_argument(&lt;span class="string"&gt;'--with-candles'&lt;/span&gt;, action=&lt;span class="string"&gt;'store_true'&lt;/span&gt;)

    args = parser.parse_args()
    run(**vars(args)) &lt;span class="comment"&gt;# Here it is.&lt;/span&gt;

&lt;span class="keyword"&gt;def&lt;/span&gt; run(N:&lt;span class="type"&gt;int&lt;/span&gt;, pid:&lt;span class="type"&gt;int&lt;/span&gt;, with_candles:&lt;span class="type"&gt;bool&lt;/span&gt;=&lt;span class="None"&gt;False&lt;/span&gt;) -&amp;gt; &lt;span class="None"&gt;None&lt;/span&gt;:
    ...

&lt;span class="control"&gt;if&lt;/span&gt; __name__ == &lt;span class="string"&gt;'__main__'&lt;/span&gt;:
    main()
&lt;/pre&gt;
&lt;p&gt;
Relatively simple pattern, but I've found it to be useful. I'm sure there are
argument parsing libraries that do nicer things, but with this pattern you can
stick to the standard library which lessens the dependency problem.
&lt;/p&gt;
&lt;/div&gt;
&lt;/article&gt;

&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Wed, 27 Jul 2022 23:29:53 GMT</pubDate><link>https://www.davidpriver.com/runvarsargs.html</link><author>david@davidpriver.com</author></item><item><title>_Generic for Type Reification in C</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;_Generic for Type Reification in C&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
.uses h3 {
  font-weight: initial;
  font-style: italic;
  margin-bottom: 0;
}
.uses p {
  margin-left: 2em;
  margin-top: 0;
}
/*endcss*/
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#generic"&gt;_Generic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generic-for-tagging"&gt;_Generic for Tagging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#use-cases"&gt;Use Cases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#appendix-other-languages"&gt;Appendix: Other Languages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#copyright"&gt;Copyright&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;&lt;h1 id="generic-for-type-reification-in-c"&gt;_Generic for Type Reification in C&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, July 29th, 2022&lt;/i&gt;
&lt;/p&gt;
&lt;article&gt;

&lt;p&gt;
Occasionally, you need to turn a type into a value. An example of when you would
need to do this is when constructing a tagged union that can hold pointers to
different types:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// anypointer.h&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class="comment"&gt;// prefixes and other types elided for brevity&lt;/span&gt;
&lt;span class="keyword"&gt;enum&lt;/span&gt; &lt;span class="type" id="type-anypointertag"&gt;AnyPointerTag&lt;/span&gt; {
    &lt;span class="enum" id="enum-uninit"&gt;UNINIT&lt;/span&gt;,
    &lt;span class="enum" id="enum-int"&gt;INT&lt;/span&gt;,
    &lt;span class="enum" id="enum-char-star"&gt;CHAR_STAR&lt;/span&gt;,
    &lt;span class="enum" id="enum-double"&gt;DOUBLE&lt;/span&gt;,
};
&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type" id="type-anypointer"&gt;AnyPointer&lt;/span&gt; &lt;span class="type" id="type-anypointer"&gt;AnyPointer&lt;/span&gt;;
&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type"&gt;AnyPointer&lt;/span&gt; {
    &lt;span class="keyword"&gt;enum&lt;/span&gt; &lt;span class="type"&gt;AnyPointerTag&lt;/span&gt; tag;
    &lt;span class="keyword"&gt;union&lt;/span&gt; {
        &lt;span class="type"&gt;void&lt;/span&gt;* pointer;
        &lt;span class="type"&gt;int&lt;/span&gt;* integer;
        &lt;span class="type"&gt;char&lt;/span&gt;** charstar;
        &lt;span class="type"&gt;double&lt;/span&gt;* double_;
    };
};

&lt;span class="type"&gt;void&lt;/span&gt;
&lt;span class="func" id="func-print-any"&gt;print_any&lt;/span&gt;(&lt;span class="type"&gt;AnyPointer&lt;/span&gt; any){
    &lt;span class="keyword"&gt;switch&lt;/span&gt;(any.tag){
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="enum"&gt;UNINIT&lt;/span&gt;: &lt;span class="keyword"&gt;return&lt;/span&gt;;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="enum"&gt;INT&lt;/span&gt;:
            &lt;span class="func"&gt;printf&lt;/span&gt;(&lt;span class="literal"&gt;"%d\n"&lt;/span&gt;, *any.integer);
            &lt;span class="keyword"&gt;return&lt;/span&gt;;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="enum"&gt;CHAR_STAR&lt;/span&gt;:
            &lt;span class="func"&gt;printf&lt;/span&gt;(&lt;span class="literal"&gt;"%s\n"&lt;/span&gt;, *any.charstar);
            &lt;span class="keyword"&gt;return&lt;/span&gt;;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="enum"&gt;DOUBLE&lt;/span&gt;:
            &lt;span class="func"&gt;printf&lt;/span&gt;(&lt;span class="literal"&gt;"%f\n"&lt;/span&gt;, *any.double_);
            &lt;span class="keyword"&gt;return&lt;/span&gt;;
        &lt;span class="keyword"&gt;default&lt;/span&gt;: &lt;span class="keyword"&gt;return&lt;/span&gt;;
    }
}
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// example.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"anypointer.h"&lt;/span&gt;

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;int&lt;/span&gt; x = &lt;span class="literal"&gt;3&lt;/span&gt;;
    &lt;span class="type"&gt;AnyPointer&lt;/span&gt; any = {.tag=&lt;span class="enum"&gt;INT&lt;/span&gt;, .integer=&amp;amp;x};
    &lt;span class="func"&gt;print_any&lt;/span&gt;(any); &lt;span class="comment"&gt;// prints 3&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;p&gt;
This example is small so it is not that difficult to manually set the tag when
constructing the tagged union. However, setting the tag wrong would be
disastrous, as you would be misinterpreting what is being pointed to.
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// problem.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"anypointer.h"&lt;/span&gt;

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;int&lt;/span&gt; x = &lt;span class="literal"&gt;3&lt;/span&gt;;
    &lt;span class="type"&gt;AnyPointer&lt;/span&gt; any = {.tag=&lt;span class="enum"&gt;CHAR_STAR&lt;/span&gt;, .integer=&amp;amp;x};
    &lt;span class="func"&gt;print_any&lt;/span&gt;(any); &lt;span class="comment"&gt;// segfaults&lt;/span&gt;
}
&lt;/pre&gt;
&lt;div&gt;
&lt;h2 id="generic"&gt;_Generic&lt;/h2&gt;
&lt;p&gt;
C11 added the rarely used feature &lt;tt&gt;&lt;a href="https://en.cppreference.com/w/c/language/generic"&gt;_Generic&lt;/a&gt;&lt;/tt&gt;. It somewhat resembles a
switch statement, but using types instead of integer constant expressions. Its
motivating use case was to simulate overloading in C, but it can select
arbitrary expressions, not just functions.
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// generic.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="comment"&gt;// prints: "int: 3"&lt;/span&gt;
    &lt;span class="func"&gt;printf&lt;/span&gt;(
        &lt;span class="keyword"&gt;_Generic&lt;/span&gt;(&lt;span class="literal"&gt;3&lt;/span&gt;,
        &lt;span class="type"&gt;int&lt;/span&gt;: &lt;span class="literal"&gt;"int: %d\n"&lt;/span&gt;,
        &lt;span class="type"&gt;float&lt;/span&gt;: &lt;span class="literal"&gt;"float: %f\n"&lt;/span&gt;), &lt;span class="literal"&gt;3&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;p&gt;
In common use, &lt;tt&gt;_Generic&lt;/tt&gt; is used in a macro.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="generic-for-tagging"&gt;_Generic for Tagging&lt;/h2&gt;
&lt;p&gt;
We can use the power of &lt;tt&gt;_Generic&lt;/tt&gt; to automatically select the
appropriate type tag for our tagged union.
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// generic_tag.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"anypointer.h"&lt;/span&gt;

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-tag"&gt;TAG&lt;/span&gt;(x) &lt;span class="keyword"&gt;_Generic&lt;/span&gt;(x, \
    &lt;span class="type"&gt;int&lt;/span&gt;: &lt;span class="enum"&gt;INT&lt;/span&gt;, \
    &lt;span class="type"&gt;char&lt;/span&gt;*: &lt;span class="enum"&gt;CHAR_STAR&lt;/span&gt;, \
    &lt;span class="type"&gt;double&lt;/span&gt;: &lt;span class="enum"&gt;DOUBLE&lt;/span&gt;)

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;int&lt;/span&gt; x = &lt;span class="literal"&gt;3&lt;/span&gt;;
    &lt;span class="type" id="type-anypointer"&gt;AnyPointer&lt;/span&gt; any = {.tag=&lt;span class="macro"&gt;TAG&lt;/span&gt;(x), .pointer=&amp;amp;x};
    &lt;span class="func"&gt;print_any&lt;/span&gt;(any); &lt;span class="comment"&gt;// prints 3&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;p&gt;
Going even farther, we can completely automate the creation of our tagged
union in a macro:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// generic_compound.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"anypointer.h"&lt;/span&gt;

&lt;span class="comment"&gt;// NOTE: we now take a pointer instead of the value&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-tag"&gt;TAG&lt;/span&gt;(x) &lt;span class="keyword"&gt;_Generic&lt;/span&gt;(x, \
    &lt;span class="type"&gt;int&lt;/span&gt;*: &lt;span class="enum"&gt;INT&lt;/span&gt;, \
    &lt;span class="type"&gt;char&lt;/span&gt;**: &lt;span class="enum"&gt;CHAR_STAR&lt;/span&gt;, \
    &lt;span class="type"&gt;double&lt;/span&gt;*: &lt;span class="enum"&gt;DOUBLE&lt;/span&gt;)

&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-any"&gt;ANY&lt;/span&gt;(x) (&lt;span class="type"&gt;AnyPointer&lt;/span&gt;){.tag=&lt;span class="macro"&gt;TAG&lt;/span&gt;(x), .pointer=x}

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;int&lt;/span&gt; x = &lt;span class="literal"&gt;3&lt;/span&gt;;
    &lt;span class="type"&gt;AnyPointer&lt;/span&gt; any = &lt;span class="macro"&gt;ANY&lt;/span&gt;(&amp;amp;x);
    &lt;span class="func"&gt;print_any&lt;/span&gt;(any); &lt;span class="comment"&gt;// prints 3&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;p&gt;
Now, we can safely and concisely construct our tagged union without the risk
of accidentally setting the wrong tag. Additionally, if we try to wrap a value of
an unsupported type, we'll get a compilation error as the &lt;tt&gt;_Generic&lt;/tt&gt; will
fail to match any of its known types.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="use-cases"&gt;Use Cases&lt;/h2&gt;
&lt;p&gt;
In practice, you don't use this technique very often. C code doesn't usually
need to use this level of indirection and using too many macros like this can
make the code obfuscated. However, there are times when a little "magic" like
this is justified in my opinion.
&lt;/p&gt;
&lt;div class="uses"&gt;
&lt;h3&gt;Argument parsing libraries&lt;/h3&gt;
&lt;p&gt;
You can use a type-reifying macro in essentially the same way as in the
above examples. When parsing arguments, you would switch on the type tag to
determine what type conversion function to call or action to take.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="uses"&gt;
&lt;h3&gt;Serialization code&lt;/h3&gt;
&lt;p&gt;
You can use a type-reifying macro like this, along with &lt;tt&gt;sizeof&lt;/tt&gt; and
&lt;tt&gt;&lt;a href="https://en.cppreference.com/w/c/types/offsetof"&gt;offsetof&lt;/a&gt;&lt;/tt&gt; to create a descriptor for a data type. The
serializer/deserializer could then use that descriptor to parse binary data
or something like JSON.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="uses"&gt;
&lt;h3&gt;Dynamic "objects"&lt;/h3&gt;
&lt;p&gt;
Instead of a type tag, you could have a pointer to a vtable. This would
allow you to convert staticly typed objects to an interface.
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
It's a useful technique to have in your toolbox. Don't overuse it.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
C11 added the means to reify types, a capability lacking from the C
programming language before then. Using the &lt;tt&gt;_Generic&lt;/tt&gt; construct, we can
bridge one of the gaps between compile time information (types) and runtime
information (type tags). Doing so allows you to implement things like an
&lt;tt&gt;Any&lt;/tt&gt; type, introspecting values for data processing and other use
cases. Opportunities to use this technique are not too frequent, but when you do
need it the technique can save error-prone manual boilerplate.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="appendix-other-languages"&gt;Appendix: Other Languages&lt;/h2&gt;
&lt;p&gt;
In C++, you can achieve the same effect by writing a collection of trivial
&lt;tt&gt;constexpr&lt;/tt&gt; overloaded functions that return the type tag. This is more
verbose, but can yield the same result.
&lt;/p&gt;
&lt;p&gt;
If you are using GCC, but for some reason can't use C11 features, you can use
&lt;tt&gt;__builtin_types_compatible_p&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
In languages with first class types, you can just store the pointer to the
type instead.
&lt;/p&gt;
&lt;/div&gt;
&lt;/article&gt;

&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Fri, 29 Jul 2022 15:33:52 GMT</pubDate><link>https://www.davidpriver.com/creification.html</link><author>david@davidpriver.com</author></item><item><title>Doctests in C</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;Doctests in C&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#copyright"&gt;Copyright&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;&lt;h1 id="doctests-in-c"&gt;Doctests in C&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, July 30th, 2022&lt;/i&gt;
&lt;/p&gt;
&lt;article&gt;

&lt;p&gt;
&lt;a href="https://docs.python.org/3/library/doctest.html"&gt;Doctests&lt;/a&gt; are a technique of testing the examples embedded in documentation.
They were first created for the Python language in 1999, but have since spread
to other languages like Rust.
&lt;/p&gt;
&lt;p&gt;
Embedding examples in documentation is very useful as it can immediately clarify
usage of an API or the meaning of unclear terms. However, they can rot as the
API changes, which can be worse than having nothing at all. What are we to do?
&lt;/p&gt;
&lt;p&gt;
Well, as usual in C when you have a problem that can't be solved directly in the
language itself, you reach for the preprocessor (this usage isn't that crazy, I
promise!). Just include the examples in the doc, but guard them with an
&lt;tt&gt;#ifdef&lt;/tt&gt;. You can then write a test program that &lt;tt&gt;#includes&lt;/tt&gt; the
documentation file, but with that macro defined so the examples are actual code.
Then, run the tests!
&lt;/p&gt;
&lt;p&gt;
An example:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// some_api.h&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stddef.h&amp;gt;&lt;/span&gt; &lt;span class="comment"&gt;// size_t&lt;/span&gt;
&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type" id="type-someapicontext"&gt;SomeApiContext&lt;/span&gt; &lt;span class="type" id="type-someapicontext"&gt;SomeApiContext&lt;/span&gt;;

&lt;span class="comment"&gt;// Visibility modifiers, dllexport, and some documentation&lt;/span&gt;
&lt;span class="comment"&gt;// elided for brevity.&lt;/span&gt;

&lt;span class="type"&gt;SomeApiContext&lt;/span&gt;* &lt;span class="func" id="func-some-api-create"&gt;some_api_create&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;);
&lt;span class="comment"&gt;// ...&lt;/span&gt;

&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="func" id="func-some-api-store-data"&gt;some_api_store_data&lt;/span&gt;(&lt;span class="type"&gt;SomeApiContext&lt;/span&gt;*, &lt;span class="type"&gt;int&lt;/span&gt;*, &lt;span class="type"&gt;size_t&lt;/span&gt;);
&lt;span class="comment"&gt;// ...&lt;/span&gt;

&lt;span class="type"&gt;size_t&lt;/span&gt;
&lt;span class="func" id="func-some-api-get-data"&gt;some_api_get_data&lt;/span&gt;(
    &lt;span class="type"&gt;SomeApiContext&lt;/span&gt;* ctx,
    &lt;span class="type"&gt;int&lt;/span&gt;* buff, &lt;span class="type"&gt;size_t&lt;/span&gt; bufflen,
    &lt;span class="type"&gt;size_t&lt;/span&gt;* cookie);
&lt;span class="comment"&gt;// Copies the data into a user provided buffer.&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="h"&gt; Arguments:&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="underline"&gt; ----------&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="param"&gt; ctx:&lt;/span&gt;
&lt;span class="comment"&gt;//      The api context&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="param"&gt; buff:&lt;/span&gt;
&lt;span class="comment"&gt;//      The buffer to copy the data into.&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="param"&gt; bufflen:&lt;/span&gt;
&lt;span class="comment"&gt;//      The length (in items, not bytes) of buff.&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="param"&gt; cookie:&lt;/span&gt;
&lt;span class="comment"&gt;//      A pointer to an opaque value for remembering where&lt;/span&gt;
&lt;span class="comment"&gt;//      in the data this function is. Initialize cookie to 0&lt;/span&gt;
&lt;span class="comment"&gt;//      before calling this function.&lt;/span&gt;
&lt;span class="comment"&gt;// &lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="h"&gt; Returns:&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="underline"&gt; --------&lt;/span&gt;
&lt;span class="comment"&gt;// The number of items copied into buff. If 0 is returned,&lt;/span&gt;
&lt;span class="comment"&gt;// no items were copied into the buff and there are no more&lt;/span&gt;
&lt;span class="comment"&gt;// items to copy.&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="h"&gt; Example:&lt;/span&gt;
&lt;span class="comment"&gt;//&lt;/span&gt;&lt;span class="underline"&gt; --------&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;ifdef&lt;/span&gt; SOME_API_EXAMPLE
&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-sum-some-api-data"&gt;sum_some_api_data&lt;/span&gt;(&lt;span class="type"&gt;SomeApiContext&lt;/span&gt;* ctx){
    &lt;span class="type"&gt;int&lt;/span&gt; result = &lt;span class="literal"&gt;0&lt;/span&gt;;
    &lt;span class="keyword"&gt;enum&lt;/span&gt; {buff_len=&lt;span class="literal"&gt;32&lt;/span&gt;};
    &lt;span class="type"&gt;int&lt;/span&gt; buff[buff_len];
    &lt;span class="type"&gt;size_t&lt;/span&gt; n = &lt;span class="literal"&gt;0&lt;/span&gt;;
    &lt;span class="type"&gt;size_t&lt;/span&gt; cookie = &lt;span class="literal"&gt;0&lt;/span&gt;;
    &lt;span class="keyword"&gt;while&lt;/span&gt;((n = &lt;span class="func"&gt;some_api_get_data&lt;/span&gt;(ctx, buff, buff_len, &amp;amp;cookie))){
        &lt;span class="keyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; i = &lt;span class="literal"&gt;0&lt;/span&gt;; i &amp;lt; n; i++){
            result += buff[i];
        }
    }
    &lt;span class="keyword"&gt;return&lt;/span&gt; result;
}
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;endif&lt;/span&gt; &lt;span class="comment"&gt;// SOME_API_EXAMPLE&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;
And the test code:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// test_some_api_docs.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;define&lt;/span&gt; &lt;span class="macro" id="macro-some-api-example"&gt;SOME_API_EXAMPLE&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"some_api.h"&lt;/span&gt;

&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="func" id="func-main"&gt;main&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    &lt;span class="type"&gt;int&lt;/span&gt; data[&lt;span class="literal"&gt;3&lt;/span&gt;] = {&lt;span class="literal"&gt;1&lt;/span&gt;, &lt;span class="literal"&gt;2&lt;/span&gt;, &lt;span class="literal"&gt;3&lt;/span&gt;};
    &lt;span class="type"&gt;SomeApiContext&lt;/span&gt;* ctx = &lt;span class="func" id="func-some-api-create"&gt;some_api_create&lt;/span&gt;();
    &lt;span class="func"&gt;some_api_store_data&lt;/span&gt;(ctx, data, &lt;span class="literal"&gt;3&lt;/span&gt;);
    assert(&lt;span class="func"&gt;sum_some_api_data&lt;/span&gt;(ctx) == &lt;span class="literal"&gt;6&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;p&gt;
This isn't as nice as automatically extracting the examples like doctest can do,
but when integrated into your test suite you will no longer have regressions in
your documentation's examples. Additionally, it is nice to have examples right
next to the definitions in the header anyway as that is what you'll jump to when
you use your editor's GoToDefinition functionality. Finally, it is easier to
write the examples as the examples are written as actual code instead of
embedded in comments (so your editor and other tools understand it as code).
&lt;/p&gt;
&lt;p&gt;
You do need a documentation generator which understands that it needs to include
these &lt;tt&gt;#ifdef&lt;/tt&gt;'d example blocks. I'm working on such a tool based on
libclang, but it is not ready for release yet.
&lt;/p&gt;
&lt;/article&gt;
&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Fri, 29 Jul 2022 19:02:35 GMT</pubDate><link>https://www.davidpriver.com/cdoctest.html</link><author>david@davidpriver.com</author></item><item><title>C in WASM</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;C in WASM&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
pre b {
  font-weight: normal;
}

pre .let {
  color: #5AB1FF;
}
pre .builtin {
  color: #87FFAF;
}
pre .field {
  color: #936;
}
/*endcss*/
&lt;/style&gt;
&lt;script&gt;
// demo.js
const prog64 = "AGFzbQEAAAABGAVgAn9/AGAAAGABfwF/YAJ/fwF/YAF/AAINAQNlbnYFd3JpdGUAAAMHBgEBAgMEBAUDAQACBisHfwFBkIgEC38AQZCIBAt/AEGACAt/AEGECAt/AEGACAt/AEEAC38AQQELB6kBDQZtZW1vcnkCABFfX3dhc21fY2FsbF9jdG9ycwABDHJlc2V0X21lbW9yeQACC19faGVhcF9iYXNlAwEGbWFsbG9jAAMGY2FsbG9jAAQEZnJlZQAFB2NsaWNrZWQABgxfX2Rzb19oYW5kbGUDAgpfX2RhdGFfZW5kAwMNX19nbG9iYWxfYmFzZQMEDV9fbWVtb3J5X2Jhc2UDBQxfX3RhYmxlX2Jhc2UDBgrVAQYCAAsRAEEAQZCIhIAANgKAiICAAAstAQF/QQBBACgCgIiAgAAiAUEEakF8cSABIAFBA3EbIgEgAGo2AoCIgIAAIAELSgECf0EAIAFBBCABQQRJGyICQQAoAoCIgIAAIgNqIAJBf2ogA3EiAmsgAyACGyIDIAEgAGwiAWo2AoCIgIAAIANBACAB/AsAIAMLAgALQgEBfyOAgICAAEEQayIBJICAgIAAIAFBCjoADyABIABBD3FB4QBqOgAOIAFBDmpBAhCAgICAACABQRBqJICAgIAACwsLAQBBgAgLBBAEAQAAwAQLLmRlYnVnX2luZm8wAgAABAAAAAAABAHFAAAADACPAAAAAAAAANoAAAAAAAAAGAAAAAI6AAAANwAAAAENBQMABAAAAzwAAAAERAAAAAgBBVIAAAAEAQcGuQAAAAQABA0AAAAHBAdkAAAAKwAAAAEGBFYAAAAHBAgFAAAAEQAAAAftAwAAAACfAAAAAAERCYkAAAABGbsAAAABCmkAAAABGVkAAAAKGgAAAAEZWQAAAAujAAAAARxZAAAACyQAAAABIbsAAAAADA0XAAAALQAAAAftAwAAAACfgQAAAAEnuwAAAA4E7QAAn2kAAAABJ1kAAAAPggAAABcAAAAqAAAAASgMEATtAACfjgAAABEEmQAAABIAAAAApAAAABIsAAAArwAAAAAADUUAAABKAAAAB+0DAAAAAJ+IAAAAASy7AAAADgTtAACfMgAAAAEsWQAAAA4E7QABn2QAAAABLFkAAAATvgAAACQAAAABLbsAAAAUggAAAAAAAAABLRQVCAEAAI4AAAAVWAAAAJkAAAASkgAAAKQAAAAS6gAAAK8AAAAAABaQAAAAAgAAAAftAwAAAACfdAAAAAE2ClIAAAABNrsAAAAAFpMAAABCAAAABO0AAZ95AAAAAgYOBO0AAJ9UAAAAAgYsAgAAFwKRDqEAAAACBxkCAAAY9gEAAMkAAAAAGW4AAAACBBoIAgAAGlkAAAAAAw0CAAAbEgIAAARNAAAABgEcEgIAAB0lAgAAAgAepQAAAAgHBBYAAAAFBAAAvwIKLmRlYnVnX2xvY/////8XAAAADgAAABAAAAAEAO0CAZ8QAAAALQAAAAQA7QABnwAAAAAAAAAA/////xcAAAAeAAAAIAAAAAQA7QIBnyAAAAAtAAAABADtAAGfAAAAAAAAAAD/////RQAAAAAAAAAPAAAABADtAAGfDwAAABEAAAAEAO0CAZ8RAAAASgAAAAQA7QACnwAAAAAAAAAA/////0UAAAAaAAAAHAAAAAQA7QICnxwAAABKAAAABADtAAOfAAAAAAAAAAD/////RQAAAC0AAAAvAAAABADtAgGfLwAAAEoAAAAEAO0AA58AAAAAAAAAAP////9FAAAALwAAAEoAAAAEAO0AA58AAAAAAAAAAP////9FAAAANAAAADYAAAAEAO0CAp82AAAASgAAAAQA7QABnwAAAAAAAAAAAFYNLmRlYnVnX3Jhbmdlc0UAAAByAAAAeQAAAIcAAAAAAAAAAAAAAAUAAAAWAAAAFwAAAEQAAABFAAAAjwAAAJAAAACSAAAAkwAAANUAAAAAAAAAAAAAAACWAw0uZGVidWdfYWJicmV2AREBJQ4TBQMOEBcbDhEBVRcAAAI0AAMOSRM6CzsLAhgAAAMPAEkTAAAEJAADDj4LCwsAAAUEAUkTCws6CzsLAAAGKAADDhwPAAAHFgBJEwMOOgs7CwAACC4AEQESBkAYl0IZAw46CzsLJxk/GQAACS4BAw46CzsLJxlJEyALAAAKBQADDjoLOwtJEwAACzQAAw46CzsLSRMAAAwPAAAADS4BEQESBkAYl0IZAw46CzsLJxlJEz8ZAAAOBQACGAMOOgs7C0kTAAAPHQExExEBEgZYC1kLVwsAABAFAAIYMRMAABEFABwPMRMAABI0AAIXMRMAABM0AAIXAw46CzsLSRMAABQdATETVRdYC1kLVwsAABUFAAIXMRMAABYuAREBEgZAGJdCGQMOOgs7CycZPxkAABc0AAIYAw46CzsLSRMAABiJggEAMRMRAQAAGS4BAw46CzsLJxk8GT8ZAAAaBQBJEwAAGyYASRMAABwBAUkTAAAdIQBJEzcLAAAeJAADDgsLPgsAAAAAjQILLmRlYnVnX2xpbmX9AAAABABBAAAAAQEB+w4NAAEBAQEAAAABAAABYy1pbi13YXNtAABwcmltaXRpdmVfbWFsbG9jLmMAAQAAZXhhbXBsZS5jAAEAAAAABQIFAAAAAxABBQ8KIQUB5QIBAAEBAAUCFwAAAAMmAQUYCgN1PAYDZKwFCAYDHUoFCgaeBQggBQ8GJQUFwAIDAAEBAAUCRQAAAAMrAQUYCgNwPAUInAUYMAUIrQUWBnQFCiAFCDwFIQYDEIIFDwN1dAUYA3qeBQUDE0pZAgMAAQEABQKQAAAAAzUBBQEKIgIBAAEBBAIABQKTAAAAFwURCgh1BRIGkAURWAUFBj0FAckCDAABAQCFAgouZGVidWdfc3RycmVzZXRfbWVtb3J5AHVuc2lnbmVkIGludABhbGlnbm1lbnQAcmVzdWx0AHNpemVfdABuX2l0ZW1zAF9iYXNlX3B0cgB1bnNpZ25lZCBjaGFyAHAAaQB1bnNpZ25lZCBsb25nAGl0ZW1fc2l6ZQB3cml0ZQBmcmVlAGNsaWNrZWQAbWFsbG9jAGNhbGxvYwBjLWluLXdhc20vZXhhbXBsZS5jAGIAX19BUlJBWV9TSVpFX1RZUEVfXwBTSVpFX1RfU0laRQBjbGFuZyB2ZXJzaW9uIDE1LjAuNgAvVXNlcnMvZHJwcml2ZXIvRG9jdW1lbnRzL0Jsb2cyAABtBG5hbWUBSAcABXdyaXRlARFfX3dhc21fY2FsbF9jdG9ycwIMcmVzZXRfbWVtb3J5AwZtYWxsb2MEBmNhbGxvYwUEZnJlZQYHY2xpY2tlZAcSAQAPX19zdGFja19wb2ludGVyCQgBAAUuZGF0YQA1CXByb2R1Y2VycwIIbGFuZ3VhZ2UBA0M5OQAMcHJvY2Vzc2VkLWJ5AQVjbGFuZwYxNS4wLjYAaw90YXJnZXRfZmVhdHVyZXMGKwtidWxrLW1lbW9yeSsKbXVsdGl2YWx1ZSsPbXV0YWJsZS1nbG9iYWxzKxNub250cmFwcGluZy1mcHRvaW50Kw9yZWZlcmVuY2UtdHlwZXMrCHNpZ24tZXh0";
"use strict";
let wasm_inst; // WebAssembly.Instance
let mem; // Uint8Array
let memview; // DataView
let exports; // WebAssembly.Exports
const decoder = new TextDecoder();
const encoder = new TextEncoder();
function wasm_string_to_js(p, len){
    const sub = mem.subarray(p, p+len);
    const text = decoder.decode(sub);
    return text;
}
function write4(p, val){
    memview.setInt32(p, val, true);
}
function js_string_to_wasm(s){
    const encoded = encoder.encode(s);
    const p = exports.malloc(encoded.length+4);
    write4(p, encoded.length);
    mem.set(encoded, p+4);
    return p;
}
const imports = {
    env:{
      write: (p, len) =&gt; {
        const s = wasm_string_to_js(p, len);
        document.getElementById('scratch').innerText+=s;
      },
    },
};
document.addEventListener('DOMContentLoaded', ()=&gt;{
  // prog64 is the base64 version of the wasm file.
  const wasm_buffer = Uint8Array.from(
    atob(prog64),
    c =&gt; c.charCodeAt(0)
  ).buffer;
  WebAssembly.compile(wasm_buffer)
    .then(x =&gt; WebAssembly.instantiate(x, imports))
    .then(x =&gt; {
      wasm_inst = x;
      wasm_inst.exports.memory.grow(24);
      exports = wasm_inst.exports;
      mem = new Uint8Array(exports.memory.buffer);
      memview = new DataView(mem.buffer);
      let i = 0;
      document.getElementById('click-me').onclick=()=&gt;{
        exports.clicked(i++);
      };
    });
});
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;h1 id="c-in-wasm"&gt;C in WASM&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, January 20th, 2023&lt;/i&gt;
&lt;/p&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-compiler"&gt;The Compiler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-flags"&gt;The Flags&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-standard-library"&gt;The Standard Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#malloc"&gt;malloc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#strings"&gt;Strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#building-the-code"&gt;Building the Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#instantiating-the-code"&gt;Instantiating the Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#debugging"&gt;Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#profiling"&gt;Profiling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#demo"&gt;Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#copyright"&gt;Copyright&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;&lt;article&gt;

&lt;p&gt;
If you search for information on how to compile C code to webassembly, most
sources will tell you to use Emscripten. For various reasons (complication,
bloat, etc.), you probably don’t want to use Emscripten. This is partially
just for my own reference, but here is how you could compile some simple C code
to wasm and access it from the browser.
&lt;/p&gt;
&lt;p&gt;
I am assuming you want to target the browser as I don’t see the point of
targeting the wasm runtimes that exist outside of the browser &amp;mdash; just generate
native code. C is already a portable language and with some care you can target
any OS used today. It will be much faster as well.
&lt;/p&gt;
&lt;div&gt;
&lt;h2 id="the-compiler"&gt;The Compiler&lt;/h2&gt;
&lt;p&gt;
You'll need Clang. Other C compilers, such as GCC or MSVC, do not support
compiling to wasm. Note that “Apple Clang” does not support generating
webassembly. Strangely, it does support compiling to webassembly, but lacks
the ability to actually generate the bytecode &amp;mdash; it will typecheck,
semantically analyze etc. just fine and error when it would generate code.
&lt;/p&gt;
&lt;p&gt;
You can get clang from your package manager or just download from their github
releases.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="the-flags"&gt;The Flags&lt;/h2&gt;
&lt;p&gt;
You'll need to pass several flags to clang:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
# Wasm
--target=wasm32

# Don't link to libc or assume there's crt1.o.
--no-standard-libraries

# Not a hosted environment.
--ffreestanding

# Don't add normal c include paths.
-nostdinc

# If you want to provide your own libc headers.
-isystem &amp;lt;your replacement libc headers&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Also, enable the wasm extensions:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
-mbulk-memory
-mreference-types
-mmultivalue
-mmutable-globals
-mnontrapping-fptoin
-msign-ext
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Basically, you want to use the wasm extensions that your targeted browsers
will support.
&lt;/p&gt;
&lt;p&gt;
Additionally, more flags need to be passed to the wasm linker (pass them
through Clang using &lt;tt&gt;-Wl&lt;/tt&gt;):
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
# export all of our non-hidden symbols
-Wl,--export-all

# don't look for _start or _main
-Wl,--no-entry

# allow functions to be defined at runtime
-Wl,--allow-undefined
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="the-standard-library"&gt;The Standard Library&lt;/h2&gt;
&lt;p&gt;
Almost nothing from the C standard library will be available out of the box.
You'll either need to write them yourself or find suitable versions to adapt.
There are a few exceptions though: notably, &lt;tt&gt;memmove&lt;/tt&gt;, &lt;tt&gt;memcpy&lt;/tt&gt;
and &lt;tt&gt;memset&lt;/tt&gt; can be provided by the host environment as long as you
enable the bulk-memory extension for wasm (which is available basically
everywhere).
&lt;/p&gt;
&lt;p&gt;
In my opinion, it is most useful to treat webassembly like an embedded
platform &amp;mdash; don’t try to provide things like printf, file IO, etc. If you
want to pretend you’re not actually targetting wasm, just use Emscripten.
&lt;/p&gt;
&lt;p&gt;
Most of the functions you want to use from libc are not actually that hard to
implement. The tough ones are things like scanf that you don’t want to use
anyway in a reasonable C lib.
&lt;/p&gt;
&lt;p&gt;
You can also always just import functions from javascript.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="malloc"&gt;malloc&lt;/h2&gt;
&lt;p&gt;
You're going to want at least a primitive version of malloc so that javascript
can alloc memory in C land (this will come up for string conversion).
&lt;/p&gt;
&lt;p&gt;
A primitive malloc can be implemented as so:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// primitive-malloc.c&lt;/span&gt;

&lt;span class="comment"&gt;// Use clang extensions to your heart's delight, it's&lt;/span&gt;
&lt;span class="comment"&gt;// your only C compiler.&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;pragma&lt;/span&gt; clang assume_nonnull begin
&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;typeof&lt;/span&gt;(&lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="literal"&gt;1&lt;/span&gt;)) &lt;span class="type"&gt;size_t&lt;/span&gt;;
&lt;span class="keyword"&gt;enum&lt;/span&gt; {&lt;span class="anonenum" id="anonenum-size-t-size"&gt;SIZE_T_SIZE&lt;/span&gt;=&lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt;)};

&lt;span class="comment"&gt;// This will be defined by the instantiating wasm&lt;/span&gt;
&lt;span class="comment"&gt;// code.&lt;/span&gt;
&lt;span class="keyword"&gt;extern&lt;/span&gt; &lt;span class="type"&gt;unsigned&lt;/span&gt; &lt;span class="type"&gt;char&lt;/span&gt; __heap_base[];

&lt;span class="keyword"&gt;static&lt;/span&gt; &lt;span class="type"&gt;unsigned&lt;/span&gt; &lt;span class="type"&gt;char&lt;/span&gt;*_base_ptr = __heap_base;

&lt;span class="comment"&gt;// Useful function expose to javascript.&lt;/span&gt;
&lt;span class="type"&gt;void&lt;/span&gt;
&lt;span class="func" id="func-reset-memory"&gt;reset_memory&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
    _base_ptr = __heap_base;
}

&lt;span class="comment"&gt;// The workhorse function.&lt;/span&gt;
&lt;span class="comment"&gt;// Just a bump allocator.&lt;/span&gt;
&lt;span class="keyword"&gt;static&lt;/span&gt; &lt;span class="keyword"&gt;inline&lt;/span&gt;
&lt;span class="type"&gt;void&lt;/span&gt;*&lt;span class="keyword"&gt;_Nonnull&lt;/span&gt;
&lt;span class="func" id="func-alloc"&gt;alloc&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; size, &lt;span class="type"&gt;size_t&lt;/span&gt; alignment){
    &lt;span class="keyword"&gt;if&lt;/span&gt;(alignment &amp;gt; &lt;span class="anonenum"&gt;SIZE_T_SIZE&lt;/span&gt;)
        alignment = &lt;span class="anonenum"&gt;SIZE_T_SIZE&lt;/span&gt;;
    &lt;span class="type"&gt;size_t&lt;/span&gt; b = (&lt;span class="type"&gt;size_t&lt;/span&gt;)_base_ptr;
    &lt;span class="keyword"&gt;if&lt;/span&gt;(b &amp;amp; (alignment-&lt;span class="literal"&gt;1&lt;/span&gt;)){
        b += alignment - (b &amp;amp; (alignment-&lt;span class="literal"&gt;1&lt;/span&gt;));
        _base_ptr = (&lt;span class="type"&gt;unsigned&lt;/span&gt; &lt;span class="type"&gt;char&lt;/span&gt;*)b;
    }
    &lt;span class="type"&gt;void&lt;/span&gt;* result = _base_ptr;
    _base_ptr += size;
    &lt;span class="keyword"&gt;return&lt;/span&gt; result;
}

&lt;span class="type"&gt;void&lt;/span&gt;*
&lt;span class="func"&gt;malloc&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; size){
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="func"&gt;alloc&lt;/span&gt;(size, &lt;span class="literal"&gt;8&lt;/span&gt;);
}

&lt;span class="type"&gt;void&lt;/span&gt;*
&lt;span class="func"&gt;calloc&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; n_items, &lt;span class="type"&gt;size_t&lt;/span&gt; item_size){
    &lt;span class="type"&gt;void&lt;/span&gt;* result = &lt;span class="func"&gt;alloc&lt;/span&gt;(n_items*item_size, item_size);
    &lt;span class="comment"&gt;// Provided by bulk memory extension.&lt;/span&gt;
    __builtin_memset(result, &lt;span class="literal"&gt;0&lt;/span&gt;, n_items*item_size);
    &lt;span class="keyword"&gt;return&lt;/span&gt; result;
}

&lt;span class="comment"&gt;// Just don't do anything.&lt;/span&gt;
&lt;span class="comment"&gt;// You could improve this by maintaining a free list.&lt;/span&gt;
&lt;span class="type"&gt;void&lt;/span&gt;
&lt;span class="func"&gt;free&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;*&lt;span class="keyword"&gt;_Nullable&lt;/span&gt; p){
    (&lt;span class="type"&gt;void&lt;/span&gt;)p;
}
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;pragma&lt;/span&gt; clang assume_nonnull end
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="strings"&gt;Strings&lt;/h2&gt;
&lt;p&gt;
You'll probably want to pass strings back and forth between C and JavaScript.
Unfortunately, there seems to be no performant way to do this - if you do this
too much it will dominate the runtime of your code. I'll show the simplest way
to do it.
&lt;/p&gt;
&lt;p&gt;
Basically, to pass JS strings to C, you have javascript malloc a buffer and
then use the TextEncoder API to encode their utf-16 strings into utf-8 (this
is half of what is slow and I can’t figure out a fast way to just copy the
utf-16 string directly as it's not &lt;b&gt;that&lt;/b&gt; hard to write your string
processing on utf-16 (like utf-8, ascii characters are the same)).
&lt;/p&gt;
&lt;p&gt;
To pass C strings to JS, you call a function provided by your javascript code
that takes a pointer + length pair. JavaScript can then decode that memory into
a JS String using the TextDecoder API.
&lt;/p&gt;
&lt;p&gt;
Code demonstrating this:
&lt;/p&gt;
&lt;pre class="js"&gt;
&lt;span class="comment"&gt;//&lt;span class="h" id="js-stringsjs"&gt;&lt;b&gt; js-strings.js&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;mem&lt;/span&gt;;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;memview&lt;/span&gt;;
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;decoder&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;TextDecoder&lt;/span&gt;();
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;encoder&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;TextEncoder&lt;/span&gt;();
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;wasm_string_to_js&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;len&lt;/span&gt;) {
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;sub&lt;/span&gt; = &lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="function"&gt;subarray&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;p&lt;/span&gt; + &lt;span class="ident"&gt;len&lt;/span&gt;);
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt; = &lt;span class="ident"&gt;decoder&lt;/span&gt;.&lt;span class="function"&gt;decode&lt;/span&gt;(&lt;span class="ident"&gt;sub&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt;;
}
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;write4&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;val&lt;/span&gt;) {
    &lt;span class="ident"&gt;memview&lt;/span&gt;.&lt;span class="function"&gt;setInt32&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;val&lt;/span&gt;, &lt;span class="literal"&gt;true&lt;/span&gt;);
}
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;js_string_to_wasm&lt;/span&gt;(&lt;span class="ident"&gt;s&lt;/span&gt;) {
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;encoded&lt;/span&gt; = &lt;span class="ident"&gt;encoder&lt;/span&gt;.&lt;span class="function"&gt;encode&lt;/span&gt;(&lt;span class="ident"&gt;s&lt;/span&gt;);
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt; = &lt;span class="function"&gt;malloc&lt;/span&gt;(&lt;span class="ident"&gt;encoded&lt;/span&gt;.&lt;span class="ident"&gt;length&lt;/span&gt; + &lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="function"&gt;write4&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;encoded&lt;/span&gt;.&lt;span class="ident"&gt;length&lt;/span&gt;);
    &lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="function"&gt;set&lt;/span&gt;(&lt;span class="ident"&gt;encoded&lt;/span&gt;, &lt;span class="ident"&gt;p&lt;/span&gt; + &lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// js-strings.c&lt;/span&gt;

&lt;span class="comment"&gt;// I've found wrapping APIs this way is easiest&lt;/span&gt;
&lt;span class="comment"&gt;// for me.&lt;/span&gt;
&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type" id="type-prefixedstring"&gt;PrefixedString&lt;/span&gt; &lt;span class="type" id="type-prefixedstring"&gt;PrefixedString&lt;/span&gt;;
&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type"&gt;PrefixedString&lt;/span&gt; {
    &lt;span class="type"&gt;size_t&lt;/span&gt; length;
    &lt;span class="type"&gt;unsigned&lt;/span&gt; &lt;span class="type"&gt;char&lt;/span&gt; data[];
};

&lt;span class="keyword"&gt;static&lt;/span&gt;
&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="func" id="func-some-api"&gt;some_api&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; length, &lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;char&lt;/span&gt;* txt);

&lt;span class="type"&gt;void&lt;/span&gt;
&lt;span class="func" id="func-some-api-js"&gt;some_api_js&lt;/span&gt;(&lt;span class="type"&gt;PrefixedString&lt;/span&gt;* ps){
    &lt;span class="func"&gt;some_api&lt;/span&gt;(ps-&amp;gt;length, (&lt;span class="type"&gt;char&lt;/span&gt;*)ps-&amp;gt;data);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="building-the-code"&gt;Building the Code&lt;/h2&gt;
&lt;p&gt;
You'll end up with a commandline that looks like this (put in a Makefile).
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
clang mycode_wasm.c -o mycode.wasm \
--target=wasm32 --no-standard-libraries \
-Wl,--export-all -Wl,--no-entry \
-Wl,--allow-undefined -ffreestanding \
-nostdinc -isystem Wasm \
-mbulk-memory -mreference-types \
-mmultivalue -mmutable-globals \
-mnontrapping-fptoint -msign-ext \
-O3
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="instantiating-the-code"&gt;Instantiating the Code&lt;/h2&gt;
&lt;p&gt;
The MDN docs are pretty good, but for completeness, here is an example of how
to instantiate a web assembly module in JavaScript.
&lt;/p&gt;
&lt;pre class="js"&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;wasm_inst&lt;/span&gt;; &lt;span class="comment"&gt;// WebAssembly.Instance&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;mem&lt;/span&gt;; &lt;span class="comment"&gt;// Uint8Array&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;memview&lt;/span&gt;; &lt;span class="comment"&gt;// DataView&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;exports&lt;/span&gt;; &lt;span class="comment"&gt;// WebAssembly.Exports&lt;/span&gt;
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;decoder&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;TextDecoder&lt;/span&gt;();
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;encoder&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;TextEncoder&lt;/span&gt;();

&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;wasm_string_to_js&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;len&lt;/span&gt;){
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;sub&lt;/span&gt; = &lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="function"&gt;subarray&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;p&lt;/span&gt;+&lt;span class="ident"&gt;len&lt;/span&gt;);
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt; = &lt;span class="ident"&gt;decoder&lt;/span&gt;.&lt;span class="function"&gt;decode&lt;/span&gt;(&lt;span class="ident"&gt;sub&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt;;
}
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;write4&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;val&lt;/span&gt;){
    &lt;span class="ident"&gt;memview&lt;/span&gt;.&lt;span class="function"&gt;setInt32&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;val&lt;/span&gt;, &lt;span class="literal"&gt;true&lt;/span&gt;);
}
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;js_string_to_wasm&lt;/span&gt;(&lt;span class="ident"&gt;s&lt;/span&gt;){
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;encoded&lt;/span&gt; = &lt;span class="ident"&gt;encoder&lt;/span&gt;.&lt;span class="function"&gt;encode&lt;/span&gt;(&lt;span class="ident"&gt;s&lt;/span&gt;);
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt; = &lt;span class="ident"&gt;exports&lt;/span&gt;.&lt;span class="function"&gt;malloc&lt;/span&gt;(&lt;span class="ident"&gt;encoded&lt;/span&gt;.&lt;span class="ident"&gt;length&lt;/span&gt;+&lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="function"&gt;write4&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;encoded&lt;/span&gt;.&lt;span class="ident"&gt;length&lt;/span&gt;);
    &lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="function"&gt;set&lt;/span&gt;(&lt;span class="ident"&gt;encoded&lt;/span&gt;, &lt;span class="ident"&gt;p&lt;/span&gt;+&lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt;;
}
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;imports&lt;/span&gt; = {
&lt;span class="comment"&gt;    //&lt;span class="h" id="js-stringsjs-javascript-functions-youre-exposing-to-c-go-here"&gt;&lt;b&gt; JavaScript functions you’re exposing to C go here.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class="field"&gt;env&lt;/span&gt;:{
    },
};
&lt;span class="function"&gt;fetch&lt;/span&gt;(&lt;span class="string"&gt;'some_wasm_path'&lt;/span&gt;)
  .&lt;span class="function"&gt;then&lt;/span&gt;(&lt;span class="ident"&gt;response&lt;/span&gt; =&amp;gt; &lt;span class="ident"&gt;response&lt;/span&gt;.&lt;span class="function"&gt;arrayBuffer&lt;/span&gt;())
  .&lt;span class="function"&gt;then&lt;/span&gt;(&lt;span class="ident"&gt;bytes&lt;/span&gt; =&amp;gt; &lt;span class="ident"&gt;WebAssembly&lt;/span&gt;.&lt;span class="function"&gt;instantiate&lt;/span&gt;(&lt;span class="ident"&gt;bytes&lt;/span&gt;, &lt;span class="ident"&gt;imports&lt;/span&gt;))
  .&lt;span class="function"&gt;then&lt;/span&gt;(&lt;span class="ident"&gt;x&lt;/span&gt;=&amp;gt;{
      &lt;span class="ident"&gt;wasm_inst&lt;/span&gt; = &lt;span class="ident"&gt;x&lt;/span&gt;.&lt;span class="ident"&gt;instance&lt;/span&gt;;
      &lt;span class="ident"&gt;exports&lt;/span&gt; = &lt;span class="ident"&gt;wasm_inst&lt;/span&gt;.&lt;span class="ident"&gt;exports&lt;/span&gt;;
      &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt; = &lt;span class="ident"&gt;exports&lt;/span&gt;.&lt;span class="ident"&gt;memory&lt;/span&gt;;
      &lt;span class="ident"&gt;m&lt;/span&gt;.&lt;span class="function"&gt;grow&lt;/span&gt;(&lt;span class="literal"&gt;1024&lt;/span&gt;);
      &lt;span class="ident"&gt;mem&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Uint8Array&lt;/span&gt;(&lt;span class="ident"&gt;m&lt;/span&gt;.&lt;span class="ident"&gt;buffer&lt;/span&gt;);
      &lt;span class="ident"&gt;memview&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;DataView&lt;/span&gt;(&lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="ident"&gt;buffer&lt;/span&gt;);
  });
&lt;/pre&gt;
&lt;p&gt;
The above example doesn’t end up doing much, but it will instantiate the C
code and have you set up for passing strings back and forth.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="debugging"&gt;Debugging&lt;/h2&gt;
&lt;p&gt;
As far as I can tell, debugging wasm code is basically only supported by
Chrome. You can step through the bytecode in Firefox and Safari, but to
actually map the instructions to your original source code requires chrome + a
chrome extension. You’ll need this &lt;a href="https://chrome.google.com/webstore/detail/cc%20%20-devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb"&gt;extension&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
You'll need to add the &lt;tt&gt;-g&lt;/tt&gt; flag to your compiler command line. That
instructs clang to include DWARF debug info in the wasm file.
&lt;/p&gt;
&lt;p&gt;
The extension looks up the source files by absolute path. This means that if
you compile on one machine and debug on another, you’ll need to have the
same file hierarchy on both machines.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="profiling"&gt;Profiling&lt;/h2&gt;
&lt;p&gt;
Profiling in the major browsers are all more or less the same - you can see how
much time is spent at the granularity of function calls. This is somewhat
unfortunate if you are used to native profiling tools which give you timings
of each line or even drop down to the assembly level. So you won't be able to
do things like optimize control flow. Hopefully this improves in the future.
&lt;/p&gt;
&lt;p&gt;
I personally prefer the Firefox profiler UI, but they are more or less
equivalent.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="demo"&gt;Demo&lt;/h2&gt;
&lt;p&gt;
Below is a complete example of using WASM.
&lt;/p&gt;
&lt;p&gt;
This does very little, but shows all the necessary pieces.
&lt;/p&gt;
&lt;pre class="js"&gt;
&lt;span class="comment"&gt;//&lt;span class="h" id="demojs"&gt;&lt;b&gt; demo.js&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="string"&gt;"use strict"&lt;/span&gt;;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;wasm_inst&lt;/span&gt;; &lt;span class="comment"&gt;// WebAssembly.Instance&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;mem&lt;/span&gt;; &lt;span class="comment"&gt;// Uint8Array&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;memview&lt;/span&gt;; &lt;span class="comment"&gt;// DataView&lt;/span&gt;
&lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;exports&lt;/span&gt;; &lt;span class="comment"&gt;// WebAssembly.Exports&lt;/span&gt;
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;decoder&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;TextDecoder&lt;/span&gt;();
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;encoder&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;TextEncoder&lt;/span&gt;();
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;wasm_string_to_js&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;len&lt;/span&gt;){
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;sub&lt;/span&gt; = &lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="function"&gt;subarray&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;p&lt;/span&gt;+&lt;span class="ident"&gt;len&lt;/span&gt;);
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt; = &lt;span class="ident"&gt;decoder&lt;/span&gt;.&lt;span class="function"&gt;decode&lt;/span&gt;(&lt;span class="ident"&gt;sub&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt;;
}
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;write4&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;val&lt;/span&gt;){
    &lt;span class="ident"&gt;memview&lt;/span&gt;.&lt;span class="function"&gt;setInt32&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;val&lt;/span&gt;, &lt;span class="literal"&gt;true&lt;/span&gt;);
}
&lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;js_string_to_wasm&lt;/span&gt;(&lt;span class="ident"&gt;s&lt;/span&gt;){
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;encoded&lt;/span&gt; = &lt;span class="ident"&gt;encoder&lt;/span&gt;.&lt;span class="function"&gt;encode&lt;/span&gt;(&lt;span class="ident"&gt;s&lt;/span&gt;);
    &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt; = &lt;span class="ident"&gt;exports&lt;/span&gt;.&lt;span class="function"&gt;malloc&lt;/span&gt;(&lt;span class="ident"&gt;encoded&lt;/span&gt;.&lt;span class="ident"&gt;length&lt;/span&gt;+&lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="function"&gt;write4&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;encoded&lt;/span&gt;.&lt;span class="ident"&gt;length&lt;/span&gt;);
    &lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="function"&gt;set&lt;/span&gt;(&lt;span class="ident"&gt;encoded&lt;/span&gt;, &lt;span class="ident"&gt;p&lt;/span&gt;+&lt;span class="literal"&gt;4&lt;/span&gt;);
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;p&lt;/span&gt;;
}
&lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;imports&lt;/span&gt; = {
    &lt;span class="field"&gt;env&lt;/span&gt;:{
      &lt;span class="field"&gt;write&lt;/span&gt;: (&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;len&lt;/span&gt;) =&amp;gt; {
        &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;s&lt;/span&gt; = &lt;span class="function"&gt;wasm_string_to_js&lt;/span&gt;(&lt;span class="ident"&gt;p&lt;/span&gt;, &lt;span class="ident"&gt;len&lt;/span&gt;);
        &lt;span class="ident"&gt;document&lt;/span&gt;.&lt;span class="function"&gt;getElementById&lt;/span&gt;(&lt;span class="string"&gt;'scratch'&lt;/span&gt;).&lt;span class="ident"&gt;innerText&lt;/span&gt;+=&lt;span class="ident"&gt;s&lt;/span&gt;;
      },
    },
};
&lt;span class="ident"&gt;document&lt;/span&gt;.&lt;span class="function"&gt;addEventListener&lt;/span&gt;(&lt;span class="string"&gt;'DOMContentLoaded'&lt;/span&gt;, ()=&amp;gt;{
&lt;span class="comment"&gt;  //&lt;span class="h" id="demojs-prog64-is-the-base64-version-of-the-wasm-file"&gt;&lt;b&gt; prog64 is the base64 version of the wasm file.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class="let"&gt;const&lt;/span&gt; &lt;span class="ident"&gt;wasm_buffer&lt;/span&gt; = &lt;span class="type"&gt;Uint8Array&lt;/span&gt;.&lt;span class="function"&gt;from&lt;/span&gt;(
    &lt;span class="function"&gt;atob&lt;/span&gt;(&lt;span class="ident"&gt;prog64&lt;/span&gt;),
    &lt;span class="ident"&gt;c&lt;/span&gt; =&amp;gt; &lt;span class="ident"&gt;c&lt;/span&gt;.&lt;span class="function"&gt;charCodeAt&lt;/span&gt;(&lt;span class="literal"&gt;0&lt;/span&gt;)
  ).&lt;span class="ident"&gt;buffer&lt;/span&gt;;
  &lt;span class="ident"&gt;WebAssembly&lt;/span&gt;.&lt;span class="function"&gt;compile&lt;/span&gt;(&lt;span class="ident"&gt;wasm_buffer&lt;/span&gt;)
    .&lt;span class="function"&gt;then&lt;/span&gt;(&lt;span class="ident"&gt;x&lt;/span&gt; =&amp;gt; &lt;span class="ident"&gt;WebAssembly&lt;/span&gt;.&lt;span class="function"&gt;instantiate&lt;/span&gt;(&lt;span class="ident"&gt;x&lt;/span&gt;, &lt;span class="ident"&gt;imports&lt;/span&gt;))
    .&lt;span class="function"&gt;then&lt;/span&gt;(&lt;span class="ident"&gt;x&lt;/span&gt; =&amp;gt; {
      &lt;span class="ident"&gt;wasm_inst&lt;/span&gt; = &lt;span class="ident"&gt;x&lt;/span&gt;;
      &lt;span class="ident"&gt;wasm_inst&lt;/span&gt;.&lt;span class="ident"&gt;exports&lt;/span&gt;.&lt;span class="ident"&gt;memory&lt;/span&gt;.&lt;span class="function"&gt;grow&lt;/span&gt;(&lt;span class="literal"&gt;24&lt;/span&gt;);
      &lt;span class="ident"&gt;exports&lt;/span&gt; = &lt;span class="ident"&gt;wasm_inst&lt;/span&gt;.&lt;span class="ident"&gt;exports&lt;/span&gt;;
      &lt;span class="ident"&gt;mem&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;Uint8Array&lt;/span&gt;(&lt;span class="ident"&gt;exports&lt;/span&gt;.&lt;span class="ident"&gt;memory&lt;/span&gt;.&lt;span class="ident"&gt;buffer&lt;/span&gt;);
      &lt;span class="ident"&gt;memview&lt;/span&gt; = &lt;span class="keyword"&gt;new&lt;/span&gt; &lt;span class="type"&gt;DataView&lt;/span&gt;(&lt;span class="ident"&gt;mem&lt;/span&gt;.&lt;span class="ident"&gt;buffer&lt;/span&gt;);
      &lt;span class="let"&gt;let&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; = &lt;span class="literal"&gt;0&lt;/span&gt;;
      &lt;span class="ident"&gt;document&lt;/span&gt;.&lt;span class="function"&gt;getElementById&lt;/span&gt;(&lt;span class="string"&gt;'click-me'&lt;/span&gt;).&lt;span class="ident"&gt;onclick&lt;/span&gt;=()=&amp;gt;{
        &lt;span class="ident"&gt;exports&lt;/span&gt;.&lt;span class="function"&gt;clicked&lt;/span&gt;(&lt;span class="ident"&gt;i&lt;/span&gt;++);
      };
    });
});
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="comment"&gt;// example.c&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;"primitive_malloc.c"&lt;/span&gt;

&lt;span class="keyword"&gt;extern&lt;/span&gt; &lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="func" id="func-write"&gt;write&lt;/span&gt;(&lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;char&lt;/span&gt;*, &lt;span class="type"&gt;size_t&lt;/span&gt;);

&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="func" id="func-clicked"&gt;clicked&lt;/span&gt;(&lt;span class="type"&gt;int&lt;/span&gt; i){
    &lt;span class="type"&gt;char&lt;/span&gt; c[&lt;span class="literal"&gt;2&lt;/span&gt;] = {(i &amp;amp;&lt;span class="literal"&gt;0xf&lt;/span&gt;)+ &lt;span class="literal"&gt;'a'&lt;/span&gt;, &lt;span class="literal"&gt;'\n'&lt;/span&gt;};
    &lt;span class="func"&gt;write&lt;/span&gt;(c, &lt;span class="keyword"&gt;sizeof&lt;/span&gt; c);
}
&lt;/pre&gt;
&lt;button id=click-me&gt;Click Me&lt;/button&gt;
&lt;pre id=scratch&gt;
&lt;/pre&gt;

&lt;/div&gt;
&lt;/article&gt;
&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Sat, 21 Jan 2023 03:08:21 GMT</pubDate><link>https://www.davidpriver.com/c-in-wasm.html</link><author>david@davidpriver.com</author></item><item><title>c-hash-table</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;Hashtable in C&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;h1 id="hashtable-in-c"&gt;Hashtable in C&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, Jan 3rd, 2024&lt;/i&gt;
&lt;/p&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#basic-reqirements"&gt;Basic Reqirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#design-decisions"&gt;Design Decisions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#data-layout"&gt;Data Layout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#implementation"&gt;Implementation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#deletion"&gt;Deletion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#alterations"&gt;Alterations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#copyright"&gt;Copyright&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;&lt;article&gt;

&lt;p&gt;
There's many times when the problem you are solving needs something like a map
of keys to values with O(1) insertion and retrieval. C doesn't come with one
already ready-for-use like more "modern" languages like Python, so you gotta
roll up your sleeves and do it yourself.
&lt;/p&gt;
&lt;p&gt;
However, if you search around for "how
to implement a hash table in C", you'll often find material that hashes to a
fixed number of buckets and then has a linked list of items. This is slower than
it needs to be and introduces complicated memory management that would be better
avoided.
&lt;/p&gt;
&lt;p&gt;
So we'll implement our own instead. As a bonus, we'll add some extra properties
like easy C-style iteration, ordered insertion and realloc-friendly memory
usage.
&lt;/p&gt;
&lt;p&gt;
You could easily "&lt;a href="ctemplates.html"&gt;templatize&lt;/a&gt;" this code.
&lt;/p&gt;
&lt;div&gt;
&lt;h2 id="basic-reqirements"&gt;Basic Reqirements&lt;/h2&gt;
&lt;p&gt;
Your key type needs two basic properties:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Equatible (can compare two keys for equality).
&lt;/li&gt;
&lt;li&gt;
Hashability (can map the key to a well-distributed number).
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Your value type can be whatever.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="design-decisions"&gt;Design Decisions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
Limit the number of items in the hashtable to pow(2, 31). This let's us use
 32 bit indexes which saves some memory.
&lt;/li&gt;
&lt;li&gt;
Single memory allocation.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="data-layout"&gt;Data Layout&lt;/h2&gt;
&lt;p&gt;
You'll (re-)allocate a block of memory such that it is laid out as follows:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
|       Items          |        Indexes        |
+---------+------------+-----------------------+
|Occupied | Unoccupied | Indexes into occupied |
+---------+------------+-----------------------+

|- count -|            |----- 2*capacity ------|
|----- capacity -------|

&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
When an item is inserted, the key is hashed and used to start the search in
the Indexes array. If it finds a valid index, it uses it to index into the
Items array and compare the key there. If it's a match, then return the
pointer to the value half of that item. Otherwise, keep going. If an invalid
index is found, that means the key is not in the table already. Insert the key
after the end of the occupied portion of the items array and increment count.
Store this new index into the Indexes array where you found the invalid index.
&lt;/p&gt;
&lt;p&gt;
When the items array is filled, realloc the memory block (the enlarged Items
array will now overlap with what was once the Indexes array). Invalidate all
indexes in the new Indexes array and regenerate it from the Items array.
&lt;/p&gt;
&lt;p&gt;
In this design, there is just a single allocation, which makes de-allocating
the table easier. Additionally, it is re-alloc friendly and if you can
re-alloc in place, then no copying of the Items needs to be done, which can be
a valuable property if you are allocating from a linear allocator.
&lt;/p&gt;
&lt;p&gt;
Another property is that the table remembers the order in which keys were
inserted, which can be a useful property and makes debugging easier.
&lt;/p&gt;
&lt;p&gt;
Finally, you don't need to remember the special way of how to iterate over
this table or have some iterator macros or construct. You iterate it like you
would an array:
&lt;/p&gt;
&lt;pre&gt;
&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="func" id="func-foo"&gt;foo&lt;/span&gt;(&lt;span class="type"&gt;void&lt;/span&gt;){
  &lt;span class="keyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; i = &lt;span class="literal"&gt;0&lt;/span&gt;; i &amp;lt; table.count; i++){
    &lt;span class="type"&gt;Pair&lt;/span&gt;* p = &amp;amp;table.data[i];
    &lt;span class="comment"&gt;// do whatever with p&lt;/span&gt;
  }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="implementation"&gt;Implementation&lt;/h2&gt;
&lt;pre&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class="preproc"&gt;#&lt;/span&gt;&lt;span class="preproc"&gt;include&lt;/span&gt; &lt;span class="literal"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span class="comment"&gt;// Define these as makes sense.&lt;/span&gt;
&lt;span class="type"&gt;uint32_t&lt;/span&gt; &lt;span class="func" id="func-hash-key"&gt;hash_key&lt;/span&gt;(&lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;KeyType&lt;/span&gt;* key);
&lt;span class="type"&gt;_Bool&lt;/span&gt; &lt;span class="func" id="func-key-eq"&gt;key_eq&lt;/span&gt;(&lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;KeyType&lt;/span&gt;* a, &lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;KeyType&lt;/span&gt;* b);

&lt;span class="comment"&gt;// You'll probably name these something else in your&lt;/span&gt;
&lt;span class="comment"&gt;// implementation to avoid collisions.&lt;/span&gt;
&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type" id="type-pair"&gt;Pair&lt;/span&gt; &lt;span class="type" id="type-pair"&gt;Pair&lt;/span&gt;;
&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type"&gt;Pair&lt;/span&gt; {
  &lt;span class="type"&gt;KeyType&lt;/span&gt; key;
  &lt;span class="type"&gt;ValueType&lt;/span&gt; value;
};

&lt;span class="keyword"&gt;typedef&lt;/span&gt; &lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type" id="type-table"&gt;Table&lt;/span&gt; &lt;span class="type" id="type-table"&gt;Table&lt;/span&gt;;
&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="type"&gt;Table&lt;/span&gt; {
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; count, capacity;
  &lt;span class="type"&gt;Pair&lt;/span&gt;* data;
};

&lt;span class="keyword"&gt;enum&lt;/span&gt; {&lt;span class="enum" id="enum-table-empty-slot"&gt;TABLE_EMPTY_SLOT&lt;/span&gt;=UINT32_MAX};

&lt;span class="comment"&gt;// Grows the table to the new size.&lt;/span&gt;
&lt;span class="comment"&gt;// Returns 0 on success and non-zero on failure (usually&lt;/span&gt;
&lt;span class="comment"&gt;// allocation failure).&lt;/span&gt;
&lt;span class="type"&gt;int&lt;/span&gt;
&lt;span class="func" id="func-grow-table"&gt;grow_table&lt;/span&gt;(&lt;span class="type"&gt;Table&lt;/span&gt;* table, &lt;span class="type"&gt;size_t&lt;/span&gt; new_size);

&lt;span class="comment"&gt;// If key is already in the table, returns the pointer to&lt;/span&gt;
&lt;span class="comment"&gt;// the corresponding value.&lt;/span&gt;
&lt;span class="comment"&gt;// Otherwise, inserts the key into the table and returns a&lt;/span&gt;
&lt;span class="comment"&gt;// pointer to the uninitialized value.&lt;/span&gt;
&lt;span class="comment"&gt;// Returns NULL if the table needed to grow and that&lt;/span&gt;
&lt;span class="comment"&gt;// failed.&lt;/span&gt;
&lt;span class="type"&gt;ValueType&lt;/span&gt;*
&lt;span class="func" id="func-table-getsert"&gt;table_getsert&lt;/span&gt;(&lt;span class="type"&gt;Table&lt;/span&gt;* table, &lt;span class="type"&gt;KeyType&lt;/span&gt;* key);

&lt;span class="comment"&gt;// If key is in the table, returns the pointer to the&lt;/span&gt;
&lt;span class="comment"&gt;// corresponding value.&lt;/span&gt;
&lt;span class="comment"&gt;// Otherwise returns NULL.&lt;/span&gt;
&lt;span class="type"&gt;ValueType&lt;/span&gt;*
&lt;span class="func" id="func-table-has"&gt;table_has&lt;/span&gt;(&lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;Table&lt;/span&gt;* table, &lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;KeyType&lt;/span&gt;* key);

&lt;span class="comment"&gt;// This is faster than modulo while preserving the same&lt;/span&gt;
&lt;span class="comment"&gt;// properties if all the bits are equally well distributed.&lt;/span&gt;
&lt;span class="comment"&gt;// Do *not* use identity hash with this.&lt;/span&gt;
&lt;span class="type"&gt;uint32_t&lt;/span&gt;
&lt;span class="func" id="func-fast-reduce32"&gt;fast_reduce32&lt;/span&gt;(&lt;span class="type"&gt;uint32_t&lt;/span&gt; x, &lt;span class="type"&gt;uint32_t&lt;/span&gt; y){
  &lt;span class="keyword"&gt;return&lt;/span&gt; ((&lt;span class="type"&gt;uint64_t&lt;/span&gt;)x * (&lt;span class="type"&gt;uint64_t&lt;/span&gt;)y) &amp;gt;&amp;gt; &lt;span class="literal"&gt;32&lt;/span&gt;;
}

&lt;span class="type"&gt;int&lt;/span&gt;
&lt;span class="func"&gt;grow_table&lt;/span&gt;(&lt;span class="type"&gt;Table&lt;/span&gt;* table, &lt;span class="type"&gt;size_t&lt;/span&gt; new_cap){
  &lt;span class="type"&gt;size_t&lt;/span&gt; cap = table-&amp;gt;capacity;
  &lt;span class="keyword"&gt;if&lt;/span&gt;(new_cap &amp;lt;= cap) &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
  &lt;span class="keyword"&gt;if&lt;/span&gt;(new_cap &amp;gt; UINT32_MAX/&lt;span class="literal"&gt;2&lt;/span&gt;) &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;1&lt;/span&gt;;

  &lt;span class="comment"&gt;// On a 32 bit system, you'll want to check&lt;/span&gt;
  &lt;span class="comment"&gt;// for overflow here.&lt;/span&gt;
  &lt;span class="type"&gt;size_t&lt;/span&gt; new_size = new_cap*(&lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;Pair&lt;/span&gt;)
                    +&lt;span class="literal"&gt;2&lt;/span&gt;*&lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;uint32_t&lt;/span&gt;));
  &lt;span class="type"&gt;char&lt;/span&gt;* new_data = &lt;span class="func"&gt;realloc&lt;/span&gt;(table-&amp;gt;data, new_size);
  &lt;span class="keyword"&gt;if&lt;/span&gt;(!new_data) &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;1&lt;/span&gt;;
  table-&amp;gt;data = (&lt;span class="type"&gt;Pair&lt;/span&gt;*)new_data;
  table-&amp;gt;capacity = (&lt;span class="type"&gt;uint32_t&lt;/span&gt;)new_cap;

  &lt;span class="type"&gt;size_t&lt;/span&gt; offset = new_cap * &lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;Pair&lt;/span&gt;);
  &lt;span class="type"&gt;uint32_t&lt;/span&gt;* indexes = (&lt;span class="type"&gt;uint32_t&lt;/span&gt;*)(new_data+offset);
  &lt;span class="type"&gt;size_t&lt;/span&gt; idx_cap = &lt;span class="literal"&gt;2&lt;/span&gt;*new_cap;
  &lt;span class="func"&gt;memset&lt;/span&gt;(indexes, &lt;span class="literal"&gt;0xff&lt;/span&gt;, idx_cap * &lt;span class="keyword"&gt;sizeof&lt;/span&gt; *indexes);

  &lt;span class="type"&gt;Pair&lt;/span&gt;* items = (&lt;span class="type"&gt;Pair&lt;/span&gt;*)new_data;
  &lt;span class="keyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;size_t&lt;/span&gt; i = &lt;span class="literal"&gt;0&lt;/span&gt;; i &amp;lt; table-&amp;gt;count; i++){
    &lt;span class="type"&gt;Pair&lt;/span&gt;* p = &amp;amp;items[i];
    &lt;span class="type"&gt;uint32_t&lt;/span&gt; hash = &lt;span class="func"&gt;hash_key&lt;/span&gt;(&amp;amp;p-&amp;gt;key);
    &lt;span class="type"&gt;uint32_t&lt;/span&gt; idx = &lt;span class="func"&gt;fast_reduce32&lt;/span&gt;(hash, (&lt;span class="type"&gt;uint32_t&lt;/span&gt;)idx_cap);
    &lt;span class="keyword"&gt;while&lt;/span&gt;(indexes[idx] != &lt;span class="enum"&gt;TABLE_EMPTY_SLOT&lt;/span&gt;){
      idx++;
      &lt;span class="keyword"&gt;if&lt;/span&gt;(idx == idx_cap) idx = &lt;span class="literal"&gt;0&lt;/span&gt;;
    }
    indexes[idx] = i;
  }
  &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;0&lt;/span&gt;;
}

&lt;span class="type"&gt;ValueType&lt;/span&gt;*
&lt;span class="func"&gt;table_getsert&lt;/span&gt;(&lt;span class="type"&gt;Table&lt;/span&gt;* table, &lt;span class="type"&gt;KeyType&lt;/span&gt;* key){
  &lt;span class="keyword"&gt;if&lt;/span&gt;(table-&amp;gt;count == table-&amp;gt;capacity){
    &lt;span class="type"&gt;size_t&lt;/span&gt; new_cap;
    &lt;span class="keyword"&gt;if&lt;/span&gt;(table-&amp;gt;capacity)
        new_cap = &lt;span class="literal"&gt;2&lt;/span&gt;*table-&amp;gt;capacity;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
        new_cap = &lt;span class="literal"&gt;32&lt;/span&gt;;
    &lt;span class="type"&gt;int&lt;/span&gt; err = &lt;span class="func"&gt;grow_table&lt;/span&gt;(table, new_cap);
    &lt;span class="keyword"&gt;if&lt;/span&gt;(err) &lt;span class="keyword"&gt;return&lt;/span&gt; NULL;
  }
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; cap = table-&amp;gt;capacity;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; idx_cap = cap * &lt;span class="literal"&gt;2&lt;/span&gt;;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; hash = &lt;span class="func"&gt;hash_key&lt;/span&gt;(key);
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; idx = &lt;span class="func"&gt;fast_reduce32&lt;/span&gt;(hash, idx_cap);

  &lt;span class="type"&gt;size_t&lt;/span&gt; offset = cap * &lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;Pair&lt;/span&gt;);
  &lt;span class="type"&gt;char&lt;/span&gt;* data = (&lt;span class="type"&gt;char&lt;/span&gt;*)table-&amp;gt;data;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt;* indexes = (&lt;span class="type"&gt;uint32_t&lt;/span&gt;*)(data + offset);
  &lt;span class="type"&gt;Pair&lt;/span&gt;* items = table-&amp;gt;data;
  &lt;span class="keyword"&gt;for&lt;/span&gt;(;;){
    &lt;span class="type"&gt;uint32_t&lt;/span&gt; i = indexes[idx];
    &lt;span class="keyword"&gt;if&lt;/span&gt;(i == &lt;span class="enum"&gt;TABLE_EMPTY_SLOT&lt;/span&gt;){
      indexes[idx] = table-&amp;gt;count;
      items[table-&amp;gt;count].key = *key;
      &lt;span class="keyword"&gt;return&lt;/span&gt; &amp;amp;items[table-&amp;gt;count++].value;
    }

    &lt;span class="type"&gt;Pair&lt;/span&gt;* p = &amp;amp;items[i];
    &lt;span class="keyword"&gt;if&lt;/span&gt;(&lt;span class="func"&gt;key_eq&lt;/span&gt;(&amp;amp;p-&amp;gt;key, key))
      &lt;span class="keyword"&gt;return&lt;/span&gt; &amp;amp;p-&amp;gt;value;

    idx++;
    &lt;span class="keyword"&gt;if&lt;/span&gt;(idx == idx_cap) idx = &lt;span class="literal"&gt;0&lt;/span&gt;;
  }
}

&lt;span class="type"&gt;ValueType&lt;/span&gt;*
&lt;span class="func"&gt;table_has&lt;/span&gt;(&lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;Table&lt;/span&gt;* table, &lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;KeyType&lt;/span&gt;* key){
  &lt;span class="keyword"&gt;if&lt;/span&gt;(!table-&amp;gt;count) &lt;span class="keyword"&gt;return&lt;/span&gt; NULL; &lt;span class="comment"&gt;// empty table&lt;/span&gt;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; cap = table-&amp;gt;capacity;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; idx_cap = cap * &lt;span class="literal"&gt;2&lt;/span&gt;;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; hash = &lt;span class="func"&gt;hash_key&lt;/span&gt;(key);
  &lt;span class="type"&gt;uint32_t&lt;/span&gt; idx = &lt;span class="func"&gt;fast_reduce32&lt;/span&gt;(hash, idx_cap);

  &lt;span class="type"&gt;size_t&lt;/span&gt; offset = cap * &lt;span class="keyword"&gt;sizeof&lt;/span&gt;(&lt;span class="type"&gt;Pair&lt;/span&gt;);
  &lt;span class="type"&gt;char&lt;/span&gt;* data = (&lt;span class="type"&gt;char&lt;/span&gt;*)table-&amp;gt;data;
  &lt;span class="type"&gt;uint32_t&lt;/span&gt;* indexes = (&lt;span class="type"&gt;uint32_t&lt;/span&gt;*)(data + offset);
  &lt;span class="type"&gt;Pair&lt;/span&gt;* items = table-&amp;gt;data;
  &lt;span class="keyword"&gt;for&lt;/span&gt;(;;){
    &lt;span class="type"&gt;uint32_t&lt;/span&gt; i = indexes[idx];
    &lt;span class="keyword"&gt;if&lt;/span&gt;(i == &lt;span class="enum"&gt;TABLE_EMPTY_SLOT&lt;/span&gt;)
      &lt;span class="keyword"&gt;return&lt;/span&gt; NULL;

    &lt;span class="type"&gt;Pair&lt;/span&gt;* p = &amp;amp;items[i];
    &lt;span class="keyword"&gt;if&lt;/span&gt;(&lt;span class="func"&gt;key_eq&lt;/span&gt;(&amp;amp;p-&amp;gt;key, key))
      &lt;span class="keyword"&gt;return&lt;/span&gt; &amp;amp;p-&amp;gt;value;

    idx++;
    &lt;span class="keyword"&gt;if&lt;/span&gt;(idx == idx_cap) idx = &lt;span class="literal"&gt;0&lt;/span&gt;;
  }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="deletion"&gt;Deletion&lt;/h2&gt;
&lt;p&gt;
I didn't show to handle deleting items. Funnily enough I haven't found much
need to delete things, but you have a few options.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Somehow mark the pair as deleted (using a sentinel for the value part or a
 book-keeping bitmask or whatever) and adjust the table growing code to shift
 non-deleted items down. This makes iteration more complicated and growing
 slower. This retains O(1) deletion.
&lt;/li&gt;
&lt;li&gt;
Eagerly shift the non-deleted items into place and fixup the indexes. This
 makes deletion O(n).
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
There's probably other options as well, but you can tune
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="alterations"&gt;Alterations&lt;/h2&gt;
&lt;p&gt;
There's some ways you could change the above design.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
If hashing is expensive, and you want to avoid the re-hashing on grow, you
 can store the hash in the Pairs.
&lt;/li&gt;
&lt;li&gt;
You could use 3 different allocations for the keys/values/indexes. There's
 not really much point to doing this.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
It's certainly inconvenient to need to implement your own basic data
structures in C, but in doing so you develop the skill to tailor them to your
specific problem. And as shown above, you can get a functional hashtable in
not very much code at all.
&lt;/p&gt;
&lt;/div&gt;
&lt;/article&gt;
&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Thu, 04 Jan 2024 04:53:59 GMT</pubDate><link>https://www.davidpriver.com/c-hash-table.html</link><author>david@davidpriver.com</author></item><item><title>C-macro-reflection-in-D</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;C-macro-reflection-in-D&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;h1 id="c-macro-reflection-in-d"&gt;C-macro-reflection-in-D&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, July 30th, 2024&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
I was reading Hacker News when I saw &lt;a href="https://jstrieb.github.io/posts/c-reflection-zig/"&gt;the link to this article&lt;/a&gt;.
I've been playing around with D lately and thought to myself "I bet D could do this as well". D added the ability to &lt;a href="https://dlang.org/spec/importc.html"&gt;import C files&lt;/a&gt; (with &lt;a href="https://dlang.org/spec/importc.html#defines"&gt;macros&lt;/a&gt;) and has strong &lt;a href="https://dlang.org/spec/traits.html#allMembers"&gt;reflection&lt;/a&gt; capabilities as well.
&lt;/p&gt;
&lt;p&gt;
So here is my attempt at that:
&lt;/p&gt;
&lt;p&gt;
With a C file with macros:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
// macros.c
// #include &amp;lt;Windows.h&amp;gt;
// just #define the macros here for simplicity
#define WM_A 0x1
#define WM_B 0x2
#define WM_C 0x3
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
And a D file to import the C file:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
// imports the C file "macros.c"
import macros;
import std.stdio: writeln;
void print_macro(int num){
    switch(num){
        // compile time foreach so we can generate cases
        static foreach(m; __traits(allMembers, macros)){
            static if(m.length &amp;gt; 3 &amp;amp;&amp;amp; m[0..3] == "WM_"){
                case __traits(getMember, macros, m):
                    writeln(m, ": ", num);
                    return;
            }
        }
        default:
            writeln("unknown macro: ", num);
            return;
    }
}

void main(){
    print_macro(0x1);
    print_macro(0x2);
    print_macro(0x3);
    print_macro(0x4);
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Compile and run it:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
$ ldc2 mac.d -of mac
$ ./mac
WM_A: 1
WM_B: 2
WM_C: 3
unknown macro: 4
&lt;/pre&gt;
&lt;/div&gt;
&lt;article&gt;


&lt;/article&gt;
&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Tue, 30 Jul 2024 20:43:23 GMT</pubDate><link>https://www.davidpriver.com/C-macro-reflection-in-D.html</link><author>david@davidpriver.com</author></item><item><title>VIM Macros are Overrated</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
&lt;title&gt;VIM Macros are Overrated&lt;/title&gt;
&lt;style&gt;
:root {
  color-scheme: light dark;
}
* {
  box-sizing: border-box;
}
body {
  max-width: 68ch;
  margin: auto;
  margin-bottom: 40em;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  padding: 12px;
  background-color: #fff;
  color: #000;
}
a {
  color: rgb(0, 0, 238);
}
@media (prefers-color-scheme: dark) {
  body {
    background-color: #333;
    color: #fff;
  }
  a:visited {
    color: #88f;
  }
  a {
    color: #88f;
  }
}
dt {
  font-weight: bold;
}
pre {
  padding-left: 2em;
  padding-right: 1em;
  padding-top: 1ex;
  padding-bottom: 1ex;
  background-color: #fdf6e3;
  border-radius: 16px;
  font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
  font-size: 1rem;
  overflow-x: auto;
  line-height: 125%;
}
tt {
  background-color: #eee;
  padding: 2px;
}
@media (prefers-color-scheme: dark) {
  pre {
    background-color: #222;
  }
  tt {
    background-color: #222;
  }
}
pre .enum {
  font-weight: bold;
}
pre .keyword {
  color: #049407;
}
@media (prefers-color-scheme: dark) {
  pre .keyword {
    color: #24c427;
  }
}
pre .comment {
  color: #000;
  font-style: italic;
}

@media (prefers-color-scheme: dark) {
  pre .comment {
    color: #fff;
  }
}
pre .literal {
  color: #2aa198;
}
pre .type {
  color: #de6e00;
}
pre .macro {
  color: #66a;
}
pre .func, pre .function {
  color: #213dde;
}
@media (prefers-color-scheme: dark) {
  pre .func, pre .function {
    color: #519dde;
  }
}
pre .string {
  color: #2aa198;
}
pre .preproc {
  color: #777;
}
.quoted {
  margin-left: 2em;
  border-left: 2px solid grey;
  padding-left: 8px;
}
pre .h {
  font-weight: bold;
}
pre .param {
  color: #6a6;
}
.python .control {
  color: rgb(200, 100, 0);
}
.python .comment {
  color: grey;
}
.python .None {
  color: purple;
}
.python .string {
  color: rgb(220, 0, 0);
}
.python .number {
  color: teal;
}
.python .import {
  color: purple;
}
/*endcss*/
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
&lt;a href="https://www.davidpriver.com"&gt;Home&lt;/a&gt;
&lt;/p&gt;
&lt;h1 id="vim-macros-are-overrated"&gt;VIM Macros are Overrated&lt;/h1&gt;
&lt;p&gt;
&lt;i&gt;&lt;a href="mailto:david@davidpriver.com"&gt;David Priver&lt;/a&gt;, Nov 29th, 2024&lt;/i&gt;
&lt;/p&gt;
&lt;article&gt;

&lt;div&gt;
&lt;h2 id="macros"&gt;Macros&lt;/h2&gt;
&lt;p&gt;
I'm a big VIM user and enjoy working in it, both professionally and
recreationally. One of vim's nice features is the ability to record macros into
a register and then replay it. As the macros can include motion, you can set
them up so that they can be easily repeated and use a count modifier, like
&lt;tt&gt;22@w&lt;/tt&gt; to apply them multiple times. Do &lt;tt&gt;:h complex-repeat&lt;/tt&gt; to
learn more.
&lt;/p&gt;
&lt;p&gt;
However, there are some drawbacks to VIM macros. If you have a long or
complicated sequence of actions, it can be error prone to record the exact
macro needed to do what you want. They are stored in normal registers, so you
can paste them into a buffer, edit them and then yank them back into a
register, but that is pretty annoying and they quickly get unreadable.
&lt;/p&gt;
&lt;p&gt;
Another common pitfall is you realize after executing the macro that you need
some small thing changed or some additional transform. You then have to either
edit the macro or record a new one from scratch. Do this a few times and you'll
find you spent more time trying to record the perfect macro than just doing the
text operation. And good luck debugging it if your macro isn't quite right.
&lt;/p&gt;
&lt;p&gt;
If only we could write the text transforms as code. Wait a minute...
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="filters"&gt;Filters&lt;/h2&gt;
&lt;p&gt;
Vim also has the feature that you can shell out to arbitrary programs,
writing to their stdin and reading from their stdout. You can feed them an
entire buffer or a selection of a buffer. The input lines are then replaced
with whatever the program wrote to stdout. Vim refers to these as "filters"
and invoke them with filter commands. Do &lt;tt&gt;:h filter&lt;/tt&gt; to learn more.
&lt;/p&gt;
&lt;p&gt;
In my experience, a better alternative to recording a complicated macro is to
just write a simple python script as the filter program.
As we are just writing normal code, this means it can be
arbitrarily complicated and you could even do syntactic/semantic analysis for
your custom text transforms. Additionally, it's just normal code instead of
weird editor commands so you can easily test and debug the transform if it's
getting hairy, write functions, break it up into multiple statements, etc.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="an-example"&gt;An Example&lt;/h2&gt;
&lt;p&gt;
Recently I was working with some C code where I needed to generate an X-macro
from a list of names. Example input would look like:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
Potion of Healing
Wand of Fireball
Magic Sword
...  etc ...

&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
I would like this to be converted to an X-macro, defining various forms of the names:
&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;
// #define X(UPPER, Title, snake, string)
#define XNames(X) \
  X(POTION_OF_HEALING, Potion_of_Healing, potion_of_healing, "Potion of Healing") \
  X(WAND_OF_FIREBALL, Wand_of_Fireball, wand_of_fireball, "Wand of Fireball") \
  X(MAGIC_SWORD, Magic_Sword, magic_sword, "Magic Sword") \
  ... etc ...

&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
You can do this with vim commands and macros, but it is not easy. But behold, the simple
python script that does this conversion:
&lt;/p&gt;
&lt;pre class="python"&gt;
&lt;span class="import"&gt;import&lt;/span&gt; sys
&lt;span class="control"&gt;for&lt;/span&gt; line &lt;span class="keyword"&gt;in&lt;/span&gt; sys.stdin:
    l = line.strip()
    s = l.replace(&lt;span class="string"&gt;' '&lt;/span&gt;, &lt;span class="string"&gt;'_'&lt;/span&gt;)
    print(f&lt;span class="string"&gt;'    X({s.upper()}, {s}, {s.lower()}, "{l}") \\'&lt;/span&gt;)

&lt;/pre&gt;
&lt;p&gt;
Simple, easy to understand code. You can debug it, you can throw examples at
it, whatever. I usually name these little scripts f.py in my working directly
and invoke them with &lt;tt&gt;:'&amp;lt;,'&amp;gt;!python3 f.py&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
That's it! When you find yourself trying to setup a complicated macro, stop
and think if it would be easier to express it as a little script that
processes stdin instead. Most of the time, the answer is yes.
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 id="copyright"&gt;Copyright&lt;/h2&gt;
&lt;p&gt;
All code in this article is released into the public domain.
&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description><pubDate>Sat, 30 Nov 2024 05:45:25 GMT</pubDate><link>https://www.davidpriver.com/vim-macros-overrated.html</link><author>david@davidpriver.com</author></item></channel>
</rss>