{
	"version": "https://jsonfeed.org/version/1.1",
	"title": "blog",
	"expired": false,
	"items": [
		{
			"id": "gen/translating-long-double-to-rust.html",
			"url": "gen/translating-long-double-to-rust.html",
			"title": "Translating Long Double to Rust",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Translating Long Double to Rust</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Translating Long Double to Rust</h1>\n<p class=\"byline\">2026-08-12T12:04:52-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#representing-f80\" id=\"toc-representing-f80\">Representing\nf80</a></li>\n</ul>\n</nav>\n<p>I\u2019ve been working on Slate, a C to Rust translator. There are a few\nparticularly thorny parts of translating C to Rust, but given how much\n<code>long double</code> made me suffer, I\u2019ve decided to write it\nup.</p>\n<p>If you\u2019ve never used <code>long double</code>, you may breathe a sigh\nof relief. If you use either <code>f64</code> (<code>double</code>) or\n<code>f128</code>s (<code>_Float128/__float128</code>) then you\u2019re\nabsolved of sin and free to go. The heathens who wish to learn suffering\nmay stay till the rest of the post to learn more.</p>\n<p><code>long double</code> has been around since C89. The standard just\nsays that it must be as precise as <code>double</code>\n(<code>f64</code>). Because of this, long double can be pretty much any\nbit-size from 64-bits to infinite bits. In practice, there are a few\ndominant ones:</p>\n<ol type=\"1\">\n<li>f64. MSVC does this for x86.</li>\n<li>f80. GCC + Clang do this for x86. This is padded to 12-bytes or\n16-bytes.</li>\n<li>double-double. Two f64s glued together. For older PowerPC and IBM\narchitectures.</li>\n<li>f128. Arm64, PowerPC, RISC-V.</li>\n</ol>\n<p><code>f64</code> and <code>f128</code> are not hard to support. On a\ntarget where <code>long double</code> ==\n<code>f64</code>/<code>f128</code>, you would just swap out every long\ndouble you see for the appropriate type in rust, and when you pass it to\nextern C code, it\u2019ll be bit aligned and properly handled.</p>\n<p><code>f80</code> is the real problem, and what the rest of the blog\nwill explain. Afaik, <a\nhref=\"https://github.com/immunant/c2rust/issues/1723\">C2Rust doesn\u2019t\nsupport <code>long double</code> properly because it translates to\nf128</a>. There have been efforts in the past to add <code>f80</code>\nsupport, but this\u2019ll probably take a while.</p>\n<section id=\"representing-f80\" class=\"level2\">\n<h2>Representing f80</h2>\n<p>With long double, we need to be able to do anything you would\nnormally be able to do with the type in C. That means the arithmetic\nops, casting to and from, passing to functions as value or pointer, and\nbeing able to use it in callbacks.</p>\n<p>A first try is this:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>repr<span class=\"at\">(</span>C<span class=\"op\">,</span> align<span class=\"at\">(</span><span class=\"dv\">16</span><span class=\"at\">))]</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> LongDouble <span class=\"op\">{</span> bytes<span class=\"op\">:</span> [<span class=\"dt\">u8</span><span class=\"op\">;</span> <span class=\"dv\">10</span>] <span class=\"op\">};</span></span></code></pre></div>\n<p>With this we fulfill the requirements of its size and alignment. We\ncould then even emulate the f80 math itself in rust, so when you call\nany long double function that has been translated to rust, and call a\nnon-translated C function, the bits are all perfectly legal.</p>\n<p>Sadly, long doubles are passed in floating point registers, whereas\nthese chars would not be, so this won\u2019t work.</p>\n<p>If we need to change the registers passed in, we would have to\nimplement it ourselves and use the backing type as storage.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">unsafe</span> <span class=\"kw\">fn</span> add(<span class=\"kw\">self</span><span class=\"op\">,</span> rhs<span class=\"op\">:</span> <span class=\"dt\">Self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Self</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> out <span class=\"op\">=</span> LongDouble <span class=\"op\">{</span> bytes<span class=\"op\">:</span> [<span class=\"dv\">0</span><span class=\"op\">;</span> <span class=\"dv\">10</span>] <span class=\"op\">};</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"pp\">core::arch::asm!</span>(</span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"st\">&quot;fld tbyte ptr [{a}]&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"st\">&quot;fld tbyte ptr [{b}]&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"st\">&quot;faddp st(1), st(0)&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"st\">&quot;fstp tbyte ptr [{out}]&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            a   <span class=\"op\">=</span> <span class=\"kw\">in</span>(reg) <span class=\"kw\">self</span><span class=\"op\">.</span>bytes<span class=\"op\">.</span>as_ptr()<span class=\"op\">,</span></span>\n<span id=\"cb2-12\"><a href=\"#cb2-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>            b   <span class=\"op\">=</span> <span class=\"kw\">in</span>(reg) rhs<span class=\"op\">.</span>bytes<span class=\"op\">.</span>as_ptr()<span class=\"op\">,</span></span>\n<span id=\"cb2-13\"><a href=\"#cb2-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out <span class=\"op\">=</span> <span class=\"kw\">in</span>(reg) out<span class=\"op\">.</span>bytes<span class=\"op\">.</span>as_mut_ptr()<span class=\"op\">,</span></span>\n<span id=\"cb2-14\"><a href=\"#cb2-14\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-15\"><a href=\"#cb2-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(0)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-16\"><a href=\"#cb2-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(1)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-17\"><a href=\"#cb2-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(2)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-18\"><a href=\"#cb2-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(3)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-19\"><a href=\"#cb2-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(4)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-20\"><a href=\"#cb2-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(5)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-21\"><a href=\"#cb2-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(6)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-22\"><a href=\"#cb2-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>            out(<span class=\"st\">&quot;st(7)&quot;</span>) _<span class=\"op\">,</span></span>\n<span id=\"cb2-23\"><a href=\"#cb2-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>        )<span class=\"op\">;</span></span>\n<span id=\"cb2-24\"><a href=\"#cb2-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb2-25\"><a href=\"#cb2-25\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-26\"><a href=\"#cb2-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    out</span>\n<span id=\"cb2-27\"><a href=\"#cb2-27\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This now works, but you would have to implement each operation\nyourself for every possible operation.</p>\n<p>There\u2019s actually a nice trick you can do as long as you control all\nof the C files: you can shim the calls and let libc do the rest.</p>\n<p>So on the rust side:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>repr<span class=\"at\">(</span>C<span class=\"op\">,</span> align<span class=\"at\">(</span><span class=\"dv\">16</span><span class=\"at\">))]</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> LongDouble(<span class=\"kw\">pub</span> [<span class=\"dt\">u8</span><span class=\"op\">;</span> <span class=\"dv\">10</span>])<span class=\"op\">;</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">unsafe</span> <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> __slate_ld_add(a<span class=\"op\">:</span> LongDouble<span class=\"op\">,</span> b<span class=\"op\">:</span> LongDouble) <span class=\"op\">-&gt;</span> LongDouble<span class=\"op\">;</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"co\">// whatever other ops you want to provide</span></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Use the same storage on the C side:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">struct</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">_Alignas</span><span class=\"op\">(</span><span class=\"dv\">16</span><span class=\"op\">)</span> <span class=\"dt\">unsigned</span> <span class=\"dt\">char</span> bytes<span class=\"op\">[</span><span class=\"dv\">10</span><span class=\"op\">];</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span> slate_f80<span class=\"op\">;</span></span></code></pre></div>\n<p>And then write two functions, one to convert chars to long double and\none back:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"kw\">inline</span> <span class=\"dt\">long</span> <span class=\"dt\">double</span> unpack<span class=\"op\">(</span>slate_f80 v<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">long</span> <span class=\"dt\">double</span> x <span class=\"op\">=</span> <span class=\"fl\">0.0</span><span class=\"bu\">L</span><span class=\"op\">;</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    memcpy<span class=\"op\">(&amp;</span>x<span class=\"op\">,</span> v<span class=\"op\">.</span>bytes<span class=\"op\">,</span> <span class=\"dv\">10</span><span class=\"op\">);</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> x<span class=\"op\">;</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"kw\">inline</span> slate_f80 pack<span class=\"op\">(</span><span class=\"dt\">long</span> <span class=\"dt\">double</span> x<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    slate_f80 v <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"dv\">0</span><span class=\"op\">};</span></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    memcpy<span class=\"op\">(</span>v<span class=\"op\">.</span>bytes<span class=\"op\">,</span> <span class=\"op\">&amp;</span>x<span class=\"op\">,</span> <span class=\"dv\">10</span><span class=\"op\">);</span></span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> v<span class=\"op\">;</span></span>\n<span id=\"cb5-13\"><a href=\"#cb5-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_ld_add<span class=\"op\">(</span>slate_f80 a<span class=\"op\">,</span> slate_f80 b<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">(</span>unpack<span class=\"op\">(</span>a<span class=\"op\">)</span> <span class=\"op\">+</span> unpack<span class=\"op\">(</span>b<span class=\"op\">));</span> <span class=\"op\">}</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_ld_sub<span class=\"op\">(</span>slate_f80 a<span class=\"op\">,</span> slate_f80 b<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">(</span>unpack<span class=\"op\">(</span>a<span class=\"op\">)</span> <span class=\"op\">-</span> unpack<span class=\"op\">(</span>b<span class=\"op\">));</span> <span class=\"op\">}</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_ld_mul<span class=\"op\">(</span>slate_f80 a<span class=\"op\">,</span> slate_f80 b<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">(</span>unpack<span class=\"op\">(</span>a<span class=\"op\">)</span> <span class=\"op\">*</span> unpack<span class=\"op\">(</span>b<span class=\"op\">));</span> <span class=\"op\">}</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_ld_div<span class=\"op\">(</span>slate_f80 a<span class=\"op\">,</span> slate_f80 b<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">(</span>unpack<span class=\"op\">(</span>a<span class=\"op\">)</span> <span class=\"op\">/</span> unpack<span class=\"op\">(</span>b<span class=\"op\">));</span> <span class=\"op\">}</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_ld_neg<span class=\"op\">(</span>slate_f80 a<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">(-</span>unpack<span class=\"op\">(</span>a<span class=\"op\">));</span> <span class=\"op\">}</span></span></code></pre></div>\n<p>You could also implement casting, relops in the same way:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> __slate_ld_eq<span class=\"op\">(</span>slate_f80 a<span class=\"op\">,</span> slate_f80 b<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> unpack<span class=\"op\">(</span>a<span class=\"op\">)</span> <span class=\"op\">==</span> unpack<span class=\"op\">(</span>b<span class=\"op\">);</span> <span class=\"op\">}</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int32_t</span> __slate_ld_to_i32<span class=\"op\">(</span>slate_f80 a<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> <span class=\"op\">(</span><span class=\"dt\">int32_t</span><span class=\"op\">)</span>unpack<span class=\"op\">(</span>a<span class=\"op\">);</span> <span class=\"op\">}</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_ld_from_i32<span class=\"op\">(</span><span class=\"dt\">int32_t</span> x<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">((</span><span class=\"dt\">long</span> <span class=\"dt\">double</span><span class=\"op\">)</span>x<span class=\"op\">);</span> <span class=\"op\">}</span></span></code></pre></div>\n<p>Likewise, for any arbitrary function:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">long</span> <span class=\"dt\">double</span> custom<span class=\"op\">(</span><span class=\"dt\">long</span> <span class=\"dt\">double</span><span class=\"op\">,</span> <span class=\"dt\">int</span><span class=\"op\">);</span></span></code></pre></div>\n<p>You would replace it with a call to:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>slate_f80 __slate_custom<span class=\"op\">(</span>slate_f80 a<span class=\"op\">,</span> <span class=\"dt\">int</span> b<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pack<span class=\"op\">(</span>custom<span class=\"op\">(</span>unpack<span class=\"op\">(</span>a<span class=\"op\">),</span> b<span class=\"op\">));</span> <span class=\"op\">}</span></span></code></pre></div>\n<p>This makes it so we don\u2019t have to know anything about the underlying\nlong double type at all (no assembly writing for me) and keeps our shim\ncode fairly light.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2026-08-12T16:04:52+00:00"
		},
		{
			"id": "gen/one-billion-row-challenge.html",
			"url": "gen/one-billion-row-challenge.html",
			"title": "The One Billion Row Challenge",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>The One Billion Row Challenge</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">The One Billion Row Challenge</h1>\n<p class=\"byline\">2026-04-25T16:30:34-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#the-one-billion-row-challenge\"\nid=\"toc-the-one-billion-row-challenge\">The One Billion Row Challenge</a>\n<ul>\n<li><a href=\"#preliminaries\"\nid=\"toc-preliminaries\">Preliminaries</a></li>\n<li><a href=\"#the-easiest-solution-btreemap\"\nid=\"toc-the-easiest-solution-btreemap\">The Easiest Solution\n(BTreeMap)</a></li>\n<li><a href=\"#the-next-solution-hashmap\"\nid=\"toc-the-next-solution-hashmap\">The Next Solution (HashMap)</a></li>\n<li><a href=\"#memory-mapping\" id=\"toc-memory-mapping\">Memory\nMapping</a></li>\n<li><a href=\"#more-changes\" id=\"toc-more-changes\">More changes</a></li>\n<li><a href=\"#handle-the-bytes\" id=\"toc-handle-the-bytes\">Handle the\nbytes</a></li>\n<li><a href=\"#a-dead-end\" id=\"toc-a-dead-end\">A Dead end</a></li>\n<li><a href=\"#parallelization\"\nid=\"toc-parallelization\">Parallelization</a></li>\n<li><a href=\"#conclusion\" id=\"toc-conclusion\">Conclusion</a></li>\n</ul></li>\n</ul>\n</nav>\n<section id=\"the-one-billion-row-challenge\" class=\"level1\">\n<h1>The One Billion Row Challenge</h1>\n<p>A couple of years ago, the <a href=\"https://1brc.dev/\">1 Billion Row\nChallenge</a> got popular. The challenge is to write a program that\nreads a text file with the format of: <code>$CITY_NAME;$TEMP\\n</code> of\nsome size, and then for each city, the program should print out the min,\nmean, and max values per city, alphabetically ordered.</p>\n<p>So if you have:</p>\n<pre><code>Hamburg;12.0\nHamburg;34.2</code></pre>\n<p>You would condense this down to:</p>\n<pre><code>Hamburg;12.0;23.1;34.2\n   ^      ^    ^    ^\n city    min  mean max</code></pre>\n<p>And print that out.</p>\n<p>I decided to do this in Rust, and this post is what I learned.</p>\n<section id=\"preliminaries\" class=\"level2\">\n<h2>Preliminaries</h2>\n<p>Since I knew I wanted to try out a few different methods, to start\noff with I defined a trait so I would only have to rewrite the core\nlogic.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">type</span> Temp <span class=\"op\">=</span> <span class=\"dt\">i16</span><span class=\"op\">;</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Debug</span><span class=\"op\">,</span> <span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">PartialEq</span><span class=\"op\">,</span> <span class=\"bu\">Eq</span><span class=\"at\">)]</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> StationResult <span class=\"op\">{</span></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> station<span class=\"op\">:</span> <span class=\"dt\">String</span><span class=\"op\">,</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> min<span class=\"op\">:</span> Temp<span class=\"op\">,</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> mean<span class=\"op\">:</span> Temp<span class=\"op\">,</span></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> max<span class=\"op\">:</span> Temp<span class=\"op\">,</span></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">trait</span> Solver<span class=\"op\">:</span> <span class=\"bu\">Default</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> process(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> station<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span><span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp)<span class=\"op\">;</span></span>\n<span id=\"cb3-13\"><a href=\"#cb3-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> process_bytes(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> station<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]<span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-14\"><a href=\"#cb3-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> station <span class=\"op\">=</span> <span class=\"pp\">std::</span><span class=\"dt\">str</span><span class=\"pp\">::</span>from_utf8(station)<span class=\"op\">.</span>map_err(<span class=\"op\">|</span>error<span class=\"op\">|</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-15\"><a href=\"#cb3-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"pp\">io::</span><span class=\"bu\">Error</span><span class=\"pp\">::</span>new(</span>\n<span id=\"cb3-16\"><a href=\"#cb3-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">io::ErrorKind::</span>InvalidData<span class=\"op\">,</span></span>\n<span id=\"cb3-17\"><a href=\"#cb3-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">format!</span>(<span class=\"st\">&quot;invalid station name UTF-8: {error}&quot;</span>)<span class=\"op\">,</span></span>\n<span id=\"cb3-18\"><a href=\"#cb3-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>            )</span>\n<span id=\"cb3-19\"><a href=\"#cb3-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span>)<span class=\"op\">?;</span></span>\n<span id=\"cb3-20\"><a href=\"#cb3-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">self</span><span class=\"op\">.</span>process(station<span class=\"op\">,</span> temp)<span class=\"op\">;</span></span>\n<span id=\"cb3-21\"><a href=\"#cb3-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cn\">Ok</span>(())</span>\n<span id=\"cb3-22\"><a href=\"#cb3-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb3-23\"><a href=\"#cb3-23\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-24\"><a href=\"#cb3-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> finish(<span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>StationResult<span class=\"op\">&gt;;</span></span>\n<span id=\"cb3-25\"><a href=\"#cb3-25\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>As well, I needed to keep the stats for each station:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">type</span> Temp <span class=\"op\">=</span> <span class=\"dt\">i16</span><span class=\"op\">;</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">type</span> TempSum <span class=\"op\">=</span> <span class=\"dt\">i64</span><span class=\"op\">;</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">type</span> Count <span class=\"op\">=</span> <span class=\"dt\">u32</span><span class=\"op\">;</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Default</span><span class=\"op\">,</span> <span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) <span class=\"kw\">struct</span> Stats <span class=\"op\">{</span></span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) sum<span class=\"op\">:</span> TempSum<span class=\"op\">,</span></span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) count<span class=\"op\">:</span> Count<span class=\"op\">,</span></span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) min<span class=\"op\">:</span> Temp<span class=\"op\">,</span></span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) max<span class=\"op\">:</span> Temp<span class=\"op\">,</span></span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> Stats <span class=\"op\">{</span></span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) <span class=\"kw\">fn</span> add(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp) <span class=\"op\">{</span></span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> <span class=\"kw\">self</span><span class=\"op\">.</span>count <span class=\"op\">==</span> <span class=\"dv\">0</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">self</span><span class=\"op\">.</span>min <span class=\"op\">=</span> temp<span class=\"op\">;</span></span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">self</span><span class=\"op\">.</span>max <span class=\"op\">=</span> temp<span class=\"op\">;</span></span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">self</span><span class=\"op\">.</span>min <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>min<span class=\"op\">.</span>min(temp)<span class=\"op\">;</span></span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">self</span><span class=\"op\">.</span>max <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>max<span class=\"op\">.</span>max(temp)<span class=\"op\">;</span></span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">self</span><span class=\"op\">.</span>sum <span class=\"op\">+=</span> <span class=\"pp\">TempSum::</span>from(temp)<span class=\"op\">;</span></span>\n<span id=\"cb4-24\"><a href=\"#cb4-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">self</span><span class=\"op\">.</span>count <span class=\"op\">+=</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb4-25\"><a href=\"#cb4-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb4-26\"><a href=\"#cb4-26\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-27\"><a href=\"#cb4-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span>(<span class=\"kw\">crate</span>) <span class=\"kw\">fn</span> into_result(<span class=\"kw\">self</span><span class=\"op\">,</span> station<span class=\"op\">:</span> <span class=\"dt\">String</span>) <span class=\"op\">-&gt;</span> StationResult <span class=\"op\">{</span></span>\n<span id=\"cb4-28\"><a href=\"#cb4-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>        StationResult <span class=\"op\">{</span></span>\n<span id=\"cb4-29\"><a href=\"#cb4-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>            station<span class=\"op\">,</span></span>\n<span id=\"cb4-30\"><a href=\"#cb4-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>            min<span class=\"op\">:</span> <span class=\"kw\">self</span><span class=\"op\">.</span>min<span class=\"op\">,</span></span>\n<span id=\"cb4-31\"><a href=\"#cb4-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>            mean<span class=\"op\">:</span> round_mean_tenths(<span class=\"kw\">self</span><span class=\"op\">.</span>sum<span class=\"op\">,</span> <span class=\"kw\">self</span><span class=\"op\">.</span>count)<span class=\"op\">,</span></span>\n<span id=\"cb4-32\"><a href=\"#cb4-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>            max<span class=\"op\">:</span> <span class=\"kw\">self</span><span class=\"op\">.</span>max<span class=\"op\">,</span></span>\n<span id=\"cb4-33\"><a href=\"#cb4-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb4-34\"><a href=\"#cb4-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb4-35\"><a href=\"#cb4-35\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>With a helper for reading input:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> process_measurements<span class=\"op\">&lt;</span>R<span class=\"op\">,</span> S<span class=\"op\">&gt;</span>(reader<span class=\"op\">:</span> R<span class=\"op\">,</span> solver<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"kw\">mut</span> S) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">where</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    R<span class=\"op\">:</span> <span class=\"bu\">BufRead</span><span class=\"op\">,</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    S<span class=\"op\">:</span> Solver<span class=\"op\">,</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">{</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> line <span class=\"kw\">in</span> reader<span class=\"op\">.</span>lines() <span class=\"op\">{</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> line <span class=\"op\">=</span> line<span class=\"op\">?;</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"cn\">Some</span>((station<span class=\"op\">,</span> temp)) <span class=\"op\">=</span> line<span class=\"op\">.</span>split_once(<span class=\"ch\">&#39;;&#39;</span>) <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">continue</span><span class=\"op\">;</span></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">};</span></span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        solver<span class=\"op\">.</span>process(station<span class=\"op\">,</span> parse_temperature_tenths(temp)<span class=\"op\">?</span>)<span class=\"op\">;</span></span>\n<span id=\"cb5-13\"><a href=\"#cb5-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb5-14\"><a href=\"#cb5-14\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-15\"><a href=\"#cb5-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cn\">Ok</span>(())</span>\n<span id=\"cb5-16\"><a href=\"#cb5-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>A helper for writing output:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> write_results_to_path(path<span class=\"op\">:</span> <span class=\"dt\">Option</span><span class=\"op\">&lt;&amp;</span><span class=\"dt\">str</span><span class=\"op\">&gt;,</span> results<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[StationResult]) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">match</span> path <span class=\"op\">{</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cn\">Some</span>(path) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> file <span class=\"op\">=</span> <span class=\"pp\">File::</span>create(path)<span class=\"op\">?;</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> writer <span class=\"op\">=</span> <span class=\"pp\">BufWriter::</span>new(file)<span class=\"op\">;</span></span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            write_results(writer<span class=\"op\">,</span> results)</span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cn\">None</span> <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> stdout <span class=\"op\">=</span> <span class=\"pp\">io::</span>stdout()<span class=\"op\">;</span></span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> writer <span class=\"op\">=</span> stdout<span class=\"op\">.</span>lock()<span class=\"op\">;</span></span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            write_results(writer<span class=\"op\">,</span> results)</span>\n<span id=\"cb6-12\"><a href=\"#cb6-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb6-13\"><a href=\"#cb6-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb6-14\"><a href=\"#cb6-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And finally, running the solver:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> run_solver<span class=\"op\">&lt;</span>S<span class=\"op\">&gt;</span>(input_path<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span><span class=\"op\">,</span> output_path<span class=\"op\">:</span> <span class=\"dt\">Option</span><span class=\"op\">&lt;&amp;</span><span class=\"dt\">str</span><span class=\"op\">&gt;</span>) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">where</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    S<span class=\"op\">:</span> Solver<span class=\"op\">,</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">{</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> file <span class=\"op\">=</span> <span class=\"pp\">File::</span>open(input_path)<span class=\"op\">.</span>map_err(<span class=\"op\">|</span>error<span class=\"op\">|</span> not_found_error(input_path<span class=\"op\">,</span> error))<span class=\"op\">?;</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> reader <span class=\"op\">=</span> <span class=\"pp\">BufReader::</span>with_capacity(<span class=\"dv\">8</span> <span class=\"op\">*</span> <span class=\"dv\">1024</span> <span class=\"op\">*</span> <span class=\"dv\">1024</span><span class=\"op\">,</span> file)<span class=\"op\">;</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> solver <span class=\"op\">=</span> <span class=\"pp\">S::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">input::</span>process_measurements(reader<span class=\"op\">,</span> <span class=\"op\">&amp;</span><span class=\"kw\">mut</span> solver)<span class=\"op\">?;</span></span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">output::</span>write_results_to_path(output_path<span class=\"op\">,</span> <span class=\"op\">&amp;</span>solver<span class=\"op\">.</span>finish())</span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>As well, I wanted to create a couple of things. First off, I needed\n<code>cargo flamegraph</code> to see where time was being spent, and I\nwrote a script so I could generate input of different sizes. The 1\nbillion rows would be wasteful to do my target runs on, so I took the\nweather data from the one billion rows repo and generated a million row\nsample to run on.</p>\n</section>\n<section id=\"the-easiest-solution-btreemap\" class=\"level2\">\n<h2>The Easiest Solution (BTreeMap)</h2>\n<p>First off, let\u2019s start off with the basics. The simplest solution I\ncould think of was to:</p>\n<ol type=\"1\">\n<li>For each line, split at the \u2018;\u2019 character.\n<ul>\n<li>The left side is the station name.</li>\n<li>The right side is the temperature.</li>\n<li>Take the temperature, and then record the current total, current\ncount, current minimum, and current maximum.</li>\n</ul></li>\n<li>Sort the cities.</li>\n<li>Calculate the mean by doing sum / count;</li>\n<li>Print out \u201c{city};{min};{mean};{max}\u201d for each city.</li>\n</ol>\n<p>You know what\u2019s better than sorting at the end? Having a data\nstructure do it for you. So at first, I used a <code>BTreeMap</code>.\nWith the <code>Solver</code> trait, I just needed to implement\n<code>process</code> and <code>finish</code>.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Default</span><span class=\"at\">)]</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> BasicBTreeMapSolver <span class=\"op\">{</span></span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    stats_by_station<span class=\"op\">:</span> BTreeMap<span class=\"op\">&lt;</span><span class=\"dt\">String</span><span class=\"op\">,</span> Stats<span class=\"op\">&gt;,</span></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> Solver <span class=\"cf\">for</span> BasicBTreeMapSolver <span class=\"op\">{</span></span>\n<span id=\"cb8-7\"><a href=\"#cb8-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> process(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> station<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span><span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp) <span class=\"op\">{</span></span>\n<span id=\"cb8-8\"><a href=\"#cb8-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station</span>\n<span id=\"cb8-9\"><a href=\"#cb8-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>entry(station<span class=\"op\">.</span>to_string())</span>\n<span id=\"cb8-10\"><a href=\"#cb8-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>or_default()</span>\n<span id=\"cb8-11\"><a href=\"#cb8-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb8-12\"><a href=\"#cb8-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb8-13\"><a href=\"#cb8-13\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb8-14\"><a href=\"#cb8-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> finish(<span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>StationResult<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb8-15\"><a href=\"#cb8-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station</span>\n<span id=\"cb8-16\"><a href=\"#cb8-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>into_iter()</span>\n<span id=\"cb8-17\"><a href=\"#cb8-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>map(<span class=\"op\">|</span>(station<span class=\"op\">,</span> stats)<span class=\"op\">|</span> stats<span class=\"op\">.</span>into_result(station))</span>\n<span id=\"cb8-18\"><a href=\"#cb8-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>collect()</span>\n<span id=\"cb8-19\"><a href=\"#cb8-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb8-20\"><a href=\"#cb8-20\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This solution crunches through one million rows in 218ms on my Ryzen\n5 7600 CPU.</p>\n<p>Not bad but we could do better. Taking a look at the flamegraph here,\nthere\u2019s not too much to say, but it looks like the btreemap logic itself\nis taking the longest amount of time, so we should tackle that\nfirst.</p>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/btreemap.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"the-next-solution-hashmap\" class=\"level2\">\n<h2>The Next Solution (HashMap)</h2>\n<p>BTreeMap is slow for this solution because we don\u2019t need a sorted\norder all the time, just at the end. To do that, we can fall back to\ngood old HashMap and sort once at the end.</p>\n<p>And with that:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> Solver <span class=\"cf\">for</span> BasicHashMapSolver <span class=\"op\">{</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> process(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> station<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span><span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp) <span class=\"op\">{</span></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> <span class=\"kw\">let</span> <span class=\"cn\">Some</span>(stats) <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station<span class=\"op\">.</span>get_mut(station) <span class=\"op\">{</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>            stats<span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> <span class=\"kw\">mut</span> stats <span class=\"op\">=</span> <span class=\"pp\">Stats::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>            stats<span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station<span class=\"op\">.</span>insert(station<span class=\"op\">.</span>to_string()<span class=\"op\">,</span> stats)<span class=\"op\">;</span></span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> finish(<span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>StationResult<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-13\"><a href=\"#cb9-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"kw\">mut</span> results<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>_<span class=\"op\">&gt;</span> <span class=\"op\">=</span> <span class=\"kw\">self</span></span>\n<span id=\"cb9-14\"><a href=\"#cb9-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>stats_by_station</span>\n<span id=\"cb9-15\"><a href=\"#cb9-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>into_iter()</span>\n<span id=\"cb9-16\"><a href=\"#cb9-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>map(<span class=\"op\">|</span>(station<span class=\"op\">,</span> stats)<span class=\"op\">|</span> stats<span class=\"op\">.</span>into_result(station))</span>\n<span id=\"cb9-17\"><a href=\"#cb9-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>collect()<span class=\"op\">;</span></span>\n<span id=\"cb9-18\"><a href=\"#cb9-18\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-19\"><a href=\"#cb9-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>        results<span class=\"op\">.</span>sort_unstable_by(<span class=\"op\">|</span>left<span class=\"op\">,</span> right<span class=\"op\">|</span> left<span class=\"op\">.</span>station<span class=\"op\">.</span>cmp(<span class=\"op\">&amp;</span>right<span class=\"op\">.</span>station))<span class=\"op\">;</span></span>\n<span id=\"cb9-20\"><a href=\"#cb9-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>        results</span>\n<span id=\"cb9-21\"><a href=\"#cb9-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-22\"><a href=\"#cb9-22\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This about halves the run time, to 110ms. I was expecting more of a\nmodest improvement, but this is pretty nice. The next chunk I see taking\na lot of time is read_line, so we can work on that next.</p>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/hashmap.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"memory-mapping\" class=\"level2\">\n<h2>Memory Mapping</h2>\n<p>The next bottleneck looked to be I/O: BufReader was taking the most\namount of time. The Bufreader already reads in chunks, but we want to\navoid going back to the kernel for reads. Memory mapping is one way to\ndo that.</p>\n<p>All we have to do is change our input hook to memory map our input\nfile.</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> run_solver_mmap<span class=\"op\">&lt;</span>S<span class=\"op\">:</span> Solver<span class=\"op\">&gt;</span>(input_path<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span><span class=\"op\">,</span> output_path<span class=\"op\">:</span> <span class=\"dt\">Option</span><span class=\"op\">&lt;&amp;</span><span class=\"dt\">str</span><span class=\"op\">&gt;</span>) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> file <span class=\"op\">=</span> <span class=\"pp\">File::</span>open(input_path)<span class=\"op\">?;</span></span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> mmap <span class=\"op\">=</span> <span class=\"kw\">unsafe</span> <span class=\"op\">{</span> <span class=\"pp\">MmapOptions::</span>new()<span class=\"op\">.</span>map(<span class=\"op\">&amp;</span>file)<span class=\"op\">?</span> <span class=\"op\">};</span></span>\n<span id=\"cb10-4\"><a href=\"#cb10-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> solver <span class=\"op\">=</span> <span class=\"pp\">S::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb10-5\"><a href=\"#cb10-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">input::</span>process_measurements_bytes(<span class=\"op\">&amp;</span>mmap<span class=\"op\">,</span> <span class=\"op\">&amp;</span><span class=\"kw\">mut</span> solver)<span class=\"op\">?;</span></span>\n<span id=\"cb10-6\"><a href=\"#cb10-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">output::</span>write_results_to_path(output_path<span class=\"op\">,</span> <span class=\"op\">&amp;</span>solver<span class=\"op\">.</span>finish())</span>\n<span id=\"cb10-7\"><a href=\"#cb10-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This gets us an even faster runtime of 79ms.</p>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/hashmap-mmap.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"more-changes\" class=\"level2\">\n<h2>More changes</h2>\n<p>At this point I was pretty satisfied. Memory mapping the input file +\nusing a HashMap was already pretty good. But the flamegraph does show\nthat <code>parse_temperature_tenths_bytes</code> is pretty slow (32% of\nruntime), so let\u2019s dig into that.</p>\n<p>The current implementation is:</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> parse_temperature_tenths_bytes(value<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>Temp<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> negative <span class=\"op\">=</span> value<span class=\"op\">.</span>first() <span class=\"op\">==</span> <span class=\"cn\">Some</span>(<span class=\"op\">&amp;</span><span class=\"ch\">b&#39;-&#39;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> digits <span class=\"op\">=</span> <span class=\"cf\">if</span> negative <span class=\"op\">{</span> <span class=\"op\">&amp;</span>value[<span class=\"dv\">1</span><span class=\"op\">..</span>] <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span> value <span class=\"op\">};</span></span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>                                                                                                                              </span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> digits<span class=\"op\">.</span>len() <span class=\"op\">&lt;</span> <span class=\"dv\">3</span> <span class=\"op\">||</span> digits[digits<span class=\"op\">.</span>len() <span class=\"op\">-</span> <span class=\"dv\">2</span>] <span class=\"op\">!=</span> <span class=\"ch\">b&#39;.&#39;</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">return</span> <span class=\"cn\">Err</span>(invalid_temperature_bytes(value))<span class=\"op\">;</span></span>\n<span id=\"cb11-7\"><a href=\"#cb11-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-8\"><a href=\"#cb11-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>                                                                                                                       </span>\n<span id=\"cb11-9\"><a href=\"#cb11-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> whole <span class=\"op\">=</span> <span class=\"op\">&amp;</span>digits[<span class=\"op\">..</span>digits<span class=\"op\">.</span>len() <span class=\"op\">-</span> <span class=\"dv\">2</span>]<span class=\"op\">;</span></span>\n<span id=\"cb11-10\"><a href=\"#cb11-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> fraction <span class=\"op\">=</span> digits[digits<span class=\"op\">.</span>len() <span class=\"op\">-</span> <span class=\"dv\">1</span>]<span class=\"op\">;</span></span>\n<span id=\"cb11-11\"><a href=\"#cb11-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> whole<span class=\"op\">.</span>is_empty()</span>\n<span id=\"cb11-12\"><a href=\"#cb11-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">||</span> <span class=\"op\">!</span>whole<span class=\"op\">.</span>iter()<span class=\"op\">.</span>all(<span class=\"op\">|</span>byte<span class=\"op\">|</span> byte<span class=\"op\">.</span>is_ascii_digit())</span>\n<span id=\"cb11-13\"><a href=\"#cb11-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">||</span> <span class=\"op\">!</span>fraction<span class=\"op\">.</span>is_ascii_digit()</span>\n<span id=\"cb11-14\"><a href=\"#cb11-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">{</span></span>\n<span id=\"cb11-15\"><a href=\"#cb11-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">return</span> <span class=\"cn\">Err</span>(invalid_temperature_bytes(value))<span class=\"op\">;</span></span>\n<span id=\"cb11-16\"><a href=\"#cb11-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-17\"><a href=\"#cb11-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>                                                                                                                       </span>\n<span id=\"cb11-18\"><a href=\"#cb11-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> temp <span class=\"op\">=</span> <span class=\"pp\">Temp::</span>from(fraction <span class=\"op\">-</span> <span class=\"ch\">b&#39;0&#39;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb11-19\"><a href=\"#cb11-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> multiplier <span class=\"op\">=</span> <span class=\"dv\">10</span><span class=\"op\">;</span></span>\n<span id=\"cb11-20\"><a href=\"#cb11-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> <span class=\"op\">&amp;</span>digit <span class=\"kw\">in</span> whole<span class=\"op\">.</span>iter()<span class=\"op\">.</span>rev() <span class=\"op\">{</span></span>\n<span id=\"cb11-21\"><a href=\"#cb11-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>        temp <span class=\"op\">+=</span> <span class=\"pp\">Temp::</span>from(digit <span class=\"op\">-</span> <span class=\"ch\">b&#39;0&#39;</span>) <span class=\"op\">*</span> multiplier<span class=\"op\">;</span></span>\n<span id=\"cb11-22\"><a href=\"#cb11-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>        multiplier <span class=\"op\">*=</span> <span class=\"dv\">10</span><span class=\"op\">;</span></span>\n<span id=\"cb11-23\"><a href=\"#cb11-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-24\"><a href=\"#cb11-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>                                                                                                                       </span>\n<span id=\"cb11-25\"><a href=\"#cb11-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cn\">Ok</span>(<span class=\"cf\">if</span> negative <span class=\"op\">{</span> <span class=\"op\">-</span>temp <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span> temp <span class=\"op\">}</span>)</span>\n<span id=\"cb11-26\"><a href=\"#cb11-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This has a few branches and error checking. We can make this\nbranchless by exploiting the fact that there are only 4 formats. We just\nneed to check if the first character is the negative sign, then grab the\nfractional part from the end, and otherwise grab the number itself. We\ncan then recreate the value itself that way, fully branchless.</p>\n<div class=\"sourceCode\" id=\"cb12\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb12-1\"><a href=\"#cb12-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> parse_temperature_tenths_bytes(value<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>Temp<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-2\"><a href=\"#cb12-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> neg <span class=\"op\">=</span> (value[<span class=\"dv\">0</span>] <span class=\"op\">==</span> <span class=\"ch\">b&#39;-&#39;</span>) <span class=\"kw\">as</span> <span class=\"dt\">usize</span><span class=\"op\">;</span></span>\n<span id=\"cb12-3\"><a href=\"#cb12-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> frac <span class=\"op\">=</span> (value[value<span class=\"op\">.</span>len() <span class=\"op\">-</span> <span class=\"dv\">1</span>] <span class=\"op\">-</span> <span class=\"ch\">b&#39;0&#39;</span>) <span class=\"kw\">as</span> Temp<span class=\"op\">;</span></span>\n<span id=\"cb12-4\"><a href=\"#cb12-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> ones <span class=\"op\">=</span> (value[value<span class=\"op\">.</span>len() <span class=\"op\">-</span> <span class=\"dv\">3</span>] <span class=\"op\">-</span> <span class=\"ch\">b&#39;0&#39;</span>) <span class=\"kw\">as</span> Temp<span class=\"op\">;</span></span>\n<span id=\"cb12-5\"><a href=\"#cb12-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> has_tens <span class=\"op\">=</span> (value<span class=\"op\">.</span>len() <span class=\"op\">-</span> neg <span class=\"op\">&gt;</span> <span class=\"dv\">3</span>) <span class=\"kw\">as</span> Temp<span class=\"op\">;</span></span>\n<span id=\"cb12-6\"><a href=\"#cb12-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> tens <span class=\"op\">=</span> has_tens <span class=\"op\">*</span> (value[neg] <span class=\"op\">-</span> <span class=\"ch\">b&#39;0&#39;</span>) <span class=\"kw\">as</span> Temp<span class=\"op\">;</span></span>\n<span id=\"cb12-7\"><a href=\"#cb12-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> sign <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">-</span> <span class=\"dv\">2</span> <span class=\"op\">*</span> neg <span class=\"kw\">as</span> Temp<span class=\"op\">;</span></span>\n<span id=\"cb12-8\"><a href=\"#cb12-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cn\">Ok</span>(sign <span class=\"op\">*</span> (tens <span class=\"op\">*</span> <span class=\"dv\">100</span> <span class=\"op\">+</span> ones <span class=\"op\">*</span> <span class=\"dv\">10</span> <span class=\"op\">+</span> frac))</span>\n<span id=\"cb12-9\"><a href=\"#cb12-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This has two advantages: one, dropping the runtime to 72ms, a nice\nimprovement, but also dropping the variance between runs. We used to\nhave about 5-8ms variance, but now this is less than &lt;1ms between\nruns, since branchless solutions are more consistent.</p>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/hashmap-mmap-branchless-bytes.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"handle-the-bytes\" class=\"level2\">\n<h2>Handle the bytes</h2>\n<p>Why bother having strings at all? Why not index a city by its bytes?\nWe can do that and combined with a faster hashmap (Fnv), I got a 60ms\nruntime on my computer.</p>\n<div class=\"sourceCode\" id=\"cb13\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> FnvBytesSolver <span class=\"op\">{</span></span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    stats_by_station<span class=\"op\">:</span> FnvHashMap<span class=\"op\">&lt;</span><span class=\"dt\">Vec</span><span class=\"op\">&lt;</span><span class=\"dt\">u8</span><span class=\"op\">&gt;,</span> Stats<span class=\"op\">&gt;,</span></span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> Solver <span class=\"cf\">for</span> FnvBytesSolver <span class=\"op\">{</span></span>\n<span id=\"cb13-6\"><a href=\"#cb13-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> process_bytes(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> station<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]<span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-7\"><a href=\"#cb13-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> <span class=\"kw\">let</span> <span class=\"cn\">Some</span>(stats) <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station<span class=\"op\">.</span>get_mut(station) <span class=\"op\">{</span></span>\n<span id=\"cb13-8\"><a href=\"#cb13-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>            stats<span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb13-9\"><a href=\"#cb13-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-10\"><a href=\"#cb13-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> <span class=\"kw\">mut</span> stats <span class=\"op\">=</span> <span class=\"pp\">Stats::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb13-11\"><a href=\"#cb13-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            stats<span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb13-12\"><a href=\"#cb13-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station<span class=\"op\">.</span>insert(station<span class=\"op\">.</span>to_vec()<span class=\"op\">,</span> stats)<span class=\"op\">;</span></span>\n<span id=\"cb13-13\"><a href=\"#cb13-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-14\"><a href=\"#cb13-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cn\">Ok</span>(())</span>\n<span id=\"cb13-15\"><a href=\"#cb13-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-16\"><a href=\"#cb13-16\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-17\"><a href=\"#cb13-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> finish(<span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>StationResult<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-18\"><a href=\"#cb13-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"kw\">mut</span> results <span class=\"op\">=</span> <span class=\"dt\">Vec</span><span class=\"pp\">::</span>with_capacity(<span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station<span class=\"op\">.</span>len())<span class=\"op\">;</span></span>\n<span id=\"cb13-19\"><a href=\"#cb13-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">for</span> (station<span class=\"op\">,</span> stats) <span class=\"kw\">in</span> <span class=\"kw\">self</span><span class=\"op\">.</span>stats_by_station <span class=\"op\">{</span></span>\n<span id=\"cb13-20\"><a href=\"#cb13-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> station <span class=\"op\">=</span> <span class=\"dt\">String</span><span class=\"pp\">::</span>from_utf8(station)<span class=\"op\">.</span>expect(<span class=\"st\">&quot;valid UTF-8&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-21\"><a href=\"#cb13-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>            results<span class=\"op\">.</span>push(stats<span class=\"op\">.</span>into_result(station))<span class=\"op\">;</span></span>\n<span id=\"cb13-22\"><a href=\"#cb13-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-23\"><a href=\"#cb13-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>        results<span class=\"op\">.</span>sort_unstable_by(<span class=\"op\">|</span>l<span class=\"op\">,</span> r<span class=\"op\">|</span> l<span class=\"op\">.</span>station<span class=\"op\">.</span>cmp(<span class=\"op\">&amp;</span>r<span class=\"op\">.</span>station))<span class=\"op\">;</span></span>\n<span id=\"cb13-24\"><a href=\"#cb13-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>        results</span>\n<span id=\"cb13-25\"><a href=\"#cb13-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-26\"><a href=\"#cb13-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/fnv-bytes-mmap.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"a-dead-end\" class=\"level2\">\n<h2>A Dead end</h2>\n<p>At this point, I had about hit wits end. About 48% of runtime was in\nFnvHasher\u2019s <code>get_mut</code>, and otherwise about 17% of runtime was\nin <code>float_to_decimal_common_exact</code>.</p>\n<p>So the next two things are to remove the hashmap and fix the output\nformatting.</p>\n<p>The biggest impact would be to rip out the hashmap itself and come up\nwith a custom flat hashmap.</p>\n<div class=\"sourceCode\" id=\"cb14\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb14-1\"><a href=\"#cb14-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> fingerprint(key<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]) <span class=\"op\">-&gt;</span> <span class=\"dt\">u64</span> <span class=\"op\">{</span></span>\n<span id=\"cb14-2\"><a href=\"#cb14-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> buf <span class=\"op\">=</span> [<span class=\"dv\">0u8</span><span class=\"op\">;</span> <span class=\"dv\">8</span>]<span class=\"op\">;</span></span>\n<span id=\"cb14-3\"><a href=\"#cb14-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> n <span class=\"op\">=</span> key<span class=\"op\">.</span>len()<span class=\"op\">.</span>min(<span class=\"dv\">8</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-4\"><a href=\"#cb14-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    buf[<span class=\"op\">..</span>n]<span class=\"op\">.</span>copy_from_slice(<span class=\"op\">&amp;</span>key[<span class=\"op\">..</span>n])<span class=\"op\">;</span></span>\n<span id=\"cb14-5\"><a href=\"#cb14-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">u64</span><span class=\"pp\">::</span>from_le_bytes(buf)</span>\n<span id=\"cb14-6\"><a href=\"#cb14-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb14-7\"><a href=\"#cb14-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-8\"><a href=\"#cb14-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> table_index(fp<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> key_len<span class=\"op\">:</span> <span class=\"dt\">usize</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">usize</span> <span class=\"op\">{</span></span>\n<span id=\"cb14-9\"><a href=\"#cb14-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> h <span class=\"op\">=</span> fp <span class=\"op\">^</span> (key_len <span class=\"kw\">as</span> <span class=\"dt\">u64</span>)<span class=\"op\">.</span>wrapping_shl(<span class=\"dv\">17</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-10\"><a href=\"#cb14-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> h <span class=\"op\">=</span> h <span class=\"op\">^</span> (h <span class=\"op\">&gt;&gt;</span> <span class=\"dv\">30</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-11\"><a href=\"#cb14-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> h <span class=\"op\">=</span> h<span class=\"op\">.</span>wrapping_mul(<span class=\"dv\">0xbf58476d1ce4e5b9</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-12\"><a href=\"#cb14-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> h <span class=\"op\">=</span> h <span class=\"op\">^</span> (h <span class=\"op\">&gt;&gt;</span> <span class=\"dv\">27</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-13\"><a href=\"#cb14-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> h <span class=\"op\">=</span> h<span class=\"op\">.</span>wrapping_mul(<span class=\"dv\">0x94d049bb133111eb</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-14\"><a href=\"#cb14-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> h <span class=\"op\">=</span> h <span class=\"op\">^</span> (h <span class=\"op\">&gt;&gt;</span> <span class=\"dv\">31</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-15\"><a href=\"#cb14-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (h <span class=\"kw\">as</span> <span class=\"dt\">usize</span>) <span class=\"op\">&amp;</span> TABLE_MASK</span>\n<span id=\"cb14-16\"><a href=\"#cb14-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb14-17\"><a href=\"#cb14-17\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-18\"><a href=\"#cb14-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">const</span> TABLE_SIZE<span class=\"op\">:</span> <span class=\"dt\">usize</span> <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">17</span><span class=\"op\">;</span> </span>\n<span id=\"cb14-19\"><a href=\"#cb14-19\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-20\"><a href=\"#cb14-20\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">struct</span> Slot<span class=\"op\">&lt;</span><span class=\"ot\">&#39;a</span><span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb14-21\"><a href=\"#cb14-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fingerprint<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span></span>\n<span id=\"cb14-22\"><a href=\"#cb14-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    key<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"ot\">&#39;a</span> [<span class=\"dt\">u8</span>]<span class=\"op\">,</span></span>\n<span id=\"cb14-23\"><a href=\"#cb14-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    stats<span class=\"op\">:</span> Stats<span class=\"op\">,</span></span>\n<span id=\"cb14-24\"><a href=\"#cb14-24\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb14-25\"><a href=\"#cb14-25\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-26\"><a href=\"#cb14-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">struct</span> FlatTable<span class=\"op\">&lt;</span><span class=\"ot\">&#39;a</span><span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb14-27\"><a href=\"#cb14-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>    slots<span class=\"op\">:</span> <span class=\"dt\">Box</span><span class=\"op\">&lt;</span>[Slot<span class=\"op\">&lt;</span><span class=\"ot\">&#39;a</span><span class=\"op\">&gt;</span>]<span class=\"op\">&gt;,</span></span>\n<span id=\"cb14-28\"><a href=\"#cb14-28\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb14-29\"><a href=\"#cb14-29\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-30\"><a href=\"#cb14-30\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span><span class=\"op\">&lt;</span><span class=\"ot\">&#39;a</span><span class=\"op\">&gt;</span> FlatTable<span class=\"op\">&lt;</span><span class=\"ot\">&#39;a</span><span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb14-31\"><a href=\"#cb14-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> update(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> key<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"ot\">&#39;a</span> [<span class=\"dt\">u8</span>]<span class=\"op\">,</span> temp<span class=\"op\">:</span> Temp) <span class=\"op\">{</span></span>\n<span id=\"cb14-32\"><a href=\"#cb14-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> fp <span class=\"op\">=</span> fingerprint(key)<span class=\"op\">;</span></span>\n<span id=\"cb14-33\"><a href=\"#cb14-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"kw\">mut</span> idx <span class=\"op\">=</span> table_index(fp<span class=\"op\">,</span> key<span class=\"op\">.</span>len())<span class=\"op\">;</span></span>\n<span id=\"cb14-34\"><a href=\"#cb14-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">loop</span> <span class=\"op\">{</span></span>\n<span id=\"cb14-35\"><a href=\"#cb14-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> slot <span class=\"op\">=</span> <span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">.</span>slots[idx]<span class=\"op\">;</span></span>\n<span id=\"cb14-36\"><a href=\"#cb14-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">if</span> slot<span class=\"op\">.</span>key<span class=\"op\">.</span>is_empty() <span class=\"op\">{</span>               </span>\n<span id=\"cb14-37\"><a href=\"#cb14-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>                slot<span class=\"op\">.</span>fingerprint <span class=\"op\">=</span> fp<span class=\"op\">;</span></span>\n<span id=\"cb14-38\"><a href=\"#cb14-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>                slot<span class=\"op\">.</span>key <span class=\"op\">=</span> key<span class=\"op\">;</span></span>\n<span id=\"cb14-39\"><a href=\"#cb14-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>                slot<span class=\"op\">.</span>stats <span class=\"op\">=</span> <span class=\"pp\">Stats::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb14-40\"><a href=\"#cb14-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>                slot<span class=\"op\">.</span>stats<span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb14-41\"><a href=\"#cb14-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"cf\">return</span><span class=\"op\">;</span></span>\n<span id=\"cb14-42\"><a href=\"#cb14-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb14-43\"><a href=\"#cb14-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">if</span> slot<span class=\"op\">.</span>fingerprint <span class=\"op\">==</span> fp <span class=\"op\">&amp;&amp;</span> slot<span class=\"op\">.</span>key <span class=\"op\">==</span> key <span class=\"op\">{</span></span>\n<span id=\"cb14-44\"><a href=\"#cb14-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>                slot<span class=\"op\">.</span>stats<span class=\"op\">.</span>add(temp)<span class=\"op\">;</span></span>\n<span id=\"cb14-45\"><a href=\"#cb14-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"cf\">return</span><span class=\"op\">;</span></span>\n<span id=\"cb14-46\"><a href=\"#cb14-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb14-47\"><a href=\"#cb14-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>            idx <span class=\"op\">=</span> (idx <span class=\"op\">+</span> <span class=\"dv\">1</span>) <span class=\"op\">&amp;</span> TABLE_MASK<span class=\"op\">;</span> </span>\n<span id=\"cb14-48\"><a href=\"#cb14-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb14-49\"><a href=\"#cb14-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb14-50\"><a href=\"#cb14-50\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>The second thing is to fix up the output formatting:</p>\n<div class=\"sourceCode\" id=\"cb15\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb15-1\"><a href=\"#cb15-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> format_temperature_tenths(temp<span class=\"op\">:</span> Temp) <span class=\"op\">-&gt;</span> <span class=\"dt\">String</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-2\"><a href=\"#cb15-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">format!</span>(<span class=\"st\">&quot;{:.1}&quot;</span><span class=\"op\">,</span> temp <span class=\"kw\">as</span> <span class=\"dt\">f64</span> <span class=\"op\">/</span> <span class=\"dv\">10.0</span>)</span>\n<span id=\"cb15-3\"><a href=\"#cb15-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Into this: avoids the 17% of runtime in outputting the float:</p>\n<div class=\"sourceCode\" id=\"cb16\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb16-1\"><a href=\"#cb16-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> format_temperature_tenths(temp<span class=\"op\">:</span> Temp) <span class=\"op\">-&gt;</span> <span class=\"dt\">String</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-2\"><a href=\"#cb16-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> neg <span class=\"op\">=</span> temp <span class=\"op\">&lt;</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb16-3\"><a href=\"#cb16-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> abs <span class=\"op\">=</span> temp<span class=\"op\">.</span>unsigned_abs()<span class=\"op\">;</span></span>\n<span id=\"cb16-4\"><a href=\"#cb16-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> neg <span class=\"op\">{</span></span>\n<span id=\"cb16-5\"><a href=\"#cb16-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"pp\">format!</span>(<span class=\"st\">&quot;-{}.{}&quot;</span><span class=\"op\">,</span> abs <span class=\"op\">/</span> <span class=\"dv\">10</span><span class=\"op\">,</span> abs <span class=\"op\">%</span> <span class=\"dv\">10</span>)</span>\n<span id=\"cb16-6\"><a href=\"#cb16-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-7\"><a href=\"#cb16-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"pp\">format!</span>(<span class=\"st\">&quot;{}.{}&quot;</span><span class=\"op\">,</span> abs <span class=\"op\">/</span> <span class=\"dv\">10</span><span class=\"op\">,</span> abs <span class=\"op\">%</span> <span class=\"dv\">10</span>)</span>\n<span id=\"cb16-8\"><a href=\"#cb16-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb16-9\"><a href=\"#cb16-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>With both of those fixes, we get a dramatic improvement to 36ms\nruntime.</p>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/fast.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"parallelization\" class=\"level2\">\n<h2>Parallelization</h2>\n<p>After this, it\u2019s pretty unclear how to improve this single-threaded\nsolution any more. I decided to drop \u2013no-inline from my cargo\nflamegraphs since it said 90% of runtime was in\n<code>process_bytes</code> and the rest was inlined into it. But looking\nat the flamegraph while counting inlining, it seems like it\u2019s doing\nabout the minimal amount of work required.</p>\n<p>A simple way to use parallelism is to cut the input into equal sized\nchunks by the number of threads, and then join at the end.</p>\n<p>To chunk:</p>\n<div class=\"sourceCode\" id=\"cb17\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb17-1\"><a href=\"#cb17-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> chunks_for_threads(bytes<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]<span class=\"op\">,</span> threads<span class=\"op\">:</span> <span class=\"dt\">usize</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>(<span class=\"dt\">usize</span><span class=\"op\">,</span> <span class=\"dt\">usize</span>)<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb17-2\"><a href=\"#cb17-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> len <span class=\"op\">=</span> bytes<span class=\"op\">.</span>len()<span class=\"op\">;</span></span>\n<span id=\"cb17-3\"><a href=\"#cb17-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> threads <span class=\"op\">=</span> threads<span class=\"op\">.</span>min(len)<span class=\"op\">;</span></span>\n<span id=\"cb17-4\"><a href=\"#cb17-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> chunks <span class=\"op\">=</span> <span class=\"dt\">Vec</span><span class=\"pp\">::</span>with_capacity(threads)<span class=\"op\">;</span></span>\n<span id=\"cb17-5\"><a href=\"#cb17-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> start <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb17-6\"><a href=\"#cb17-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> index <span class=\"kw\">in</span> <span class=\"dv\">0</span><span class=\"op\">..</span>threads <span class=\"op\">{</span></span>\n<span id=\"cb17-7\"><a href=\"#cb17-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> start <span class=\"op\">&gt;=</span> len <span class=\"op\">{</span> <span class=\"cf\">break</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb17-8\"><a href=\"#cb17-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> end <span class=\"op\">=</span> <span class=\"cf\">if</span> index <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">==</span> threads <span class=\"op\">{</span></span>\n<span id=\"cb17-9\"><a href=\"#cb17-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            len</span>\n<span id=\"cb17-10\"><a href=\"#cb17-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb17-11\"><a href=\"#cb17-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            align_end_to_line(bytes<span class=\"op\">,</span> len <span class=\"op\">*</span> (index <span class=\"op\">+</span> <span class=\"dv\">1</span>) <span class=\"op\">/</span> threads)</span>\n<span id=\"cb17-12\"><a href=\"#cb17-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">};</span></span>\n<span id=\"cb17-13\"><a href=\"#cb17-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> start <span class=\"op\">&lt;</span> end <span class=\"op\">{</span> chunks<span class=\"op\">.</span>push((start<span class=\"op\">,</span> end))<span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb17-14\"><a href=\"#cb17-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        start <span class=\"op\">=</span> end<span class=\"op\">;</span></span>\n<span id=\"cb17-15\"><a href=\"#cb17-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb17-16\"><a href=\"#cb17-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    chunks</span>\n<span id=\"cb17-17\"><a href=\"#cb17-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb17-18\"><a href=\"#cb17-18\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb17-19\"><a href=\"#cb17-19\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> align_end_to_line(bytes<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">u8</span>]<span class=\"op\">,</span> pos<span class=\"op\">:</span> <span class=\"dt\">usize</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">usize</span> <span class=\"op\">{</span></span>\n<span id=\"cb17-20\"><a href=\"#cb17-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    memchr(<span class=\"ch\">b&#39;</span><span class=\"sc\">\\n</span><span class=\"ch\">&#39;</span><span class=\"op\">,</span> <span class=\"op\">&amp;</span>bytes[pos<span class=\"op\">..</span>])<span class=\"op\">.</span>map_or(bytes<span class=\"op\">.</span>len()<span class=\"op\">,</span> <span class=\"op\">|</span>offset<span class=\"op\">|</span> pos <span class=\"op\">+</span> offset <span class=\"op\">+</span> <span class=\"dv\">1</span>)</span>\n<span id=\"cb17-21\"><a href=\"#cb17-21\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>To run in parallel:</p>\n<div class=\"sourceCode\" id=\"cb18\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb18-1\"><a href=\"#cb18-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">fn</span> run_parallel_borrowed_mmap(input_path<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span><span class=\"op\">,</span> output_path<span class=\"op\">:</span> <span class=\"dt\">Option</span><span class=\"op\">&lt;&amp;</span><span class=\"dt\">str</span><span class=\"op\">&gt;,</span> threads<span class=\"op\">:</span> <span class=\"dt\">usize</span>) <span class=\"op\">-&gt;</span> <span class=\"pp\">io::</span><span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb18-2\"><a href=\"#cb18-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> file <span class=\"op\">=</span> <span class=\"pp\">File::</span>open(input_path)<span class=\"op\">?;</span></span>\n<span id=\"cb18-3\"><a href=\"#cb18-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> mmap <span class=\"op\">=</span> <span class=\"kw\">unsafe</span> <span class=\"op\">{</span> <span class=\"pp\">MmapOptions::</span>new()<span class=\"op\">.</span>map(<span class=\"op\">&amp;</span>file)<span class=\"op\">?</span> <span class=\"op\">};</span></span>\n<span id=\"cb18-4\"><a href=\"#cb18-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> chunks <span class=\"op\">=</span> chunks_for_threads(<span class=\"op\">&amp;</span>mmap<span class=\"op\">,</span> threads<span class=\"op\">.</span>max(<span class=\"dv\">1</span>))<span class=\"op\">;</span></span>\n<span id=\"cb18-5\"><a href=\"#cb18-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb18-6\"><a href=\"#cb18-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> local_tables <span class=\"op\">=</span> <span class=\"pp\">thread::</span>scope(<span class=\"op\">|</span>scope<span class=\"op\">|</span> <span class=\"op\">{</span></span>\n<span id=\"cb18-7\"><a href=\"#cb18-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> handles<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>_<span class=\"op\">&gt;</span> <span class=\"op\">=</span> chunks<span class=\"op\">.</span>iter()<span class=\"op\">.</span>map(<span class=\"op\">|&amp;</span>(start<span class=\"op\">,</span> end)<span class=\"op\">|</span> <span class=\"op\">{</span></span>\n<span id=\"cb18-8\"><a href=\"#cb18-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> bytes <span class=\"op\">=</span> <span class=\"op\">&amp;</span>mmap[start<span class=\"op\">..</span>end]<span class=\"op\">;</span></span>\n<span id=\"cb18-9\"><a href=\"#cb18-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            scope<span class=\"op\">.</span>spawn(<span class=\"kw\">move</span> <span class=\"op\">||</span> <span class=\"op\">{</span></span>\n<span id=\"cb18-10\"><a href=\"#cb18-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"kw\">let</span> <span class=\"kw\">mut</span> table <span class=\"op\">=</span> <span class=\"pp\">FlatTable::</span>new()<span class=\"op\">;</span></span>\n<span id=\"cb18-11\"><a href=\"#cb18-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>                process_bytes(bytes<span class=\"op\">,</span> <span class=\"op\">&amp;</span><span class=\"kw\">mut</span> table)<span class=\"op\">;</span></span>\n<span id=\"cb18-12\"><a href=\"#cb18-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>                table</span>\n<span id=\"cb18-13\"><a href=\"#cb18-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span>)</span>\n<span id=\"cb18-14\"><a href=\"#cb18-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span>)<span class=\"op\">.</span>collect()<span class=\"op\">;</span></span>\n<span id=\"cb18-15\"><a href=\"#cb18-15\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb18-16\"><a href=\"#cb18-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>        handles<span class=\"op\">.</span>into_iter()</span>\n<span id=\"cb18-17\"><a href=\"#cb18-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span>map(<span class=\"op\">|</span>h<span class=\"op\">|</span> h<span class=\"op\">.</span>join()<span class=\"op\">.</span>expect(<span class=\"st\">&quot;worker thread panicked&quot;</span>))</span>\n<span id=\"cb18-18\"><a href=\"#cb18-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">.</span><span class=\"pp\">collect::</span><span class=\"op\">&lt;</span><span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>_<span class=\"op\">&gt;&gt;</span>()</span>\n<span id=\"cb18-19\"><a href=\"#cb18-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span>)<span class=\"op\">;</span></span>\n<span id=\"cb18-20\"><a href=\"#cb18-20\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb18-21\"><a href=\"#cb18-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> table <span class=\"op\">=</span> <span class=\"pp\">FlatTable::</span>new()<span class=\"op\">;</span></span>\n<span id=\"cb18-22\"><a href=\"#cb18-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> local <span class=\"kw\">in</span> local_tables <span class=\"op\">{</span></span>\n<span id=\"cb18-23\"><a href=\"#cb18-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>        table<span class=\"op\">.</span>merge_from(<span class=\"op\">&amp;</span>local)<span class=\"op\">;</span></span>\n<span id=\"cb18-24\"><a href=\"#cb18-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb18-25\"><a href=\"#cb18-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"co\">// sort and write</span></span>\n<span id=\"cb18-26\"><a href=\"#cb18-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>To merge:</p>\n<div class=\"sourceCode\" id=\"cb19\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb19-1\"><a href=\"#cb19-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> merge_from(<span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">,</span> other<span class=\"op\">:</span> <span class=\"op\">&amp;</span>FlatTable<span class=\"op\">&lt;</span><span class=\"ot\">&#39;a</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb19-2\"><a href=\"#cb19-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> <span class=\"op\">&amp;</span>slot <span class=\"kw\">in</span> other<span class=\"op\">.</span>slots<span class=\"op\">.</span>iter() <span class=\"op\">{</span></span>\n<span id=\"cb19-3\"><a href=\"#cb19-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> slot<span class=\"op\">.</span>key<span class=\"op\">.</span>is_empty() <span class=\"op\">{</span> <span class=\"cf\">continue</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb19-4\"><a href=\"#cb19-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"kw\">mut</span> idx <span class=\"op\">=</span> table_index(slot<span class=\"op\">.</span>fingerprint<span class=\"op\">,</span> slot<span class=\"op\">.</span>key<span class=\"op\">.</span>len())<span class=\"op\">;</span></span>\n<span id=\"cb19-5\"><a href=\"#cb19-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">loop</span> <span class=\"op\">{</span></span>\n<span id=\"cb19-6\"><a href=\"#cb19-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> target <span class=\"op\">=</span> <span class=\"op\">&amp;</span><span class=\"kw\">mut</span> <span class=\"kw\">self</span><span class=\"op\">.</span>slots[idx]<span class=\"op\">;</span></span>\n<span id=\"cb19-7\"><a href=\"#cb19-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">if</span> target<span class=\"op\">.</span>key<span class=\"op\">.</span>is_empty() <span class=\"op\">{</span></span>\n<span id=\"cb19-8\"><a href=\"#cb19-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"op\">*</span>target <span class=\"op\">=</span> slot<span class=\"op\">;</span></span>\n<span id=\"cb19-9\"><a href=\"#cb19-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb19-10\"><a href=\"#cb19-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb19-11\"><a href=\"#cb19-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">if</span> target<span class=\"op\">.</span>fingerprint <span class=\"op\">==</span> slot<span class=\"op\">.</span>fingerprint <span class=\"op\">&amp;&amp;</span> target<span class=\"op\">.</span>key <span class=\"op\">==</span> slot<span class=\"op\">.</span>key <span class=\"op\">{</span></span>\n<span id=\"cb19-12\"><a href=\"#cb19-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>                target<span class=\"op\">.</span>stats<span class=\"op\">.</span>sum <span class=\"op\">+=</span> slot<span class=\"op\">.</span>stats<span class=\"op\">.</span>sum<span class=\"op\">;</span></span>\n<span id=\"cb19-13\"><a href=\"#cb19-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>                target<span class=\"op\">.</span>stats<span class=\"op\">.</span>count <span class=\"op\">+=</span> slot<span class=\"op\">.</span>stats<span class=\"op\">.</span>count<span class=\"op\">;</span></span>\n<span id=\"cb19-14\"><a href=\"#cb19-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>                target<span class=\"op\">.</span>stats<span class=\"op\">.</span>min <span class=\"op\">=</span> target<span class=\"op\">.</span>stats<span class=\"op\">.</span>min<span class=\"op\">.</span>min(slot<span class=\"op\">.</span>stats<span class=\"op\">.</span>min)<span class=\"op\">;</span></span>\n<span id=\"cb19-15\"><a href=\"#cb19-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>                target<span class=\"op\">.</span>stats<span class=\"op\">.</span>max <span class=\"op\">=</span> target<span class=\"op\">.</span>stats<span class=\"op\">.</span>max<span class=\"op\">.</span>max(slot<span class=\"op\">.</span>stats<span class=\"op\">.</span>max)<span class=\"op\">;</span></span>\n<span id=\"cb19-16\"><a href=\"#cb19-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb19-17\"><a href=\"#cb19-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb19-18\"><a href=\"#cb19-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>            idx <span class=\"op\">=</span> (idx <span class=\"op\">+</span> <span class=\"dv\">1</span>) <span class=\"op\">&amp;</span> TABLE_MASK<span class=\"op\">;</span></span>\n<span id=\"cb19-19\"><a href=\"#cb19-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb19-20\"><a href=\"#cb19-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb19-21\"><a href=\"#cb19-21\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>With that, we get a runtime of about 21ms.</p>\n<object type=\"image/svg+xml\" data=\"../assets/obrc/fast-par.svg\" width=\"100%\" height=\"100%\">\n</object>\n</section>\n<section id=\"conclusion\" class=\"level2\">\n<h2>Conclusion</h2>\n<p>In the end, we started out with about a 220ms runtime and got it down\nall the way to 21ms, about a 10x improvement. The first improvement of\njust using a hashmap did most of the work, down to 110ms, and each\nrespective improvement took more and more work to do for less and less\ngain.</p>\n<p>Cargo flamegraph made it easy to find hotspots, but it doesn\u2019t tell\nyou how to improve your solution \u2013 that requires hard thought, but it\u2019s\nuseful to figure out where there\u2019s room to improve.</p>\n</section>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2026-04-25T20:30:34+00:00"
		},
		{
			"id": "gen/bigints.html",
			"url": "gen/bigints.html",
			"title": "Bigints",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Bigints</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Bigints</h1>\n<p class=\"byline\">2026-03-02T18:32:16-05:00</p>\n</header>\n<p>Let\u2019s talk about writing Bigints. A Bigint is a data structure that\nallows one to do math on integers that are larger than the computer\u2019s\nregister size. On a 64 bit computer, registers are 64 bits, so if you\nwant to add two numbers that are larger than can fit in 64 bits, you\u2019d\nneed to put them in two registers or more per number, and then apply\neach mathematical operation to all the registers.</p>\n<p>Let\u2019s start off with a <code>u128</code> type. That would look\nsomething like this:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Debug</span><span class=\"op\">,</span> <span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> h<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> </span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> l<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> </span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>For addition, subtraction, and multiplication thankfully nightly rust\nhas <code>overflowing_*</code>, <code>widening_*</code> and\n<code>wrapping_*</code> methods on integers that allow us a simple\nimplementation.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> <span class=\"pp\">std::ops::</span><span class=\"bu\">Add</span> <span class=\"cf\">for</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">type</span> Output <span class=\"op\">=</span> <span class=\"dt\">Self</span><span class=\"op\">;</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"at\">#[</span>inline<span class=\"at\">(</span>never<span class=\"at\">)]</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> add(<span class=\"kw\">self</span><span class=\"op\">,</span> rhs<span class=\"op\">:</span> <span class=\"dt\">Self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Self</span><span class=\"pp\">::</span>Output <span class=\"op\">{</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> (l<span class=\"op\">,</span> carry) <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>l<span class=\"op\">.</span>overflowing_add(rhs<span class=\"op\">.</span>l)<span class=\"op\">;</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> h <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>h<span class=\"op\">.</span>wrapping_add(rhs<span class=\"op\">.</span>h)<span class=\"op\">.</span>wrapping_add(carry <span class=\"kw\">as</span> <span class=\"dt\">u64</span>)<span class=\"op\">;</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">Self</span> <span class=\"op\">{</span> l<span class=\"op\">,</span> h <span class=\"op\">}</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> <span class=\"pp\">std::ops::</span><span class=\"bu\">Sub</span> <span class=\"cf\">for</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">type</span> Output <span class=\"op\">=</span> <span class=\"dt\">Self</span><span class=\"op\">;</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"at\">#[</span>inline<span class=\"at\">(</span>never<span class=\"at\">)]</span></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> sub(<span class=\"kw\">self</span><span class=\"op\">,</span> rhs<span class=\"op\">:</span> <span class=\"dt\">Self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Self</span><span class=\"pp\">::</span>Output <span class=\"op\">{</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> (l<span class=\"op\">,</span> borrow) <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>l<span class=\"op\">.</span>overflowing_sub(rhs<span class=\"op\">.</span>l)<span class=\"op\">;</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> h <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>h<span class=\"op\">.</span>wrapping_sub(rhs<span class=\"op\">.</span>h)<span class=\"op\">.</span>wrapping_sub(borrow <span class=\"kw\">as</span> <span class=\"dt\">u64</span>)<span class=\"op\">;</span></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">Self</span> <span class=\"op\">{</span> l<span class=\"op\">,</span> h <span class=\"op\">}</span></span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> <span class=\"pp\">std::ops::</span><span class=\"bu\">Mul</span> <span class=\"cf\">for</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> mul(<span class=\"kw\">self</span><span class=\"op\">,</span> rhs<span class=\"op\">:</span> <span class=\"dt\">Self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Self</span><span class=\"pp\">::</span>Output <span class=\"op\">{</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> (p0_lo<span class=\"op\">,</span> p0_hi) <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>l<span class=\"op\">.</span>widening_mul(rhs<span class=\"op\">.</span>l)<span class=\"op\">;</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> t1_lo <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>l<span class=\"op\">.</span>wrapping_mul(rhs<span class=\"op\">.</span>h)<span class=\"op\">;</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> t2_lo <span class=\"op\">=</span> <span class=\"kw\">self</span><span class=\"op\">.</span>h<span class=\"op\">.</span>wrapping_mul(rhs<span class=\"op\">.</span>l)<span class=\"op\">;</span></span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> h <span class=\"op\">=</span> p0_hi<span class=\"op\">.</span>wrapping_add(t1_lo)<span class=\"op\">.</span>wrapping_add(t2_lo)<span class=\"op\">;</span></span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">Self</span> <span class=\"op\">{</span> h<span class=\"op\">,</span> l<span class=\"op\">:</span> p0_lo <span class=\"op\">}</span></span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>For division we have to handwrite and lean on the <code>u128</code>\ntype, but we get a pretty nice result in the end:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">impl</span> <span class=\"pp\">std::ops::</span><span class=\"bu\">Div</span> <span class=\"cf\">for</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">fn</span> div(<span class=\"kw\">self</span><span class=\"op\">,</span> rhs<span class=\"op\">:</span> <span class=\"dt\">Self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Self</span><span class=\"pp\">::</span>Output <span class=\"op\">{</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> n <span class=\"op\">=</span> (<span class=\"kw\">self</span><span class=\"op\">.</span>h <span class=\"kw\">as</span> <span class=\"dt\">u128</span>) <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">64</span> <span class=\"op\">|</span> <span class=\"kw\">self</span><span class=\"op\">.</span>l <span class=\"kw\">as</span> <span class=\"dt\">u128</span><span class=\"op\">;</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> d <span class=\"op\">=</span> (rhs<span class=\"op\">.</span>h <span class=\"kw\">as</span> <span class=\"dt\">u128</span>) <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">64</span> <span class=\"op\">|</span> rhs<span class=\"op\">.</span>l <span class=\"kw\">as</span> <span class=\"dt\">u128</span><span class=\"op\">;</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> q <span class=\"op\">=</span> n <span class=\"op\">/</span> d<span class=\"op\">;</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">Self</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>            l<span class=\"op\">:</span> q <span class=\"kw\">as</span> <span class=\"dt\">u64</span><span class=\"op\">,</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>            h<span class=\"op\">:</span> (q <span class=\"op\">&gt;&gt;</span> <span class=\"dv\">64</span>) <span class=\"kw\">as</span> <span class=\"dt\">u64</span><span class=\"op\">,</span></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>The assembly delegates to a compiler builtin called\n<code>__udivti3</code>, so our code is pretty much loads that up and all\nthe hairy work is done for us.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>&lt;bigints<span class=\"op\">::</span>u128<span class=\"op\">::</span>Uint128 as core<span class=\"op\">::</span>ops<span class=\"op\">::</span>arith<span class=\"op\">::</span>Div<span class=\"op\">&gt;::</span>div<span class=\"op\">:</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">push</span> <span class=\"kw\">rax</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rdx</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">or</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rcx</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">je</span> <span class=\"op\">.</span>LBB_2</span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">call</span> <span class=\"dt\">qword</span> <span class=\"dt\">ptr</span> <span class=\"op\">[</span>rip <span class=\"op\">+</span> __udivti3<span class=\"fu\">@</span><span class=\"er\">G</span>OTPCREL<span class=\"op\">]</span></span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">pop</span> <span class=\"kw\">rcx</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">ret</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">.LBB_2:</span></span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">lea</span> <span class=\"kw\">rdi</span><span class=\"op\">,</span> <span class=\"op\">[</span>rip <span class=\"op\">+</span> <span class=\"op\">.</span>Lanon<span class=\"op\">.</span><span class=\"dv\">12</span><span class=\"op\">]</span></span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">call</span> <span class=\"dt\">qword</span> <span class=\"dt\">ptr</span> <span class=\"op\">[</span>rip <span class=\"op\">+</span> core<span class=\"op\">::</span>panicking<span class=\"op\">::</span>panic_const<span class=\"op\">::</span>panic_const_div_by_zero<span class=\"fu\">@</span><span class=\"er\">G</span>OTPCREL<span class=\"op\">]</span></span></code></pre></div>\n<p>And that\u2019s it, right?</p>\n<p>Sadly I wrote a bug in the beginning for my platform (x86_64). The\nbigints struct has to flip its members since this is a little-endian\nplatform.</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Debug</span><span class=\"op\">,</span> <span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> l<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> </span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> h<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> </span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Otherwise the multiplication incurs two extra <code>mov</code>s at\nthe start of the function to load the members into the right place.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">mov</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rdx</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">mov</span> <span class=\"kw\">rdx</span><span class=\"op\">,</span> <span class=\"kw\">rcx</span></span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">mulx</span> <span class=\"kw\">r8</span><span class=\"op\">,</span> <span class=\"kw\">rdx</span><span class=\"op\">,</span> <span class=\"kw\">rsi</span></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">imul</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rsi</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">imul</span> <span class=\"kw\">rdi</span><span class=\"op\">,</span> <span class=\"kw\">rcx</span></span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">add</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rdi</span></span>\n<span id=\"cb8-7\"><a href=\"#cb8-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">add</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">r8</span></span></code></pre></div>\n<p>If you write the struct the other way, i.e:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Debug</span><span class=\"op\">,</span> <span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_endian <span class=\"op\">=</span> <span class=\"st\">&quot;little&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> l<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> <span class=\"co\">// bits 0-63 (lower address)</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> h<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> <span class=\"co\">// bits 64-127 (higher address)</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>derive<span class=\"at\">(</span><span class=\"bu\">Debug</span><span class=\"op\">,</span> <span class=\"bu\">Clone</span><span class=\"op\">,</span> <span class=\"bu\">Copy</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_endian <span class=\"op\">=</span> <span class=\"st\">&quot;big&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">struct</span> Uint128 <span class=\"op\">{</span></span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> h<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> <span class=\"co\">// bits 64-127 (lower address)</span></span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">pub</span> l<span class=\"op\">:</span> <span class=\"dt\">u64</span><span class=\"op\">,</span> <span class=\"co\">// bits 0-63 (higher address)</span></span>\n<span id=\"cb9-13\"><a href=\"#cb9-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Then the two <code>mov</code>s disappear from the x86_64 generated\ncodegen.</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">mulx</span> <span class=\"kw\">r8</span><span class=\"op\">,</span> <span class=\"kw\">rdx</span><span class=\"op\">,</span> <span class=\"kw\">rsi</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">imul</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rsi</span></span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">imul</span> <span class=\"kw\">rdi</span><span class=\"op\">,</span> <span class=\"kw\">rcx</span></span>\n<span id=\"cb10-4\"><a href=\"#cb10-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">add</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rdi</span></span>\n<span id=\"cb10-5\"><a href=\"#cb10-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">add</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">r8</span></span></code></pre></div>\n<p>Now I needed a way to make sure all my operations were closer to\nnative, so I wrote up a test harness that used\n<code>cargo-show-asm</code> to check the generated assembly on a variety\nof platforms (including a big-endian one, s390x) to make sure that there\nwere no unnecessary moves being produced.</p>\n<p>I used this and compared my implementations to native to see if they\nwere being properly optimized and found out that for aarch64, using\n<code>overflowing_sub</code> and <code>wrapping_sub</code> nets\nthis:</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>&lt;bigints<span class=\"op\">::</span>u128<span class=\"op\">::</span>Uint128 as core<span class=\"op\">::</span>ops<span class=\"op\">::</span>arith<span class=\"op\">::</span>Sub<span class=\"op\">&gt;::</span>sub<span class=\"op\">:</span>                                                                                                                                                                                                                                                                                                                                </span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subs x0<span class=\"op\">,</span> x0<span class=\"op\">,</span> x2                                                                                                                                                                                                                                                                                                                                                                    </span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sub</span> x8<span class=\"op\">,</span> x1<span class=\"op\">,</span> x3                                                                                                                                                                                                                                                                                                                                                                     </span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    cset w9<span class=\"op\">,</span> lo                                                                                                                                                                                                                                                                                                                                                                        </span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sub</span> x1<span class=\"op\">,</span> x8<span class=\"op\">,</span> x9                                                                                                                                                                                                                                                                                                                                                                     </span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">ret</span>                                                                                                                                                                                                                                                                                                                                                                                </span></code></pre></div>\n<p>Whereas the native version looks like so:</p>\n<div class=\"sourceCode\" id=\"cb12\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb12-1\"><a href=\"#cb12-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>&lt;bigints<span class=\"op\">::</span>u128<span class=\"op\">::</span>Uint128 as core<span class=\"op\">::</span>ops<span class=\"op\">::</span>arith<span class=\"op\">::</span>Sub<span class=\"op\">&gt;::</span>sub<span class=\"op\">:</span>                                                                                                                                                                                                                                                                                                                                </span>\n<span id=\"cb12-2\"><a href=\"#cb12-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  subs x0<span class=\"op\">,</span> x0<span class=\"op\">,</span> x2</span>\n<span id=\"cb12-3\"><a href=\"#cb12-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  sbc  x1<span class=\"op\">,</span> x1<span class=\"op\">,</span> x3</span>\n<span id=\"cb12-4\"><a href=\"#cb12-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">ret</span></span></code></pre></div>\n<p>While for x86_64, it\u2019s properly optimized:</p>\n<div class=\"sourceCode\" id=\"cb13\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>&lt;bigints<span class=\"op\">::</span>u128<span class=\"op\">::</span>Uint128 as core<span class=\"op\">::</span>ops<span class=\"op\">::</span>arith<span class=\"op\">::</span>Sub<span class=\"op\">&gt;::</span>sub<span class=\"op\">:</span></span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rdi</span></span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sub</span> <span class=\"kw\">rax</span><span class=\"op\">,</span> <span class=\"kw\">rdx</span></span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sbb</span> <span class=\"kw\">rsi</span><span class=\"op\">,</span> <span class=\"kw\">rcx</span></span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span> <span class=\"kw\">rdx</span><span class=\"op\">,</span> <span class=\"kw\">rsi</span></span>\n<span id=\"cb13-6\"><a href=\"#cb13-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">ret</span></span></code></pre></div>\n<p>As well, for multiplication, there\u2019s an extra instruction due to\nscheduling:</p>\n<div class=\"sourceCode\" id=\"cb14\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb14-1\"><a href=\"#cb14-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>&lt;bigints<span class=\"op\">::</span>u128<span class=\"op\">::</span>Uint128 as core<span class=\"op\">::</span>ops<span class=\"op\">::</span>arith<span class=\"op\">::</span>Mul<span class=\"op\">&gt;::</span>mul<span class=\"op\">:</span></span>\n<span id=\"cb14-2\"><a href=\"#cb14-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mul</span> x9<span class=\"op\">,</span> x2<span class=\"op\">,</span> x1</span>\n<span id=\"cb14-3\"><a href=\"#cb14-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mul</span> x8<span class=\"op\">,</span> x2<span class=\"op\">,</span> x0</span>\n<span id=\"cb14-4\"><a href=\"#cb14-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    umulh x10<span class=\"op\">,</span> x2<span class=\"op\">,</span> x0</span>\n<span id=\"cb14-5\"><a href=\"#cb14-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    madd x9<span class=\"op\">,</span> x3<span class=\"op\">,</span> x0<span class=\"op\">,</span> x9</span>\n<span id=\"cb14-6\"><a href=\"#cb14-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span> x0<span class=\"op\">,</span> x8</span>\n<span id=\"cb14-7\"><a href=\"#cb14-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">add</span> x1<span class=\"op\">,</span> x9<span class=\"op\">,</span> x10</span>\n<span id=\"cb14-8\"><a href=\"#cb14-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">ret</span></span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb15\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb15-1\"><a href=\"#cb15-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>&lt;bigints<span class=\"op\">::</span>u128<span class=\"op\">::</span>Uint128 as core<span class=\"op\">::</span>ops<span class=\"op\">::</span>arith<span class=\"op\">::</span>Mul<span class=\"op\">&gt;::</span>mul<span class=\"op\">:</span></span>\n<span id=\"cb15-2\"><a href=\"#cb15-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    umulh x10<span class=\"op\">,</span> x0<span class=\"op\">,</span> x2    </span>\n<span id=\"cb15-3\"><a href=\"#cb15-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mul</span> x9<span class=\"op\">,</span> x1<span class=\"op\">,</span> x2       </span>\n<span id=\"cb15-4\"><a href=\"#cb15-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    madd x9<span class=\"op\">,</span> x3<span class=\"op\">,</span> x0<span class=\"op\">,</span> x9  </span>\n<span id=\"cb15-5\"><a href=\"#cb15-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mul</span> x0<span class=\"op\">,</span> x0<span class=\"op\">,</span> x2       </span>\n<span id=\"cb15-6\"><a href=\"#cb15-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">add</span> x1<span class=\"op\">,</span> x9<span class=\"op\">,</span> x10      </span>\n<span id=\"cb15-7\"><a href=\"#cb15-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">ret</span></span></code></pre></div>\n<p>I assume this is an LLVM backend issue somewhere, but it\u2019s hard to\nfault them, I doubt anyone would write this code anyway since the u128\ntypes exist.</p>\n<p>The resulting code is here: <a\nhref=\"https://github.com/takashiidobe/bigints\">Bigints</a></p>\n</article>\n</body>\n</html>\n",
			"date_published": "2026-03-02T23:32:16+00:00"
		},
		{
			"id": "gen/assembly-language.html",
			"url": "gen/assembly-language.html",
			"title": "Assembly Language",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Assembly Language</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Assembly Language</h1>\n<p class=\"byline\">2025-12-02T22:28:56-05:00</p>\n</header>\n<p>Confession: I don\u2019t know much about assembly. Thankfully compilers\nare good enough these days that it doesn\u2019t matter, but I\u2019ve always been\ncurious about writing assembly as is. I ended up writing some m68k\nassembly last post when writing an m68k to x86_64 interpreter. So I had\nthe bright idea to write my own assembly language. For fun.</p>\n<p>Now the actual plan was as follows: write an assembly language spec,\nwrite an interpreter, and write an encoder/decoder (so I could test out\nhow different design decisions affected code density in the binary). My\nfirst order of business was to decide on the size of my opcodes. I\ndecided to go with 16-bit like the m68k \u2013 I thought it would be spartan\nenough to not endlessly iterate and be compact yet give me enough space\nto design instructions. My first decision was to reverse one design\ndecision I think hampered the m68k, splitting registers into address and\ndata registers.</p>\n<p>On the m68k, there are 16 32-bit registers. This is for a CPU that\ncame out in 1979; compare it to a similar Intel CPU at the time, the\n8086. The 8086 came with 8 16-bit registers. You get 2 times the\nregisters with 2 times the bit-width. Sadly, with the data\nregister/address register split, the 8 data registers store the usual\ndata and the 8 address registers are for indirect accessing of memory. I\nassume this was chosen because this made registers take 3-bits (2^3 = 8)\ninstead of 4-bits (2^4 = 16), and because the m68k had support for 8\neffective addressing modes on its two operands, which took up 6 bits in\ntotal (EA + Reg). Given a 4-bit group, you\u2019d be left with another 3 bits\nfor the register for a binary operator, or to do what you wanted.</p>\n<p>I wanted to see if it was possible to support 16 registers, so I bit\nthe 4-bit bullet per register. Given that an instruction set needs to\nhave at least 30 must have instructions, you also need to reserve at\nleast 5 bits for every instruction so you know which opcode to use. I\ndecided to go with a scheme that would allow me to have up to 64\ninstructions \u2013 a 4-bit major group, with a further 2-bits subdividing\neach group with 4 instructions each, so I would have 16 groups with 4\nsubgroups in each group. This left me with 10-bits. You see the problem.\nIf each register costs you 4-bits, and you have 2 of them, you\u2019re left\nwith 2 bits per instruction. But wait, there\u2019s more. Each instruction\nmust also carry bits for its size. I wanted 16 64-bit registers, so each\ninstruction had to support an 8-bit, 16-bit, 32-bit, and 64-bit variant\n(I called these byte, short, long, word). This is 4 choices, so this\ntakes up 2-bits.</p>\n<p>So there you have it. Each binary instruction has 4-bits for group,\n4-bits for subgroup, 2-bits for size, 4-bits for register 1 (which is\nthe target) and 4-bits for register 2. This works out for most\ninstructions, like arithmetic ones, but you cannot do an arithmetic\noperation + change the addressing mode.</p>\n<p>To do so, I added three instructions as full 12-bit instructions.\n<code>lea</code>, (load effective address), a load and store\ninstruction. These took up 4 instructions a pop (since they take up a\nwhole group), but I was able to cram in a 2-bit effective address for\neach of these.</p>\n<p>The effective addresses are:</p>\n<ol type=\"1\">\n<li>register direct, as is: <code>%rX</code></li>\n<li>register indirect, the address of the register,\n<code>(%rX)</code></li>\n<li>immediate, <code>$10</code></li>\n<li>offset indirect <code>-4(%sp)</code></li>\n</ol>\n<p>Since you can only place this on either the src or the target, this\nis a bit barebones, but it works out fine.</p>\n<p>I decided not to go with a condition flag design (like m68k, arm,\nx86) and take a flagless design \u2013 in exchange though, you have to\nimplement a lot of branching operations. For the branching\ninstructions:</p>\n<ol type=\"1\">\n<li>Branch if Equal</li>\n<li>Branch if not equal</li>\n<li>Branch less than</li>\n<li>Branch less than equal</li>\n<li>Branch if Zero</li>\n<li>Branch if not zero</li>\n</ol>\n<p>I could\u2019ve gone with a sparser set, but I figured it\u2019d be ok to use\nthe instructions since branching is quite commonplace. For the cmp side,\nI decided to go with a sparser set, explicitly requiring a not or a flip\nof operands to get <code>&lt;=</code>, <code>&gt;</code>, and\n<code>&gt;=</code>.</p>\n<ol type=\"1\">\n<li>Cmp equal</li>\n<li>Cmp not equal</li>\n<li>Cmp less than equal</li>\n<li>Cmp less than</li>\n</ol>\n<p>I also wanted compact operations that used immediates a lot, so I\nprovided immediate verisons of add, sub, mul, mov. If I dropped the\nsize, I could have 6-bits left over. So I can have immediates from\n0..63. However, I really wanted to be able to use <code>64</code>. It\nturns out you actually can support the range of 0..64 for these ops:</p>\n<p>For <code>add</code> and <code>sub</code> with 0, this does nothing,\nso you can read this code and emit a no-op instead. For <code>mul</code>\nand <code>mov</code>, it zeroes out the target register. You can do the\nsame with <code>xor %rX, %rX</code>, which zeroes out the target\nregister. Thus, in the textual assembly format, You can support 65\nvalues (which requires 7-bits) by rewriting the last case to something\nsupported. You can also do this with div (rewrite\n<code>div %rX, $0</code> with <code>trap</code>), or <code>mod</code> as\nwell.</p>\n<p>I decided to add a few extra assembly directives:</p>\n<ul>\n<li><code>.byte</code> to include a byte array,</li>\n<li><code>.ascii</code> to include an ascii string,</li>\n<li><code>.asciz</code> to include an ascii string with a null\nterminator</li>\n<li><code>.include</code> to include the file copy pasted as in C, to\nlink multiple assembly files together.</li>\n</ul>\n<p>After hooking up syscall write on linux, you can write assembly\npretty well:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>        movi <span class=\"op\">%</span>r0<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">1</span>         <span class=\"op\">#</span> syscall write </span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>        movi <span class=\"op\">%</span>r1<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">1</span>         <span class=\"op\">#</span> stdout</span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">load</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r2<span class=\"op\">,</span> msg      <span class=\"op\">#</span> r2 <span class=\"op\">=</span> <span class=\"op\">&amp;</span>msg</span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        movi <span class=\"op\">%</span>r3<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">12</span>        <span class=\"op\">#</span> length</span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        trap                 <span class=\"op\">#</span> perform write</span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">ret</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">msg:</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        .asciz <span class=\"st\">&quot;hello world\\n&quot;</span></span></code></pre></div>\n<p>And recursive fibonacci isn\u2019t so bad:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a># Calculate fib<span class=\"op\">(</span><span class=\"dv\">10</span><span class=\"op\">)</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>        movi <span class=\"op\">%</span>r1<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">10</span>        <span class=\"op\">#</span> n <span class=\"op\">=</span> <span class=\"dv\">10</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">call</span> fib</span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">jmp</span> done</span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">fib:</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # Prologue<span class=\"op\">:</span> save caller<span class=\"op\">-</span>saved registers</span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">push</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r2</span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">push</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r3</span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # Base case<span class=\"op\">:</span> if n <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">,</span> return <span class=\"dv\">0</span></span>\n<span id=\"cb2-12\"><a href=\"#cb2-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        brz<span class=\"op\">.</span>l <span class=\"op\">%</span>r1<span class=\"op\">,</span> base_case</span>\n<span id=\"cb2-13\"><a href=\"#cb2-13\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-14\"><a href=\"#cb2-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # Base case<span class=\"op\">:</span> if n <span class=\"op\">==</span> <span class=\"dv\">1</span><span class=\"op\">,</span> return <span class=\"dv\">1</span></span>\n<span id=\"cb2-15\"><a href=\"#cb2-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">mov</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r3<span class=\"op\">,</span> <span class=\"op\">%</span>r1</span>\n<span id=\"cb2-16\"><a href=\"#cb2-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>        subi<span class=\"op\">.</span>l <span class=\"op\">%</span>r3<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">1</span></span>\n<span id=\"cb2-17\"><a href=\"#cb2-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>        brz<span class=\"op\">.</span>l <span class=\"op\">%</span>r3<span class=\"op\">,</span> base_case</span>\n<span id=\"cb2-18\"><a href=\"#cb2-18\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-19\"><a href=\"#cb2-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # Recursive case<span class=\"op\">:</span> fib<span class=\"op\">(</span>n<span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb2-20\"><a href=\"#cb2-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>        subi  <span class=\"op\">%</span>r1<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">1</span></span>\n<span id=\"cb2-21\"><a href=\"#cb2-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">push</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r1            <span class=\"op\">#</span> Save n<span class=\"op\">-</span><span class=\"dv\">1</span></span>\n<span id=\"cb2-22\"><a href=\"#cb2-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">call</span> fib</span>\n<span id=\"cb2-23\"><a href=\"#cb2-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">mov</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r2<span class=\"op\">,</span> <span class=\"op\">%</span>r0        <span class=\"op\">#</span> r2 <span class=\"op\">=</span> fib<span class=\"op\">(</span>n<span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb2-24\"><a href=\"#cb2-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">pop</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r1             <span class=\"op\">#</span> Restore n<span class=\"op\">-</span><span class=\"dv\">1</span></span>\n<span id=\"cb2-25\"><a href=\"#cb2-25\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-26\"><a href=\"#cb2-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # fib<span class=\"op\">(</span>n<span class=\"op\">-</span><span class=\"dv\">2</span><span class=\"op\">)</span></span>\n<span id=\"cb2-27\"><a href=\"#cb2-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>        subi<span class=\"op\">.</span>l <span class=\"op\">%</span>r1<span class=\"op\">,</span> <span class=\"op\">$</span><span class=\"bn\">1</span></span>\n<span id=\"cb2-28\"><a href=\"#cb2-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">push</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r1</span>\n<span id=\"cb2-29\"><a href=\"#cb2-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">call</span> fib</span>\n<span id=\"cb2-30\"><a href=\"#cb2-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">mov</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r3<span class=\"op\">,</span> <span class=\"op\">%</span>r0        <span class=\"op\">#</span> r3 <span class=\"op\">=</span> fib<span class=\"op\">(</span>n<span class=\"op\">-</span><span class=\"dv\">2</span><span class=\"op\">)</span></span>\n<span id=\"cb2-31\"><a href=\"#cb2-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">pop</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r1</span>\n<span id=\"cb2-32\"><a href=\"#cb2-32\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-33\"><a href=\"#cb2-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # Return fib<span class=\"op\">(</span>n<span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span> <span class=\"op\">+</span> fib<span class=\"op\">(</span>n<span class=\"op\">-</span><span class=\"dv\">2</span><span class=\"op\">)</span></span>\n<span id=\"cb2-34\"><a href=\"#cb2-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">mov</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r0<span class=\"op\">,</span> <span class=\"op\">%</span>r2</span>\n<span id=\"cb2-35\"><a href=\"#cb2-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">add</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r0<span class=\"op\">,</span> <span class=\"op\">%</span>r3</span>\n<span id=\"cb2-36\"><a href=\"#cb2-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">jmp</span> end_fib</span>\n<span id=\"cb2-37\"><a href=\"#cb2-37\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-38\"><a href=\"#cb2-38\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">base_case:</span></span>\n<span id=\"cb2-39\"><a href=\"#cb2-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">mov</span><span class=\"op\">.</span>l <span class=\"op\">%</span>r0<span class=\"op\">,</span> <span class=\"op\">%</span>r1        <span class=\"op\">#</span> Return n</span>\n<span id=\"cb2-40\"><a href=\"#cb2-40\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-41\"><a href=\"#cb2-41\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">end_fib:</span></span>\n<span id=\"cb2-42\"><a href=\"#cb2-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>        # Epilogue<span class=\"op\">:</span> restore registers</span>\n<span id=\"cb2-43\"><a href=\"#cb2-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">pop</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r3</span>\n<span id=\"cb2-44\"><a href=\"#cb2-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">pop</span><span class=\"op\">.</span>w <span class=\"op\">%</span>r2</span>\n<span id=\"cb2-45\"><a href=\"#cb2-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">ret</span></span>\n<span id=\"cb2-46\"><a href=\"#cb2-46\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-47\"><a href=\"#cb2-47\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">done:</span></span>\n<span id=\"cb2-48\"><a href=\"#cb2-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"bu\">nop</span></span></code></pre></div>\n<p>I really enjoyed this project \u2013 it was interesting to design an\nassembly language, since it made me value what instructions could be\nsupported with such little space. I still won\u2019t be writing assembly, but\nat least I can understand why it\u2019s so hard to design a good ISA!</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2025-12-03T03:28:56+00:00"
		},
		{
			"id": "gen/an-m68k-to-x86-64-linux-interpreter.html",
			"url": "gen/an-m68k-to-x86-64-linux-interpreter.html",
			"title": "An M68k to x86_64 linux interpreter",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>An M68k to x86_64 linux interpreter</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">An M68k to x86_64 linux interpreter</h1>\n<p class=\"byline\">2025-11-28T19:17:00-05:00</p>\n</header>\n<p>I\u2019ve always been interested in Virtual Machines, even having a copy\nof <a\nhref=\"https://www.amazon.com/Virtual-Machines-Versatile-Platforms-Architecture/dp/1558609105\">Virtual\nMachines: Versatile Platforms</a> on my bookshelf. I decided it would be\nfun to implement a program that could read an m68000 ELF binary and run\nit on my x86_64 linux computer. The repo is here: <a\nhref=\"https://github.com/Takashiidobe/behistun/\">Behistun</a>.</p>\n<p>First things first, we had to compile some m68k ELF binaries. I fired\nup my copy of crosstool and made myself an\n<code>m68k-unknown-linux-gnu-gcc</code> toolchain.</p>\n<p>To decode a binary, you have to first read the relevant ELF sections\nof a binary. To do so, I used the <code>goblin</code> library, which\ntook care of that. The rest was to decode each instruction, and then\nexecute it on a virtual CPU.</p>\n<p>So, I started writing out a file with a new <code>m68k</code>\nassembly instruction, compiled it, and then tried to decode it with my\nprogram. This would fail, so I would go to work decoding it.</p>\n<p>I did this until I implemented the whole <code>m68000</code> set,\nwhich wasn\u2019t too bad, given that the <code>m68k</code> instruction set\nis pretty compact. After decoding, I had to write a CPU that would\nemulate everything, and I was good to go. This took a bit longer than\nplain decoding, but after I got this to work out. Perfect! A fun little\nweekend project, right?</p>\n<p>Unfortunately I wanted more. And this is where the pain really\nstarted. I wanted to compile C code for the <code>m68000</code> and run\nit on my little interpreter. Couldn\u2019t be so bad, right?</p>\n<p>Unfortunately not. I wrote <code>cat</code> in c and then compiled it\nand tried to run it on my interpreter \u2013 decoding error. It turned out\nthat the ELF binary had smuggled in an <code>fmove</code> (floating\npoint register move). Why does <code>cat</code>, a program which does\nnot have any floating point usage, need to move a floating point\nregister?</p>\n<p>No matter what flags you use to compile your code, <code>glibc</code>\nfor the <code>m68k</code> target actually is compiled with floating\npoint support. Thus, it\u2019s not possible to use <code>glibc</code> as your\n<code>libc</code> for compiling <code>m68000</code>. Bummer. Sadly this\ntook me a day of searching to find out why floating point registers were\nbeing smuggled into my user code. The <code>-mcpu=X</code> flag was\nuseless, even using <code>-msoft-float</code> was useless. Anyway, I\ndecided to go back to crosstool and try to compile a <code>musl</code>\ntoolchain. Musl would never betray me, would it?</p>\n<p>Sadly it too requires floating point registers, and thus does not\nsupport the 68000, on <code>setjmp</code>, to clear registers. I was\nlosing hope. But crosstool supports one last libc.\n<code>uclibc-ng</code>. And <code>uclibc</code> delivered. It actually\ndid support non-floating point <code>m68k</code> and we were in\nbusiness. I compiled for the <code>m68020</code> to play it safe (each\ncompiler takes about 30 minutes to compile on my computer), and was back\nat my interpreter, ready to compile some C.</p>\n<p>To get <code>cat</code> to work though, I needed to do some syscall\npassthrough. I needed to map the <code>m68000</code>\u2019s pointers from\nguest to host, and also map the syscall numbers from m68k linux to\nx86_64 linux. But once that was done, I could finally write C, compile\nto m68000 linux elf, and run it on my x86_64 linux elf machine.</p>\n<p>Of course, there was a bit more to do \u2013 I had to implement the rest\nof the <code>m68010</code> and <code>m68020</code> instruction set,\nwhich I discovered I didn\u2019t complete by using fuzzing to generate random\nC programs with <code>csmith</code>, so I implemented those\ninstructions, and was off to the races \u2013 all I had to do was implement\nsyscalls.</p>\n<p>In the end, I decided to translate about 200 or so syscalls, wrote\ntests for them, and tested them out against\n<code>qemu-m68k-static</code> for compatibility. There\u2019s plenty more\nsyscalls left to do, but I figured these would be a good chunk of\nsyscalls, so I was done with that. Maybe I\u2019ll come back and implement\nthe rest of them, who knows. The remaining ones are really tough, so I\nskipped most of those.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2025-11-29T00:17:00+00:00"
		},
		{
			"id": "gen/writing-rust-for-the-atari-mint.html",
			"url": "gen/writing-rust-for-the-atari-mint.html",
			"title": "Writing Rust for the Atari Mint",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing Rust for the Atari Mint</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing Rust for the Atari Mint</h1>\n<p class=\"byline\">2025-11-28T18:21:40-05:00</p>\n</header>\n<p>Recently I decided to get into a retrocomputing mood. I watched <a\nhref=\"https://www.youtube.com/watch?v=8VsiYWW9r48&amp;list=PLzH6n4zXuckpwdGMHgRH5N9xNHzVGCxwf\">Matt\nGodbolt\u2019s videos on Computerphile talking about how computers work</a>\nand after listening to him talk about learning how to program on these\nold computers, I was ready to learn more. I was ready to open my wallet\nand buy a retrocomputer and test out programming on these computers. On\nebay an Atari ST costs about $200. I reached into my pocket to grab my\ncredit card to buy one before coming to the realization that I\u2019m broke.\nLuckily, there\u2019s a pretty active community programming these retro\ncomputers, complete with emulators. I found a couple emulators like <a\nhref=\"https://aranym.github.io/\">aranym</a> <a\nhref=\"https://hatari-emu.org/\">hatari</a> and went on my way.</p>\n<p>You could write code for these emulators in assembly or C, due to\nthere being a gcc toolchain for them: <a\nhref=\"https://tho-otto.de/crossmint.php\"\nclass=\"uri\">https://tho-otto.de/crossmint.php</a>. I downloaded gcc,\nhooked up binutils and libraries, and started to write some code.</p>\n<p>I went to go write some simple coreutils for the emulator, but\ncompiling my first binary (<code>rm</code>), my binary was &gt;100KB.\nGiven that the atari ST was supposed to run on 1.44MB floppies, eating\nup a little over 1/15th of your storage on a 50-line C program is a\nlittle absurd.</p>\n<p>It turns out that the <code>libc</code> that the Atari mint toolchain\nships with links to a library called <code>mintlib</code>, which is a\npretty complete <code>libc</code>, but its binaries are huge. There\u2019s an\nalternative <code>libc</code> which isn\u2019t as complete, called\n<code>libcmini</code>. I linked to that <code>libc</code> instead and\nsaw the familiar file size of 4KB. Nice.</p>\n<p>However, the binaries are still pretty large if you think about it.\nAn assembly version of this would probably fit in a few hundred bytes,\nso C in this case does have a pretty large penalty.</p>\n<p>I decided to start writing my own minimalistic <code>libc</code> and\nincrementally build out some parts of it. The first part was the C\nruntime, <code>crt0.S</code>. Afterwards, writing initializers and\nfinalizers, setting up the stack, env vars, and jumping to start. All of\nthis was pretty tricky but doable. Some interesting bits were the system\ncalls: <a\nhref=\"https://github.com/Takashiidobe/mintbox/blob/main/src/libc/include/mint/mintbind.h\">mintbind.h</a>\nwhere, given this isn\u2019t a Linux OS, a lot of the system calls are pretty\ninteresting \u2013 there\u2019s even a \u201cmalloc\u201d so you can delegate memory\nmanagement to the kernel.</p>\n<p>While writing the libc was fun to see what was under the hood, I\nwanted some higher-level code. So I decided I wanted to write Rust.\nFirst things first \u2013 I downloaded the <code>a.out</code> toolchain from\nThorsten Otto\u2019s website. I needed the ELF one, since that was what\nrust\u2019s toolchain supported. Next, I had to write up a <a\nhref=\"https://github.com/Takashiidobe/mints/blob/main/m68k-atari-mintelf.json\">target.json\nfile</a>, describing the properties of the architecture I was\ntargeting.</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode json\"><code class=\"sourceCode json\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">{</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;arch&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;m68k&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;atomic-cas&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">false</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;cpu&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;M68040&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;crt-objects-fallback&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;false&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;crt-static-default&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">false</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;crt-static-respected&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">false</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;code-model&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;large&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;data-layout&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;dynamic-linking&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">true</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;eh-frame-header&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">false</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-12\"><a href=\"#cb1-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;executables&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">true</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-13\"><a href=\"#cb1-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;has-rpath&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">true</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-14\"><a href=\"#cb1-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;has-thread-local&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">true</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-15\"><a href=\"#cb1-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;linker&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;m68k-atari-mintelf-gcc&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-16\"><a href=\"#cb1-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;llvm-target&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;m68k-unknown-elf&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-17\"><a href=\"#cb1-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;linker-is-gnu&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">true</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-18\"><a href=\"#cb1-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;linker-flavor&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;gcc&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-19\"><a href=\"#cb1-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;pre-link-args&quot;</span><span class=\"fu\">:</span> <span class=\"fu\">{</span></span>\n<span id=\"cb1-20\"><a href=\"#cb1-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">&quot;gcc&quot;</span><span class=\"fu\">:</span> <span class=\"ot\">[</span></span>\n<span id=\"cb1-21\"><a href=\"#cb1-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-nostartfiles&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-22\"><a href=\"#cb1-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-nostdlib&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-23\"><a href=\"#cb1-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-m68000&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-24\"><a href=\"#cb1-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-no-pie&quot;</span></span>\n<span id=\"cb1-25\"><a href=\"#cb1-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"ot\">]</span></span>\n<span id=\"cb1-26\"><a href=\"#cb1-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">},</span></span>\n<span id=\"cb1-27\"><a href=\"#cb1-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;late-link-args&quot;</span><span class=\"fu\">:</span> <span class=\"fu\">{</span></span>\n<span id=\"cb1-28\"><a href=\"#cb1-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">&quot;gcc&quot;</span><span class=\"fu\">:</span> <span class=\"ot\">[</span></span>\n<span id=\"cb1-29\"><a href=\"#cb1-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-Wl,--gc-sections&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-30\"><a href=\"#cb1-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;/home/takashi/current/mintbox/build/objs/crt0.o&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-31\"><a href=\"#cb1-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-Wl,--start-group&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-32\"><a href=\"#cb1-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-L/home/takashi/current/mintbox/build&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-33\"><a href=\"#cb1-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-lcbox&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-34\"><a href=\"#cb1-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-Wl,--end-group&quot;</span><span class=\"ot\">,</span></span>\n<span id=\"cb1-35\"><a href=\"#cb1-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"st\">&quot;-lgcc&quot;</span></span>\n<span id=\"cb1-36\"><a href=\"#cb1-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"ot\">]</span></span>\n<span id=\"cb1-37\"><a href=\"#cb1-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">},</span></span>\n<span id=\"cb1-38\"><a href=\"#cb1-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;max-atomic-width&quot;</span><span class=\"fu\">:</span> <span class=\"dv\">32</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-39\"><a href=\"#cb1-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;os&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;mint&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-40\"><a href=\"#cb1-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;panic-strategy&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;abort&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-41\"><a href=\"#cb1-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;position-independent-executables&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">false</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-42\"><a href=\"#cb1-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;relocation-model&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;static&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-43\"><a href=\"#cb1-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;static-position-independent-executables&quot;</span><span class=\"fu\">:</span> <span class=\"kw\">false</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-44\"><a href=\"#cb1-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;target-endian&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;big&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-45\"><a href=\"#cb1-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;target-mcount&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;_mcount&quot;</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-46\"><a href=\"#cb1-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;target-pointer-width&quot;</span><span class=\"fu\">:</span> <span class=\"dv\">32</span><span class=\"fu\">,</span></span>\n<span id=\"cb1-47\"><a href=\"#cb1-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">&quot;vendor&quot;</span><span class=\"fu\">:</span> <span class=\"st\">&quot;atari&quot;</span></span>\n<span id=\"cb1-48\"><a href=\"#cb1-48\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">}</span></span></code></pre></div>\n<p>After quite a bit of fumbling around, reading docs online, reading\nthe forums I was able to compile some code for rust. However, I ran into\nthe same problem where my binaries were 100KB. I couldn\u2019t link to\nlibcmini, however, since I wanted to link to <code>alloc</code> in my\nno_std Rust code. To do so, I needed an allocator, which I wanted to\ndelegate to the libc for. However, this requires\n<code>posix_memalign</code>, which <code>libcmini</code> does not\nprovide. I implemented it in my libc, and was off to the races.</p>\n<p>However, Rust turned out to be a pain in a very different way than\nwriting C. If you try to implement printing with <a\nhref=\"https://github.com/Takashiidobe/mints/blob/main/src/lib.rs#L38-L43\">Rust\u2019s\nfmt helpers</a> when you try to print a type that can\u2019t be \u201cinlined\u201d by\nthe compiler, it\u2019ll pull in compiler builtins, and bundle a 300KB\nruntime, bloating your binary by that much. If you for example, try to\ndebug print an integer, that\u2019s 300KB. There might be some workaround by\nusing <code>args.as_str()</code> and failing, but this didn\u2019t work in my\ncase. So I decided to stop here. But it was a fun experiment.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2025-11-28T23:21:40+00:00"
		},
		{
			"id": "gen/daemons.html",
			"url": "gen/daemons.html",
			"title": "Daemons",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Daemons</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Daemons</h1>\n<p class=\"byline\">2025-11-13T09:42:06-05:00</p>\n</header>\n<p>Daemons are processes that run in the background without interaction.\nAn example would be <code>sshd</code>, which accepts ssh connections in\nthe background.</p>\n<p>Nowadays, on linux, it\u2019s recommended to use <code>systemd</code> to\nmanage your daemons. <code>sshd</code> and other services are registered\nthrough <code>systemd</code>. We\u2019re going to go old school in this post\nfor fun.</p>\n<p>A daemon shouldn\u2019t be reachable from the outside world, and it should\ndo a task on some activity or change. You can run one or as many of them\nas you want to \u2013 maybe you want just one like a singleton, or many\nsplitting up a task, or you can emulate a single writer many readers\npattern.</p>\n<p>Regardless, here\u2019s the checklist of \u201chow to daemon\u201d</p>\n<ol type=\"1\">\n<li>Fork + exit from the parent.</li>\n<li><code>setsid()</code> after the first fork to get a new progress\ngroup id.</li>\n<li>disable <code>SIGHUP</code> to prevent the terminal from killing the\ndaemon.</li>\n<li>Fork again to make sure the daemon process cannot get a\nterminal.</li>\n<li><code>umask(027)</code> to set permissions for files it owns</li>\n<li><code>chdir()</code> to the directory you want</li>\n<li>Close all FDs that aren\u2019t 0/1/2, and redirect 0/1/2 to log\nfiles.</li>\n<li>Get the <code>pidfile</code>, write your pid, keep the file open\nwhile alive.</li>\n<li>Install signal handling, <code>SIGTERM</code>, <code>SIGINT</code>\nfor shutdown, <code>SIGHUP</code> for reloading.</li>\n<li>Open any files required for the task.</li>\n<li>Do the task.</li>\n<li>Install code on exit, to close resources used + unlink the\npidfile.</li>\n</ol>\n<p>That\u2019s a lot of work. Luckily, the <code>bsd</code> folks have us\n(the linux folks) covered. They have <code>libdaemon</code>, which has a\nset of helpers to write daemons. If you choose a higher level language\nlike Rust or Python, setting up a daemon is 15 lines of code.</p>\n<p>In C, the setup code is closer to 40 lines, but it\u2019s not that bad\nregardless with <code>libdaemon</code> \u2013 it sets up steps 1 to 7 for us.\nThat leaves just a few steps. We set the path for the pidfile, and\nregister it with <code>daemon_pid_file_proc</code> for it to be set up\nin the <code>daemon_pid_file_create</code> call later, returning if we\ncouldn\u2019t create it.</p>\n<p>Next, there\u2019s signal handlers installed for <code>SIGTERM</code> and\n<code>SIGINT</code>, and then we do our main loop.</p>\n<p>Finally, we\u2019ll do our work, which in this case, reads the\nrequest_path, checks how many bytes it has, and then every 5 seconds,\nlogs that to another file.</p>\n<p>Pretty simple, but does the trick in showcasing how a daemon\nworks.</p>\n<p>First, we have our includes.</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;errno.h&gt;</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;fcntl.h&gt;</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;libdaemon/daemon.h&gt;</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;libdaemon/dpid.h&gt;</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;signal.h&gt;</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;string.h&gt;</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;sys/stat.h&gt;</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;time.h&gt;</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;unistd.h&gt;</span></span></code></pre></div>\n<p>Next, our actual work, which will print to the fd we provide.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> log_file_size<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>request_path<span class=\"op\">,</span> <span class=\"dt\">int</span> result_fd<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"kw\">struct</span> stat st<span class=\"op\">;</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>stat<span class=\"op\">(</span>request_path<span class=\"op\">,</span> <span class=\"op\">&amp;</span>st<span class=\"op\">)</span> <span class=\"op\">&lt;</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>errno <span class=\"op\">==</span> ENOENT<span class=\"op\">)</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>      dprintf<span class=\"op\">(</span>result_fd<span class=\"op\">,</span> <span class=\"st\">&quot;# </span><span class=\"sc\">%s</span><span class=\"st\"> missing</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> request_path<span class=\"op\">);</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">else</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>      dprintf<span class=\"op\">(</span>result_fd<span class=\"op\">,</span> <span class=\"st\">&quot;# error reading </span><span class=\"sc\">%s</span><span class=\"st\">: </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> request_path<span class=\"op\">,</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>              strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span><span class=\"op\">;</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>  dprintf<span class=\"op\">(</span>result_fd<span class=\"op\">,</span> <span class=\"st\">&quot;# </span><span class=\"sc\">%s</span><span class=\"st\"> has </span><span class=\"sc\">%ld</span><span class=\"st\"> bytes</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> request_path<span class=\"op\">,</span> st<span class=\"op\">.</span>st_size<span class=\"op\">);</span></span>\n<span id=\"cb2-12\"><a href=\"#cb2-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Next, setting up the variables we need for\n<code>libdaemon</code>.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">volatile</span> <span class=\"dt\">sig_atomic_t</span> stop_flag <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> on_stop<span class=\"op\">(</span><span class=\"dt\">int</span> _sig<span class=\"op\">)</span> <span class=\"op\">{</span> stop_flag <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>pidfile_path <span class=\"op\">=</span> <span class=\"st\">&quot;/tmp/byte_count_daemon.pid&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>request_path <span class=\"op\">=</span> <span class=\"st\">&quot;/tmp/byte_count_requests.txt&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>result_path <span class=\"op\">=</span> <span class=\"st\">&quot;/tmp/byte_count_results.txt&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>pidfile_proc<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> pidfile_path<span class=\"op\">;</span> <span class=\"op\">}</span></span></code></pre></div>\n<p>And then the main function:</p>\n<ol type=\"1\">\n<li>You can pass it a <code>-f</code> flag as the first argument, if you\nwant to run in the foreground for testing.</li>\n<li>Next, the daemon identifier comes from the name of the binary, and\nthen the pidfile path is set afterwards.</li>\n<li>The daemon call is made only if it\u2019s not foregrounded \u2013 so we can\nkill the process.</li>\n<li>Signal handlers are registered.</li>\n<li>Pidfile is created \u2013 if it can\u2019t be exclusively owned, return\nhere.</li>\n<li>Open up an fd we need exclusively to write our results to. If we\ncan\u2019t, we return.</li>\n<li>The main loop, along with sleeping for 5 seconds between tasks.</li>\n<li>Stopping and cleaning up.</li>\n</ol>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">int</span> argc<span class=\"op\">,</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>argv<span class=\"op\">[])</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 1.</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> foreground <span class=\"op\">=</span> <span class=\"op\">(</span>argc <span class=\"op\">&gt;</span> <span class=\"dv\">1</span> <span class=\"op\">&amp;&amp;</span> strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">1</span><span class=\"op\">],</span> <span class=\"st\">&quot;-f&quot;</span><span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 2.</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>  daemon_pid_file_ident <span class=\"op\">=</span> daemon_ident_from_argv0<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]);</span></span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  daemon_pid_file_proc <span class=\"op\">=</span> pidfile_proc<span class=\"op\">;</span></span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 3.</span></span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!</span>foreground<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>daemon<span class=\"op\">(</span><span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">&lt;</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">return</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 4.</span></span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"kw\">struct</span> sigaction sa <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"dv\">0</span><span class=\"op\">};</span></span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>  sa<span class=\"op\">.</span>sa_handler <span class=\"op\">=</span> on_stop<span class=\"op\">;</span></span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>  sigaction<span class=\"op\">(</span>SIGINT<span class=\"op\">,</span> <span class=\"op\">&amp;</span>sa<span class=\"op\">,</span> NULL<span class=\"op\">);</span></span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>  sigaction<span class=\"op\">(</span>SIGTERM<span class=\"op\">,</span> <span class=\"op\">&amp;</span>sa<span class=\"op\">,</span> NULL<span class=\"op\">);</span></span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 5.</span></span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>daemon_pid_file_create<span class=\"op\">()</span> <span class=\"op\">&lt;</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb4-24\"><a href=\"#cb4-24\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-25\"><a href=\"#cb4-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 6.</span></span>\n<span id=\"cb4-26\"><a href=\"#cb4-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> results_fd <span class=\"op\">=</span> open<span class=\"op\">(</span>result_path<span class=\"op\">,</span> O_WRONLY <span class=\"op\">|</span> O_CREAT <span class=\"op\">|</span> O_APPEND<span class=\"op\">,</span> <span class=\"bn\">0644</span><span class=\"op\">);</span></span>\n<span id=\"cb4-27\"><a href=\"#cb4-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>results_fd <span class=\"op\">&lt;</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb4-28\"><a href=\"#cb4-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb4-29\"><a href=\"#cb4-29\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-30\"><a href=\"#cb4-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 7.</span></span>\n<span id=\"cb4-31\"><a href=\"#cb4-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>  dprintf<span class=\"op\">(</span>results_fd<span class=\"op\">,</span> <span class=\"st\">&quot;# byte count request daemon started pid=</span><span class=\"sc\">%d\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> getpid<span class=\"op\">());</span></span>\n<span id=\"cb4-32\"><a href=\"#cb4-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">while</span> <span class=\"op\">(!</span>stop_flag<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-33\"><a href=\"#cb4-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>    log_file_size<span class=\"op\">(</span>request_path<span class=\"op\">,</span> results_fd<span class=\"op\">);</span></span>\n<span id=\"cb4-34\"><a href=\"#cb4-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>    nanosleep<span class=\"op\">(&amp;(</span><span class=\"kw\">struct</span> timespec<span class=\"op\">){</span><span class=\"dv\">5</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">},</span> NULL<span class=\"op\">);</span> </span>\n<span id=\"cb4-35\"><a href=\"#cb4-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-36\"><a href=\"#cb4-36\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-37\"><a href=\"#cb4-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// 8.</span></span>\n<span id=\"cb4-38\"><a href=\"#cb4-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>  dprintf<span class=\"op\">(</span>results_fd<span class=\"op\">,</span> <span class=\"st\">&quot;# stopping</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb4-39\"><a href=\"#cb4-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>  daemon_pid_file_remove<span class=\"op\">();</span></span>\n<span id=\"cb4-40\"><a href=\"#cb4-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close<span class=\"op\">(</span>results_fd<span class=\"op\">);</span></span>\n<span id=\"cb4-41\"><a href=\"#cb4-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb4-42\"><a href=\"#cb4-42\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Compile the daemon with <code>cc daemon.c -o daemon -ldaemon</code>,\nand run it in the foreground with <code>daemon -f</code>.</p>\n<p>Once you start the daemon, you can write and save into\n<code>/tmp/byte_count_requests.txt</code> and then\n<code>tail -f /tmp/byte_count_results.txt</code> to see what the daemon\nis doing.</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode txt\"><code class=\"sourceCode default\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a># byte count request daemon started pid=438577</span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt missing</span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt missing</span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt has 11 bytes</span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt has 25 bytes</span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt has 25 bytes</span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt has 25 bytes</span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a># /tmp/byte_count_requests.txt has 25 bytes</span></code></pre></div>\n<p>A crash course on daemons in a handful of lines!</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2025-11-13T14:42:06+00:00"
		},
		{
			"id": "gen/writing-a-container.html",
			"url": "gen/writing-a-container.html",
			"title": "Writing a Container",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing a Container</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing a Container</h1>\n<p class=\"byline\">2025-11-12T15:55:26-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#dependencies\" id=\"toc-dependencies\">Dependencies</a></li>\n<li><a href=\"#a-shell\" id=\"toc-a-shell\">A Shell</a></li>\n<li><a href=\"#a-userspace\" id=\"toc-a-userspace\">A Userspace</a></li>\n<li><a href=\"#an-operating-system\" id=\"toc-an-operating-system\">An\noperating system?</a></li>\n<li><a href=\"#chrooting-to-our-os\"\nid=\"toc-chrooting-to-our-os\">Chrooting to our OS</a></li>\n<li><a href=\"#some-more-security\" id=\"toc-some-more-security\">Some more\nsecurity</a></li>\n<li><a href=\"#even-more-security\" id=\"toc-even-more-security\">Even More\nSecurity</a></li>\n</ul>\n</nav>\n<p>I use containers on the job daily, but to be honest, don\u2019t have much\nidea other than they\u2019re vaguely <code>chroot()</code> +\n<code>cgroupsv2</code> + <code>seccomp</code>. So, to rectify that,\nlet\u2019s build our own containers.</p>\n<section id=\"dependencies\" class=\"level2\">\n<h2>Dependencies</h2>\n<p>First off, some dependencies. Since we want to run binaries inside of\nour chroot, and our chroot is going to be far away from root, we have\ntwo options:</p>\n<ol type=\"1\">\n<li>compile with vanilla <code>gcc</code> and then copy our shared\nlibraries to our chroot.</li>\n<li>Statically compile our dependencies.</li>\n</ol>\n<p>I went with 2. But that leaves the compiler itself. Luckily, there\u2019s\na project called <a\nhref=\"https://crosstool-ng.github.io/\">crosstool-NG</a> that allows you\nto generate cross-compilers pretty easily. My target is\n<code>x86_64-unknown-linux-gnu</code>, so I just needed a build of\n<code>x86_64-unknown-linux-musl</code>. After adding the compiler to\nyour <code>$PATH</code>, you\u2019re also ready to statically compile some\ncode.</p>\n</section>\n<section id=\"a-shell\" class=\"level2\">\n<h2>A Shell</h2>\n<p>To get interactivity in our <code>chroot</code>, we\u2019ll need a shell.\nI chose <code>dash</code> because it\u2019s easier to compile. Clone it, and\nlet\u2019s compile it with our cross compiler.</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">git</span> clone https://git.kernel.org/pub/scm/utils/dash/dash.git/ <span class=\"at\">--depth</span><span class=\"op\">=</span>1</span></code></pre></div>\n<p>In bash or zsh, set your compiler, and build. Dash will be built in\n<code>src/dash</code>. Copy it for later.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">cd</span> dash</span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">PATH</span><span class=\"op\">=</span><span class=\"st\">&quot;</span><span class=\"va\">$HOME</span><span class=\"st\">/x-tools/x86_64-unknown-linux-musl/bin:</span><span class=\"va\">$PATH</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">CC</span><span class=\"op\">=</span><span class=\"st\">&quot;x86_64-unknown-linux-musl-gcc&quot;</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">LD</span><span class=\"op\">=</span><span class=\"st\">&quot;x86_64-unknown-linux-musl-ld&quot;</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">CFLAGS</span><span class=\"op\">=</span><span class=\"st\">&quot;-Os&quot;</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">LDFLAGS</span><span class=\"op\">=</span><span class=\"st\">&quot;--static&quot;</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">make</span></span></code></pre></div>\n</section>\n<section id=\"a-userspace\" class=\"level2\">\n<h2>A Userspace</h2>\n<p>For a userspace, I decided to use toybox.</p>\n<p>Same drill, compile it statically.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">git</span> clone https://github.com/landley/toybox.git <span class=\"at\">--depth</span><span class=\"op\">=</span>1</span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">cd</span> toybox</span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">PATH</span><span class=\"op\">=</span><span class=\"st\">&quot;</span><span class=\"va\">$HOME</span><span class=\"st\">/x-tools/x86_64-unknown-linux-musl/bin:</span><span class=\"va\">$PATH</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">CROSS_COMPILE</span><span class=\"op\">=</span>x86_64-unknown-linux-musl- </span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"bu\">export</span> <span class=\"va\">LDFLAGS</span><span class=\"op\">=</span><span class=\"st\">&quot;--static&quot;</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">make</span> distclean</span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">make</span> defconfig</span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">make</span> toybox CROSS_COMPILE=<span class=\"va\">$CROSS_COMPILE</span></span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">make</span></span></code></pre></div>\n<p><code>toybox</code> will be in the root directory. Keep it for\nlater.</p>\n</section>\n<section id=\"an-operating-system\" class=\"level2\">\n<h2>An operating system?</h2>\n<p>Now we\u2019ll need the directory structure of an operating system.\nLuckily, toybox also has us covered. There\u2019s a script called\n<code>mkroot/mkroot.sh</code> which when run, will create our root\nfilesystem.</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> mkroot/mkroot.sh</span></code></pre></div>\n<p>Run it, and copy the <code>root</code> dir to where you want your OS\nto be. Now, copy over <code>dash</code> and <code>toybox</code> into\n<code>root/bin</code>, and you have a userspace and a shell. What more\ncould you want?</p>\n</section>\n<section id=\"chrooting-to-our-os\" class=\"level2\">\n<h2>Chrooting to our OS</h2>\n<p>If you <code>cd</code> into <code>root</code> and then run\n<code>bin/toybox ls</code>, you actually have an OS inside your OS. Of\ncourse, it\u2019s pretty useless since you can <code>cd</code> out. This is\nbasically what <code>chroot</code> does for us \u2013 it puts the root dir\nwherever you specify, and that\u2019s it.</p>\n<p>With that out of the way, let\u2019s write a program that uses\n<code>chroot</code>.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define </span><span class=\"ot\">_GNU_SOURCE</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;errno.h&gt;</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdarg.h&gt;</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdbool.h&gt;</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdlib.h&gt;</span></span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;string.h&gt;</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;unistd.h&gt;</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">/*</span></span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"> * Stage 0: Minimal chroot launcher.</span></span>\n<span id=\"cb6-12\"><a href=\"#cb6-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"> *</span></span>\n<span id=\"cb6-13\"><a href=\"#cb6-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"> * This version demonstrates the tiniest &quot;container&quot;: it simply chroots into a</span></span>\n<span id=\"cb6-14\"><a href=\"#cb6-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"> * user-specified directory and execs a command. You must run it as root and</span></span>\n<span id=\"cb6-15\"><a href=\"#cb6-15\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"> * it is trivial to escape by pointing -r at &quot;/&quot; or any other host path</span></span>\n<span id=\"cb6-16\"><a href=\"#cb6-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">   and escaping.</span></span>\n<span id=\"cb6-17\"><a href=\"#cb6-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"> */</span></span>\n<span id=\"cb6-18\"><a href=\"#cb6-18\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-19\"><a href=\"#cb6-19\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> die<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>fmt<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-20\"><a href=\"#cb6-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">va_list</span> ap<span class=\"op\">;</span></span>\n<span id=\"cb6-21\"><a href=\"#cb6-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>  va_start<span class=\"op\">(</span>ap<span class=\"op\">,</span> fmt<span class=\"op\">);</span></span>\n<span id=\"cb6-22\"><a href=\"#cb6-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>  vfprintf<span class=\"op\">(</span>stderr<span class=\"op\">,</span> fmt<span class=\"op\">,</span> ap<span class=\"op\">);</span></span>\n<span id=\"cb6-23\"><a href=\"#cb6-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>  va_end<span class=\"op\">(</span>ap<span class=\"op\">);</span></span>\n<span id=\"cb6-24\"><a href=\"#cb6-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!*</span>fmt <span class=\"op\">||</span> fmt<span class=\"op\">[</span>strlen<span class=\"op\">(</span>fmt<span class=\"op\">)</span> <span class=\"op\">-</span> <span class=\"dv\">1</span><span class=\"op\">]</span> <span class=\"op\">!=</span> <span class=\"ch\">&#39;</span><span class=\"sc\">\\n</span><span class=\"ch\">&#39;</span><span class=\"op\">)</span></span>\n<span id=\"cb6-25\"><a href=\"#cb6-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fputc<span class=\"op\">(</span><span class=\"ch\">&#39;</span><span class=\"sc\">\\n</span><span class=\"ch\">&#39;</span><span class=\"op\">,</span> stderr<span class=\"op\">);</span></span>\n<span id=\"cb6-26\"><a href=\"#cb6-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>  exit<span class=\"op\">(</span>EXIT_FAILURE<span class=\"op\">);</span></span>\n<span id=\"cb6-27\"><a href=\"#cb6-27\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb6-28\"><a href=\"#cb6-28\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-29\"><a href=\"#cb6-29\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> usage<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>prog<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-30\"><a href=\"#cb6-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>  fprintf<span class=\"op\">(</span>stderr<span class=\"op\">,</span> <span class=\"st\">&quot;Usage: </span><span class=\"sc\">%s</span><span class=\"st\"> -r &lt;rootfs&gt; -- &lt;cmd&gt; [args...]</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> prog<span class=\"op\">);</span></span>\n<span id=\"cb6-31\"><a href=\"#cb6-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>  exit<span class=\"op\">(</span><span class=\"dv\">2</span><span class=\"op\">);</span></span>\n<span id=\"cb6-32\"><a href=\"#cb6-32\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb6-33\"><a href=\"#cb6-33\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-34\"><a href=\"#cb6-34\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">int</span> argc<span class=\"op\">,</span> <span class=\"dt\">char</span> <span class=\"op\">**</span>argv<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-35\"><a href=\"#cb6-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>root <span class=\"op\">=</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb6-36\"><a href=\"#cb6-36\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-37\"><a href=\"#cb6-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">/* Parse: expect -r &lt;root&gt; followed by -- and the command */</span></span>\n<span id=\"cb6-38\"><a href=\"#cb6-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> i <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> argc<span class=\"op\">;</span> i<span class=\"op\">++)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-39\"><a href=\"#cb6-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-r&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-40\"><a href=\"#cb6-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>      root <span class=\"op\">=</span> argv<span class=\"op\">[++</span>i<span class=\"op\">];</span></span>\n<span id=\"cb6-41\"><a href=\"#cb6-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;--&quot;</span><span class=\"op\">))</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-42\"><a href=\"#cb6-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argv <span class=\"op\">+=</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb6-43\"><a href=\"#cb6-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argc <span class=\"op\">-=</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb6-44\"><a href=\"#cb6-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb6-45\"><a href=\"#cb6-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">][</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">==</span> <span class=\"ch\">&#39;-&#39;</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-46\"><a href=\"#cb6-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>      usage<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]);</span></span>\n<span id=\"cb6-47\"><a href=\"#cb6-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-48\"><a href=\"#cb6-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argv <span class=\"op\">+=</span> i<span class=\"op\">;</span></span>\n<span id=\"cb6-49\"><a href=\"#cb6-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argc <span class=\"op\">-=</span> i<span class=\"op\">;</span></span>\n<span id=\"cb6-50\"><a href=\"#cb6-50\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb6-51\"><a href=\"#cb6-51\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb6-52\"><a href=\"#cb6-52\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb6-53\"><a href=\"#cb6-53\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!</span>root <span class=\"op\">||</span> argc <span class=\"op\">&lt;</span> <span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb6-54\"><a href=\"#cb6-54\" aria-hidden=\"true\" tabindex=\"-1\"></a>    usage<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]);</span></span>\n<span id=\"cb6-55\"><a href=\"#cb6-55\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-56\"><a href=\"#cb6-56\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>chroot<span class=\"op\">(</span>root<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb6-57\"><a href=\"#cb6-57\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;chroot(</span><span class=\"sc\">%s</span><span class=\"st\">): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> root<span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb6-58\"><a href=\"#cb6-58\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>chdir<span class=\"op\">(</span><span class=\"st\">&quot;/&quot;</span><span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb6-59\"><a href=\"#cb6-59\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;chdir(/): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb6-60\"><a href=\"#cb6-60\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-61\"><a href=\"#cb6-61\" aria-hidden=\"true\" tabindex=\"-1\"></a>  execvp<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">],</span> argv<span class=\"op\">);</span></span>\n<span id=\"cb6-62\"><a href=\"#cb6-62\" aria-hidden=\"true\" tabindex=\"-1\"></a>  die<span class=\"op\">(</span><span class=\"st\">&quot;execvp(&#39;</span><span class=\"sc\">%s</span><span class=\"st\">&#39;) failed: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">],</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb6-63\"><a href=\"#cb6-63\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Compile this and we have to run it as root. Point it to our little\nfilesystem and we can drop into the shell.</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">gcc</span> container.c <span class=\"at\">-o</span> container <span class=\"at\">-lseccomp</span></span></code></pre></div>\n<p>Note that we have to use <code>sudo</code> here otherwise we can\u2019t\nget into the <code>chroot</code>.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">sudo</span> ./container <span class=\"at\">-r</span> ./root <span class=\"at\">--</span> /bin/dash</span></code></pre></div>\n<p>We\u2019re actually not able to do too much to just leave:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># pwd</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">/</span></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># cd /root/takashi</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">/bin/dash:</span> 5: cd: can<span class=\"st\">&#39;t cd to /root/takashi</span></span></code></pre></div>\n<p>But remember, we\u2019re root. We can escape using proc.</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># toybox mkdir /proc</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># toybox mount -t proc proc /proc</span></span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># toybox chroot /proc/1/root /bin/sh</span></span>\n<span id=\"cb10-4\"><a href=\"#cb10-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> whoami</span>\n<span id=\"cb10-5\"><a href=\"#cb10-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">root</span></span></code></pre></div>\n<p>And you\u2019re in a root shell as root. Freedom, so very easily.</p>\n</section>\n<section id=\"some-more-security\" class=\"level2\">\n<h2>Some more security</h2>\n<p>We\u2019ll want to prevent running as root. And also escaping so easily.\nThis time around, we\u2019ll make the container runnable without root, mount\n<code>/proc</code> privately, clean up the environment, and change our\nuser to nobody. We can still run any syscall we want though.</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> make_private_mounts<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>mount<span class=\"op\">(</span>NULL<span class=\"op\">,</span> <span class=\"st\">&quot;/&quot;</span><span class=\"op\">,</span> NULL<span class=\"op\">,</span> MS_REC <span class=\"op\">|</span> MS_PRIVATE<span class=\"op\">,</span> NULL<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;mount(/, MS_PRIVATE): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> bind_mount_self<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>path<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-7\"><a href=\"#cb11-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>mount<span class=\"op\">(</span>path<span class=\"op\">,</span> path<span class=\"op\">,</span> NULL<span class=\"op\">,</span> MS_BIND <span class=\"op\">|</span> MS_REC<span class=\"op\">,</span> NULL<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb11-8\"><a href=\"#cb11-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;bind-mount </span><span class=\"sc\">%s</span><span class=\"st\">: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> path<span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-9\"><a href=\"#cb11-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-10\"><a href=\"#cb11-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-11\"><a href=\"#cb11-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> close_all_fds_except012<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-12\"><a href=\"#cb11-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> dir <span class=\"op\">=</span> open<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/fd&quot;</span><span class=\"op\">,</span> O_RDONLY <span class=\"op\">|</span> O_DIRECTORY <span class=\"op\">|</span> O_CLOEXEC<span class=\"op\">);</span></span>\n<span id=\"cb11-13\"><a href=\"#cb11-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>dir <span class=\"op\">&lt;</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-14\"><a href=\"#cb11-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> fd <span class=\"op\">=</span> <span class=\"dv\">3</span><span class=\"op\">;</span> fd <span class=\"op\">&lt;</span> <span class=\"dv\">1024</span><span class=\"op\">;</span> <span class=\"op\">++</span>fd<span class=\"op\">)</span></span>\n<span id=\"cb11-15\"><a href=\"#cb11-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>      close<span class=\"op\">(</span>fd<span class=\"op\">);</span></span>\n<span id=\"cb11-16\"><a href=\"#cb11-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span><span class=\"op\">;</span></span>\n<span id=\"cb11-17\"><a href=\"#cb11-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb11-18\"><a href=\"#cb11-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">char</span> name<span class=\"op\">[</span>PATH_MAX<span class=\"op\">];</span></span>\n<span id=\"cb11-19\"><a href=\"#cb11-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(;;)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-20\"><a href=\"#cb11-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">ssize_t</span> n <span class=\"op\">=</span> syscall<span class=\"op\">(</span>SYS_getdents64<span class=\"op\">,</span> dir<span class=\"op\">,</span> name<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>name<span class=\"op\">));</span></span>\n<span id=\"cb11-21\"><a href=\"#cb11-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>n <span class=\"op\">&lt;=</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb11-22\"><a href=\"#cb11-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb11-23\"><a href=\"#cb11-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">ssize_t</span> i <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> n<span class=\"op\">;)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-24\"><a href=\"#cb11-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"kw\">struct</span> linux_dirent64 <span class=\"op\">{</span></span>\n<span id=\"cb11-25\"><a href=\"#cb11-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>        ino64_t d_ino<span class=\"op\">;</span></span>\n<span id=\"cb11-26\"><a href=\"#cb11-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>        off64_t d_off<span class=\"op\">;</span></span>\n<span id=\"cb11-27\"><a href=\"#cb11-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">unsigned</span> <span class=\"dt\">short</span> d_reclen<span class=\"op\">;</span></span>\n<span id=\"cb11-28\"><a href=\"#cb11-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">unsigned</span> <span class=\"dt\">char</span> d_type<span class=\"op\">;</span></span>\n<span id=\"cb11-29\"><a href=\"#cb11-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dt\">char</span> d_name<span class=\"op\">[];</span></span>\n<span id=\"cb11-30\"><a href=\"#cb11-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"op\">};</span></span>\n<span id=\"cb11-31\"><a href=\"#cb11-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"kw\">struct</span> linux_dirent64 <span class=\"op\">*</span>d <span class=\"op\">=</span> <span class=\"op\">(</span><span class=\"kw\">struct</span> linux_dirent64 <span class=\"op\">*)(</span>name <span class=\"op\">+</span> i<span class=\"op\">);</span></span>\n<span id=\"cb11-32\"><a href=\"#cb11-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>      i <span class=\"op\">+=</span> d<span class=\"op\">-&gt;</span>d_reclen<span class=\"op\">;</span></span>\n<span id=\"cb11-33\"><a href=\"#cb11-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>d<span class=\"op\">-&gt;</span>d_name<span class=\"op\">,</span> <span class=\"st\">&quot;.&quot;</span><span class=\"op\">)</span> <span class=\"op\">||</span> <span class=\"op\">!</span>strcmp<span class=\"op\">(</span>d<span class=\"op\">-&gt;</span>d_name<span class=\"op\">,</span> <span class=\"st\">&quot;..&quot;</span><span class=\"op\">))</span></span>\n<span id=\"cb11-34\"><a href=\"#cb11-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">continue</span><span class=\"op\">;</span></span>\n<span id=\"cb11-35\"><a href=\"#cb11-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"dt\">int</span> fd <span class=\"op\">=</span> atoi<span class=\"op\">(</span>d<span class=\"op\">-&gt;</span>d_name<span class=\"op\">);</span></span>\n<span id=\"cb11-36\"><a href=\"#cb11-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">if</span> <span class=\"op\">(</span>fd <span class=\"op\">&gt;</span> <span class=\"dv\">2</span> <span class=\"op\">&amp;&amp;</span> fd <span class=\"op\">!=</span> dir<span class=\"op\">)</span></span>\n<span id=\"cb11-37\"><a href=\"#cb11-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>        close<span class=\"op\">(</span>fd<span class=\"op\">);</span></span>\n<span id=\"cb11-38\"><a href=\"#cb11-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-39\"><a href=\"#cb11-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb11-40\"><a href=\"#cb11-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close<span class=\"op\">(</span>dir<span class=\"op\">);</span></span>\n<span id=\"cb11-41\"><a href=\"#cb11-41\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-42\"><a href=\"#cb11-42\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-43\"><a href=\"#cb11-43\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> drop_privileges<span class=\"op\">(</span>uid_t uid<span class=\"op\">,</span> gid_t gid<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-44\"><a href=\"#cb11-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>setgroups<span class=\"op\">(</span><span class=\"dv\">0</span><span class=\"op\">,</span> NULL<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span> <span class=\"op\">&amp;&amp;</span> errno <span class=\"op\">!=</span> EPERM<span class=\"op\">)</span></span>\n<span id=\"cb11-45\"><a href=\"#cb11-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;setgroups: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-46\"><a href=\"#cb11-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>setgid<span class=\"op\">(</span>gid<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb11-47\"><a href=\"#cb11-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;setgid: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-48\"><a href=\"#cb11-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>setuid<span class=\"op\">(</span>uid<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb11-49\"><a href=\"#cb11-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;setuid: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-50\"><a href=\"#cb11-50\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-51\"><a href=\"#cb11-51\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-52\"><a href=\"#cb11-52\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> write_file_fmt<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>path<span class=\"op\">,</span> <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>fmt<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-53\"><a href=\"#cb11-53\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> fd <span class=\"op\">=</span> open<span class=\"op\">(</span>path<span class=\"op\">,</span> O_WRONLY<span class=\"op\">);</span></span>\n<span id=\"cb11-54\"><a href=\"#cb11-54\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>fd <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb11-55\"><a href=\"#cb11-55\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;open(</span><span class=\"sc\">%s</span><span class=\"st\">): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> path<span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-56\"><a href=\"#cb11-56\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-57\"><a href=\"#cb11-57\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">char</span> buf<span class=\"op\">[</span><span class=\"dv\">256</span><span class=\"op\">];</span></span>\n<span id=\"cb11-58\"><a href=\"#cb11-58\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">va_list</span> ap<span class=\"op\">;</span></span>\n<span id=\"cb11-59\"><a href=\"#cb11-59\" aria-hidden=\"true\" tabindex=\"-1\"></a>  va_start<span class=\"op\">(</span>ap<span class=\"op\">,</span> fmt<span class=\"op\">);</span></span>\n<span id=\"cb11-60\"><a href=\"#cb11-60\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> len <span class=\"op\">=</span> vsnprintf<span class=\"op\">(</span>buf<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>buf<span class=\"op\">),</span> fmt<span class=\"op\">,</span> ap<span class=\"op\">);</span></span>\n<span id=\"cb11-61\"><a href=\"#cb11-61\" aria-hidden=\"true\" tabindex=\"-1\"></a>  va_end<span class=\"op\">(</span>ap<span class=\"op\">);</span></span>\n<span id=\"cb11-62\"><a href=\"#cb11-62\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">&lt;</span> <span class=\"dv\">0</span> <span class=\"op\">||</span> <span class=\"op\">(</span><span class=\"dt\">size_t</span><span class=\"op\">)</span>len <span class=\"op\">&gt;=</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>buf<span class=\"op\">))</span></span>\n<span id=\"cb11-63\"><a href=\"#cb11-63\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;formatting </span><span class=\"sc\">%s</span><span class=\"st\"> failed&quot;</span><span class=\"op\">,</span> path<span class=\"op\">);</span></span>\n<span id=\"cb11-64\"><a href=\"#cb11-64\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>write<span class=\"op\">(</span>fd<span class=\"op\">,</span> buf<span class=\"op\">,</span> len<span class=\"op\">)</span> <span class=\"op\">!=</span> len<span class=\"op\">)</span></span>\n<span id=\"cb11-65\"><a href=\"#cb11-65\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;write(</span><span class=\"sc\">%s</span><span class=\"st\">): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> path<span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-66\"><a href=\"#cb11-66\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close<span class=\"op\">(</span>fd<span class=\"op\">);</span></span>\n<span id=\"cb11-67\"><a href=\"#cb11-67\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-68\"><a href=\"#cb11-68\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-69\"><a href=\"#cb11-69\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> setup_user_namespace<span class=\"op\">(</span>uid_t host_uid<span class=\"op\">,</span> gid_t host_gid<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-70\"><a href=\"#cb11-70\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>unshare<span class=\"op\">(</span>CLONE_NEWUSER<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb11-71\"><a href=\"#cb11-71\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;unshare(CLONE_NEWUSER): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb11-72\"><a href=\"#cb11-72\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-73\"><a href=\"#cb11-73\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>access<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/setgroups&quot;</span><span class=\"op\">,</span> F_OK<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb11-74\"><a href=\"#cb11-74\" aria-hidden=\"true\" tabindex=\"-1\"></a>    write_file_fmt<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/setgroups&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;deny</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb11-75\"><a href=\"#cb11-75\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-76\"><a href=\"#cb11-76\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write_file_fmt<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/uid_map&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;0 </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> host_uid<span class=\"op\">);</span></span>\n<span id=\"cb11-77\"><a href=\"#cb11-77\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write_file_fmt<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/gid_map&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;0 </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> host_gid<span class=\"op\">);</span></span>\n<span id=\"cb11-78\"><a href=\"#cb11-78\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And the changes to main:</p>\n<div class=\"sourceCode\" id=\"cb12\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb12-1\"><a href=\"#cb12-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">int</span> argc<span class=\"op\">,</span> <span class=\"dt\">char</span> <span class=\"op\">**</span>argv<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-2\"><a href=\"#cb12-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>root <span class=\"op\">=</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb12-3\"><a href=\"#cb12-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  uid_t host_uid <span class=\"op\">=</span> geteuid<span class=\"op\">();</span></span>\n<span id=\"cb12-4\"><a href=\"#cb12-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  gid_t host_gid <span class=\"op\">=</span> getegid<span class=\"op\">();</span></span>\n<span id=\"cb12-5\"><a href=\"#cb12-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">bool</span> rootless <span class=\"op\">=</span> <span class=\"op\">(</span>host_uid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb12-6\"><a href=\"#cb12-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>  uid_t uid <span class=\"op\">=</span> rootless <span class=\"op\">?</span> <span class=\"dv\">0</span> <span class=\"op\">:</span> <span class=\"dv\">65534</span><span class=\"op\">;</span></span>\n<span id=\"cb12-7\"><a href=\"#cb12-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  gid_t gid <span class=\"op\">=</span> rootless <span class=\"op\">?</span> <span class=\"dv\">0</span> <span class=\"op\">:</span> <span class=\"dv\">65534</span><span class=\"op\">;</span></span>\n<span id=\"cb12-8\"><a href=\"#cb12-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-9\"><a href=\"#cb12-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> i <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> argc<span class=\"op\">;</span> i<span class=\"op\">++)</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-10\"><a href=\"#cb12-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-r&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-11\"><a href=\"#cb12-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>      root <span class=\"op\">=</span> argv<span class=\"op\">[++</span>i<span class=\"op\">];</span></span>\n<span id=\"cb12-12\"><a href=\"#cb12-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-u&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-13\"><a href=\"#cb12-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>      uid <span class=\"op\">=</span> <span class=\"op\">(</span>uid_t<span class=\"op\">)</span>strtoul<span class=\"op\">(</span>argv<span class=\"op\">[++</span>i<span class=\"op\">],</span> NULL<span class=\"op\">,</span> <span class=\"dv\">10</span><span class=\"op\">);</span></span>\n<span id=\"cb12-14\"><a href=\"#cb12-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-g&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-15\"><a href=\"#cb12-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>      gid <span class=\"op\">=</span> <span class=\"op\">(</span>gid_t<span class=\"op\">)</span>strtoul<span class=\"op\">(</span>argv<span class=\"op\">[++</span>i<span class=\"op\">],</span> NULL<span class=\"op\">,</span> <span class=\"dv\">10</span><span class=\"op\">);</span></span>\n<span id=\"cb12-16\"><a href=\"#cb12-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;--&quot;</span><span class=\"op\">))</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-17\"><a href=\"#cb12-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argv <span class=\"op\">+=</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb12-18\"><a href=\"#cb12-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argc <span class=\"op\">-=</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb12-19\"><a href=\"#cb12-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb12-20\"><a href=\"#cb12-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">][</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">==</span> <span class=\"ch\">&#39;-&#39;</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-21\"><a href=\"#cb12-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>      usage<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]);</span></span>\n<span id=\"cb12-22\"><a href=\"#cb12-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb12-23\"><a href=\"#cb12-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argv <span class=\"op\">+=</span> i<span class=\"op\">;</span></span>\n<span id=\"cb12-24\"><a href=\"#cb12-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argc <span class=\"op\">-=</span> i<span class=\"op\">;</span></span>\n<span id=\"cb12-25\"><a href=\"#cb12-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb12-26\"><a href=\"#cb12-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb12-27\"><a href=\"#cb12-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb12-28\"><a href=\"#cb12-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!</span>root <span class=\"op\">||</span> argc <span class=\"op\">&lt;</span> <span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb12-29\"><a href=\"#cb12-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>    usage<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]);</span></span>\n<span id=\"cb12-30\"><a href=\"#cb12-30\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-31\"><a href=\"#cb12-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>rootless <span class=\"op\">&amp;&amp;</span> <span class=\"op\">(</span>uid <span class=\"op\">!=</span> <span class=\"dv\">0</span> <span class=\"op\">||</span> gid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">))</span></span>\n<span id=\"cb12-32\"><a href=\"#cb12-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;non-root users must use -u/-g 0 in this stage&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb12-33\"><a href=\"#cb12-33\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-34\"><a href=\"#cb12-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>  setup_user_namespace<span class=\"op\">(</span>host_uid<span class=\"op\">,</span> host_gid<span class=\"op\">);</span></span>\n<span id=\"cb12-35\"><a href=\"#cb12-35\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-36\"><a href=\"#cb12-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>unshare<span class=\"op\">(</span>CLONE_NEWNS<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb12-37\"><a href=\"#cb12-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;unshare(CLONE_NEWNS): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb12-38\"><a href=\"#cb12-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>  make_private_mounts<span class=\"op\">();</span></span>\n<span id=\"cb12-39\"><a href=\"#cb12-39\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-40\"><a href=\"#cb12-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>  bind_mount_self<span class=\"op\">(</span>root<span class=\"op\">);</span></span>\n<span id=\"cb12-41\"><a href=\"#cb12-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>chroot<span class=\"op\">(</span>root<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb12-42\"><a href=\"#cb12-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;chroot(</span><span class=\"sc\">%s</span><span class=\"st\">): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> root<span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb12-43\"><a href=\"#cb12-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>chdir<span class=\"op\">(</span><span class=\"st\">&quot;/&quot;</span><span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb12-44\"><a href=\"#cb12-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;chdir(/): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb12-45\"><a href=\"#cb12-45\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-46\"><a href=\"#cb12-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>  mkdir<span class=\"op\">(</span><span class=\"st\">&quot;/proc&quot;</span><span class=\"op\">,</span> <span class=\"bn\">0555</span><span class=\"op\">);</span></span>\n<span id=\"cb12-47\"><a href=\"#cb12-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>  mount<span class=\"op\">(</span><span class=\"st\">&quot;proc&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;/proc&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;proc&quot;</span><span class=\"op\">,</span> MS_NOSUID <span class=\"op\">|</span> MS_NODEV <span class=\"op\">|</span> MS_NOEXEC<span class=\"op\">,</span> NULL<span class=\"op\">);</span></span>\n<span id=\"cb12-48\"><a href=\"#cb12-48\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-49\"><a href=\"#cb12-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>  clearenv<span class=\"op\">();</span></span>\n<span id=\"cb12-50\"><a href=\"#cb12-50\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close_all_fds_except012<span class=\"op\">();</span></span>\n<span id=\"cb12-51\"><a href=\"#cb12-51\" aria-hidden=\"true\" tabindex=\"-1\"></a>  drop_privileges<span class=\"op\">(</span>uid<span class=\"op\">,</span> gid<span class=\"op\">);</span></span>\n<span id=\"cb12-52\"><a href=\"#cb12-52\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-53\"><a href=\"#cb12-53\" aria-hidden=\"true\" tabindex=\"-1\"></a>  execvp<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">],</span> argv<span class=\"op\">);</span></span>\n<span id=\"cb12-54\"><a href=\"#cb12-54\" aria-hidden=\"true\" tabindex=\"-1\"></a>  die<span class=\"op\">(</span><span class=\"st\">&quot;execvp(&#39;</span><span class=\"sc\">%s</span><span class=\"st\">&#39;) failed: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">],</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb12-55\"><a href=\"#cb12-55\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Now, do we have an escape? If you do it right, no. However, there\u2019s a\nconvoluted way of getting out.</p>\n<p>If we know there\u2019s a process that has access to the root file system,\nmounting, etc, we \u201chack\u201d it in a bit of an odd way with\n<code>ptrace</code>. <code>Ptrace</code> allows us to \u201cobserve\u201d and\n\u201ccontrol\u201d the execution of other processes. With this, we can have it be\na confused deputy and mount our file system and therefore get a way to\nchroot out. Compile this program and point it to a victim pid on the\nhost that can mount for us:</p>\n<div class=\"sourceCode\" id=\"cb13\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">int</span> argc<span class=\"op\">,</span> <span class=\"dt\">char</span> <span class=\"op\">**</span>argv<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  pid_t pid <span class=\"op\">=</span> atoi<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">1</span><span class=\"op\">]);</span></span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"kw\">struct</span> user_regs_struct regs<span class=\"op\">;</span></span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  </span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ptrace<span class=\"op\">(</span>PTRACE_ATTACH<span class=\"op\">,</span> pid<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb13-6\"><a href=\"#cb13-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>  waitpid<span class=\"op\">(</span>pid<span class=\"op\">,</span> NULL<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb13-7\"><a href=\"#cb13-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ptrace<span class=\"op\">(</span>PTRACE_GETREGS<span class=\"op\">,</span> pid<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"op\">&amp;</span>regs<span class=\"op\">);</span></span>\n<span id=\"cb13-8\"><a href=\"#cb13-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>  regs<span class=\"op\">.</span>orig_rax <span class=\"op\">=</span> SYS_mount<span class=\"op\">;</span></span>\n<span id=\"cb13-9\"><a href=\"#cb13-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  regs<span class=\"op\">.</span>rdi <span class=\"op\">=</span> <span class=\"op\">(</span><span class=\"dt\">unsigned</span> <span class=\"dt\">long</span><span class=\"op\">)</span><span class=\"st\">&quot;/host&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb13-10\"><a href=\"#cb13-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  regs<span class=\"op\">.</span>rsi <span class=\"op\">=</span> <span class=\"op\">(</span><span class=\"dt\">unsigned</span> <span class=\"dt\">long</span><span class=\"op\">)</span><span class=\"st\">&quot;/mnt&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb13-11\"><a href=\"#cb13-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>  regs<span class=\"op\">.</span>rdx <span class=\"op\">=</span> MS_BIND<span class=\"op\">;</span></span>\n<span id=\"cb13-12\"><a href=\"#cb13-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>  regs<span class=\"op\">.</span>r10 <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb13-13\"><a href=\"#cb13-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ptrace<span class=\"op\">(</span>PTRACE_SETREGS<span class=\"op\">,</span> pid<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"op\">&amp;</span>regs<span class=\"op\">);</span></span>\n<span id=\"cb13-14\"><a href=\"#cb13-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ptrace<span class=\"op\">(</span>PTRACE_SYSCALL<span class=\"op\">,</span> pid<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb13-15\"><a href=\"#cb13-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>  waitpid<span class=\"op\">(</span>pid<span class=\"op\">,</span> NULL<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb13-16\"><a href=\"#cb13-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ptrace<span class=\"op\">(</span>PTRACE_DETACH<span class=\"op\">,</span> pid<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb13-17\"><a href=\"#cb13-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb13-18\"><a href=\"#cb13-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And we are out:</p>\n<div class=\"sourceCode\" id=\"cb14\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb14-1\"><a href=\"#cb14-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> toybox chroot /mnt /bin/sh</span></code></pre></div>\n</section>\n<section id=\"even-more-security\" class=\"level2\">\n<h2>Even More Security</h2>\n<p>So we\u2019ve learned that <code>ptrace</code> is evil in this case. What\nwe need is a way to only allow certain syscalls. Thankfully,\n<code>seccomp</code> will do that for us \u2013 if you try to run a syscall,\nit will get killed.</p>\n<p>Let\u2019s add some extra headers and some helpers:</p>\n<div class=\"sourceCode\" id=\"cb15\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb15-1\"><a href=\"#cb15-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;seccomp.h&gt;</span></span>\n<span id=\"cb15-2\"><a href=\"#cb15-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;signal.h&gt;</span></span>\n<span id=\"cb15-3\"><a href=\"#cb15-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;sys/prctl.h&gt;</span></span>\n<span id=\"cb15-4\"><a href=\"#cb15-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;sys/resource.h&gt;</span></span>\n<span id=\"cb15-5\"><a href=\"#cb15-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-6\"><a href=\"#cb15-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> setup_user_namespace<span class=\"op\">(</span>uid_t host_uid<span class=\"op\">,</span> gid_t host_gid<span class=\"op\">,</span></span>\n<span id=\"cb15-7\"><a href=\"#cb15-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>                                 uid_t target_uid<span class=\"op\">,</span> gid_t target_gid<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-8\"><a href=\"#cb15-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">char</span> map_buf<span class=\"op\">[</span><span class=\"dv\">256</span><span class=\"op\">];</span></span>\n<span id=\"cb15-9\"><a href=\"#cb15-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> len <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb15-10\"><a href=\"#cb15-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-11\"><a href=\"#cb15-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>host_uid <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-12\"><a href=\"#cb15-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    len <span class=\"op\">=</span> snprintf<span class=\"op\">(</span>map_buf<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">),</span> <span class=\"st\">&quot;0 </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> host_uid<span class=\"op\">);</span></span>\n<span id=\"cb15-13\"><a href=\"#cb15-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>target_uid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb15-14\"><a href=\"#cb15-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>      len <span class=\"op\">+=</span> snprintf<span class=\"op\">(</span>map_buf <span class=\"op\">+</span> len<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">)</span> <span class=\"op\">-</span> len<span class=\"op\">,</span> <span class=\"st\">&quot;</span><span class=\"sc\">%u</span><span class=\"st\"> </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb15-15\"><a href=\"#cb15-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>                      target_uid<span class=\"op\">,</span> target_uid<span class=\"op\">);</span></span>\n<span id=\"cb15-16\"><a href=\"#cb15-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-17\"><a href=\"#cb15-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>target_uid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb15-18\"><a href=\"#cb15-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>      die<span class=\"op\">(</span><span class=\"st\">&quot;non-root users must run with -u 0 (got </span><span class=\"sc\">%u</span><span class=\"st\">)&quot;</span><span class=\"op\">,</span> target_uid<span class=\"op\">);</span></span>\n<span id=\"cb15-19\"><a href=\"#cb15-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    len <span class=\"op\">=</span> snprintf<span class=\"op\">(</span>map_buf<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">),</span> <span class=\"st\">&quot;0 </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> host_uid<span class=\"op\">);</span></span>\n<span id=\"cb15-20\"><a href=\"#cb15-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb15-21\"><a href=\"#cb15-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">&lt;</span> <span class=\"dv\">0</span> <span class=\"op\">||</span> <span class=\"op\">(</span><span class=\"dt\">size_t</span><span class=\"op\">)</span>len <span class=\"op\">&gt;=</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">))</span></span>\n<span id=\"cb15-22\"><a href=\"#cb15-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;uid_map formatting overflow&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb15-23\"><a href=\"#cb15-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write_file_fmt<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/uid_map&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;</span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> map_buf<span class=\"op\">);</span></span>\n<span id=\"cb15-24\"><a href=\"#cb15-24\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-25\"><a href=\"#cb15-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>  len <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb15-26\"><a href=\"#cb15-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>host_uid <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-27\"><a href=\"#cb15-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>    len <span class=\"op\">=</span> snprintf<span class=\"op\">(</span>map_buf<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">),</span> <span class=\"st\">&quot;0 </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> host_gid<span class=\"op\">);</span></span>\n<span id=\"cb15-28\"><a href=\"#cb15-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>target_gid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb15-29\"><a href=\"#cb15-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>      len <span class=\"op\">+=</span> snprintf<span class=\"op\">(</span>map_buf <span class=\"op\">+</span> len<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">)</span> <span class=\"op\">-</span> len<span class=\"op\">,</span> <span class=\"st\">&quot;</span><span class=\"sc\">%u</span><span class=\"st\"> </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb15-30\"><a href=\"#cb15-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>                      target_gid<span class=\"op\">,</span> target_gid<span class=\"op\">);</span></span>\n<span id=\"cb15-31\"><a href=\"#cb15-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-32\"><a href=\"#cb15-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>target_gid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb15-33\"><a href=\"#cb15-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>      die<span class=\"op\">(</span><span class=\"st\">&quot;non-root users must run with -g 0 (got </span><span class=\"sc\">%u</span><span class=\"st\">)&quot;</span><span class=\"op\">,</span> target_gid<span class=\"op\">);</span></span>\n<span id=\"cb15-34\"><a href=\"#cb15-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>    len <span class=\"op\">=</span> snprintf<span class=\"op\">(</span>map_buf<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">),</span> <span class=\"st\">&quot;0 </span><span class=\"sc\">%u</span><span class=\"st\"> 1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> host_gid<span class=\"op\">);</span></span>\n<span id=\"cb15-35\"><a href=\"#cb15-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb15-36\"><a href=\"#cb15-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">&lt;</span> <span class=\"dv\">0</span> <span class=\"op\">||</span> <span class=\"op\">(</span><span class=\"dt\">size_t</span><span class=\"op\">)</span>len <span class=\"op\">&gt;=</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>map_buf<span class=\"op\">))</span></span>\n<span id=\"cb15-37\"><a href=\"#cb15-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;gid_map formatting overflow&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb15-38\"><a href=\"#cb15-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write_file_fmt<span class=\"op\">(</span><span class=\"st\">&quot;/proc/self/gid_map&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;</span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> map_buf<span class=\"op\">);</span></span>\n<span id=\"cb15-39\"><a href=\"#cb15-39\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb15-40\"><a href=\"#cb15-40\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-41\"><a href=\"#cb15-41\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> sigsys_handler<span class=\"op\">(</span><span class=\"dt\">int</span> _nr<span class=\"op\">,</span> siginfo_t <span class=\"op\">*</span>info<span class=\"op\">,</span> <span class=\"dt\">void</span> <span class=\"op\">*</span>_uctx<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-42\"><a href=\"#cb15-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span>_nr<span class=\"op\">;</span></span>\n<span id=\"cb15-43\"><a href=\"#cb15-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span>_uctx<span class=\"op\">;</span></span>\n<span id=\"cb15-44\"><a href=\"#cb15-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!</span>info<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-45\"><a href=\"#cb15-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fprintf<span class=\"op\">(</span>stderr<span class=\"op\">,</span> <span class=\"st\">&quot;blocked syscall (no info)</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb15-46\"><a href=\"#cb15-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-47\"><a href=\"#cb15-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fprintf<span class=\"op\">(</span>stderr<span class=\"op\">,</span> <span class=\"st\">&quot;blocked syscall </span><span class=\"sc\">%d</span><span class=\"st\"> (arch </span><span class=\"sc\">%#x</span><span class=\"st\">, addr </span><span class=\"sc\">%p</span><span class=\"st\">)</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb15-48\"><a href=\"#cb15-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>            info<span class=\"op\">-&gt;</span>si_syscall<span class=\"op\">,</span> info<span class=\"op\">-&gt;</span>si_arch<span class=\"op\">,</span> info<span class=\"op\">-&gt;</span>si_call_addr<span class=\"op\">);</span></span>\n<span id=\"cb15-49\"><a href=\"#cb15-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb15-50\"><a href=\"#cb15-50\" aria-hidden=\"true\" tabindex=\"-1\"></a>  _exit<span class=\"op\">(</span><span class=\"dv\">1</span><span class=\"op\">);</span></span>\n<span id=\"cb15-51\"><a href=\"#cb15-51\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb15-52\"><a href=\"#cb15-52\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-53\"><a href=\"#cb15-53\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> install_sigsys_logger<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-54\"><a href=\"#cb15-54\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"kw\">struct</span> sigaction sa<span class=\"op\">;</span></span>\n<span id=\"cb15-55\"><a href=\"#cb15-55\" aria-hidden=\"true\" tabindex=\"-1\"></a>  memset<span class=\"op\">(&amp;</span>sa<span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>sa<span class=\"op\">));</span></span>\n<span id=\"cb15-56\"><a href=\"#cb15-56\" aria-hidden=\"true\" tabindex=\"-1\"></a>  sa<span class=\"op\">.</span>sa_sigaction <span class=\"op\">=</span> sigsys_handler<span class=\"op\">;</span></span>\n<span id=\"cb15-57\"><a href=\"#cb15-57\" aria-hidden=\"true\" tabindex=\"-1\"></a>  sa<span class=\"op\">.</span>sa_flags <span class=\"op\">=</span> SA_SIGINFO <span class=\"op\">|</span> SA_RESETHAND<span class=\"op\">;</span></span>\n<span id=\"cb15-58\"><a href=\"#cb15-58\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>sigaction<span class=\"op\">(</span>SIGSYS<span class=\"op\">,</span> <span class=\"op\">&amp;</span>sa<span class=\"op\">,</span> NULL<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb15-59\"><a href=\"#cb15-59\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;sigaction(SIGSYS): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb15-60\"><a href=\"#cb15-60\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb15-61\"><a href=\"#cb15-61\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-62\"><a href=\"#cb15-62\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> install_seccomp_allowlist<span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-63\"><a href=\"#cb15-63\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>prctl<span class=\"op\">(</span>PR_SET_NO_NEW_PRIVS<span class=\"op\">,</span> <span class=\"dv\">1</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb15-64\"><a href=\"#cb15-64\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;prctl(NO_NEW_PRIVS): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb15-65\"><a href=\"#cb15-65\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-66\"><a href=\"#cb15-66\" aria-hidden=\"true\" tabindex=\"-1\"></a>  scmp_filter_ctx ctx <span class=\"op\">=</span> seccomp_init<span class=\"op\">(</span>SCMP_ACT_TRAP<span class=\"op\">);</span></span>\n<span id=\"cb15-67\"><a href=\"#cb15-67\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!</span>ctx<span class=\"op\">)</span></span>\n<span id=\"cb15-68\"><a href=\"#cb15-68\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;seccomp_init failed&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb15-69\"><a href=\"#cb15-69\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-70\"><a href=\"#cb15-70\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define ALLOW</span><span class=\"op\">(</span><span class=\"pp\">syscall</span><span class=\"op\">)</span><span class=\"pp\">                                                         </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-71\"><a href=\"#cb15-71\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">  </span><span class=\"cf\">do</span><span class=\"pp\"> </span><span class=\"op\">{</span><span class=\"pp\">                                                                         </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-72\"><a href=\"#cb15-72\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"cf\">if</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">seccomp_rule_add</span><span class=\"op\">(</span><span class=\"pp\">ctx</span><span class=\"op\">,</span><span class=\"pp\"> SCMP_ACT_ALLOW</span><span class=\"op\">,</span><span class=\"pp\"> SCMP_SYS</span><span class=\"op\">(</span><span class=\"pp\">syscall</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"dv\">0</span><span class=\"op\">))</span><span class=\"pp\">           </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-73\"><a href=\"#cb15-73\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">      die</span><span class=\"op\">(</span><span class=\"st\">&quot;allow &quot;</span><span class=\"pp\"> </span><span class=\"op\">#</span><span class=\"pp\">syscall </span><span class=\"st\">&quot; failed&quot;</span><span class=\"op\">);</span><span class=\"pp\">                                        </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-74\"><a href=\"#cb15-74\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">  </span><span class=\"op\">}</span><span class=\"pp\"> </span><span class=\"cf\">while</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb15-75\"><a href=\"#cb15-75\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define ALLOW_ARG</span><span class=\"op\">(</span><span class=\"pp\">syscall</span><span class=\"op\">,</span><span class=\"pp\"> idx</span><span class=\"op\">,</span><span class=\"pp\"> cmp</span><span class=\"op\">,</span><span class=\"pp\"> val</span><span class=\"op\">)</span><span class=\"pp\">                                      </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-76\"><a href=\"#cb15-76\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">  </span><span class=\"cf\">do</span><span class=\"pp\"> </span><span class=\"op\">{</span><span class=\"pp\">                                                                         </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-77\"><a href=\"#cb15-77\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"cf\">if</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">seccomp_rule_add</span><span class=\"op\">(</span><span class=\"pp\">ctx</span><span class=\"op\">,</span><span class=\"pp\"> SCMP_ACT_ALLOW</span><span class=\"op\">,</span><span class=\"pp\"> SCMP_SYS</span><span class=\"op\">(</span><span class=\"pp\">syscall</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"dv\">1</span><span class=\"op\">,</span><span class=\"pp\">            </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-78\"><a href=\"#cb15-78\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                         SCMP_CMP</span><span class=\"op\">(</span><span class=\"pp\">idx</span><span class=\"op\">,</span><span class=\"pp\"> cmp</span><span class=\"op\">,</span><span class=\"pp\"> val</span><span class=\"op\">)))</span><span class=\"pp\">                             </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-79\"><a href=\"#cb15-79\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">      die</span><span class=\"op\">(</span><span class=\"st\">&quot;allow &quot;</span><span class=\"pp\"> </span><span class=\"op\">#</span><span class=\"pp\">syscall </span><span class=\"st\">&quot; arg failed&quot;</span><span class=\"op\">);</span><span class=\"pp\">                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-80\"><a href=\"#cb15-80\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">  </span><span class=\"op\">}</span><span class=\"pp\"> </span><span class=\"cf\">while</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dv\">0</span><span class=\"op\">)</span></span>\n<span id=\"cb15-81\"><a href=\"#cb15-81\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-82\"><a href=\"#cb15-82\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>rt_sigaction<span class=\"op\">);</span></span>\n<span id=\"cb15-83\"><a href=\"#cb15-83\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>rt_sigprocmask<span class=\"op\">);</span></span>\n<span id=\"cb15-84\"><a href=\"#cb15-84\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>umask<span class=\"op\">);</span></span>\n<span id=\"cb15-85\"><a href=\"#cb15-85\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>rt_sigreturn<span class=\"op\">);</span></span>\n<span id=\"cb15-86\"><a href=\"#cb15-86\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>exit<span class=\"op\">);</span></span>\n<span id=\"cb15-87\"><a href=\"#cb15-87\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>exit_group<span class=\"op\">);</span></span>\n<span id=\"cb15-88\"><a href=\"#cb15-88\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getpid<span class=\"op\">);</span></span>\n<span id=\"cb15-89\"><a href=\"#cb15-89\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getppid<span class=\"op\">);</span></span>\n<span id=\"cb15-90\"><a href=\"#cb15-90\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>gettid<span class=\"op\">);</span></span>\n<span id=\"cb15-91\"><a href=\"#cb15-91\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>futex<span class=\"op\">);</span></span>\n<span id=\"cb15-92\"><a href=\"#cb15-92\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>clone<span class=\"op\">);</span></span>\n<span id=\"cb15-93\"><a href=\"#cb15-93\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>set_tid_address<span class=\"op\">);</span></span>\n<span id=\"cb15-94\"><a href=\"#cb15-94\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>set_robust_list<span class=\"op\">);</span></span>\n<span id=\"cb15-95\"><a href=\"#cb15-95\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-96\"><a href=\"#cb15-96\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>clock_gettime<span class=\"op\">);</span></span>\n<span id=\"cb15-97\"><a href=\"#cb15-97\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>clock_nanosleep<span class=\"op\">);</span></span>\n<span id=\"cb15-98\"><a href=\"#cb15-98\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>nanosleep<span class=\"op\">);</span></span>\n<span id=\"cb15-99\"><a href=\"#cb15-99\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getrandom<span class=\"op\">);</span></span>\n<span id=\"cb15-100\"><a href=\"#cb15-100\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-101\"><a href=\"#cb15-101\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>brk<span class=\"op\">);</span></span>\n<span id=\"cb15-102\"><a href=\"#cb15-102\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>mmap<span class=\"op\">);</span></span>\n<span id=\"cb15-103\"><a href=\"#cb15-103\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>munmap<span class=\"op\">);</span></span>\n<span id=\"cb15-104\"><a href=\"#cb15-104\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>mremap<span class=\"op\">);</span></span>\n<span id=\"cb15-105\"><a href=\"#cb15-105\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>mprotect<span class=\"op\">);</span></span>\n<span id=\"cb15-106\"><a href=\"#cb15-106\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-107\"><a href=\"#cb15-107\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>arch_prctl<span class=\"op\">);</span></span>\n<span id=\"cb15-108\"><a href=\"#cb15-108\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getuid<span class=\"op\">);</span></span>\n<span id=\"cb15-109\"><a href=\"#cb15-109\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>geteuid<span class=\"op\">);</span></span>\n<span id=\"cb15-110\"><a href=\"#cb15-110\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getgid<span class=\"op\">);</span></span>\n<span id=\"cb15-111\"><a href=\"#cb15-111\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getegid<span class=\"op\">);</span></span>\n<span id=\"cb15-112\"><a href=\"#cb15-112\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>prlimit64<span class=\"op\">);</span></span>\n<span id=\"cb15-113\"><a href=\"#cb15-113\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>prctl<span class=\"op\">);</span></span>\n<span id=\"cb15-114\"><a href=\"#cb15-114\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>madvise<span class=\"op\">);</span></span>\n<span id=\"cb15-115\"><a href=\"#cb15-115\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>access<span class=\"op\">);</span></span>\n<span id=\"cb15-116\"><a href=\"#cb15-116\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>faccessat2<span class=\"op\">);</span></span>\n<span id=\"cb15-117\"><a href=\"#cb15-117\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>pread64<span class=\"op\">);</span></span>\n<span id=\"cb15-118\"><a href=\"#cb15-118\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>rseq<span class=\"op\">);</span></span>\n<span id=\"cb15-119\"><a href=\"#cb15-119\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>fadvise64<span class=\"op\">);</span></span>\n<span id=\"cb15-120\"><a href=\"#cb15-120\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-121\"><a href=\"#cb15-121\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>read<span class=\"op\">);</span></span>\n<span id=\"cb15-122\"><a href=\"#cb15-122\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>write<span class=\"op\">);</span></span>\n<span id=\"cb15-123\"><a href=\"#cb15-123\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>writev<span class=\"op\">);</span></span>\n<span id=\"cb15-124\"><a href=\"#cb15-124\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>close<span class=\"op\">);</span></span>\n<span id=\"cb15-125\"><a href=\"#cb15-125\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>lseek<span class=\"op\">);</span></span>\n<span id=\"cb15-126\"><a href=\"#cb15-126\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getdents64<span class=\"op\">);</span></span>\n<span id=\"cb15-127\"><a href=\"#cb15-127\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>ioctl<span class=\"op\">);</span></span>\n<span id=\"cb15-128\"><a href=\"#cb15-128\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>statx<span class=\"op\">);</span></span>\n<span id=\"cb15-129\"><a href=\"#cb15-129\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>fstat<span class=\"op\">);</span></span>\n<span id=\"cb15-130\"><a href=\"#cb15-130\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>fstatfs<span class=\"op\">);</span></span>\n<span id=\"cb15-131\"><a href=\"#cb15-131\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>newfstatat<span class=\"op\">);</span></span>\n<span id=\"cb15-132\"><a href=\"#cb15-132\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>fcntl<span class=\"op\">);</span></span>\n<span id=\"cb15-133\"><a href=\"#cb15-133\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>dup<span class=\"op\">);</span></span>\n<span id=\"cb15-134\"><a href=\"#cb15-134\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>dup2<span class=\"op\">);</span></span>\n<span id=\"cb15-135\"><a href=\"#cb15-135\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>dup3<span class=\"op\">);</span></span>\n<span id=\"cb15-136\"><a href=\"#cb15-136\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>pipe<span class=\"op\">);</span></span>\n<span id=\"cb15-137\"><a href=\"#cb15-137\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>pipe2<span class=\"op\">);</span></span>\n<span id=\"cb15-138\"><a href=\"#cb15-138\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>readlink<span class=\"op\">);</span></span>\n<span id=\"cb15-139\"><a href=\"#cb15-139\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>readlinkat<span class=\"op\">);</span></span>\n<span id=\"cb15-140\"><a href=\"#cb15-140\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>uname<span class=\"op\">);</span></span>\n<span id=\"cb15-141\"><a href=\"#cb15-141\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>open<span class=\"op\">);</span></span>\n<span id=\"cb15-142\"><a href=\"#cb15-142\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>openat<span class=\"op\">);</span></span>\n<span id=\"cb15-143\"><a href=\"#cb15-143\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-144\"><a href=\"#cb15-144\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>execve<span class=\"op\">);</span></span>\n<span id=\"cb15-145\"><a href=\"#cb15-145\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>execveat<span class=\"op\">);</span></span>\n<span id=\"cb15-146\"><a href=\"#cb15-146\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-147\"><a href=\"#cb15-147\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>socket<span class=\"op\">);</span></span>\n<span id=\"cb15-148\"><a href=\"#cb15-148\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>connect<span class=\"op\">);</span></span>\n<span id=\"cb15-149\"><a href=\"#cb15-149\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>bind<span class=\"op\">);</span></span>\n<span id=\"cb15-150\"><a href=\"#cb15-150\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>listen<span class=\"op\">);</span></span>\n<span id=\"cb15-151\"><a href=\"#cb15-151\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>accept<span class=\"op\">);</span></span>\n<span id=\"cb15-152\"><a href=\"#cb15-152\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>accept4<span class=\"op\">);</span></span>\n<span id=\"cb15-153\"><a href=\"#cb15-153\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getsockopt<span class=\"op\">);</span></span>\n<span id=\"cb15-154\"><a href=\"#cb15-154\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>setsockopt<span class=\"op\">);</span></span>\n<span id=\"cb15-155\"><a href=\"#cb15-155\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getsockname<span class=\"op\">);</span></span>\n<span id=\"cb15-156\"><a href=\"#cb15-156\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getpeername<span class=\"op\">);</span></span>\n<span id=\"cb15-157\"><a href=\"#cb15-157\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>sendto<span class=\"op\">);</span></span>\n<span id=\"cb15-158\"><a href=\"#cb15-158\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>recvfrom<span class=\"op\">);</span></span>\n<span id=\"cb15-159\"><a href=\"#cb15-159\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>sendmsg<span class=\"op\">);</span></span>\n<span id=\"cb15-160\"><a href=\"#cb15-160\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>recvmsg<span class=\"op\">);</span></span>\n<span id=\"cb15-161\"><a href=\"#cb15-161\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>shutdown<span class=\"op\">);</span></span>\n<span id=\"cb15-162\"><a href=\"#cb15-162\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-163\"><a href=\"#cb15-163\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>clone3<span class=\"op\">);</span></span>\n<span id=\"cb15-164\"><a href=\"#cb15-164\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>eventfd2<span class=\"op\">);</span></span>\n<span id=\"cb15-165\"><a href=\"#cb15-165\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>poll<span class=\"op\">);</span></span>\n<span id=\"cb15-166\"><a href=\"#cb15-166\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>statfs<span class=\"op\">);</span></span>\n<span id=\"cb15-167\"><a href=\"#cb15-167\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getcwd<span class=\"op\">);</span></span>\n<span id=\"cb15-168\"><a href=\"#cb15-168\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>getpgid<span class=\"op\">);</span></span>\n<span id=\"cb15-169\"><a href=\"#cb15-169\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>setpgid<span class=\"op\">);</span></span>\n<span id=\"cb15-170\"><a href=\"#cb15-170\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>stat<span class=\"op\">);</span></span>\n<span id=\"cb15-171\"><a href=\"#cb15-171\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>vfork<span class=\"op\">);</span></span>\n<span id=\"cb15-172\"><a href=\"#cb15-172\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ALLOW<span class=\"op\">(</span>wait4<span class=\"op\">);</span></span>\n<span id=\"cb15-173\"><a href=\"#cb15-173\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-174\"><a href=\"#cb15-174\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>chroot<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-175\"><a href=\"#cb15-175\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>pivot_root<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-176\"><a href=\"#cb15-176\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>mount<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-177\"><a href=\"#cb15-177\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>umount2<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-178\"><a href=\"#cb15-178\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>open_by_handle_at<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-179\"><a href=\"#cb15-179\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>name_to_handle_at<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-180\"><a href=\"#cb15-180\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>bpf<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-181\"><a href=\"#cb15-181\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>kexec_load<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-182\"><a href=\"#cb15-182\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>kexec_file_load<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-183\"><a href=\"#cb15-183\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_rule_add<span class=\"op\">(</span>ctx<span class=\"op\">,</span> SCMP_ACT_KILL<span class=\"op\">,</span> SCMP_SYS<span class=\"op\">(</span>ptrace<span class=\"op\">),</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb15-184\"><a href=\"#cb15-184\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb15-185\"><a href=\"#cb15-185\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>seccomp_load<span class=\"op\">(</span>ctx<span class=\"op\">)</span> <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb15-186\"><a href=\"#cb15-186\" aria-hidden=\"true\" tabindex=\"-1\"></a>    seccomp_release<span class=\"op\">(</span>ctx<span class=\"op\">);</span></span>\n<span id=\"cb15-187\"><a href=\"#cb15-187\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;seccomp_load failed&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb15-188\"><a href=\"#cb15-188\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb15-189\"><a href=\"#cb15-189\" aria-hidden=\"true\" tabindex=\"-1\"></a>  seccomp_release<span class=\"op\">(</span>ctx<span class=\"op\">);</span></span>\n<span id=\"cb15-190\"><a href=\"#cb15-190\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#undef ALLOW</span></span>\n<span id=\"cb15-191\"><a href=\"#cb15-191\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#undef ALLOW_ARG</span></span></code></pre></div>\n<p>And fix up main.</p>\n<div class=\"sourceCode\" id=\"cb16\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb16-1\"><a href=\"#cb16-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">int</span> argc<span class=\"op\">,</span> <span class=\"dt\">char</span> <span class=\"op\">**</span>argv<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-2\"><a href=\"#cb16-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>root <span class=\"op\">=</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb16-3\"><a href=\"#cb16-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  uid_t host_uid <span class=\"op\">=</span> geteuid<span class=\"op\">();</span></span>\n<span id=\"cb16-4\"><a href=\"#cb16-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  gid_t host_gid <span class=\"op\">=</span> getegid<span class=\"op\">();</span></span>\n<span id=\"cb16-5\"><a href=\"#cb16-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">bool</span> rootless <span class=\"op\">=</span> <span class=\"op\">(</span>host_uid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb16-6\"><a href=\"#cb16-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>  uid_t uid <span class=\"op\">=</span> rootless <span class=\"op\">?</span> <span class=\"dv\">0</span> <span class=\"op\">:</span> <span class=\"dv\">65534</span><span class=\"op\">;</span></span>\n<span id=\"cb16-7\"><a href=\"#cb16-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  gid_t gid <span class=\"op\">=</span> rootless <span class=\"op\">?</span> <span class=\"dv\">0</span> <span class=\"op\">:</span> <span class=\"dv\">65534</span><span class=\"op\">;</span></span>\n<span id=\"cb16-8\"><a href=\"#cb16-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-9\"><a href=\"#cb16-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> i <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> argc<span class=\"op\">;</span> i<span class=\"op\">++)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-10\"><a href=\"#cb16-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-r&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-11\"><a href=\"#cb16-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>      root <span class=\"op\">=</span> argv<span class=\"op\">[++</span>i<span class=\"op\">];</span></span>\n<span id=\"cb16-12\"><a href=\"#cb16-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-u&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-13\"><a href=\"#cb16-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>      uid <span class=\"op\">=</span> <span class=\"op\">(</span>uid_t<span class=\"op\">)</span>strtoul<span class=\"op\">(</span>argv<span class=\"op\">[++</span>i<span class=\"op\">],</span> NULL<span class=\"op\">,</span> <span class=\"dv\">10</span><span class=\"op\">);</span></span>\n<span id=\"cb16-14\"><a href=\"#cb16-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;-g&quot;</span><span class=\"op\">)</span> <span class=\"op\">&amp;&amp;</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;</span> argc<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-15\"><a href=\"#cb16-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>      gid <span class=\"op\">=</span> <span class=\"op\">(</span>gid_t<span class=\"op\">)</span>strtoul<span class=\"op\">(</span>argv<span class=\"op\">[++</span>i<span class=\"op\">],</span> NULL<span class=\"op\">,</span> <span class=\"dv\">10</span><span class=\"op\">);</span></span>\n<span id=\"cb16-16\"><a href=\"#cb16-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(!</span>strcmp<span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">],</span> <span class=\"st\">&quot;--&quot;</span><span class=\"op\">))</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-17\"><a href=\"#cb16-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argv <span class=\"op\">+=</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb16-18\"><a href=\"#cb16-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argc <span class=\"op\">-=</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb16-19\"><a href=\"#cb16-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb16-20\"><a href=\"#cb16-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> <span class=\"op\">(</span>argv<span class=\"op\">[</span>i<span class=\"op\">][</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">==</span> <span class=\"ch\">&#39;-&#39;</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-21\"><a href=\"#cb16-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>      usage<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]);</span></span>\n<span id=\"cb16-22\"><a href=\"#cb16-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-23\"><a href=\"#cb16-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argv <span class=\"op\">+=</span> i<span class=\"op\">;</span></span>\n<span id=\"cb16-24\"><a href=\"#cb16-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>      argc <span class=\"op\">-=</span> i<span class=\"op\">;</span></span>\n<span id=\"cb16-25\"><a href=\"#cb16-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb16-26\"><a href=\"#cb16-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb16-27\"><a href=\"#cb16-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb16-28\"><a href=\"#cb16-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(!</span>root <span class=\"op\">||</span> argc <span class=\"op\">&lt;</span> <span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb16-29\"><a href=\"#cb16-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>    usage<span class=\"op\">(</span><span class=\"st\">&quot;container&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb16-30\"><a href=\"#cb16-30\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-31\"><a href=\"#cb16-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>rootless <span class=\"op\">&amp;&amp;</span> <span class=\"op\">(</span>uid <span class=\"op\">!=</span> <span class=\"dv\">0</span> <span class=\"op\">||</span> gid <span class=\"op\">!=</span> <span class=\"dv\">0</span><span class=\"op\">))</span></span>\n<span id=\"cb16-32\"><a href=\"#cb16-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;non-root users can only use -u/-g 0 (try running as root for other &quot;</span></span>\n<span id=\"cb16-33\"><a href=\"#cb16-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;ids)&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb16-34\"><a href=\"#cb16-34\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-35\"><a href=\"#cb16-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>  setup_user_namespace<span class=\"op\">(</span>host_uid<span class=\"op\">,</span> host_gid<span class=\"op\">,</span> uid<span class=\"op\">,</span> gid<span class=\"op\">);</span></span>\n<span id=\"cb16-36\"><a href=\"#cb16-36\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-37\"><a href=\"#cb16-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>unshare<span class=\"op\">(</span>CLONE_NEWNS<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb16-38\"><a href=\"#cb16-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;unshare(CLONE_NEWNS): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb16-39\"><a href=\"#cb16-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>  make_private_mounts<span class=\"op\">();</span></span>\n<span id=\"cb16-40\"><a href=\"#cb16-40\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-41\"><a href=\"#cb16-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>  bind_mount_self<span class=\"op\">(</span>root<span class=\"op\">);</span></span>\n<span id=\"cb16-42\"><a href=\"#cb16-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>chroot<span class=\"op\">(</span>root<span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb16-43\"><a href=\"#cb16-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;chroot(</span><span class=\"sc\">%s</span><span class=\"st\">): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> root<span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb16-44\"><a href=\"#cb16-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>chdir<span class=\"op\">(</span><span class=\"st\">&quot;/&quot;</span><span class=\"op\">)</span> <span class=\"op\">==</span> <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span></span>\n<span id=\"cb16-45\"><a href=\"#cb16-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>    die<span class=\"op\">(</span><span class=\"st\">&quot;chdir(/): </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb16-46\"><a href=\"#cb16-46\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-47\"><a href=\"#cb16-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>  mkdir<span class=\"op\">(</span><span class=\"st\">&quot;/proc&quot;</span><span class=\"op\">,</span> <span class=\"bn\">0555</span><span class=\"op\">);</span></span>\n<span id=\"cb16-48\"><a href=\"#cb16-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>mount<span class=\"op\">(</span><span class=\"st\">&quot;proc&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;/proc&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;proc&quot;</span><span class=\"op\">,</span> MS_NOSUID <span class=\"op\">|</span> MS_NODEV <span class=\"op\">|</span> MS_NOEXEC<span class=\"op\">,</span> NULL<span class=\"op\">)</span> <span class=\"op\">==</span></span>\n<span id=\"cb16-49\"><a href=\"#cb16-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"op\">-</span><span class=\"dv\">1</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-50\"><a href=\"#cb16-50\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb16-51\"><a href=\"#cb16-51\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-52\"><a href=\"#cb16-52\" aria-hidden=\"true\" tabindex=\"-1\"></a>  clearenv<span class=\"op\">();</span></span>\n<span id=\"cb16-53\"><a href=\"#cb16-53\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close_all_fds_except_std<span class=\"op\">();</span></span>\n<span id=\"cb16-54\"><a href=\"#cb16-54\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-55\"><a href=\"#cb16-55\" aria-hidden=\"true\" tabindex=\"-1\"></a>  drop_privileges<span class=\"op\">(</span>uid<span class=\"op\">,</span> gid<span class=\"op\">);</span></span>\n<span id=\"cb16-56\"><a href=\"#cb16-56\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-57\"><a href=\"#cb16-57\" aria-hidden=\"true\" tabindex=\"-1\"></a>  install_sigsys_logger<span class=\"op\">();</span></span>\n<span id=\"cb16-58\"><a href=\"#cb16-58\" aria-hidden=\"true\" tabindex=\"-1\"></a>  install_seccomp_allowlist<span class=\"op\">();</span></span>\n<span id=\"cb16-59\"><a href=\"#cb16-59\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-60\"><a href=\"#cb16-60\" aria-hidden=\"true\" tabindex=\"-1\"></a>  execvp<span class=\"op\">(</span>argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">],</span> argv<span class=\"op\">);</span></span>\n<span id=\"cb16-61\"><a href=\"#cb16-61\" aria-hidden=\"true\" tabindex=\"-1\"></a>  die<span class=\"op\">(</span><span class=\"st\">&quot;execvp(&#39;</span><span class=\"sc\">%s</span><span class=\"st\">&#39;) failed: </span><span class=\"sc\">%s</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> argv<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">],</span> strerror<span class=\"op\">(</span>errno<span class=\"op\">));</span></span>\n<span id=\"cb16-62\"><a href=\"#cb16-62\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Now with this, we can\u2019t try any <code>ptrace</code> tricks, since\nwe\u2019ve explicitly disallowed it. As well, we\u2019ve added a helper that lets\nus strace a task to see which syscall killed our task (good for\ndebugging).</p>\n<p>I\u2019ve allowed enough syscalls to allow for one last party trick \u2013 a\nway to call the network (on your own computer).</p>\n<p>I spun up an http server serving the <code>container.c</code> file at\n<code>127.0.0.1:8080/container.c</code>:</p>\n<p>And look, there\u2019s the code.</p>\n<div class=\"sourceCode\" id=\"cb17\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb17-1\"><a href=\"#cb17-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">./container_3</span> <span class=\"at\">-r</span> root/ <span class=\"at\">--</span> /bin/dash</span>\n<span id=\"cb17-2\"><a href=\"#cb17-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> toybox wget http://127.0.0.1:8080/container.c <span class=\"at\">-O</span> <span class=\"at\">-</span></span>\n<span id=\"cb17-3\"><a href=\"#cb17-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># the code we&#39;ve been writing today.</span></span></code></pre></div>\n<p>If you\u2019re a little too overzealous with the system calls, there\u2019s\nprobably an escape out, but we can cover the most egregious ones with\nthe seccomp denylist. You can configure the list how you like and you\ncan get a passable toy container and play around with it.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2025-11-12T20:55:26+00:00"
		},
		{
			"id": "gen/c-vs-asm.html",
			"url": "gen/c-vs-asm.html",
			"title": "C vs. Asm",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>C vs.\u00a0Asm</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">C vs.\u00a0Asm</h1>\n<p class=\"byline\">2025-11-12T08:22:49-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#its-faster-in-assembly\"\nid=\"toc-its-faster-in-assembly\">It\u2019s faster in Assembly</a></li>\n<li><a href=\"#but-what-about-at--o3\" id=\"toc-but-what-about-at--o3\">But\nwhat about at <code>-O3</code>?</a></li>\n<li><a href=\"#why-this-matters\" id=\"toc-why-this-matters\">Why this\nmatters</a></li>\n</ul>\n</nav>\n<section id=\"its-faster-in-assembly\" class=\"level2\">\n<h2>It\u2019s faster in Assembly</h2>\n<p>A common refrain is if something is slow, to rewrite it in a\n<strong>faster</strong> language. For python, if your python is slow, to\nwrite the hot parts in C. For C, to write your code in pure\nassembly.</p>\n<p>Let\u2019s put that to the test.</p>\n<p>I have this code here that defines <code>strnlen</code> from linux\u2019s\nm68k tree. This computes <code>strnlen</code> as you would expect.</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"kw\">inline</span> <span class=\"dt\">size_t</span> strnlen_asm<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>s<span class=\"op\">,</span> <span class=\"dt\">size_t</span> count<span class=\"op\">)</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">{</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>sc <span class=\"op\">=</span> s<span class=\"op\">;</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    asm <span class=\"dt\">volatile</span> <span class=\"op\">(</span><span class=\"st\">&quot;</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;1:     subq.l  #1,%1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;       jcs     2f</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;       tst.b   (%0)+</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;       jne     1b</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;       subq.l  #1,%0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"st\">&quot;2:&quot;</span></span>\n<span id=\"cb1-12\"><a href=\"#cb1-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">:</span> <span class=\"st\">&quot;+a&quot;</span> <span class=\"op\">(</span>sc<span class=\"op\">),</span> <span class=\"st\">&quot;+d&quot;</span> <span class=\"op\">(</span>count<span class=\"op\">));</span></span>\n<span id=\"cb1-13\"><a href=\"#cb1-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> sc <span class=\"op\">-</span> s<span class=\"op\">;</span></span>\n<span id=\"cb1-14\"><a href=\"#cb1-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>The c translation here would look like this:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">static</span> <span class=\"kw\">inline</span> <span class=\"dt\">size_t</span> strnlen<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>s<span class=\"op\">,</span> <span class=\"dt\">size_t</span> count<span class=\"op\">)</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">{</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>sc <span class=\"op\">=</span> s<span class=\"op\">;</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">while</span> <span class=\"op\">(</span>count<span class=\"op\">--)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">if</span> <span class=\"op\">(*</span>sc<span class=\"op\">++</span> <span class=\"op\">==</span> <span class=\"ch\">&#39;</span><span class=\"sc\">\\0</span><span class=\"ch\">&#39;</span><span class=\"op\">)</span> <span class=\"op\">{</span>   </span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            sc<span class=\"op\">--;</span>              </span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> sc <span class=\"op\">-</span> s<span class=\"op\">;</span></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Now if we compile with <code>-O0</code>, we\u2019ll see that the asm\nversion is better, even though functionally, they\u2019re pretty much the\nsame. The compiler does only a few optimizations in <code>-O0</code>, so\nthe generated code is quite poor.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>strnlen_asm<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">):</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    link<span class=\"op\">.</span>w <span class=\"op\">%</span>fp<span class=\"op\">,#-</span><span class=\"dv\">4</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">8</span><span class=\"op\">),%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">)</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">),%</span>d1</span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">12</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    movea<span class=\"op\">.</span>l <span class=\"op\">%</span>d1<span class=\"op\">,%</span>a0</span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bcss <span class=\"dv\">1</span><span class=\"er\">e</span> <span class=\"op\">&lt;</span>strnlen_asm<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)+</span><span class=\"bn\">0x1e</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    tstb <span class=\"op\">%</span>a0<span class=\"fu\">@</span><span class=\"er\">+</span></span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bnes <span class=\"dv\">14</span> <span class=\"op\">&lt;</span>strnlen_asm<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)+</span><span class=\"bn\">0x14</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>a0</span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>a0<span class=\"op\">,%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">)</span></span>\n<span id=\"cb3-13\"><a href=\"#cb3-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>d0<span class=\"op\">,%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">12</span><span class=\"op\">)</span></span>\n<span id=\"cb3-14\"><a href=\"#cb3-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb3-15\"><a href=\"#cb3-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sub</span><span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">8</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb3-16\"><a href=\"#cb3-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    unlk <span class=\"op\">%</span>fp</span>\n<span id=\"cb3-17\"><a href=\"#cb3-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    rts</span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">):</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    linkw <span class=\"op\">%</span>fp<span class=\"op\">,#-</span><span class=\"dv\">4</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">8</span><span class=\"op\">),%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">)</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bras <span class=\"dv\">5</span><span class=\"er\">a</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)+</span><span class=\"bn\">0x28</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>d0<span class=\"op\">,%</span>d1</span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    addq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>d1</span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>d1<span class=\"op\">,%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">)</span></span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    movea<span class=\"op\">.</span>l <span class=\"op\">%</span>d0<span class=\"op\">,%</span>a0</span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    moveb <span class=\"op\">%</span>a0<span class=\"fu\">@</span><span class=\"er\">,</span><span class=\"op\">%</span>d0</span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    seq <span class=\"op\">%</span>d0</span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    negb <span class=\"op\">%</span>d0</span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    beqs <span class=\"dv\">5</span><span class=\"er\">a</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)+</span><span class=\"bn\">0x28</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">)</span></span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bras <span class=\"dv\">6</span><span class=\"er\">e</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)+</span><span class=\"bn\">0x3c</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">12</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>d0<span class=\"op\">,%</span>d1</span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>d1</span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>d1<span class=\"op\">,%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">12</span><span class=\"op\">)</span></span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    tstl <span class=\"op\">%</span>d0</span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    sne <span class=\"op\">%</span>d0</span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    negb <span class=\"op\">%</span>d0</span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bnes <span class=\"dv\">3</span><span class=\"er\">e</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)+</span><span class=\"bn\">0xc</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb4-24\"><a href=\"#cb4-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"op\">-</span><span class=\"dv\">4</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb4-25\"><a href=\"#cb4-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sub</span><span class=\"op\">.</span>l <span class=\"op\">%</span>fp<span class=\"fu\">@</span><span class=\"er\">(</span><span class=\"dv\">8</span><span class=\"op\">),%</span>d0</span>\n<span id=\"cb4-26\"><a href=\"#cb4-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    unlk <span class=\"op\">%</span>fp</span>\n<span id=\"cb4-27\"><a href=\"#cb4-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>    rts</span></code></pre></div>\n<p>However, as soon as we up the optimization for the C version (this\ntime at <code>-O2</code>), the code looks much better:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]:</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">lea</span> <span class=\"dv\">0</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]&gt;,%</span>a0</span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    tstb <span class=\"op\">%</span>a0<span class=\"fu\">@</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    beqs <span class=\"dv\">14</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]+</span><span class=\"bn\">0x14</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    addq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>a0</span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    cmpa<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">0</span><span class=\"op\">,%</span>a0</span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bnes <span class=\"dv\">6</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]+</span><span class=\"bn\">0x6</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>a0<span class=\"op\">,%</span>d0</span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subi<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">0</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    rts</span></code></pre></div>\n<p>But the assembly version also improves.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>strnlen_asm<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>isra<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]:</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">lea</span> <span class=\"dv\">0</span> <span class=\"op\">&lt;</span>strnlen<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]&gt;,%</span>a0</span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>       R_68K_32 <span class=\"op\">.</span>rodata<span class=\"op\">.</span>str1<span class=\"op\">.</span><span class=\"dv\">1</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>q <span class=\"op\">#</span><span class=\"dv\">8</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bcss <span class=\"dv\">30</span> <span class=\"op\">&lt;</span>strnlen_asm<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>isra<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]+</span><span class=\"bn\">0x12</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    tstb <span class=\"op\">%</span>a0<span class=\"fu\">@</span><span class=\"er\">+</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    bnes <span class=\"dv\">26</span> <span class=\"op\">&lt;</span>strnlen_asm<span class=\"op\">(</span>char const<span class=\"op\">*,</span> unsigned long<span class=\"op\">)</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>constprop<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">[</span>clone <span class=\"op\">.</span>isra<span class=\"op\">.</span><span class=\"dv\">0</span><span class=\"op\">]+</span><span class=\"bn\">0x8</span><span class=\"op\">&gt;</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    subq<span class=\"op\">.</span>l <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>a0</span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    rts</span></code></pre></div>\n</section>\n<section id=\"but-what-about-at--o3\" class=\"level2\">\n<h2>But what about at <code>-O3</code>?</h2>\n<p>However, the real changes happens at <code>-O3</code> which has very\naggressive inlining: let\u2019s say our program is:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">()</span> </span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">{</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">size_t</span> n <span class=\"op\">=</span> strnlen_asm<span class=\"op\">(</span><span class=\"st\">&quot;hello&quot;</span><span class=\"op\">,</span> <span class=\"dv\">8</span><span class=\"op\">);</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">size_t</span> c <span class=\"op\">=</span> strnlen<span class=\"op\">(</span><span class=\"st\">&quot;hello&quot;</span><span class=\"op\">,</span> <span class=\"dv\">8</span><span class=\"op\">);</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> n <span class=\"op\">+</span> c<span class=\"op\">;</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>What\u2019s the resulting assembly when compiled at <code>-O3</code>?</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">main:</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">lea</span> <span class=\"op\">.</span>LC0<span class=\"op\">,%</span>a0 <span class=\"op\">|</span> <span class=\"op\">&lt;</span> this provides <span class=\"op\">%</span>a0 as the first arg</span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    moveq <span class=\"op\">#</span><span class=\"dv\">8</span><span class=\"op\">,%</span>d0 <span class=\"op\">|</span> <span class=\"op\">&lt;</span> <span class=\"op\">and</span> <span class=\"dv\">8</span> as the second arg</span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>#APP <span class=\"op\">|</span> <span class=\"op\">&lt;</span> this is the start of the assembly version</span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>| 5 &quot;test<span class=\"op\">.</span>c<span class=\"st\">&quot; 1</span></span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    </span>\n<span id=\"cb8-7\"><a href=\"#cb8-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>1:     subq<span class=\"op\">.</span>l  <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb8-8\"><a href=\"#cb8-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>       jcs     <span class=\"fl\">2</span><span class=\"bn\">f</span></span>\n<span id=\"cb8-9\"><a href=\"#cb8-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>       tst<span class=\"op\">.</span>b   <span class=\"op\">(%</span>a0<span class=\"op\">)+</span></span>\n<span id=\"cb8-10\"><a href=\"#cb8-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>       <span class=\"cf\">jne</span>     <span class=\"bn\">1b</span></span>\n<span id=\"cb8-11\"><a href=\"#cb8-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>       subq<span class=\"op\">.</span>l  <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>a0</span>\n<span id=\"cb8-12\"><a href=\"#cb8-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>2:</span>\n<span id=\"cb8-13\"><a href=\"#cb8-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>| 0 &quot;&quot; 2</span>\n<span id=\"cb8-14\"><a href=\"#cb8-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>#NO_APP <span class=\"op\">|</span> <span class=\"op\">&lt;</span> this is the end of the assembly version</span>\n<span id=\"cb8-15\"><a href=\"#cb8-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>a0<span class=\"op\">,%</span>d0 <span class=\"op\">|</span> <span class=\"op\">&lt;</span> this stores the result in <span class=\"op\">%</span>d0</span>\n<span id=\"cb8-16\"><a href=\"#cb8-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">sub</span><span class=\"op\">.</span>l <span class=\"op\">#.</span>LC0<span class=\"op\">-</span><span class=\"dv\">5</span><span class=\"op\">,%</span>d0 <span class=\"op\">|</span> the var c gets folded into the sub<span class=\"op\">.</span>l to add <span class=\"fl\">5.</span></span>\n<span id=\"cb8-17\"><a href=\"#cb8-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    rts</span></code></pre></div>\n<p>You\u2019ll note <code>lea</code> to <code>move.l</code> are the assembly\nversion. So, the C code itself is folded into a constant\n<code>5</code>.</p>\n<p>In this case, the C version is much better than the assembly\nversion.</p>\n<p>The problem is visibility. The assembly code <strong>can not</strong>\nbe optimized past what is provided inline + its dependencies (loads in\nand stores out). Thus, the optimized assembly version <strong>can\nnever</strong> be optimized past this:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">lea</span> <span class=\"op\">.</span>LC0<span class=\"op\">,%</span>a0</span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    moveq <span class=\"op\">#</span><span class=\"dv\">8</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>1:     subq<span class=\"op\">.</span>l  <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>d0</span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>       jcs     <span class=\"fl\">2</span><span class=\"bn\">f</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>       tst<span class=\"op\">.</span>b   <span class=\"op\">(%</span>a0<span class=\"op\">)+</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>       <span class=\"cf\">jne</span>     <span class=\"bn\">1b</span></span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>       subq<span class=\"op\">.</span>l  <span class=\"op\">#</span><span class=\"dv\">1</span><span class=\"op\">,%</span>a0</span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>2:</span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    move<span class=\"op\">.</span>l <span class=\"op\">%</span>a0<span class=\"op\">,%</span>d0</span></code></pre></div>\n<p>Whereas for the C version, we saw it could range from pretty bad code\nto a constant which is folded into a previous instruction, which is as\noptimal as can be.</p>\n</section>\n<section id=\"why-this-matters\" class=\"level2\">\n<h2>Why this matters</h2>\n<p>This problem comes up a lot in areas other than OS programming \u2013 for\na database, you could choose to have a static query plan for a given\nquery. Since query plans are generally chosen dynamically for a given\nquery, this gives you stable performance + less overhead per query\nbecause there\u2019s no overhead in having to choose a given query plan.\nHowever, you give up future optimizations \u2013 if there\u2019s a new version of\nyour database that can optimize your query, you\u2019ll lose out on that \u2013\nand for databases, this can be much more than a 100x improvement, that\nyou get for free just by upgrading, that you can\u2019t get with static query\nplans.</p>\n<p>For compilers, JITs work their magic by having visibility into\nrunning code. If a JIT has to run code that it does not have visibility\ninto, to maintain correctness, it <strong>must not</strong> optimize\nthat code in any way. Thus, any optimizing program that has no\nvisibility into the code it runs <strong>can never</strong> optimize the\nprogram at all, lest it break correctness. Thus, in language design,\nthere\u2019s a fundamental tension between higher-level and lower-level\nconstructs. Lower-level constructs are easier to optimize now, because\nthey\u2019re closer to the machine. Higher-level constructs may have some\noverhead now. In the future, however, higher-level constructs may do\nbetter than lower-level constructs \u2013 because they can provide the\ncompiler with more visibility and thus more chances for optimization.\nThus, languages that are higher level tend to do better over time \u2013\nthink Lisp vs.\u00a0COBOL \u2013 Lisp was much higher level and had much more\noverhead at the time, but compilers can optimize most of it away\nnow.</p>\n<p>Declarative languages, like CSS, SQL, and prolog, will probably never\ndie \u2013 the user offloads the complexity of their tasks to the language\nimplementer, and grants them higher visibility which let the runtime\nchoose creative paths toward optimization.</p>\n<p>Maybe we should all be writing Haskell.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2025-11-12T13:22:49+00:00"
		},
		{
			"id": "gen/writing-a-vm.html",
			"url": "gen/writing-a-vm.html",
			"title": "Writing a VM",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing a VM</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing a VM</h1>\n<p class=\"byline\">2024-07-20T11:45:44-04:00</p>\n</header>\n<p>I promised a while back to learn compilers in earnest \u2013 the programs\nthat turn your high-level code into the low-level bits that your\ncomputer can execute.</p>\n<p>I wrote up a few tree-walk interpreters \u2013 they would tokenize the\nprogramming language provided, parse it, and then execute the AST\nitself, executing the code.</p>\n<p>Tree-walk interpreters work pretty well for the most part \u2013 they\u2019re\neasier to write, and have great introspection (each node has all the\ninfo it needs). But it didn\u2019t really scratch my itch of going all the\nway to the metal.</p>\n<p>If I write an assembly file to return the number 10, I would\nwrite:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>.globl main</span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">main:</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span> <span class=\"op\">$</span><span class=\"bn\">10</span><span class=\"op\">,</span> <span class=\"op\">%</span><span class=\"kw\">rax</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">ret</span></span></code></pre></div>\n<p>I can compile that output:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> gcc test.s <span class=\"at\">-o</span> a.out</span></code></pre></div>\n<p>And <code>objdump -d</code> the generated file:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> objdump <span class=\"at\">-d</span> a.out</span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">0000000000401106</span> <span class=\"op\">&lt;</span>main<span class=\"op\">&gt;</span>:</span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"ex\">401106:</span>   48 c7 c0 0a 00 00 00    mov    <span class=\"va\">$0</span>xa,%rax</span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"ex\">40110d:</span>   c3                      ret</span></code></pre></div>\n<p>So our instructions are encoded as\n<code>48 c7 c0 0a 00 00 00 c3</code> as bytes.</p>\n<p><code>mov $10 %rax</code> corresponds to\n<code>48 c7 c0 0a 00 00 00</code>, and <code>ret</code> turns into\n<code>c3</code>.</p>\n<p>So, our \u201chigh-level\u201d assembly that we wrote is turned into those\nbytes, and the computer can read those bytes and execute them.</p>\n<p>A tree-walk interpreter stops before serializing and deserializing\ninstructions \u2013 it runs the instructions from in-memory, so there\u2019s no\nneed to dump the state to disk.</p>\n<p>To be fair, interpreters have a way to dump the tree that they\u2019re\nexecuting to disk, like running this command:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> clang <span class=\"at\">-Xclang</span> <span class=\"at\">-ast-dump</span><span class=\"op\">=</span>json <span class=\"at\">-fsyntax-only</span> <span class=\"at\">-Wno-visibility</span> test.c</span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># emitted JSON here.</span></span></code></pre></div>\n<p>So we\u2019d like to do that, by turning our instruction stream from those\nhigh level instructions into bytes, and then being able to read those\nbytes back and execute the program from binary.</p>\n<p>The way I did was sketching out a VM with a set amount of\ninstructions. Each instruction would be the first byte (so I had a cap\nof 256 instructions), and then the following bytes would be the\narguments.</p>\n<p>Next, I had to handle the arity of each instruction. If you have say\n<code>mov $10, %rax</code> and <code>mov %rbx, %rax</code>, these have\nto be encoded as two distinct instructions \u2013 one is an immediate to\nregister move, and the other is a register to register move, even though\nthey\u2019re both called <code>mov</code> in the written assembly.</p>\n<p>So, I ended up with some 25 instructions, and each instruction would\nslurp up the bytes it wanted from a binary, or serialize to those bytes,\nand then voila, as long as you had a VM that could take those bytes and\nreturn them to the assembly instructions, you could write any program\nyou wanted.</p>\n<p>An example program, which would print 10 and then exit would look\nlike this in assembly:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>putreg <span class=\"dv\">10</span> R0</span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>printreg R0</span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">ret</span></span></code></pre></div>\n<p>I could then encode that file as binary:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> cargo r <span class=\"at\">-q</span> <span class=\"at\">--</span> <span class=\"at\">-e</span> print.asm <span class=\"op\">&gt;</span> out.bin</span></code></pre></div>\n<p>And look at its contents:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> xxd out.bin</span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">00000000:</span> 010a 0000 0900 00                        .......</span></code></pre></div>\n<p>And run it from the binary format.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> r <span class=\"at\">-q</span> <span class=\"at\">--</span> <span class=\"at\">-d</span> out.bin</span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">10</span></span></code></pre></div>\n<p>So the program went all the way from the assembly itself, to bytes,\nand then was run properly by the VM.</p>\n<p>If you\u2019d like to take a look at the VM code on github I\u2019ve linked it\nhere.</p>\n<p><a href=\"https://github.com/takashiidobe/vm\">VM Code</a></p>\n<p>Next step \u2013 writing a high level language that can emit the bytecode,\nso I can go all the way from a high-level language to the bare\nmetal.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2024-07-20T15:45:44+00:00"
		},
		{
			"id": "gen/10-more-predictions.html",
			"url": "gen/10-more-predictions.html",
			"title": "10 More Predictions",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>10 More Predictions</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">10 More Predictions</h1>\n<p class=\"byline\">2024-03-11T08:48:55-04:00</p>\n</header>\n<p>Five years ago, in 2019, I made 10 predictions for the next 10 years\n(so 2029).</p>\n<p>Let\u2019s see how they turned out, halfway through in 2024.</p>\n<p>I\u2019ll grade myself out of 10 points for each prediction based on how\ngood they\u2019re looking at the moment.</p>\n<p>Here\u2019s the list:</p>\n<ol type=\"1\">\n<li>Self-driving cars will still be two years out</li>\n</ol>\n<p>This one is still true. By self-driving, I meant take a nap as the\ndriver and leave your life in the hands of your car. Two years out was a\njab at some indefinite future, which I think is also true \u2013 people are\nstill gunning for self-driving cars, but it\u2019ll most likely take longer\nthan expected. This prediction is looking good, we\u2019ll see in 2029.</p>\n<p>Verdict: 10 points.</p>\n<ol start=\"2\" type=\"1\">\n<li>Rust will become a top 10 language in popularity</li>\n</ol>\n<p>By 2019, Rust was the most admired language on stack overflow\u2019s\ndeveloper survey for four years. In 2024, it\u2019s won that title nine times\nin a row. No easy feat, given the amount of programming languages in\ncommon use.</p>\n<p>Currently, Rust is the 17th most popular language according to the\nTIOBE index, and it has quite a ways to go to crack the top 10. But it\u2019s\ngot momentum for sure.</p>\n<p>Verdict: 5 points.</p>\n<ol start=\"3\" type=\"1\">\n<li>WebAssembly will kill JavaScript and Desktop Apps</li>\n</ol>\n<p>In 2019, webassembly was hyped as freeing us from having to write our\nfront-ends in javascript, but also bringing the browser sandbox with\nextra security to the desktop. It had a lot of hype. Five years later,\nhowever, there hasn\u2019t been much progress. Maybe something will change,\nbut this one is not looking good \u2013 few people have replaced their\nelectron usage with WASM sandboxed apps, and wasm is still struggling by\ncommittee. We\u2019ll see.</p>\n<p>Verdict: 2 points.</p>\n<ol start=\"4\" type=\"1\">\n<li>JSON will be replaced with a Typed Transfer Protocol</li>\n</ol>\n<p>This is the prediction I regret the most. First of all, protobuf was\nalready somewhat popular at the time, and there were other protocols\nthat were typed transfer protocols. On the other hand, it\u2019s gutsy. JSON\nhad been the interface between the frontend and backend since XHR\nrequests, so seeing it replaced with something else like it replaced XML\nwould be an interesting bet. Regardless, this one isn\u2019t looking good\neither.</p>\n<p>Verdict: 0 points.</p>\n<ol start=\"5\" type=\"1\">\n<li>Functional Programming will finally become popular</li>\n</ol>\n<p>By 2019, most languages had adopted functional programming features \u2013\nRust was a popular language that married idioms that allowed for\nlow-level control and functional programming in a tasteful way, Swift,\nKotlin, and Typescript have all improved mobile and web development with\ntheir adoption of functional programming features as well. But I meant\nthis prediction to be: We\u2019d all be using languages that were FP first,\nlike Elixir, Clojure, OCaml, Haskell, etc. It seems like programming\nlanguages are adopting FP features (as they always have) but the\ncommunity at large is not using FP languages for development (more than\nthey used to, at least), so this one is also an easy grade.</p>\n<p>Verdict: 0 points.</p>\n<ol start=\"6\" type=\"1\">\n<li>Microservice hype will wear off</li>\n</ol>\n<p>In 2019, at the hype of low interest rates, hiring became widespread\nand microservice architecture spread like wildfire. At some size of\ncompany, I think it\u2019s inevitable to have lots of services, but that\ndoesn\u2019t mean every team gets its own set of services, like microservices\nimplies. In 2024, with interest rates being closer to 4%, companies have\ncut hiring and the microservice fad has gone down in hype, with\ncompanies favoring more monolithic approaches to web development. I\u2019m\nnot sure if it\u2019ll continue on (this is like betting that interest rates\nwill stay at 4%+ until 2029) but since the hype has worn off once, I\u2019m\nassuming it could do so again.</p>\n<p>Verdict: 8 points.</p>\n<ol start=\"7\" type=\"1\">\n<li>Facebook will no longer be a top 10 company</li>\n</ol>\n<p>(I should\u2019ve been more specific, in my mind I was thinking top 10\nAmerican company by market cap)</p>\n<p>In 2019, some people (myself included) were seeing Facebook as a one\ntrick pony. They had three services (Facebook, WhatsApp, Instagram), of\nwhich they bought two, that were overindexed in social media (which was\nwaning in popularity at the time), and only relied on ad revenue.\nBasically, if social media becomes less popular, then Facebook will go\ndown.</p>\n<p>Zuckerberg understood this pretty well, so in 2021, Facebook decided\nto change its name to Meta and go all-in on VR technology. This failed\npretty miserably, with Meta\u2019s stock price tanking in response. It\u2019s back\nnow, but Meta is currently 6th in market cap for American companies and\ncould be pushed out from the top 10 by some upstarts. We\u2019ll see.</p>\n<p>Verdict: 5 points.</p>\n<ol start=\"8\" type=\"1\">\n<li>An AI startup will become this decade\u2019s hottest startup</li>\n</ol>\n<p>In 2019, AI was not as hyped as it was, but in 2022, when OpenAI\nreleased Chatgpt, things changed forever. In my opinion, OpenAI\ncurrently holds the title of \u201chottest startup\u201d, so I think this one was\nright, within 3 years.</p>\n<p>Verdict: 10 points.</p>\n<ol start=\"9\" type=\"1\">\n<li>Blockchain will be this decade\u2019s beanie babies</li>\n</ol>\n<p>Basically every blockchain outside of Bitcoin and Ethereum are\ntotally useless, just as they were in 2019. So, they haven\u2019t really\nbecome more popular or less popular in 5 years. Easy grade.</p>\n<p>Verdict: 0 points.</p>\n<ol start=\"10\" type=\"1\">\n<li>You and I will host our apps on a new cloud provider (read. not\nAWS)</li>\n</ol>\n<p>I still hate configuring AWS, but with Azure and GCP fumbling the\nball to try and take market share, and AWS releasing more fundamental\nservices, AWS has maintained its position as market leader. I don\u2019t see\nmyself (or a lot of other big companies) hosting their software on any\nother cloud. This one is also easy to score.</p>\n<p>Verdict: 0 points.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2024-03-11T12:48:55+00:00"
		},
		{
			"id": "gen/how-fast-are-computers-these-days.html",
			"url": "gen/how-fast-are-computers-these-days.html",
			"title": "How fast are computers these days",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>How fast are computers these days</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">How fast are computers these days</h1>\n<p class=\"byline\">2024-01-16T08:50:36-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#http-servers\" id=\"toc-http-servers\">HTTP Servers</a></li>\n<li><a href=\"#redis\" id=\"toc-redis\">Redis</a></li>\n<li><a href=\"#sqlite\" id=\"toc-sqlite\">Sqlite</a></li>\n<li><a href=\"#disk\" id=\"toc-disk\">Disk</a></li>\n<li><a href=\"#hashing\" id=\"toc-hashing\">Hashing</a></li>\n<li><a href=\"#networks\" id=\"toc-networks\">Networks</a></li>\n<li><a href=\"#talking-about-systems\"\nid=\"toc-talking-about-systems\">Talking about Systems</a>\n<ul>\n<li><a href=\"#google-search\" id=\"toc-google-search\">Google\nSearch</a></li>\n<li><a href=\"#amazon-s3\" id=\"toc-amazon-s3\">Amazon S3</a></li>\n</ul></li>\n<li><a href=\"#conclusion\" id=\"toc-conclusion\">Conclusion</a></li>\n</ul>\n</nav>\n<p>I\u2019ve been doing a lot of reading about distributed systems, but I\u2019ve\nnever known how fast hardware goes these days. Some common advice like\n\u201cI/O is slow\u201d or \u201csystem calls are slow\u201d might not matter that much,\ndepending on the performance requirements of the system that\u2019s using\nthem.</p>\n<p>General performance numbers are useful for building distributed\nsystems \u2013 let\u2019s say you have a system with 1PB of data and you want to\nbackup all that data to one node, where you can write to disk at 1GB/s.\nHow long does it take to back up the whole node? That would take about\n10 days to complete (1PB / 1GB) is 1M, and 1M seconds is about 10 days.\nIf we were using HDDs from 20 years ago instead of SSDs, where writes\nmight be closer to 40MB/s, it would take closer to 250 days, which is\nreally crazy.</p>\n<p>Armed with this information, we might say a total outage cannot\nhappen, or we carefully design the system to partition the data so\nbackups can happen in parallel, where if we have 1000 nodes, then our 10\nday backup might take 10 / 1000 days, or closer to 90 seconds.</p>\n<p>For a twist, I decided to benchmark my phone (a Samsung S10) vs my\npersonal laptop (a Framework laptop with a 12th gen intel i5-1240p\nprocessor, 32GB of DDR4-3200 RAM, and a 2TB Western Digital SN750). The\nS10 has a value of about $200 used these days, and the laptop about\n$1000. So, we can also see how much money it would cost to build a\nsystem using these parts (although I assume building a system with NUCs\nor the like would be much more cost efficient), we can get a ballpark\nestimation of how much certain distributed systems would cost to build.\nAs well, I\u2019ll put down my guesses for how fast I thought each benchmark\nwould be for my phone and my laptop, and see how far off I was. In the\nend, we\u2019ll discuss some in the wild systems and see how feasible it\nwould be to build them.</p>\n<section id=\"http-servers\" class=\"level2\">\n<h2>HTTP Servers</h2>\n<p>The communication layer of a service might use HTTP. Thus, I wanted\nto benchmark a \u201chello world\u201d HTTP service to see how fast a networked\nservice could run, given it does no work.</p>\n<p>I assumed my laptop would run about 100k req/s, with around 10\nmicrosecond latency, and my phone would do around 10k req/s, with 100\nmicrosecond latency.</p>\n<p>Try to guess how fast each device was:</p>\n<p>The computer had these results:</p>\n<pre><code>Running 5s test @ http://localhost:3000\n  256 goroutine(s) running concurrently\n975712 requests in 4.929485946s, 105.15MB read\nRequests/sec:       197933.82\nTransfer/sec:       21.33MB\nAvg Req Time:       1.293361ms\nFastest Request:    21.095\u00b5s\nSlowest Request:    67.116949ms\nNumber of Errors:   0</code></pre>\n<p>And the phone:</p>\n<pre><code>Running 5s test @ http://localhost:3000\n  32 goroutine(s) running concurrently\n107649 requests in 4.909044953s, 11.29MB read\nRequests/sec:       21928.71\nTransfer/sec:       2.30MB\nAvg Req Time:       1.459274ms\nFastest Request:    85.677\u00b5s\nSlowest Request:    48.922239ms\nNumber of Errors:   0</code></pre>\n<p>The laptop had about 200k req/s and the phone had about 20k req/s.\nBoth were about twice as fast as I expected.</p>\n<p>So, if we had to create a \u201cHello world\u201d server and reach 1M req/s, it\nwould take 50 phones or 5 laptops. The 50 phones would cost $10000, and\nthe 5 laptops would cost about $5000. Computers are cheaper.</p>\n</section>\n<section id=\"redis\" class=\"level2\">\n<h2>Redis</h2>\n<p>What if we put a cache in front of our servers? How fast could it\nrespond?</p>\n<p>Since redis is single-threaded and in-memory, it should have similar\nnumbers to the HTTP server.</p>\n<p>I would assume that it would perform the same as the HTTP servers,\nsince they\u2019d be doing about the same amount of work: ~200k req/s for the\nlaptop and ~20k req/s for the phone.</p>\n<p>The laptop ran at ~200k for read, write, ping.</p>\n<p>The phone ran at ~40k req/s for read, write, ping.</p>\n<p>Pretty good \u2013 if we could hold our dataset in memory, we could\nrespond with 200k req/s.</p>\n</section>\n<section id=\"sqlite\" class=\"level2\">\n<h2>Sqlite</h2>\n<p>We\u2019ll need a database to store our data. Let\u2019s say we use sqlite, and\nbenchmark it, using row sizes of 1000B.</p>\n<p>I assume that we can write about 50k/second rows on the laptop and\n10k rows/second on the phone.</p>\n<p>The laptop:</p>\n<p>Batching 1000 writes at a time:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ./sqlite-bench <span class=\"at\">-batch-count</span> 1000 <span class=\"at\">-batch-size</span> 1000 <span class=\"at\">-row-size</span> 1000 <span class=\"at\">-journal-mode</span> wal <span class=\"at\">-synchronous</span> normal ./bench.db</span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Inserts:</span>   1000000 rows</span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Elapsed:</span>   7.824s</span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Rate:</span>      127817.265 insert/sec</span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">File</span> size: 1026584576 bytes</span></code></pre></div>\n<p>Writing 1 row at a time:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ./sqlite-bench <span class=\"at\">-batch-count</span> 1000000 <span class=\"at\">-batch-size</span> 1 <span class=\"at\">-row-size</span> 1000 <span class=\"at\">-journal-mode</span> wal <span class=\"at\">-synchronous</span> normal ./bench.db</span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Inserts:</span>   1000000 rows</span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Elapsed:</span>   43.839s</span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Rate:</span>      22810.910 insert/sec</span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">File</span> size: 1026584576 bytes</span></code></pre></div>\n<p>The phone:</p>\n<p>Batching 1000 writes at a time:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ./sqlite-bench <span class=\"at\">-batch-count</span> 1000 <span class=\"at\">-batch-size</span> 1000 <span class=\"at\">-row-size</span> 1000 <span class=\"at\">-journal-mode</span> wal <span class=\"at\">-synchronous</span> normal ./bench.db</span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Inserts:</span> 1000000 rows</span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Elapsed:</span> 66.006s</span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Rate:</span> 15150.53 insert/sec</span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">File</span> size: 1026584576 bytes</span></code></pre></div>\n<p>Writing 1 row at a time:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ./sqlite-bench <span class=\"at\">-batch-count</span> 1000000 <span class=\"at\">-batch-size</span> 1 <span class=\"at\">-row-size</span> 1000 <span class=\"at\">-journal-mode</span> wal <span class=\"at\">-synchronous</span> normal ./bench.db</span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Inserts:</span>   1000000 rows</span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Elapsed:</span>   200.473s</span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Rate:</span>      4884.369 insert/sec</span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">File</span> size: 1026584576 bytes</span></code></pre></div>\n<p>Here we see the phone\u2019s weakness \u2013 its disk. Inserting row by row,\nthe phone only can write 5k rows/s, whereas the computer can do about\n20k rows/s, probably due to the phone having a flash disk and the\ncomputer having an SSD.</p>\n</section>\n<section id=\"disk\" class=\"level2\">\n<h2>Disk</h2>\n<p>Since the sqlite bench uncovered the weakness of the phone\u2019s disk,\nlets test out some numbers for the file system:</p>\n<p>I decided to benchmark sequential reads + writes for both and with\nfsync for the writes. Since I used <code>fio</code> as my tool, and it\nsupports <code>io_uring</code>, I gave that a shot on my laptop. Android\ndoesn\u2019t support <code>io_uring</code> for security reasons, so I only\nran <code>io_uring</code> on the computer.</p>\n<p>I\u2019d expect about 4GB/s read and 3GB/s write on the computer (since\nthat\u2019s what the SSD is rated at) and maybe 1GB/s read and 200MB/s write\nfor the phone?</p>\n<p>The numbers looked like this, with a blocksize of 1MB and running 8\njobs in parallel, which seemed to be the best, throughput wise:</p>\n<p>Computer:</p>\n<table>\n<colgroup>\n<col style=\"width: 31%\" />\n<col style=\"width: 9%\" />\n<col style=\"width: 8%\" />\n<col style=\"width: 9%\" />\n<col style=\"width: 10%\" />\n<col style=\"width: 32%\" />\n</colgroup>\n<thead>\n<tr>\n<th>job name</th>\n<th>p50</th>\n<th>p90</th>\n<th>p99</th>\n<th>p99.99</th>\n<th>throughput</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>sync sequential read</td>\n<td>113\u03bcs</td>\n<td>5014\u03bcs</td>\n<td>33424\u03bcs</td>\n<td>37487\u03bcs</td>\n<td>3387MB/s</td>\n</tr>\n<tr>\n<td>sync sequential write - fsync</td>\n<td>169\u03bcs</td>\n<td>529\u03bcs</td>\n<td>1319\u03bcs</td>\n<td>333448\u03bcs</td>\n<td>2830MB/s</td>\n</tr>\n<tr>\n<td>sync sequential write + fsync</td>\n<td>775\u03bcs</td>\n<td>1090\u03bcs</td>\n<td>1369\u03bcs</td>\n<td>2147\u03bcs</td>\n<td>1714MB/s</td>\n</tr>\n<tr>\n<td>sync readwrite - fsync</td>\n<td>204\u03bcs</td>\n<td>416\u03bcs</td>\n<td>865\u03bcs</td>\n<td>14222\u03bcs</td>\n<td>Read: 2556MB/s Write: 2665MB/s</td>\n</tr>\n<tr>\n<td>sync readwrite + fsync</td>\n<td>416\u03bcs</td>\n<td>832\u03bcs</td>\n<td>2769\u03bcs</td>\n<td>9372\u03bcs</td>\n<td>Read: 1052MB/s Write: 1093MB/s</td>\n</tr>\n</tbody>\n</table>\n<p>Phone:</p>\n<p>With a blocksize of 256k and running 8 jobs in parallel:</p>\n<table>\n<colgroup>\n<col style=\"width: 31%\" />\n<col style=\"width: 9%\" />\n<col style=\"width: 9%\" />\n<col style=\"width: 9%\" />\n<col style=\"width: 10%\" />\n<col style=\"width: 32%\" />\n</colgroup>\n<thead>\n<tr>\n<th>job name</th>\n<th>p50</th>\n<th>p90</th>\n<th>p99</th>\n<th>p99.99</th>\n<th>throughput</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>sync sequential read</td>\n<td>1549\u03bcs</td>\n<td>4490\u03bcs</td>\n<td>4752\u03bcs</td>\n<td>22152\u03bcs</td>\n<td>866MB/s</td>\n</tr>\n<tr>\n<td>sync sequential write - fsync</td>\n<td>18482\u03bcs</td>\n<td>39584\u03bcs</td>\n<td>89654\u03bcs</td>\n<td>109577\u03bcs</td>\n<td>100MB/s</td>\n</tr>\n<tr>\n<td>sync sequential write + fsync</td>\n<td>510\u03bcs</td>\n<td>865\u03bcs</td>\n<td>1729\u03bcs</td>\n<td>1860\u03bcs</td>\n<td>86.3MB/s</td>\n</tr>\n<tr>\n<td>sync readwrite - fsync</td>\n<td>314\u03bcs</td>\n<td>1926\u03bcs</td>\n<td>41681\u03bcs</td>\n<td>41681\u03bcs</td>\n<td>Read: 77.4MB/s Write: 75.5MB/s</td>\n</tr>\n<tr>\n<td>sync readwrite + fsync</td>\n<td>379\u03bcs</td>\n<td>717\u03bcs</td>\n<td>10421\u03bcs</td>\n<td>10421\u03bcs</td>\n<td>Read: 38.5MB/s Write: 41.4MB/s</td>\n</tr>\n</tbody>\n</table>\n<p>The phone was substantially slower than I expected.</p>\n</section>\n<section id=\"hashing\" class=\"level2\">\n<h2>Hashing</h2>\n<p>I was expecting about 400MB/s hashing on the laptop and about 100MB/s\nhashing on the phone for a non-cryptographic hash, and ~40MB/s for a\ncryptographic hash on a laptop, and 10MB/s on a phone.</p>\n<p>Laptop:</p>\n<ul>\n<li>sha3-256: 56.14 MiB/sec</li>\n<li>md5: 404.15 MiB/sec</li>\n<li>sha1: 432.36 MiB/sec</li>\n<li>xxhash: 1827.80 MiB/sec</li>\n<li>murmur3: 1826.07 MiB/sec</li>\n<li>jhash: 1542.84 MiB/sec</li>\n<li>fnv: 3720.28 MiB/sec</li>\n<li>crc32c: 4682.73 MiB/sec</li>\n</ul>\n<p>Phone:</p>\n<ul>\n<li>sha3-256: 217.77 MiB/sec</li>\n<li>md5: 391.14 MiB/sec</li>\n<li>sha1: 334.32 MiB/sec</li>\n<li>xxhash: 2037.18 MiB/sec</li>\n<li>murmur3: 1328.81 MiB/sec</li>\n<li>jhash: 1754.98 MiB/sec</li>\n<li>fnv: 2928.83 MiB/sec</li>\n<li>crc32c: 14255.49 MiB/sec</li>\n</ul>\n<p>I could not have been more wrong.</p>\n<p>The phone hashes very quickly compared to the laptop, maybe because\nof some hardware instructions?</p>\n</section>\n<section id=\"networks\" class=\"level2\">\n<h2>Networks</h2>\n<p>The Computer can support 2.5Gbit/s ethernet, and the phone can\nsupport 2000Mb/s DL and 316Mb/s UL, which is pretty fast, even faster\nthan disk, so network probably won\u2019t be the bottleneck.</p>\n</section>\n<section id=\"talking-about-systems\" class=\"level2\">\n<h2>Talking about Systems</h2>\n<p>With some numbers to work with, let\u2019s talk about some famous products\nand their requirements.</p>\n<section id=\"google-search\" class=\"level3\">\n<h3>Google Search</h3>\n<p>In 2006, according to <a\nhref=\"http://googlesystem.blogspot.com/2006/09/how-much-data-does-google-store.html\">Source</a>,\nthe google search engine contained about 850TB of information.</p>\n<p>Assuming google search needs to handle 100k requests/second, and each\nrequest would return 4KB of data, our bandwidth requirement would be\n400MB/s. That\u2019s feasible to handle on a few laptops.</p>\n<p>Assuming that we didn\u2019t have an index at all. We would need to\nsomehow read 850TB of data per request \u2013 even with a sequential read\nspeed of ~3GB/s, each request would take 3 days of compute time to\ncomplete. Since we have to handle 100k reads a second, and each request\ntakes 3 days of compute time, in one second we would need to spend 866\nyears of compute time to serve reads. One second of requests would also\nrequire 100,000 computers * the amount of seconds in three days, or\nabout 250,000, for 2.5B computers required to serve google search. At\n$800/computer, this would be $2.5T, 1/10th the GDP of the US. Crazy.</p>\n<p>However, if the computer only needed to search a gigabyte of data on\ndisk to fetch a result, since a laptop\u2019s SSD can read about 3GB/s\nsequentially, even having to search on disk for 100MB would take 30ms.\nEven worse would be the computer requirement \u2013 each machine would only\nbe able to handle 30 req/s, so 3,000 laptops would be required at any\ngiven time to serve all search requests.</p>\n<p>If we can lower the seeking on disk to only 1MB, we could handle\n3,000 req/s, and only require 30 laptops \u2013 so having a fast index\nmatters a lot. It would be even better if we could search in RAM, where\nmemory throughput is closer to 25GB/s. If the entire index was in-memory\nand needed to read 1MB of data, each laptop would be able to handle\n25,000 req/s, and we\u2019d only need 4 laptops.</p>\n</section>\n<section id=\"amazon-s3\" class=\"level3\">\n<h3>Amazon S3</h3>\n<p>According to <a\nhref=\"https://www.allthingsdistributed.com/2023/07/building-and-operating-a-pretty-big-storage-system.html\">Source</a>\nAmazon S3 holds 280 trillion objects, and handles about 100 million\nreq/s. S3 sends 125 billion events per day (1.25M req/s), and S3 handles\n4 billion checksum computations per second.</p>\n<p>Assuming that\u2019s 80M reads and 20M writes, each of 1MB, that would\ninvolve 80TB/s of reads, and 20TB/s of writes. For the disk usage alone,\nyou\u2019d need ~7,000 laptops to handle the writes, and ~27,000 laptops to\nhandle the reads every second. But assuming we use 2.5Gb internet, at\n~300MB/s, we\u2019d need 10 times that amount, or 70,000 laptops to handle\nthe writes and 270,000 laptops for the reads.</p>\n<p>For the hashing, assuming each hash is over 1MB of data, would\nrequire hashing 4PB/s of data. Using xxhash at 2GB/s would require\n2,000,000 laptops to just hash the data. Servers can hash xxhash data at\nover 100GB/s, so I assume amazon uses those to reduce the computer\nrequirement to a modest less than 400,000.</p>\n</section>\n</section>\n<section id=\"conclusion\" class=\"level2\">\n<h2>Conclusion</h2>\n<p>While going through this I learned a lot about how fast my computers\nare \u2013 they can handle hosting lots of services. Also, computers are\nreally cheap \u2013 an 8GB RAM, 80GB SSD instance on hetzner is ~$5/month,\nand the equivalent NUC would cost ~$100 to own, and these can handle\nthousands of requests per second at the very least, more than enough for\nthe large majority of services.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2024-01-16T13:50:36+00:00"
		},
		{
			"id": "gen/writing-a-small-search-engine.html",
			"url": "gen/writing-a-small-search-engine.html",
			"title": "Writing a Small Search Engine",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing a Small Search Engine</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing a Small Search Engine</h1>\n<p class=\"byline\">2023-07-27T07:20:52-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#index-implementation\" id=\"toc-index-implementation\">Index\nImplementation</a></li>\n<li><a href=\"#searching-our-index\"\nid=\"toc-searching-our-index\">Searching our Index</a></li>\n<li><a href=\"#giving-it-a-test-run\" id=\"toc-giving-it-a-test-run\">Giving\nit a test run</a></li>\n</ul>\n</nav>\n<p>Today we\u2019re going to write a small search engine in ~70 lines of\ncode:</p>\n<pre><code>$ cloc --quiet src/main.rs\n\ngithub.com/AlDanial/cloc v 1.90  T=0.00 s (271.8 files/s, 22288.4 lines/s)\n-------------------------------------------------------------------------------\nLanguage                     files          blank        comment           code\n-------------------------------------------------------------------------------\nRust                             1             12              1             69\n-------------------------------------------------------------------------------</code></pre>\n<p>The implementation leans on using a few dependencies from crates.io,\nso let\u2019s fetch those first.</p>\n<p>Initialize a new rust project:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> new tinysearch</span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> add anyhow</span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> add bincode</span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> add glob</span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> add patricia_tree <span class=\"at\">--features</span><span class=\"op\">=</span>serde</span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> add serde <span class=\"at\">--features</span><span class=\"op\">=</span>derive</span></code></pre></div>\n<p>With that, your Cargo.toml should have this for its dependencies.</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode toml\"><code class=\"sourceCode toml\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">[dependencies]</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">anyhow</span> <span class=\"op\">=</span> <span class=\"st\">&quot;1.0.70&quot;</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">bincode</span> <span class=\"op\">=</span> <span class=\"st\">&quot;1.3.3&quot;</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">glob</span> <span class=\"op\">=</span> <span class=\"st\">&quot;0.3.1&quot;</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">patricia_tree</span> <span class=\"op\">=</span> <span class=\"op\">{ </span><span class=\"dt\">version</span><span class=\"op\"> =</span> <span class=\"st\">&quot;0.5.7&quot;</span><span class=\"op\">, </span><span class=\"dt\">features</span><span class=\"op\"> =</span> <span class=\"op\">[</span><span class=\"st\">&quot;serde&quot;</span><span class=\"op\">] }</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">serde</span> <span class=\"op\">=</span> <span class=\"op\">{ </span><span class=\"dt\">version</span><span class=\"op\"> =</span> <span class=\"st\">&quot;1.0.160&quot;</span><span class=\"op\">, </span><span class=\"dt\">features</span><span class=\"op\"> =</span> <span class=\"op\">[</span><span class=\"st\">&quot;derive&quot;</span><span class=\"op\">] }</span></span></code></pre></div>\n<p>Anyhow is used as <code>box&lt;dyn Error&gt;</code>, so it\u2019s not\nreally necessary, but it\u2019s nice to not have to write.</p>\n<p>Bincode is used for serialization and deserialization to disk for\ndata structures. We\u2019ll need this to store the search index on disk and\nfetch it when we do a search.</p>\n<p>Glob is for making glob queries, like <code>src/**/*.rs</code> to\nfetch all rust files recursively under the <code>src</code>\ndirectory.</p>\n<p>Patricia tree is a trie data structure, that has the same ADT as a\nmap or set. Since this is a trie, and not a hashmap or btree, if there\nare redundant prefixes, they are compressed on disk. Since we\u2019re\nserializing and deserializing text, which tends to be somewhat\nredundant, this potentially saves a lot of memory compared to using a\nhash-based or normal tree-based structure.</p>\n<p>Serde is used to serialize the tree onto disk and deserialize it, for\nbincode.</p>\n<section id=\"index-implementation\" class=\"level2\">\n<h2>Index Implementation</h2>\n<p>Given the explanation above, your mental model to populate the index\nshould be something like this:</p>\n<ol type=\"1\">\n<li>Initialize Trie</li>\n<li>Fill Trie with some data (how?)</li>\n<li>Save Trie to disk</li>\n</ol>\n<p>And to read from it:</p>\n<ol type=\"1\">\n<li>Read the file containing Trie to disk</li>\n<li>Deserialize it back to a Trie</li>\n<li>Query the trie</li>\n</ol>\n<p>The open question is what data we fill the Trie with. Obviously it\nwould be something from our dataset, but if we make a mapping from each\nword to its document name, then this works, but we can only query one\nword at a time.</p>\n<p>With this index, a query like \u201cice cream\u201d would only be able to query\nfor either \u201cice\u201d or \u201ccream\u201d.</p>\n<p>To keep it simple, we\u2019ll choose an indexing strategy referred to as\nn-grams. N-grams indexes windows of length n.\u00a0Our previous strategy of\nindexing every word could be considered a 1-gram. We\u2019ll go with 5, since\nthat allows us to query up to 5 words. I queried my search history and\nfound that 5 word queries just about covers my querying needs.</p>\n<p>Let\u2019s get coding:</p>\n<p>in <code>src/main.rs</code>, add the imports required:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">use</span> <span class=\"pp\">std::</span><span class=\"op\">{</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">collections::</span><span class=\"op\">{</span>BTreeSet<span class=\"op\">,</span> HashSet<span class=\"op\">},</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">fs::</span><span class=\"op\">{</span><span class=\"kw\">self</span><span class=\"op\">,</span> File<span class=\"op\">},</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">io::</span><span class=\"op\">{</span><span class=\"bu\">BufRead</span><span class=\"op\">,</span> BufReader<span class=\"op\">},</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">};</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">use</span> <span class=\"pp\">patricia_tree::</span>PatriciaMap<span class=\"op\">;</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">use</span> <span class=\"pp\">anyhow::</span><span class=\"dt\">Result</span><span class=\"op\">;</span></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">use</span> <span class=\"pp\">glob::</span>glob<span class=\"op\">;</span></span></code></pre></div>\n<p>Next, let\u2019s create the cli flags with the two commands we\u2019ll support,\n<code>search</code> and <code>index</code>.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> main() <span class=\"op\">-&gt;</span> <span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">use</span> <span class=\"pp\">std::env::</span>args<span class=\"op\">;</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">match</span> args()<span class=\"op\">.</span>len() <span class=\"op\">{</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"dv\">0</span> <span class=\"op\">=&gt;</span> <span class=\"pp\">eprintln!</span>(<span class=\"st\">&quot;Please provide a top level command of search or index&quot;</span>)<span class=\"op\">,</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        _ <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">let</span> arguments<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>_<span class=\"op\">&gt;</span> <span class=\"op\">=</span> args()<span class=\"op\">.</span>collect()<span class=\"op\">;</span></span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"cf\">if</span> args()<span class=\"op\">.</span>len() <span class=\"op\">&gt;</span> <span class=\"dv\">2</span> <span class=\"op\">&amp;&amp;</span> arguments[<span class=\"dv\">1</span>] <span class=\"op\">==</span> <span class=\"st\">&quot;index&quot;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"kw\">let</span> _ <span class=\"op\">=</span> index(<span class=\"op\">&amp;</span>arguments[<span class=\"dv\">2</span>])<span class=\"op\">;</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"cf\">if</span> args()<span class=\"op\">.</span>len() <span class=\"op\">&gt;</span> <span class=\"dv\">2</span> <span class=\"op\">&amp;&amp;</span> arguments[<span class=\"dv\">1</span>] <span class=\"op\">==</span> <span class=\"st\">&quot;search&quot;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"kw\">let</span> _ <span class=\"op\">=</span> search(<span class=\"op\">&amp;</span>arguments[<span class=\"dv\">2</span><span class=\"op\">..</span>])<span class=\"op\">;</span></span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-12\"><a href=\"#cb6-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">eprintln!</span>(<span class=\"st\">&quot;Please provide a top level command of search or index&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb6-13\"><a href=\"#cb6-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb6-14\"><a href=\"#cb6-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb6-15\"><a href=\"#cb6-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb6-16\"><a href=\"#cb6-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cn\">Ok</span>(())</span>\n<span id=\"cb6-17\"><a href=\"#cb6-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Next, the function definition and matching patterns based on it.</p>\n<p>This code matches a regex provided (like \u201c**/*.rs\u201d), and then returns\nall matching files. We then iterate through the files and process each\nline.</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> index(pattern<span class=\"op\">:</span> <span class=\"op\">&amp;</span><span class=\"dt\">str</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> mytrie <span class=\"op\">=</span> <span class=\"pp\">PatriciaMap::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> entry <span class=\"kw\">in</span> glob(pattern)<span class=\"op\">?</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> path <span class=\"op\">=</span> entry<span class=\"op\">?;</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> path <span class=\"op\">=</span> path<span class=\"op\">.</span>to_string_lossy()<span class=\"op\">.</span>to_string()<span class=\"op\">;</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> f <span class=\"op\">=</span> <span class=\"pp\">File::</span>open(<span class=\"op\">&amp;*</span>path)<span class=\"op\">?;</span></span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> f <span class=\"op\">=</span> <span class=\"pp\">BufReader::</span>new(f)<span class=\"op\">;</span></span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">for</span> line <span class=\"kw\">in</span> f<span class=\"op\">.</span>lines() <span class=\"op\">{</span></span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"co\">// process each line, the next step</span></span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Next, we want to do something for each line. First, split each line\non whitespace to get a list of words. A production worthy search engine\nwould do stemming and remove unnecessary punctuation here, but we won\u2019t\nworry about that. Finally, we\u2019ll use the <a\nhref=\"https://doc.rust-lang.org/std/primitive.slice.html#method.windows\"><code>windows</code></a>\nfunction on slices, to return arrays with the length provided (5) across\nthe entire list. This is n-grams in a nutshell.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">let</span> line <span class=\"op\">=</span> line<span class=\"op\">?;</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">let</span> s<span class=\"op\">:</span> <span class=\"dt\">String</span> <span class=\"op\">=</span> line<span class=\"op\">.</span>to_string()<span class=\"op\">;</span></span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">let</span> words<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span><span class=\"dt\">String</span><span class=\"op\">&gt;</span> <span class=\"op\">=</span> s<span class=\"op\">.</span>split_whitespace()<span class=\"op\">.</span>map(<span class=\"op\">|</span>s<span class=\"op\">|</span> s<span class=\"op\">.</span>to_owned())<span class=\"op\">.</span>collect()<span class=\"op\">;</span></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">let</span> word_windows<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span><span class=\"dt\">String</span><span class=\"op\">&gt;</span> <span class=\"op\">=</span> words<span class=\"op\">.</span>windows(<span class=\"dv\">5</span>)<span class=\"op\">.</span>map(<span class=\"op\">|</span>w<span class=\"op\">|</span> w<span class=\"op\">.</span>join(<span class=\"st\">&quot; &quot;</span>))<span class=\"op\">.</span>collect()<span class=\"op\">;</span></span></code></pre></div>\n<p>With that, the next thing to do is to put each five gram as a key to\nthe trie, with a value of the path of the document. If that fivegram\nalready exists, we just add the new path to the list of paths it\nmatches.</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> fivegram <span class=\"kw\">in</span> <span class=\"op\">&amp;</span>word_windows <span class=\"op\">{</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">if</span> <span class=\"op\">!</span>mytrie<span class=\"op\">.</span>contains_key(fivegram) <span class=\"op\">{</span></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"kw\">mut</span> set <span class=\"op\">=</span> <span class=\"pp\">BTreeSet::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        set<span class=\"op\">.</span>insert(path<span class=\"op\">.</span>clone())<span class=\"op\">;</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        mytrie<span class=\"op\">.</span>insert(fivegram<span class=\"op\">,</span> set)<span class=\"op\">;</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"co\">// we know that the trie contains fivegram, so unwrapping is safe.</span></span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> <span class=\"kw\">mut</span> set<span class=\"op\">:</span> BTreeSet<span class=\"op\">&lt;</span><span class=\"dt\">String</span><span class=\"op\">&gt;</span> <span class=\"op\">=</span> mytrie<span class=\"op\">.</span>get(fivegram)<span class=\"op\">.</span>unwrap()<span class=\"op\">.</span>to_owned()<span class=\"op\">;</span></span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        set<span class=\"op\">.</span>insert(path<span class=\"op\">.</span>clone())<span class=\"op\">;</span></span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>        mytrie<span class=\"op\">.</span>insert(fivegram<span class=\"op\">,</span> set)<span class=\"op\">;</span></span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Finally, we serialize it and write it to a file:</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">let</span> encoded <span class=\"op\">=</span> <span class=\"pp\">bincode::</span>serialize(<span class=\"op\">&amp;</span>mytrie)<span class=\"op\">?;</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">fs::</span>write(<span class=\"st\">&quot;./data.index&quot;</span><span class=\"op\">,</span> encoded)<span class=\"op\">?;</span></span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cn\">Ok</span>(())</span></code></pre></div>\n</section>\n<section id=\"searching-our-index\" class=\"level2\">\n<h2>Searching our Index</h2>\n<p>Fortunately, searching is easier. We take our list of search words,\nand then index into the map. Then, we grab the matches, and we append\nthem to all matching paths. At the end, we print them out.</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> search(search_words<span class=\"op\">:</span> <span class=\"op\">&amp;</span>[<span class=\"dt\">String</span>]) <span class=\"op\">-&gt;</span> <span class=\"dt\">Result</span><span class=\"op\">&lt;</span>()<span class=\"op\">&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> needle<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span><span class=\"dt\">u8</span><span class=\"op\">&gt;</span> <span class=\"op\">=</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">let</span> joined <span class=\"op\">=</span> search_words<span class=\"op\">.</span>join(<span class=\"st\">&quot; &quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>        joined<span class=\"op\">.</span>bytes()<span class=\"op\">.</span>collect()</span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">};</span></span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-7\"><a href=\"#cb11-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> index_file <span class=\"op\">=</span> <span class=\"pp\">File::</span>open(<span class=\"st\">&quot;./data.index&quot;</span>)<span class=\"op\">?;</span></span>\n<span id=\"cb11-8\"><a href=\"#cb11-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> decoded<span class=\"op\">:</span> PatriciaMap<span class=\"op\">&lt;</span>BTreeSet<span class=\"op\">&lt;</span><span class=\"dt\">String</span><span class=\"op\">&gt;&gt;</span> <span class=\"op\">=</span> <span class=\"pp\">bincode::</span>deserialize_from(index_file)<span class=\"op\">?;</span></span>\n<span id=\"cb11-9\"><a href=\"#cb11-9\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-10\"><a href=\"#cb11-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> matches<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;</span>_<span class=\"op\">&gt;</span> <span class=\"op\">=</span> decoded<span class=\"op\">.</span>iter_prefix(<span class=\"op\">&amp;</span>needle)<span class=\"op\">.</span>collect()<span class=\"op\">;</span></span>\n<span id=\"cb11-11\"><a href=\"#cb11-11\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-12\"><a href=\"#cb11-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> <span class=\"kw\">mut</span> paths<span class=\"op\">:</span> HashSet<span class=\"op\">&lt;</span>_<span class=\"op\">&gt;</span> <span class=\"op\">=</span> <span class=\"pp\">HashSet::</span><span class=\"kw\">default</span>()<span class=\"op\">;</span></span>\n<span id=\"cb11-13\"><a href=\"#cb11-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> (_key<span class=\"op\">,</span> val) <span class=\"kw\">in</span> <span class=\"op\">&amp;</span>matches <span class=\"op\">{</span></span>\n<span id=\"cb11-14\"><a href=\"#cb11-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>        paths<span class=\"op\">.</span>extend(val<span class=\"op\">.</span>iter())<span class=\"op\">;</span></span>\n<span id=\"cb11-15\"><a href=\"#cb11-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-16\"><a href=\"#cb11-16\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb11-17\"><a href=\"#cb11-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"pp\">println!</span>(<span class=\"st\">&quot;{:#?}&quot;</span><span class=\"op\">,</span> paths)<span class=\"op\">;</span></span>\n<span id=\"cb11-18\"><a href=\"#cb11-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cn\">Ok</span>(())</span>\n<span id=\"cb11-19\"><a href=\"#cb11-19\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And with that, we\u2019re done. A simple search engine.</p>\n</section>\n<section id=\"giving-it-a-test-run\" class=\"level2\">\n<h2>Giving it a test run</h2>\n<p>I indexed my notes:</p>\n<div class=\"sourceCode\" id=\"cb12\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb12-1\"><a href=\"#cb12-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> r <span class=\"at\">-q</span> <span class=\"at\">--</span> index <span class=\"st\">&quot;data/**/*.md&quot;</span></span></code></pre></div>\n<p>And then searched for mentions of distributed systems:</p>\n<div class=\"sourceCode\" id=\"cb13\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">cargo</span> r <span class=\"at\">-q</span> <span class=\"at\">--</span> search distributed system</span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">{</span></span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;data/books/system-design-interview-an-insiders-guide-volume-2/distributed-message-queue.md&quot;</span><span class=\"ex\">,</span></span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;data/books/designing-data-intensive-applications/distributed-systems-trouble.md&quot;</span><span class=\"ex\">,</span></span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">}</span></span></code></pre></div>\n<p>Not so bad for 70 lines of code.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-07-27T11:20:52+00:00"
		},
		{
			"id": "gen/hardware.html",
			"url": "gen/hardware.html",
			"title": "Hardware for development",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Hardware for development</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Hardware for development</h1>\n<p class=\"byline\">2023-05-23T20:00:51-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#current\" id=\"toc-current\">Current</a></li>\n<li><a href=\"#past\" id=\"toc-past\">Past</a></li>\n</ul>\n</nav>\n<p>A list of the hardware I\u2019ve used throughout the years.</p>\n<section id=\"current\" class=\"level2\">\n<h2>Current</h2>\n<ul>\n<li>Framework Laptop: (2022-) $1200\n<ul>\n<li>i5-1240P processor</li>\n<li>32GB DDR4-3200 RAM</li>\n<li>2TB NVMe SSD</li>\n</ul></li>\n<li>Galaxy S10: (2019-) $599\n<ul>\n<li>Octa-core (1x2.84 GHz Kryo 485 &amp; 3x2.42 GHz Kryo 485 &amp;\n4x1.78 GHz Kryo 485)</li>\n<li>8GB RAM</li>\n<li>128GB SSD</li>\n</ul></li>\n<li>Remarkable 2: (2020-) $499\n<ul>\n<li>512MB RAM</li>\n<li>8GB SSD</li>\n</ul></li>\n</ul>\n</section>\n<section id=\"past\" class=\"level2\">\n<h2>Past</h2>\n<ul>\n<li>Macbook Pro 2017: (2017-2022) $1199\n<ul>\n<li>2.3GHz dual-core Intel Core i5</li>\n<li>8GB LPDDR3-2133MHz RAM</li>\n<li>128GB NVMe SSD</li>\n</ul></li>\n<li>LG Phoenix 2: (2017-2019) $39\n<ul>\n<li>Qualcomm\u00ae MSM8909 1.3 GHz Quad-Core</li>\n<li>1.5GB RAM</li>\n<li>16GB Flash</li>\n</ul></li>\n<li>Huawei G7 Plus: (2015-2017) $180\n<ul>\n<li>Octa-core (4x1.5 GHz Cortex-A53 &amp; 4x1.2 GHz Cortex-A53)</li>\n<li>3GB RAM</li>\n<li>16GB Flash</li>\n</ul></li>\n<li>iTouch 4th Gen: (2011-2015) $399\n<ul>\n<li>ARM Cortex-A8 Apple A4 800 MHz</li>\n<li>256MB RAM</li>\n<li>16GB Flash</li>\n</ul></li>\n<li>Windows 7 Desktop: (2009-2013) $450\n<ul>\n<li>AMD Athlon 64 2.4GHz</li>\n<li>4GB DDR3-1066 RAM</li>\n<li>1TB HDD</li>\n</ul></li>\n<li>Windows 2000 Server: (2002-2009) $1500\n<ul>\n<li>Intel Xeon 1.7GHz</li>\n<li>1GB DDR3 RAM</li>\n<li>32GB HDD</li>\n</ul></li>\n<li>Windows 98 Desktop: (1998-2002) $2000\n<ul>\n<li>300MHz Intel Processor</li>\n<li>128MB RAM</li>\n<li>4GB HDD</li>\n</ul></li>\n</ul>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-05-24T00:00:51+00:00"
		},
		{
			"id": "gen/offline-rust.html",
			"url": "gen/offline-rust.html",
			"title": "Offline Rust",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Offline Rust</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Offline Rust</h1>\n<p class=\"byline\">2023-05-23T18:29:34-04:00</p>\n</header>\n<p>Rust, and its respective package manager, Cargo, easily allow for\nprogramming on the go. You can use <code>sccache</code> to cache\ndependencies you\u2019ve already downloaded, so if you\u2019ve already downloaded\nthem, there\u2019s no need to redownload them for any other project you use\nthe same dependency for. Sadly, that stops short when you want to\ndownload a new dependency you\u2019ve never downloaded before. If you\u2019re\noffline and don\u2019t have that exact dependency cached, you\u2019re SOL. But we\ncan do better, can\u2019t we?</p>\n<p>You probably already know that <code>crates.io</code> is a thin layer\nover git. So, you can grep all the crates on it, download their source\ncode, and host your own local repository that acts as a stand-in for\ncrates.io. Luckily (if you have ~150GB to spare), there\u2019s already a\nproject that has done that for us: <code>panamax</code>. After you\ninstall it with <code>cargo (b)install panamax</code>, and initialize\nsome directory. I initialized one at <code>~/crates</code> with\n<code>panamax init ~/crates</code>.</p>\n<p>You\u2019ll want to set your config up: I didn\u2019t want to clone any\ntoolchains since I didn\u2019t need them, so I only cloned down the crates: I\nedited my <code>mirror.toml</code> inside the initialized repository to\nbe the following:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode toml\"><code class=\"sourceCode toml\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">[mirror]</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">retries</span> <span class=\"op\">=</span> <span class=\"dv\">5</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">[rustup]</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">sync</span> <span class=\"op\">=</span> <span class=\"cn\">false</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">[crates]</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">sync</span> <span class=\"op\">=</span> <span class=\"cn\">true</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">download_threads</span> <span class=\"op\">=</span> <span class=\"dv\">64</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">source</span> <span class=\"op\">=</span> <span class=\"st\">&quot;https://crates.io/api/v1/crates&quot;</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">source_index</span> <span class=\"op\">=</span> <span class=\"st\">&quot;https://github.com/rust-lang/crates.io-index&quot;</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">base_url</span> <span class=\"op\">=</span> <span class=\"st\">&quot;http://localhost:27428/crates&quot;</span></span></code></pre></div>\n<p>And then I ran <code>panamax sync ~/crates</code> and waited for a\nday for the internet to download all the crates.</p>\n<p>Once that\u2019s done, we have all the crates we need. Add these lines to\nyour cargo config (normally at <code>~/.cargo/config.toml)</code> to use\nthe new repository:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode toml\"><code class=\"sourceCode toml\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">[source.panamax-sparse]</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">registry</span> <span class=\"op\">=</span> <span class=\"st\">&quot;sparse+http://localhost:27428/index/&quot;</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">[source.crates-io]</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">replace-with</span> <span class=\"op\">=</span> <span class=\"st\">&quot;panamax-sparse&quot;</span></span></code></pre></div>\n<p>Start up the server with\n<code>panamax serve ~/crates --port=27428</code> and you\u2019re ready to\ncode offline in rust.</p>\n<p>For maintenance, I sync crates with\n<code>panamax sync ~/crates</code> once a week with <code>systemd</code>\nand that works for me.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-05-23T22:29:34+00:00"
		},
		{
			"id": "gen/writing-your-own-libc-in-rust.html",
			"url": "gen/writing-your-own-libc-in-rust.html",
			"title": "Writing Your own Libc in Rust",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing Your own Libc in Rust</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing Your own Libc in Rust</h1>\n<p class=\"byline\">2023-05-22T08:58:02-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#implementation\" id=\"toc-implementation\">Implementation</a>\n<ul>\n<li><a href=\"#arm64\" id=\"toc-arm64\">ARM64</a></li>\n<li><a href=\"#x86_64\" id=\"toc-x86_64\">x86_64</a></li>\n</ul></li>\n<li><a href=\"#conclusions\" id=\"toc-conclusions\">Conclusions</a></li>\n</ul>\n</nav>\n<p>A few posts ago, we wrote our own <a\nhref=\"./writing-your-own-libc.md\">libc</a> in C. There was some inline\nassembly required to call functions. Lots of languages can call\nassembly, but since I mainly use rust, I decided to rewrite most of it\nin rust, since there are some nice advantages.</p>\n<p>First: <code>cfg</code> definitions are a lot easier to remember. I\ncan never remember if the <code>#ifdef</code> for linux is\n<code>__LINUX__</code> or <code>linux</code> or <code>__linux__</code>,\nor the <code>#ifdef</code>s for other platforms. Apple\u2019s is also odd\n(<code>__APPLE__</code>), and there are other <code>#ifdef</code>s for\ntargets: <code>TARGET_OS_IPHONE</code>\n<code>TARGET_IPHONE_SIMULATOR</code> <code>TARGET_OS_MAC</code>, and\nwindows with <code>_WIN_32</code> and <code>_WIN_64</code>. With\nandroid, there\u2019s <code>__ANDROID__</code> and\n<code>__ANDROID_API__</code> as well. Getting tired? Well, there\u2019s also\nall the architecture related ones, which there are hundreds of, and\nthey\u2019re slightly different per compiler, so you have to know which\ncompiler you\u2019re using to even define macros.</p>\n<p>There are 3 main wrappers around cfgs which are easy to wrap your\nhead around. <code>not</code>, which is anything that doesn\u2019t fit inside\nthe definition, like <code>#[cfg(not(target_arch = \"x86_64\")))]</code>\nmeans anything that isn\u2019t <code>x86_64</code>. There\u2019s <code>any</code>,\nwhich means for anything that matches an item in the list, like\n<code>#[cfg(any(target_arch = \"x86_64\", target_arch = \"i686\"))]</code>\nfor <code>x86_64</code> or <code>i686</code>. There\u2019s <code>all</code>,\nwhich means that all items must match, like\n<code>#[cfg(all(target_arch = \"aarch64\", target_os = \"linux\"))]</code>\nmeans to only run on aarch64 linux.</p>\n<p>Second: the inline <code>asm</code> syntax is much better. You have\nthree choices: <code>global_asm!</code>, which lets you write code\nanywhere, like if you\u2019d like to embed a string into your binary\u2019s text\nsection, <code>asm!</code>, which goes in the code section, and\n<code>llvm_asm!</code>, which is for llvm specific asm. You don\u2019t have\nto specify clobbers on x86_64, so the relevant <code>x86_64</code>\nsyscall code from C:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>asm <span class=\"dt\">volatile</span> <span class=\"op\">(</span>                                                    \\</span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                                                   \\</span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">:</span> <span class=\"st\">&quot;0&quot;</span><span class=\"op\">(</span>_num<span class=\"op\">)</span>                                                   \\</span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">:</span> <span class=\"st\">&quot;rcx&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;r11&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span> <span class=\"st\">&quot;cc&quot;</span>                                \\</span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">);</span></span></code></pre></div>\n<p>In rust would look like this:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">asm!</span>(</span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr</span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>)<span class=\"op\">;</span></span></code></pre></div>\n<p>Anyway, let\u2019s get started.</p>\n<section id=\"implementation\" class=\"level2\">\n<h2>Implementation</h2>\n<p>Create a new rust binary, and call it whatever you like. I called\nmine <code>syscalls</code>.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>cargo new syscalls</span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>cd syscalls</span></code></pre></div>\n<p>Open up <code>src/main.rs</code> and start off with importing the\nstandard assembly library.</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">use</span> <span class=\"pp\">std::arch::</span>asm<span class=\"op\">;</span></span></code></pre></div>\n<p>Next, since we\u2019ll be supporting <code>linux</code>, with\n<code>x86_64</code> <span\nclass=\"sidenote-wrapper\"><label for=\"sn-0\" class=\"margin-toggle sidenote-number\"></label><input type=\"checkbox\" id=\"sn-0\" class=\"margin-toggle\"/><span\nclass=\"sidenote\">Also known as <code>amd64</code>. <a\nhref=\"https://github.com/golang/go/blob/1176052bb40378272cfbe83d873b65fcc2ed8502/src/go/build/syslist.go#L58\">Go</a>\ncalls it this due to amd coming up with it, whereas intel popularized\nit, calling it <code>x86_64</code>.<br />\n<br />\n</span></span> and <code>aarch64</code> <span\nclass=\"sidenote-wrapper\"><label for=\"sn-1\" class=\"margin-toggle sidenote-number\"></label><input type=\"checkbox\" id=\"sn-1\" class=\"margin-toggle\"/><span\nclass=\"sidenote\">Also known as <code>ARM64</code>. Apple uses\n<code>ARM64</code> whereas others use <code>aarch64</code>.<br />\n<br />\n</span></span>, we can force every other architecture/OS mix to have a\ncompiler error, so no one will miscompile and have a runtime error.</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>all<span class=\"at\">(</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    target_os <span class=\"op\">=</span> <span class=\"st\">&quot;linux&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">)))]</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;Only works on linux on aarch64 or x86_64&quot;</span>)<span class=\"op\">;</span></span></code></pre></div>\n<p>This is really helpful \u2013 no more running a library and wondering what\nwent wrong at runtime.</p>\n<p>So, lets start off with the skeleton of the first syscall function,\n<code>syscall0</code>. We\u2019ll generate a function with the name of the\nsyscall, and the syscall\u2019s number. We\u2019ll make a compiler error to start\noff with since we haven\u2019t implemented anything yet.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall0 <span class=\"op\">{</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name() <span class=\"op\">{</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">};</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<section id=\"arm64\" class=\"level3\">\n<h3>ARM64</h3>\n<p>So we\u2019ll start implementing syscalls in <code>ARM64</code> first.</p>\n<p>Let\u2019s look at an example of Hello World in ARM64 to familiarize\nourselves with syscalls in ARM64:</p>\n<p>Taken from <a\nhref=\"https://peterdn.com/post/2020/08/22/hello-world-in-arm64-assembly/\"\nclass=\"uri\">https://peterdn.com/post/2020/08/22/hello-world-in-arm64-assembly/</a></p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode asm\"><code class=\"sourceCode fasm\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>.<span class=\"bu\">data</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>/* <span class=\"bu\">Data</span> segment<span class=\"op\">:</span> define our message string <span class=\"op\">and</span> calculate its length<span class=\"op\">.</span> <span class=\"op\">*/</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">msg:</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    .ascii        <span class=\"st\">&quot;Hello, ARM64!\\n&quot;</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>len <span class=\"op\">=</span> <span class=\"op\">.</span> <span class=\"op\">-</span> msg</span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>.text</span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>/* Our application<span class=\"st\">&#39;s entry point. */</span></span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>.globl _start</span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">_start:</span></span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    /* <span class=\"cf\">syscall</span> write<span class=\"op\">(</span>int fd<span class=\"op\">,</span> const void <span class=\"op\">*</span>buf<span class=\"op\">,</span> size_t count<span class=\"op\">)</span> <span class=\"op\">*/</span></span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span>     x0<span class=\"op\">,</span> <span class=\"op\">#</span><span class=\"dv\">1</span>      <span class=\"op\">/*</span> fd <span class=\"op\">:=</span> STDOUT_FILENO <span class=\"op\">*/</span></span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    ldr     x1<span class=\"op\">,</span> <span class=\"op\">=</span>msg    <span class=\"op\">/*</span> buf <span class=\"op\">:=</span> msg <span class=\"op\">*/</span></span>\n<span id=\"cb7-16\"><a href=\"#cb7-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    ldr     x2<span class=\"op\">,</span> <span class=\"op\">=</span>len    <span class=\"op\">/*</span> count <span class=\"op\">:=</span> len <span class=\"op\">*/</span></span>\n<span id=\"cb7-17\"><a href=\"#cb7-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span>     w8<span class=\"op\">,</span> <span class=\"op\">#</span><span class=\"dv\">64</span>     <span class=\"op\">/*</span> write is syscall <span class=\"op\">#</span><span class=\"dv\">64</span> <span class=\"op\">*/</span></span>\n<span id=\"cb7-18\"><a href=\"#cb7-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    svc     <span class=\"op\">#</span><span class=\"dv\">0</span>          <span class=\"op\">/*</span> invoke syscall <span class=\"op\">*/</span></span>\n<span id=\"cb7-19\"><a href=\"#cb7-19\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-20\"><a href=\"#cb7-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    /* <span class=\"cf\">syscall</span> exit<span class=\"op\">(</span>int status<span class=\"op\">)</span> <span class=\"op\">*/</span></span>\n<span id=\"cb7-21\"><a href=\"#cb7-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span>     x0<span class=\"op\">,</span> <span class=\"op\">#</span><span class=\"dv\">0</span>      <span class=\"op\">/*</span> status <span class=\"op\">:=</span> <span class=\"dv\">0</span> <span class=\"op\">*/</span></span>\n<span id=\"cb7-22\"><a href=\"#cb7-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">mov</span>     w8<span class=\"op\">,</span> <span class=\"op\">#</span><span class=\"dv\">93</span>     <span class=\"op\">/*</span> exit is syscall <span class=\"op\">#</span><span class=\"dv\">93</span> <span class=\"op\">*/</span></span>\n<span id=\"cb7-23\"><a href=\"#cb7-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    svc     <span class=\"op\">#</span><span class=\"dv\">0</span>          <span class=\"op\">/*</span> invoke syscall <span class=\"op\">*/</span></span></code></pre></div>\n<p>To write, we first set <code>x0</code> to the number 1\n(<code>#1</code>), to set our <code>fd</code> to stdout. Then, we move\nthe message to <code>x1</code>, which is write\u2019s second argument, Then\nwe move the len to <code>x2</code>, which is write\u2019s third argument,\nThen we move the number 64 to <code>w8</code>, which is the syscall\nnumber, And then we invoke the syscall with <code>svc</code> and the\nnumber 0.</p>\n<p>We do something similar for exit, just without moving any arguments\nto <code>x1</code> or <code>x2</code>.</p>\n<p>Let\u2019s do that for our first syscall:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">asm!</span>(</span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr</span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>)<span class=\"op\">;</span></span></code></pre></div>\n<p>with <code>in(\"w8\") $nr</code>, we can pass in our system call\nnumber, represented by <code>$nr</code>, and rust will put it into\n<code>w8</code> for us. This is equivalent to <code>mov w8 =$nr</code>,\nbut we don\u2019t have to remember that syntax, as the rust compiler will\ngenerate it for us.</p>\n<p>As well, we\u2019ll set the compiler errors for all architectures that\naren\u2019t <code>aarch64</code> for now.</p>\n<p>We repeat the following for the next 6 system calls, with\n<code>x0-x5</code> being used as registers to pass in arguments.</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall1 <span class=\"op\">{</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb9-13\"><a href=\"#cb9-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb9-14\"><a href=\"#cb9-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb9-15\"><a href=\"#cb9-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-16\"><a href=\"#cb9-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-17\"><a href=\"#cb9-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb9-18\"><a href=\"#cb9-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall2 <span class=\"op\">{</span></span>\n<span id=\"cb9-19\"><a href=\"#cb9-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-20\"><a href=\"#cb9-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb9-21\"><a href=\"#cb9-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-22\"><a href=\"#cb9-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-23\"><a href=\"#cb9-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb9-24\"><a href=\"#cb9-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-25\"><a href=\"#cb9-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-26\"><a href=\"#cb9-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb9-27\"><a href=\"#cb9-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-28\"><a href=\"#cb9-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-29\"><a href=\"#cb9-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb9-30\"><a href=\"#cb9-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb9-31\"><a href=\"#cb9-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb9-32\"><a href=\"#cb9-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb9-33\"><a href=\"#cb9-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-34\"><a href=\"#cb9-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-35\"><a href=\"#cb9-35\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb9-36\"><a href=\"#cb9-36\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-37\"><a href=\"#cb9-37\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall3 <span class=\"op\">{</span></span>\n<span id=\"cb9-38\"><a href=\"#cb9-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-39\"><a href=\"#cb9-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb9-40\"><a href=\"#cb9-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-41\"><a href=\"#cb9-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-42\"><a href=\"#cb9-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb9-43\"><a href=\"#cb9-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-44\"><a href=\"#cb9-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-45\"><a href=\"#cb9-45\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb9-46\"><a href=\"#cb9-46\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-47\"><a href=\"#cb9-47\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-48\"><a href=\"#cb9-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-49\"><a href=\"#cb9-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb9-50\"><a href=\"#cb9-50\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb9-51\"><a href=\"#cb9-51\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb9-52\"><a href=\"#cb9-52\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb9-53\"><a href=\"#cb9-53\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-54\"><a href=\"#cb9-54\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-55\"><a href=\"#cb9-55\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb9-56\"><a href=\"#cb9-56\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-57\"><a href=\"#cb9-57\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall4 <span class=\"op\">{</span></span>\n<span id=\"cb9-58\"><a href=\"#cb9-58\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-59\"><a href=\"#cb9-59\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg4<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb9-60\"><a href=\"#cb9-60\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-61\"><a href=\"#cb9-61\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-62\"><a href=\"#cb9-62\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb9-63\"><a href=\"#cb9-63\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-64\"><a href=\"#cb9-64\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-65\"><a href=\"#cb9-65\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb9-66\"><a href=\"#cb9-66\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-67\"><a href=\"#cb9-67\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-68\"><a href=\"#cb9-68\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-69\"><a href=\"#cb9-69\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x3&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-70\"><a href=\"#cb9-70\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb9-71\"><a href=\"#cb9-71\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb9-72\"><a href=\"#cb9-72\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb9-73\"><a href=\"#cb9-73\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb9-74\"><a href=\"#cb9-74\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-75\"><a href=\"#cb9-75\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-76\"><a href=\"#cb9-76\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb9-77\"><a href=\"#cb9-77\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-78\"><a href=\"#cb9-78\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall5 <span class=\"op\">{</span></span>\n<span id=\"cb9-79\"><a href=\"#cb9-79\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-80\"><a href=\"#cb9-80\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg4<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg5<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb9-81\"><a href=\"#cb9-81\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-82\"><a href=\"#cb9-82\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-83\"><a href=\"#cb9-83\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb9-84\"><a href=\"#cb9-84\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-85\"><a href=\"#cb9-85\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-86\"><a href=\"#cb9-86\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb9-87\"><a href=\"#cb9-87\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-88\"><a href=\"#cb9-88\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-89\"><a href=\"#cb9-89\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-90\"><a href=\"#cb9-90\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x3&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-91\"><a href=\"#cb9-91\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x4&quot;</span>) arg5<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-92\"><a href=\"#cb9-92\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb9-93\"><a href=\"#cb9-93\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb9-94\"><a href=\"#cb9-94\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb9-95\"><a href=\"#cb9-95\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb9-96\"><a href=\"#cb9-96\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-97\"><a href=\"#cb9-97\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-98\"><a href=\"#cb9-98\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb9-99\"><a href=\"#cb9-99\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-100\"><a href=\"#cb9-100\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall6 <span class=\"op\">{</span></span>\n<span id=\"cb9-101\"><a href=\"#cb9-101\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-102\"><a href=\"#cb9-102\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg4<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg5<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg6<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb9-103\"><a href=\"#cb9-103\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-104\"><a href=\"#cb9-104\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb9-105\"><a href=\"#cb9-105\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb9-106\"><a href=\"#cb9-106\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-107\"><a href=\"#cb9-107\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb9-108\"><a href=\"#cb9-108\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb9-109\"><a href=\"#cb9-109\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-110\"><a href=\"#cb9-110\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-111\"><a href=\"#cb9-111\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-112\"><a href=\"#cb9-112\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x3&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-113\"><a href=\"#cb9-113\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x4&quot;</span>) arg5<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-114\"><a href=\"#cb9-114\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x5&quot;</span>) arg6<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb9-115\"><a href=\"#cb9-115\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb9-116\"><a href=\"#cb9-116\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb9-117\"><a href=\"#cb9-117\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb9-118\"><a href=\"#cb9-118\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb9-119\"><a href=\"#cb9-119\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb9-120\"><a href=\"#cb9-120\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb9-121\"><a href=\"#cb9-121\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Note that the functions take <code>impl Into&lt;usize&gt;</code>, and\nthen the args are converted in the body of the function. That means that\nthe caller doesn\u2019t have to <code>as usize</code> or\n<code>try_into().unwrap()</code> if they don\u2019t pass in a\n<code>usize</code>, which is nice, as long as the argument is\nconvertable to a <code>usize</code>.</p>\n<p>Finally, we\u2019re ready to implement some system calls in ARM64!</p>\n<p><code>exit</code> takes 0 arguments and has a syscall number of 93,\nso we use <code>syscall0!</code> thusly:</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">syscall0!</span>(exit<span class=\"op\">,</span> <span class=\"dv\">93</span>)<span class=\"op\">;</span></span></code></pre></div>\n<p>And write takes 3 arguments, the <code>fd</code>, a string, and a\nlength, and it has a syscall number of 64, so we pass it in:</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">syscall3!</span>(write<span class=\"op\">,</span> <span class=\"dv\">64</span>)<span class=\"op\">;</span></span></code></pre></div>\n<p>And finally, we can write hello world:</p>\n<div class=\"sourceCode\" id=\"cb12\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb12-1\"><a href=\"#cb12-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> main() <span class=\"op\">{</span></span>\n<span id=\"cb12-2\"><a href=\"#cb12-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb12-3\"><a href=\"#cb12-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> string <span class=\"op\">=</span> <span class=\"st\">&quot;Hello ARM64</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb12-4\"><a href=\"#cb12-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb12-5\"><a href=\"#cb12-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> ptr <span class=\"op\">=</span> string<span class=\"op\">.</span>as_ptr() <span class=\"kw\">as</span> <span class=\"dt\">usize</span><span class=\"op\">;</span></span>\n<span id=\"cb12-6\"><a href=\"#cb12-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> len <span class=\"op\">=</span> string<span class=\"op\">.</span>len()<span class=\"op\">;</span></span>\n<span id=\"cb12-7\"><a href=\"#cb12-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    write(<span class=\"dv\">1usize</span><span class=\"op\">,</span> ptr<span class=\"op\">,</span> len)<span class=\"op\">;</span></span>\n<span id=\"cb12-8\"><a href=\"#cb12-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    exit()<span class=\"op\">;</span></span>\n<span id=\"cb12-9\"><a href=\"#cb12-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p><code>cargo run</code> your file to see <code>Hello ARM64</code> in\nall its glory flash onto the screen.</p>\n<p>Now we\u2019re not done yet \u2013 let\u2019s do the same for x86_64!</p>\n</section>\n<section id=\"x86_64\" class=\"level3\">\n<h3>x86_64</h3>\n<p>So for <code>x86</code>, <code>rax</code> takes in the system call\nnumber, and then the registers are the following: <code>rdi</code>,\n<code>rsi</code>, <code>rdx</code>, <code>r10</code>, <code>r9</code>,\n<code>r8</code>.</p>\n<p>So now we add in those to our syscall macros:</p>\n<div class=\"sourceCode\" id=\"cb13\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall0 <span class=\"op\">{</span></span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name() <span class=\"op\">{</span></span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-6\"><a href=\"#cb13-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-7\"><a href=\"#cb13-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-8\"><a href=\"#cb13-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-9\"><a href=\"#cb13-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr</span>\n<span id=\"cb13-10\"><a href=\"#cb13-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-11\"><a href=\"#cb13-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-12\"><a href=\"#cb13-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-13\"><a href=\"#cb13-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-14\"><a href=\"#cb13-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr</span>\n<span id=\"cb13-15\"><a href=\"#cb13-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-16\"><a href=\"#cb13-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-17\"><a href=\"#cb13-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-18\"><a href=\"#cb13-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-19\"><a href=\"#cb13-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-20\"><a href=\"#cb13-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">};</span></span>\n<span id=\"cb13-21\"><a href=\"#cb13-21\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-22\"><a href=\"#cb13-22\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-23\"><a href=\"#cb13-23\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall1 <span class=\"op\">{</span></span>\n<span id=\"cb13-24\"><a href=\"#cb13-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-25\"><a href=\"#cb13-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb13-26\"><a href=\"#cb13-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-27\"><a href=\"#cb13-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-28\"><a href=\"#cb13-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-29\"><a href=\"#cb13-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-30\"><a href=\"#cb13-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-31\"><a href=\"#cb13-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-32\"><a href=\"#cb13-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-33\"><a href=\"#cb13-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-34\"><a href=\"#cb13-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-35\"><a href=\"#cb13-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-36\"><a href=\"#cb13-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-37\"><a href=\"#cb13-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-38\"><a href=\"#cb13-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdi&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-39\"><a href=\"#cb13-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-40\"><a href=\"#cb13-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-41\"><a href=\"#cb13-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-42\"><a href=\"#cb13-42\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-43\"><a href=\"#cb13-43\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-44\"><a href=\"#cb13-44\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-45\"><a href=\"#cb13-45\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-46\"><a href=\"#cb13-46\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-47\"><a href=\"#cb13-47\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall2 <span class=\"op\">{</span></span>\n<span id=\"cb13-48\"><a href=\"#cb13-48\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-49\"><a href=\"#cb13-49\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb13-50\"><a href=\"#cb13-50\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-51\"><a href=\"#cb13-51\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-52\"><a href=\"#cb13-52\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-53\"><a href=\"#cb13-53\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-54\"><a href=\"#cb13-54\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-55\"><a href=\"#cb13-55\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-56\"><a href=\"#cb13-56\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-57\"><a href=\"#cb13-57\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-58\"><a href=\"#cb13-58\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-59\"><a href=\"#cb13-59\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-60\"><a href=\"#cb13-60\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-61\"><a href=\"#cb13-61\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-62\"><a href=\"#cb13-62\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-63\"><a href=\"#cb13-63\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdi&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-64\"><a href=\"#cb13-64\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rsi&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-65\"><a href=\"#cb13-65\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-66\"><a href=\"#cb13-66\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-67\"><a href=\"#cb13-67\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-68\"><a href=\"#cb13-68\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-69\"><a href=\"#cb13-69\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-70\"><a href=\"#cb13-70\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-71\"><a href=\"#cb13-71\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-72\"><a href=\"#cb13-72\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-73\"><a href=\"#cb13-73\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall3 <span class=\"op\">{</span></span>\n<span id=\"cb13-74\"><a href=\"#cb13-74\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-75\"><a href=\"#cb13-75\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb13-76\"><a href=\"#cb13-76\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-77\"><a href=\"#cb13-77\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-78\"><a href=\"#cb13-78\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-79\"><a href=\"#cb13-79\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-80\"><a href=\"#cb13-80\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-81\"><a href=\"#cb13-81\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-82\"><a href=\"#cb13-82\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-83\"><a href=\"#cb13-83\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-84\"><a href=\"#cb13-84\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-85\"><a href=\"#cb13-85\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-86\"><a href=\"#cb13-86\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-87\"><a href=\"#cb13-87\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-88\"><a href=\"#cb13-88\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-89\"><a href=\"#cb13-89\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-90\"><a href=\"#cb13-90\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdi&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-91\"><a href=\"#cb13-91\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rsi&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-92\"><a href=\"#cb13-92\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdx&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-93\"><a href=\"#cb13-93\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-94\"><a href=\"#cb13-94\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-95\"><a href=\"#cb13-95\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-96\"><a href=\"#cb13-96\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-97\"><a href=\"#cb13-97\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-98\"><a href=\"#cb13-98\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-99\"><a href=\"#cb13-99\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-100\"><a href=\"#cb13-100\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-101\"><a href=\"#cb13-101\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall4 <span class=\"op\">{</span></span>\n<span id=\"cb13-102\"><a href=\"#cb13-102\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-103\"><a href=\"#cb13-103\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg4<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb13-104\"><a href=\"#cb13-104\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-105\"><a href=\"#cb13-105\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-106\"><a href=\"#cb13-106\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-107\"><a href=\"#cb13-107\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-108\"><a href=\"#cb13-108\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-109\"><a href=\"#cb13-109\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-110\"><a href=\"#cb13-110\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-111\"><a href=\"#cb13-111\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-112\"><a href=\"#cb13-112\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-113\"><a href=\"#cb13-113\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x3&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-114\"><a href=\"#cb13-114\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-115\"><a href=\"#cb13-115\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-116\"><a href=\"#cb13-116\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-117\"><a href=\"#cb13-117\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-118\"><a href=\"#cb13-118\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-119\"><a href=\"#cb13-119\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdi&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-120\"><a href=\"#cb13-120\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rsi&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-121\"><a href=\"#cb13-121\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdx&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-122\"><a href=\"#cb13-122\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;r10&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-123\"><a href=\"#cb13-123\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-124\"><a href=\"#cb13-124\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-125\"><a href=\"#cb13-125\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-126\"><a href=\"#cb13-126\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-127\"><a href=\"#cb13-127\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-128\"><a href=\"#cb13-128\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-129\"><a href=\"#cb13-129\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-130\"><a href=\"#cb13-130\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-131\"><a href=\"#cb13-131\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall5 <span class=\"op\">{</span></span>\n<span id=\"cb13-132\"><a href=\"#cb13-132\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-133\"><a href=\"#cb13-133\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg4<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg5<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb13-134\"><a href=\"#cb13-134\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-135\"><a href=\"#cb13-135\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-136\"><a href=\"#cb13-136\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-137\"><a href=\"#cb13-137\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-138\"><a href=\"#cb13-138\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-139\"><a href=\"#cb13-139\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-140\"><a href=\"#cb13-140\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-141\"><a href=\"#cb13-141\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-142\"><a href=\"#cb13-142\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-143\"><a href=\"#cb13-143\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x3&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-144\"><a href=\"#cb13-144\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x4&quot;</span>) arg5<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-145\"><a href=\"#cb13-145\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-146\"><a href=\"#cb13-146\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-147\"><a href=\"#cb13-147\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-148\"><a href=\"#cb13-148\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-149\"><a href=\"#cb13-149\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-150\"><a href=\"#cb13-150\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdi&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-151\"><a href=\"#cb13-151\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rsi&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-152\"><a href=\"#cb13-152\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdx&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-153\"><a href=\"#cb13-153\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;r10&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-154\"><a href=\"#cb13-154\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;r9&quot;</span>) arg5<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-155\"><a href=\"#cb13-155\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-156\"><a href=\"#cb13-156\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-157\"><a href=\"#cb13-157\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-158\"><a href=\"#cb13-158\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-159\"><a href=\"#cb13-159\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-160\"><a href=\"#cb13-160\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-161\"><a href=\"#cb13-161\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb13-162\"><a href=\"#cb13-162\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb13-163\"><a href=\"#cb13-163\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">macro_rules!</span> syscall6 <span class=\"op\">{</span></span>\n<span id=\"cb13-164\"><a href=\"#cb13-164\" aria-hidden=\"true\" tabindex=\"-1\"></a>    (<span class=\"op\">$</span>name<span class=\"op\">:</span>ident<span class=\"op\">,</span> <span class=\"op\">$</span>nr<span class=\"op\">:</span>expr) <span class=\"op\">=&gt;</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-165\"><a href=\"#cb13-165\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"kw\">extern</span> <span class=\"st\">&quot;C&quot;</span> <span class=\"kw\">fn</span> $name(arg1<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg2<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg3<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg4<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg5<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;,</span> arg6<span class=\"op\">:</span> <span class=\"kw\">impl</span> <span class=\"bu\">Into</span><span class=\"op\">&lt;</span><span class=\"dt\">usize</span><span class=\"op\">&gt;</span>) <span class=\"op\">{</span></span>\n<span id=\"cb13-166\"><a href=\"#cb13-166\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"kw\">unsafe</span> <span class=\"op\">{</span></span>\n<span id=\"cb13-167\"><a href=\"#cb13-167\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-168\"><a href=\"#cb13-168\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-169\"><a href=\"#cb13-169\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;mov x0, #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-170\"><a href=\"#cb13-170\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;svc #0&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-171\"><a href=\"#cb13-171\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;w8&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-172\"><a href=\"#cb13-172\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x0&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-173\"><a href=\"#cb13-173\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x1&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-174\"><a href=\"#cb13-174\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x2&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-175\"><a href=\"#cb13-175\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x3&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-176\"><a href=\"#cb13-176\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x4&quot;</span>) arg5<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-177\"><a href=\"#cb13-177\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;x5&quot;</span>) arg6<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-178\"><a href=\"#cb13-178\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-179\"><a href=\"#cb13-179\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb13-180\"><a href=\"#cb13-180\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">asm!</span>(</span>\n<span id=\"cb13-181\"><a href=\"#cb13-181\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"st\">&quot;syscall&quot;</span><span class=\"op\">,</span></span>\n<span id=\"cb13-182\"><a href=\"#cb13-182\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rax&quot;</span>) <span class=\"op\">$</span>nr<span class=\"op\">,</span></span>\n<span id=\"cb13-183\"><a href=\"#cb13-183\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdi&quot;</span>) arg1<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-184\"><a href=\"#cb13-184\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rsi&quot;</span>) arg2<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-185\"><a href=\"#cb13-185\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;rdx&quot;</span>) arg3<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-186\"><a href=\"#cb13-186\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;r10&quot;</span>) arg4<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-187\"><a href=\"#cb13-187\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;r9&quot;</span>) arg5<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-188\"><a href=\"#cb13-188\" aria-hidden=\"true\" tabindex=\"-1\"></a>                    <span class=\"kw\">in</span>(<span class=\"st\">&quot;r8&quot;</span>) arg6<span class=\"op\">.</span>into()<span class=\"op\">,</span></span>\n<span id=\"cb13-189\"><a href=\"#cb13-189\" aria-hidden=\"true\" tabindex=\"-1\"></a>                )<span class=\"op\">;</span></span>\n<span id=\"cb13-190\"><a href=\"#cb13-190\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>not<span class=\"at\">(</span>any<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;aarch64&quot;</span><span class=\"op\">,</span> target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)))]</span></span>\n<span id=\"cb13-191\"><a href=\"#cb13-191\" aria-hidden=\"true\" tabindex=\"-1\"></a>                <span class=\"pp\">compile_error!</span>(<span class=\"st\">&quot;not implemented&quot;</span>)<span class=\"op\">;</span></span>\n<span id=\"cb13-192\"><a href=\"#cb13-192\" aria-hidden=\"true\" tabindex=\"-1\"></a>            <span class=\"op\">}</span></span>\n<span id=\"cb13-193\"><a href=\"#cb13-193\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"op\">}</span></span>\n<span id=\"cb13-194\"><a href=\"#cb13-194\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb13-195\"><a href=\"#cb13-195\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Finally, we\u2019ll implement the system calls:</p>\n<div class=\"sourceCode\" id=\"cb14\"><pre\nclass=\"sourceCode rust\"><code class=\"sourceCode rust\"><span id=\"cb14-1\"><a href=\"#cb14-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb14-2\"><a href=\"#cb14-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">syscall0!</span>(exit<span class=\"op\">,</span> <span class=\"dv\">60</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-3\"><a href=\"#cb14-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb14-4\"><a href=\"#cb14-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">syscall3!</span>(write<span class=\"op\">,</span> <span class=\"dv\">1</span>)<span class=\"op\">;</span></span>\n<span id=\"cb14-5\"><a href=\"#cb14-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-6\"><a href=\"#cb14-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">fn</span> main() <span class=\"op\">{</span></span>\n<span id=\"cb14-7\"><a href=\"#cb14-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"at\">#[</span>cfg<span class=\"at\">(</span>target_arch <span class=\"op\">=</span> <span class=\"st\">&quot;x86_64&quot;</span><span class=\"at\">)]</span></span>\n<span id=\"cb14-8\"><a href=\"#cb14-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"kw\">let</span> string <span class=\"op\">=</span> <span class=\"st\">&quot;Hello x86</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb14-9\"><a href=\"#cb14-9\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb14-10\"><a href=\"#cb14-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"co\">// the same as before</span></span>\n<span id=\"cb14-11\"><a href=\"#cb14-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And this time, if run on an <code>x86_64</code> linux machine, you\nshould see the following when running: <code>Hello x86</code>.</p>\n</section>\n</section>\n<section id=\"conclusions\" class=\"level2\">\n<h2>Conclusions</h2>\n<p>That wasn\u2019t so bad, just like the last blog post \u2013 but it was also\nmuch easier, and you wouldn\u2019t have to remember the magic defines that\nare compiler dependent. As well, <code>cfg</code> attributes are\nextremely powerful \u2013 much better than C defines because they\u2019re caught\nfor you at compile time, and there are a bunch of useful ones already\npredefined.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-05-22T12:58:02+00:00"
		},
		{
			"id": "gen/coding-on-android.html",
			"url": "gen/coding-on-android.html",
			"title": "Coding on Android",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Coding on Android</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Coding on Android</h1>\n<p class=\"byline\">2023-05-15T22:33:07-04:00</p>\n</header>\n<p>I like to tinker. No surprises there. But when my tinkering made it\nso my laptop wouldn\u2019t boot, I realized I\u2019d need a plan B computer for\nwhen my laptop was out of business. The solution? My android phone.</p>\n<p>I have a Samsung S10 phone, which is about 4 years old at this point\nand gets by just fine \u2013 it has 8GB of RAM, with 8 cores, 2.84GHz\nprocessor, and 128GB of disk space. The computer I used growing up had a\n200MHz processor, with 64MB of RAM, and a 2GB hard drive. Computers are\nreally fast these days, and I was wondering how fast my phone would be\nas a general computing device.</p>\n<p>Thankfully, the people at F-droid and Termux made that easy \u2013 F-droid\nis an alternative app store for android, which comes with lots of\ngoodies, including Termux, a unix terminal for your android that doesn\u2019t\nrequire root. I installed both and was off to the races. Termux allows\nyou to create a symlink to your normal files, so you can still fetch\nthem from the cli. I also used tailscale to quickly move files between\nmy computer and my phone, so I could get my ssh keys, and other config\nfiles quickly onto the device.</p>\n<p>I then got myself a c compiler and rust compiler and started writing\ncode. My target triplet for rust is <code>aarch64-linux-android</code>,\nwhich is in tier-2 support for rust, so there would be some rough edges.\nThere certainly were.</p>\n<p>I tried to compile some command line utilities I had wrote for\nmyself, like <code>host</code>, <code>dig</code>, <code>strace</code>,\nand others. The DNS library that the network requests relied upon had a\nbug that made them not compile on android. As well,\n<code>cargo binstall</code>, a utility which downloads binaries of rust\ncode for you, would crash at runtime due to a DNS misconfiguration. I\nhad to recompile the library with a feature flag turned off. But\nignoring all those papercuts, it was mindblowing that a 4 year old phone\nthat costs ~$200 these days could be \u201cgood enough\u201d for writing code, and\nyou could get by with a $50 or less phone for coding and still have a\ngreat experience (you\u2019d also need a keyboard and a mouse and a USB-2 to\nUSB-3 converter so you\u2019re not stuck on the default keypad, but that\u2019s\nnot expensive, the local mart had a pair for $10).</p>\n<p>The folks at termux do a really good job packaging code \u2013 even though\nTermux Android doesn\u2019t follow the unix file specification (there is no\n<code>root</code> dir), they repackage debian packages to make them work\nanyway. And my neovim config worked flawlessly on the phone. It was a\nsurreal experience \u2013 and one differentiator to apple, who locks down\ntheir devices a lot more.</p>\n<p>I even tried briefly hosting my own website and other services on the\ninternet from my phone by using tailscale. That worked flawlessly, and\nI\u2019m sure my phone could serve thousands of concurrent visitors.</p>\n<p>The experience made me think of two things: Do I really need a laptop\nthese days? I\u2019ll keep mine around for tinkering, but a phone is just\nabout good enough \u2013 with a USB-C monitor that can accept a keyboard and\nmouse, you could have a desktop setup for your phone, even with just one\nUSB-C port. And a phone just fits in your pocket, with a great battery\nlife, so you can take it on the go.</p>\n<p>In sum, coding on my phone was a delightful experience. In fact, I\nliked it so much, I decided to write this post on my phone and build my\nblog on my phone and serve it from there. Given the backdrop of tech\ndoom these days, it\u2019s hard to find any tech news to feel happy about \u2013\nbut Termux + Android is so good that it\u2019s mindblowing. If anything, I\u2019m\nglad that computing has gotten so cheap \u2013 I\u2019m sure there\u2019s lots of young\npeople learning how to code on hardware just like this, and that\u2019s\nsomething that brings a smile to my face.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-05-16T02:33:07+00:00"
		},
		{
			"id": "gen/writing-your-own-libc.html",
			"url": "gen/writing-your-own-libc.html",
			"title": "Writing Your own Libc",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing Your own Libc</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing Your own Libc</h1>\n<p class=\"byline\">2023-02-16T16:05:35-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#what-are-system-calls\" id=\"toc-what-are-system-calls\">What\nare System Calls?</a>\n<ul>\n<li><a href=\"#system-call-numbers\" id=\"toc-system-call-numbers\">System\nCall Numbers</a></li>\n<li><a href=\"#writing-system-calls-with-assembly\"\nid=\"toc-writing-system-calls-with-assembly\">Writing system calls (with\nassembly)</a></li>\n<li><a href=\"#writing-a-c-function-that-makes-a-system-call\"\nid=\"toc-writing-a-c-function-that-makes-a-system-call\">Writing a C\nFunction that makes a system call</a></li>\n<li><a href=\"#putting-it-all-together\"\nid=\"toc-putting-it-all-together\">Putting it all together</a></li>\n<li><a href=\"#reading-and-writing-to-files\"\nid=\"toc-reading-and-writing-to-files\">Reading and writing to\nfiles</a></li>\n</ul></li>\n</ul>\n</nav>\n<p>Note: This code was taken from Linux\u2019s nolibc: <a\nhref=\"https://github.com/torvalds/linux/tree/master/tools/include/nolibc\"\nclass=\"uri\">https://github.com/torvalds/linux/tree/master/tools/include/nolibc</a>.\nCheck it out to learn more about implementing libc!</p>\n<section id=\"what-are-system-calls\" class=\"level1\">\n<h1>What are System Calls?</h1>\n<p>Let\u2019s write some libc functions.</p>\n<p>Libc is C\u2019s standard library, which implements a group of functions\nthat can be used by all C programs. Libc provides wrappers for OS level\nconstructs, like <code>printf</code>, <code>open</code>,\n<code>puts</code>, and so on.</p>\n<p>There\u2019s two parts to libc:</p>\n<ol type=\"1\">\n<li>functions like <code>max</code>, or <code>islower</code>, which\ndon\u2019t require any system calls.</li>\n<li>functions that do require system calls, like <code>write</code>,\n<code>read</code>, or <code>open</code>.</li>\n</ol>\n<p>Functions in the first category can be implemented without calling\ninto the OS.</p>\n<p>For example, <code>max</code> would look like this:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> max<span class=\"op\">(</span><span class=\"dt\">int</span> a<span class=\"op\">,</span> <span class=\"dt\">int</span> b<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> a <span class=\"op\">&gt;</span> b <span class=\"op\">?</span> a <span class=\"op\">:</span> b<span class=\"op\">;</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>or <code>islower</code>:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> islower<span class=\"op\">(</span><span class=\"dt\">int</span> c<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> <span class=\"op\">(</span>c <span class=\"op\">&gt;=</span> <span class=\"ch\">&#39;a&#39;</span> <span class=\"op\">&amp;&amp;</span> c <span class=\"op\">&lt;=</span> <span class=\"ch\">&#39;z&#39;</span><span class=\"op\">)</span> <span class=\"op\">?</span> <span class=\"dv\">1</span> <span class=\"op\">:</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>However, when writing our own <code>write</code> or <code>read</code>\nor <code>open</code>, we hit a roadblock:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> open<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span><span class=\"op\">*</span> path<span class=\"op\">,</span> <span class=\"dt\">int</span> flags<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"co\">// how do I open a file???</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Open is a system call that needs to manipulate hardware; we need to\nask the OS to do the action for us before being able to read and/or\nwrite to the file.</p>\n<p>The OS supports an interface to facilitate that, called\n<code>system calls</code>. These system calls allow us to request the OS\nto do something on our behalf. These calls normally manipuluate hardware\nin some fashion, or have to do with processes.</p>\n<p>So <code>open</code> might look like this:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> open<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span><span class=\"op\">*</span> path<span class=\"op\">,</span> <span class=\"dt\">int</span> flags<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> system_call<span class=\"op\">(</span>SYSCALL_OPEN<span class=\"op\">,</span> path<span class=\"op\">,</span> flags<span class=\"op\">,</span> <span class=\"op\">...);</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And we defer to the OS, which takes care of everything for us.</p>\n<p>That leaves the question: what should our <code>system_call</code>\nfunction look like? And what is <code>SYSCALL_OPEN</code>?</p>\n<section id=\"system-call-numbers\" class=\"level2\">\n<h2>System Call Numbers</h2>\n<p>System calls take as their first argument a number, which indicates\nwhat system call the OS should execute. The OS then reads the first\nargument from the <code>system_call</code> function, looksup which\nsystem call it corresponds to, and the remaining arguments, and executes\nthat system call.</p>\n<p>Let\u2019s say that we call open, which is the number 2:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define SYSCALL_OPEN </span><span class=\"dv\">2</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>system_call<span class=\"op\">(</span>SYSCALL_OPEN<span class=\"op\">,</span> path<span class=\"op\">,</span> flags<span class=\"op\">,</span> <span class=\"op\">...);</span></span></code></pre></div>\n<p>The OS will then take that number and run the desired code.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define SYSCALL_OPEN </span><span class=\"dv\">2</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> system_call<span class=\"op\">(</span>SYSCALL syscall<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">switch</span> <span class=\"op\">(</span>syscall<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">case</span> SYSCALL_OPEN<span class=\"op\">:</span></span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"co\">// run code to open up a file in the hardware</span></span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">default</span><span class=\"op\">:</span></span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>We now need a correct list of system calls. Imagine if we thought\n<code>SYSCALL_OPEN</code> was <code>3</code>, but the OS thought\n<code>3</code> means <code>close</code>:</p>\n<p>The computer could crash, our process could crash, anything could\nhappen.</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define SYSCALL_OPEN </span><span class=\"dv\">3</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>system_call<span class=\"op\">(</span>SYSCALL_OPEN<span class=\"op\">,</span> path<span class=\"op\">,</span> flags<span class=\"op\">,</span> <span class=\"op\">...);</span></span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb8\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define SYSCALL_OPEN  </span><span class=\"dv\">2</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define SYSCALL_CLOSE </span><span class=\"dv\">3</span></span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> system_call<span class=\"op\">(</span>SYSCALL syscall<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">switch</span> <span class=\"op\">(</span>syscall<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">case</span> SYSCALL_OPEN<span class=\"op\">:</span></span>\n<span id=\"cb8-7\"><a href=\"#cb8-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"co\">// run code to open up a file in the hardware</span></span>\n<span id=\"cb8-8\"><a href=\"#cb8-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb8-9\"><a href=\"#cb8-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">case</span> SYSCALL_CLOSE<span class=\"op\">:</span></span>\n<span id=\"cb8-10\"><a href=\"#cb8-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"co\">// run code to close  a file</span></span>\n<span id=\"cb8-11\"><a href=\"#cb8-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"co\">// oops, we called the wrong function</span></span>\n<span id=\"cb8-12\"><a href=\"#cb8-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb8-13\"><a href=\"#cb8-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">default</span><span class=\"op\">:</span></span>\n<span id=\"cb8-14\"><a href=\"#cb8-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">break</span><span class=\"op\">;</span></span>\n<span id=\"cb8-15\"><a href=\"#cb8-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb8-16\"><a href=\"#cb8-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>So we need to get that list of system calls:</p>\n<p>You can find the system calls in your linux system with\n<code>ausyscall</code>:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ausyscall <span class=\"at\">--dump</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Using</span> x86_64 syscall table:</span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">0</span>       read</span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">1</span>       write</span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">2</span>       open</span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">3</span>       close</span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">...</span></span></code></pre></div>\n<p>This differs per architecture:</p>\n<p>for example, on aarch64 (ARM 64 bit):</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ausyscall aarch64 <span class=\"at\">--dump</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Using</span> aarch64 syscall table:</span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">0</span>       io_setup</span>\n<span id=\"cb10-4\"><a href=\"#cb10-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">1</span>       io_destroy</span>\n<span id=\"cb10-5\"><a href=\"#cb10-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">2</span>       io_submit</span>\n<span id=\"cb10-6\"><a href=\"#cb10-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">3</span>       io_cancel</span></code></pre></div>\n<p>We could define these ourselves, or rely on the system to export them\nat <code>asm/unistd.h</code>. I\u2019m going to include it instead of\nrewriting it.</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;asm/unistd.h&gt;</span></span></code></pre></div>\n</section>\n<section id=\"writing-system-calls-with-assembly\" class=\"level2\">\n<h2>Writing system calls (with assembly)</h2>\n<p>Now that we have the system call number we need, let\u2019s write that\nsyscall!</p>\n<p>We need to know a few things:</p>\n<ol type=\"1\">\n<li>What the system call function is called, so we can tell the OS we\u2019re\nrunning a system call</li>\n<li>Where to put the system call number</li>\n<li>Where to put any other arguments required (<code>open</code> needs a\nfile to open, for example)</li>\n<li>Where our return values are placed.</li>\n</ol>\n<p>What better way to learn than through the manual pages: run\n<code>man 2 syscall</code> in the shell to learn more:</p>\n<p>First, there\u2019s a table that tells us what a system call is called in\nthe <code>instruction</code> column. For x86-64, it is called\n<code>syscall</code>. Next, the table tells us the register to put the\nsystem call number. In x86-64, it is <code>rax</code>. Finally, the\nregisters to check for return values, which in x86-64 are\n<code>rax</code> and <code>rdx</code>, and the register to check for\nerrors (in x86-64, no registers store errors after a system call).</p>\n<pre><code>Arch/ABI    Instruction           System  Ret  Ret  Error    Notes\n                                  call #  val  val2\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nalpha       callsys               v0      v0   a4   a3       1, 6\narc         trap0                 r8      r0   -    -\narm/OABI    swi NR                -       r0   -    -        2\narm/EABI    swi 0x0               r7      r0   r1   -\narm64       svc #0                w8      x0   x1   -\nblackfin    excpt 0x0             P0      R0   -    -\ni386        int $0x80             eax     eax  edx  -\nia64        break 0x100000        r15     r8   r9   r10      1, 6\nm68k        trap #0               d0      d0   -    -\nmicroblaze  brki r14,8            r12     r3   -    -\nmips        syscall               v0      v0   v1   a3       1, 6\nnios2       trap                  r2      r2   -    r7\nparisc      ble 0x100(%sr2, %r0)  r20     r28  -    -\npowerpc     sc                    r0      r3   -    r0       1\npowerpc64   sc                    r0      r3   -    cr0.SO   1\nriscv       ecall                 a7      a0   a1   -\ns390        svc 0                 r1      r2   r3   -        3\ns390x       svc 0                 r1      r2   r3   -        3\nsuperh      trapa #31             r3      r0   r1   -        4, 6\nsparc/32    t 0x10                g1      o0   o1   psr/csr  1, 6\nsparc/64    t 0x6d                g1      o0   o1   psr/csr  1, 6\ntile        swint1                R10     R00  -    R01      1\nx86-64      syscall               rax     rax  rdx  -        5\nx32         syscall               rax     rax  rdx  -        5\nxtensa      syscall               a2      a2   -    -</code></pre>\n<p>Later down the page, there\u2019s another table that shows where arguments\ngo.</p>\n<p>For x86-64, <code>rdi</code> <code>rsi</code> <code>rdx</code>\n<code>r10</code> <code>r8</code> <code>r9</code> are the registers to\nput arguments in order, with <code>rax</code> being the system call\nnumber.</p>\n<p>An interesting thing to note: <code>mips/o32</code> here only\nsupports 4 arguments in registers. That doesn\u2019t necessarily mean it only\nsupports system calls with 4 or less arguments \u2013 arguments 5 through 8\nare placed on the stack and read when the system call instruction is\nexecuted.</p>\n<pre><code>Arch/ABI      arg1  arg2  arg3  arg4  arg5  arg6  arg7  Notes\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nalpha         a0    a1    a2    a3    a4    a5    -\narc           r0    r1    r2    r3    r4    r5    -\narm/OABI      r0    r1    r2    r3    r4    r5    r6\narm/EABI      r0    r1    r2    r3    r4    r5    r6\narm64         x0    x1    x2    x3    x4    x5    -\nblackfin      R0    R1    R2    R3    R4    R5    -\ni386          ebx   ecx   edx   esi   edi   ebp   -\nia64          out0  out1  out2  out3  out4  out5  -\nm68k          d1    d2    d3    d4    d5    a0    -\nmicroblaze    r5    r6    r7    r8    r9    r10   -\nmips/o32      a0    a1    a2    a3    -     -     -     1\nmips/n32,64   a0    a1    a2    a3    a4    a5    -\nnios2         r4    r5    r6    r7    r8    r9    -\nparisc        r26   r25   r24   r23   r22   r21   -\npowerpc       r3    r4    r5    r6    r7    r8    r9\npowerpc64     r3    r4    r5    r6    r7    r8    -\nriscv         a0    a1    a2    a3    a4    a5    -\ns390          r2    r3    r4    r5    r6    r7    -\ns390x         r2    r3    r4    r5    r6    r7    -\nsuperh        r4    r5    r6    r7    r0    r1    r2\nsparc/32      o0    o1    o2    o3    o4    o5    -\nsparc/64      o0    o1    o2    o3    o4    o5    -\ntile          R00   R01   R02   R03   R04   R05   -\nx86-64        rdi   rsi   rdx   r10   r8    r9    -\nx32           rdi   rsi   rdx   r10   r8    r9    -\nxtensa        a6    a3    a4    a5    a8    a9    -</code></pre>\n<p>With all that information out of the way, we want to write a function\nthat does the following:</p>\n<ol type=\"1\">\n<li>Write out the system call instruction in assembly\n(<code>syscall</code> for x86).</li>\n<li>Set the <code>rax</code> register to the system call we want to\ncall.</li>\n<li>Read the register has the return value and return it.</li>\n</ol>\n<p>On x86, the registers <code>rcx</code>, <code>r11</code>,\n<code>cc</code>, and <code>memory</code> are clobbered by the syscall,\nso our assembly call must include them in the last line of the syscall\ninstruction. The last line notes the clobbered registers that are\noverwritten by the OS, as well as other directives.</p>\n<p>For an explanation why <code>rcx</code> and <code>r11</code> are\nclobbered.</p>\n<ul>\n<li><code>rcx</code></li>\n</ul>\n<blockquote>\n<p><code>rcx</code> is clobbered to store the address of the next\ninstruction to return to.</p>\n</blockquote>\n<ul>\n<li><code>r11</code></li>\n</ul>\n<blockquote>\n<p><code>r11</code> is clobbered to store the value of the rflags\nregister.</p>\n</blockquote>\n<p>And for <code>cc</code> and <code>memory</code>, from: <a\nhref=\"https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm\"\nclass=\"uri\">https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm</a></p>\n<ul>\n<li><code>cc</code></li>\n</ul>\n<blockquote>\n<p>The <code>cc</code> clobber indicates that the assembler code\nmodifies the flags register. On some machines, GCC represents the\ncondition codes as a specific hardware register; \u201ccc\u201d serves to name\nthis register. On other machines, condition code handling is different,\nand specifying \u201ccc\u201d has no effect. But it is valid no matter what the\ntarget.</p>\n</blockquote>\n<ul>\n<li><code>memory</code></li>\n</ul>\n<blockquote>\n<p>The <code>memory</code> clobber tells the compiler that the assembly\ncode performs memory reads or writes to items other than those listed in\nthe input and output operands (for example, accessing the memory pointed\nto by one of the input parameters). To ensure memory contains correct\nvalues, GCC may need to flush specific register values to memory before\nexecuting the asm. Further, the compiler does not assume that any values\nread from memory before an asm remain unchanged after that asm; it\nreloads them as needed. Using the \u201cmemory\u201d clobber effectively forms a\nread/write memory barrier for the compiler.</p>\n</blockquote>\n<blockquote>\n<p>Note that this clobber does not prevent the processor from doing\nspeculative reads past the asm statement. To prevent that, you need\nprocessor-specific fence instructions.</p>\n</blockquote>\n<p>So on x86, a system call will look like:</p>\n<div class=\"sourceCode\" id=\"cb14\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb14-1\"><a href=\"#cb14-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall0</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">)</span><span class=\"pp\">                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-2\"><a href=\"#cb14-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                        </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-3\"><a href=\"#cb14-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">long</span><span class=\"pp\"> _ret</span><span class=\"op\">;</span><span class=\"pp\">                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-4\"><a href=\"#cb14-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rax&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-5\"><a href=\"#cb14-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                            </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-6\"><a href=\"#cb14-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-7\"><a href=\"#cb14-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-8\"><a href=\"#cb14-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=a&quot;</span><span class=\"op\">(</span><span class=\"pp\">_ret</span><span class=\"op\">)</span><span class=\"pp\">                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-9\"><a href=\"#cb14-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;0&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-10\"><a href=\"#cb14-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;rcx&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;r11&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">        </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-11\"><a href=\"#cb14-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                      </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-12\"><a href=\"#cb14-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _ret</span><span class=\"op\">;</span><span class=\"pp\">                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb14-13\"><a href=\"#cb14-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span></code></pre></div>\n<p>For the Arm64 (aarch64) version:</p>\n<div class=\"sourceCode\" id=\"cb15\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb15-1\"><a href=\"#cb15-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall0</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">)</span><span class=\"pp\">                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-2\"><a href=\"#cb15-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                       </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-3\"><a href=\"#cb15-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x8&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-4\"><a href=\"#cb15-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x0&quot;</span><span class=\"op\">);</span><span class=\"pp\">         </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-5\"><a href=\"#cb15-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-6\"><a href=\"#cb15-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                         </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-7\"><a href=\"#cb15-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-8\"><a href=\"#cb15-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">)</span><span class=\"pp\">                        </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-9\"><a href=\"#cb15-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-10\"><a href=\"#cb15-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-11\"><a href=\"#cb15-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-12\"><a href=\"#cb15-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _arg1</span><span class=\"op\">;</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb15-13\"><a href=\"#cb15-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span></code></pre></div>\n</section>\n<section id=\"writing-a-c-function-that-makes-a-system-call\"\nclass=\"level2\">\n<h2>Writing a C Function that makes a system call</h2>\n<p>Let\u2019s write our first libc function, <code>getpid</code>.</p>\n<p><code>getpid</code> returns the <code>pid</code> of the current\nprocess.</p>\n<p>It has a signature of <code>pid_t getpid(void);</code>, where\n<code>pid_t</code> is <code>int</code>.</p>\n<p>All we have to do is to make the right system call to the OS and\nreturn it.</p>\n<div class=\"sourceCode\" id=\"cb16\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb16-1\"><a href=\"#cb16-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">int</span> pid_t<span class=\"op\">;</span></span>\n<span id=\"cb16-2\"><a href=\"#cb16-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb16-3\"><a href=\"#cb16-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>pid_t getpid<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb16-4\"><a href=\"#cb16-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall0<span class=\"op\">(</span>__NR_getpid<span class=\"op\">);</span></span>\n<span id=\"cb16-5\"><a href=\"#cb16-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This should return your pid, and we\u2019re done creating a libc function\nthat calls into the kernel.</p>\n</section>\n<section id=\"putting-it-all-together\" class=\"level2\">\n<h2>Putting it all together</h2>\n<p>To put it all together, we need to write the <code>_start</code>\nfunction of our program, since we are going to link to our own libc.</p>\n<p>For x86, that means adding this code to the top of your file:</p>\n<div class=\"sourceCode\" id=\"cb17\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb17-1\"><a href=\"#cb17-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>asm<span class=\"op\">(</span><span class=\"st\">&quot;.section .text</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb17-2\"><a href=\"#cb17-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.weak _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb17-3\"><a href=\"#cb17-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.global _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb17-4\"><a href=\"#cb17-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;_start:</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb17-5\"><a href=\"#cb17-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;pop %rdi</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                <span class=\"co\">// argc   (first arg, %rdi)</span></span>\n<span id=\"cb17-6\"><a href=\"#cb17-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov %rsp, %rsi</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// argv[] (second arg, %rsi)</span></span>\n<span id=\"cb17-7\"><a href=\"#cb17-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;lea 8(%rsi,%rdi,8),%rdx</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span> <span class=\"co\">// then a NULL then envp (third arg, %rdx)</span></span>\n<span id=\"cb17-8\"><a href=\"#cb17-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;xor </span><span class=\"sc\">%e</span><span class=\"st\">bp, </span><span class=\"sc\">%e</span><span class=\"st\">bp</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// zero the stack frame</span></span>\n<span id=\"cb17-9\"><a href=\"#cb17-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;and $-16, %rsp</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// x86 ABI : esp must be 16-byte aligned before call</span></span>\n<span id=\"cb17-10\"><a href=\"#cb17-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;call main</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>               <span class=\"co\">// main() returns the status code, we&#39;ll exit with it.</span></span>\n<span id=\"cb17-11\"><a href=\"#cb17-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov </span><span class=\"sc\">%e</span><span class=\"st\">ax, </span><span class=\"sc\">%e</span><span class=\"st\">di</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// retrieve exit code (32 bit)</span></span>\n<span id=\"cb17-12\"><a href=\"#cb17-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov $60, </span><span class=\"sc\">%e</span><span class=\"st\">ax</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>           <span class=\"co\">// NR_exit == 60</span></span>\n<span id=\"cb17-13\"><a href=\"#cb17-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                 <span class=\"co\">// really exit</span></span>\n<span id=\"cb17-14\"><a href=\"#cb17-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;hlt</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                     <span class=\"co\">// ensure it does not return</span></span>\n<span id=\"cb17-15\"><a href=\"#cb17-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;&quot;</span><span class=\"op\">);</span></span></code></pre></div>\n<p>This sets up everything main needs to run.</p>\n<p>For ARM64 (aarch64):</p>\n<div class=\"sourceCode\" id=\"cb18\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb18-1\"><a href=\"#cb18-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>asm<span class=\"op\">(</span><span class=\"st\">&quot;.section .text</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb18-2\"><a href=\"#cb18-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.weak _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb18-3\"><a href=\"#cb18-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.global _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb18-4\"><a href=\"#cb18-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;_start:</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb18-5\"><a href=\"#cb18-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;ldr x0, [sp]</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>              <span class=\"co\">// argc (x0) was in the stack</span></span>\n<span id=\"cb18-6\"><a href=\"#cb18-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;add x1, sp, 8</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>             <span class=\"co\">// argv (x1) = sp</span></span>\n<span id=\"cb18-7\"><a href=\"#cb18-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;lsl x2, x0, 3</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>             <span class=\"co\">// envp (x2) = 8*argc ...</span></span>\n<span id=\"cb18-8\"><a href=\"#cb18-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;add x2, x2, 8</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>             <span class=\"co\">//           + 8 (skip null)</span></span>\n<span id=\"cb18-9\"><a href=\"#cb18-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;add x2, x2, x1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>            <span class=\"co\">//           + argv</span></span>\n<span id=\"cb18-10\"><a href=\"#cb18-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;and sp, x1, -16</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>           <span class=\"co\">// sp must be 16-byte aligned in the callee</span></span>\n<span id=\"cb18-11\"><a href=\"#cb18-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;bl main</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                   <span class=\"co\">// main() returns the status code, we&#39;ll exit with it.</span></span>\n<span id=\"cb18-12\"><a href=\"#cb18-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov x8, 93</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                <span class=\"co\">// NR_exit == 93</span></span>\n<span id=\"cb18-13\"><a href=\"#cb18-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb18-14\"><a href=\"#cb18-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;&quot;</span><span class=\"op\">);</span></span></code></pre></div>\n<p>And aggregating that together:</p>\n<p>For x86:</p>\n<div class=\"sourceCode\" id=\"cb19\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb19-1\"><a href=\"#cb19-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;asm/unistd.h&gt;</span></span>\n<span id=\"cb19-2\"><a href=\"#cb19-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb19-3\"><a href=\"#cb19-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall0</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">)</span><span class=\"pp\">                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-4\"><a href=\"#cb19-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                        </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-5\"><a href=\"#cb19-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">long</span><span class=\"pp\"> _ret</span><span class=\"op\">;</span><span class=\"pp\">                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-6\"><a href=\"#cb19-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rax&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-7\"><a href=\"#cb19-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                            </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-8\"><a href=\"#cb19-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-9\"><a href=\"#cb19-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-10\"><a href=\"#cb19-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=a&quot;</span><span class=\"op\">(</span><span class=\"pp\">_ret</span><span class=\"op\">)</span><span class=\"pp\">                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-11\"><a href=\"#cb19-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;0&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-12\"><a href=\"#cb19-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;rcx&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;r11&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">        </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-13\"><a href=\"#cb19-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                      </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-14\"><a href=\"#cb19-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _ret</span><span class=\"op\">;</span><span class=\"pp\">                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb19-15\"><a href=\"#cb19-15\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span>\n<span id=\"cb19-16\"><a href=\"#cb19-16\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb19-17\"><a href=\"#cb19-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>asm<span class=\"op\">(</span><span class=\"st\">&quot;.section .text</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb19-18\"><a href=\"#cb19-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.weak _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb19-19\"><a href=\"#cb19-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.global _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb19-20\"><a href=\"#cb19-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;_start:</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb19-21\"><a href=\"#cb19-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;pop %rdi</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                <span class=\"co\">// argc   (first arg, %rdi)</span></span>\n<span id=\"cb19-22\"><a href=\"#cb19-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov %rsp, %rsi</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// argv[] (second arg, %rsi)</span></span>\n<span id=\"cb19-23\"><a href=\"#cb19-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;lea 8(%rsi,%rdi,8),%rdx</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span> <span class=\"co\">// then a NULL then envp (third arg, %rdx)</span></span>\n<span id=\"cb19-24\"><a href=\"#cb19-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;xor </span><span class=\"sc\">%e</span><span class=\"st\">bp, </span><span class=\"sc\">%e</span><span class=\"st\">bp</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// zero the stack frame</span></span>\n<span id=\"cb19-25\"><a href=\"#cb19-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;and $-16, %rsp</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// x86 ABI : esp must be 16-byte aligned before call</span></span>\n<span id=\"cb19-26\"><a href=\"#cb19-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;call main</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>               <span class=\"co\">// main() returns the status code, we&#39;ll exit with it.</span></span>\n<span id=\"cb19-27\"><a href=\"#cb19-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov </span><span class=\"sc\">%e</span><span class=\"st\">ax, </span><span class=\"sc\">%e</span><span class=\"st\">di</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>          <span class=\"co\">// retrieve exit code (32 bit)</span></span>\n<span id=\"cb19-28\"><a href=\"#cb19-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov $60, </span><span class=\"sc\">%e</span><span class=\"st\">ax</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>           <span class=\"co\">// NR_exit == 60</span></span>\n<span id=\"cb19-29\"><a href=\"#cb19-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                 <span class=\"co\">// really exit</span></span>\n<span id=\"cb19-30\"><a href=\"#cb19-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;hlt</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                     <span class=\"co\">// ensure it does not return</span></span>\n<span id=\"cb19-31\"><a href=\"#cb19-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb19-32\"><a href=\"#cb19-32\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb19-33\"><a href=\"#cb19-33\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">int</span> pid_t<span class=\"op\">;</span></span>\n<span id=\"cb19-34\"><a href=\"#cb19-34\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb19-35\"><a href=\"#cb19-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>pid_t getpid<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb19-36\"><a href=\"#cb19-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall0<span class=\"op\">(</span>__NR_getpid<span class=\"op\">);</span></span>\n<span id=\"cb19-37\"><a href=\"#cb19-37\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb19-38\"><a href=\"#cb19-38\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb19-39\"><a href=\"#cb19-39\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb19-40\"><a href=\"#cb19-40\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> getpid<span class=\"op\">();</span></span>\n<span id=\"cb19-41\"><a href=\"#cb19-41\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>For ARM64 (aarch64):</p>\n<div class=\"sourceCode\" id=\"cb20\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb20-1\"><a href=\"#cb20-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall0</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">)</span><span class=\"pp\">                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-2\"><a href=\"#cb20-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                       </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-3\"><a href=\"#cb20-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x8&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-4\"><a href=\"#cb20-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x0&quot;</span><span class=\"op\">);</span><span class=\"pp\">         </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-5\"><a href=\"#cb20-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-6\"><a href=\"#cb20-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                         </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-7\"><a href=\"#cb20-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                           </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-8\"><a href=\"#cb20-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">)</span><span class=\"pp\">                        </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-9\"><a href=\"#cb20-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-10\"><a href=\"#cb20-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-11\"><a href=\"#cb20-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-12\"><a href=\"#cb20-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _arg1</span><span class=\"op\">;</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb20-13\"><a href=\"#cb20-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span>\n<span id=\"cb20-14\"><a href=\"#cb20-14\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb20-15\"><a href=\"#cb20-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>asm<span class=\"op\">(</span><span class=\"st\">&quot;.section .text</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb20-16\"><a href=\"#cb20-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.weak _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb20-17\"><a href=\"#cb20-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;.global _start</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb20-18\"><a href=\"#cb20-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;_start:</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb20-19\"><a href=\"#cb20-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;ldr x0, [sp]</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>              <span class=\"co\">// argc (x0) was in the stack</span></span>\n<span id=\"cb20-20\"><a href=\"#cb20-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;add x1, sp, 8</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>             <span class=\"co\">// argv (x1) = sp</span></span>\n<span id=\"cb20-21\"><a href=\"#cb20-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;lsl x2, x0, 3</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>             <span class=\"co\">// envp (x2) = 8*argc ...</span></span>\n<span id=\"cb20-22\"><a href=\"#cb20-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;add x2, x2, 8</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>             <span class=\"co\">//           + 8 (skip null)</span></span>\n<span id=\"cb20-23\"><a href=\"#cb20-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;add x2, x2, x1</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>            <span class=\"co\">//           + argv</span></span>\n<span id=\"cb20-24\"><a href=\"#cb20-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;and sp, x1, -16</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>           <span class=\"co\">// sp must be 16-byte aligned in the callee</span></span>\n<span id=\"cb20-25\"><a href=\"#cb20-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;bl main</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                   <span class=\"co\">// main() returns the status code, we&#39;ll exit with it.</span></span>\n<span id=\"cb20-26\"><a href=\"#cb20-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;mov x8, 93</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span>                <span class=\"co\">// NR_exit == 93</span></span>\n<span id=\"cb20-27\"><a href=\"#cb20-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb20-28\"><a href=\"#cb20-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"st\">&quot;&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb20-29\"><a href=\"#cb20-29\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb20-30\"><a href=\"#cb20-30\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">int</span> pid_t<span class=\"op\">;</span></span>\n<span id=\"cb20-31\"><a href=\"#cb20-31\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb20-32\"><a href=\"#cb20-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>pid_t getpid<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb20-33\"><a href=\"#cb20-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall0<span class=\"op\">(</span>__NR_getpid<span class=\"op\">);</span></span>\n<span id=\"cb20-34\"><a href=\"#cb20-34\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb20-35\"><a href=\"#cb20-35\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb20-36\"><a href=\"#cb20-36\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb20-37\"><a href=\"#cb20-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> getpid<span class=\"op\">();</span></span>\n<span id=\"cb20-38\"><a href=\"#cb20-38\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Now to compile this program, we can\u2019t link to libc, so, assuming the\nc file is called <code>main.c</code></p>\n<div class=\"sourceCode\" id=\"cb21\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb21-1\"><a href=\"#cb21-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> gcc <span class=\"at\">-static</span> <span class=\"at\">-lgcc</span> <span class=\"at\">-nostdlib</span> <span class=\"at\">-g</span> main.c <span class=\"at\">-o</span> main</span></code></pre></div>\n<p>to compile it, and run it:</p>\n<div class=\"sourceCode\" id=\"cb22\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb22-1\"><a href=\"#cb22-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ./main</span></code></pre></div>\n<p>Grab the exit status of the binary:</p>\n<div class=\"sourceCode\" id=\"cb23\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb23-1\"><a href=\"#cb23-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"va\">$?</span> <span class=\"co\"># some random number</span></span></code></pre></div>\n<p>And we\u2019re done with implementing <code>getpid</code>!</p>\n</section>\n<section id=\"reading-and-writing-to-files\" class=\"level2\">\n<h2>Reading and writing to files</h2>\n<p><code>getpid</code> is a fine starting function, but we want to be\nable to read and write to files.</p>\n<p>Let\u2019s start by defining the system calls that take 1 argument to 3\narguments:</p>\n<p>In x86-64:</p>\n<div class=\"sourceCode\" id=\"cb24\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb24-1\"><a href=\"#cb24-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall1</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">,</span><span class=\"pp\"> arg1</span><span class=\"op\">)</span><span class=\"pp\">                      </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-2\"><a href=\"#cb24-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                               </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-3\"><a href=\"#cb24-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">long</span><span class=\"pp\"> _ret</span><span class=\"op\">;</span><span class=\"pp\">                                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-4\"><a href=\"#cb24-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rax&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\">        </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-5\"><a href=\"#cb24-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rdi&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg1</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-6\"><a href=\"#cb24-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-7\"><a href=\"#cb24-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-8\"><a href=\"#cb24-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-9\"><a href=\"#cb24-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=a&quot;</span><span class=\"op\">(</span><span class=\"pp\">_ret</span><span class=\"op\">)</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-10\"><a href=\"#cb24-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">),</span><span class=\"pp\">                                </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-11\"><a href=\"#cb24-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">          </span><span class=\"st\">&quot;0&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-12\"><a href=\"#cb24-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;rcx&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;r11&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">               </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-13\"><a href=\"#cb24-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                             </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-14\"><a href=\"#cb24-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _ret</span><span class=\"op\">;</span><span class=\"pp\">                                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-15\"><a href=\"#cb24-15\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span>\n<span id=\"cb24-16\"><a href=\"#cb24-16\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb24-17\"><a href=\"#cb24-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall2</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">,</span><span class=\"pp\"> arg1</span><span class=\"op\">,</span><span class=\"pp\"> arg2</span><span class=\"op\">)</span><span class=\"pp\">                </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-18\"><a href=\"#cb24-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                               </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-19\"><a href=\"#cb24-19\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">long</span><span class=\"pp\"> _ret</span><span class=\"op\">;</span><span class=\"pp\">                                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-20\"><a href=\"#cb24-20\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rax&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\">        </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-21\"><a href=\"#cb24-21\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rdi&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg1</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-22\"><a href=\"#cb24-22\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg2 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rsi&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg2</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-23\"><a href=\"#cb24-23\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-24\"><a href=\"#cb24-24\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-25\"><a href=\"#cb24-25\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-26\"><a href=\"#cb24-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=a&quot;</span><span class=\"op\">(</span><span class=\"pp\">_ret</span><span class=\"op\">)</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-27\"><a href=\"#cb24-27\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg2</span><span class=\"op\">),</span><span class=\"pp\">                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-28\"><a href=\"#cb24-28\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">          </span><span class=\"st\">&quot;0&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-29\"><a href=\"#cb24-29\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;rcx&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;r11&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">               </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-30\"><a href=\"#cb24-30\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                             </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-31\"><a href=\"#cb24-31\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _ret</span><span class=\"op\">;</span><span class=\"pp\">                                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-32\"><a href=\"#cb24-32\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span>\n<span id=\"cb24-33\"><a href=\"#cb24-33\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb24-34\"><a href=\"#cb24-34\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall3</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">,</span><span class=\"pp\"> arg1</span><span class=\"op\">,</span><span class=\"pp\"> arg2</span><span class=\"op\">,</span><span class=\"pp\"> arg3</span><span class=\"op\">)</span><span class=\"pp\">          </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-35\"><a href=\"#cb24-35\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                               </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-36\"><a href=\"#cb24-36\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">long</span><span class=\"pp\"> _ret</span><span class=\"op\">;</span><span class=\"pp\">                                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-37\"><a href=\"#cb24-37\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rax&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\">        </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-38\"><a href=\"#cb24-38\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rdi&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg1</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-39\"><a href=\"#cb24-39\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg2 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rsi&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg2</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-40\"><a href=\"#cb24-40\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg3 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;rdx&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg3</span><span class=\"op\">);</span><span class=\"pp\"> </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-41\"><a href=\"#cb24-41\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-42\"><a href=\"#cb24-42\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-43\"><a href=\"#cb24-43\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;syscall</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-44\"><a href=\"#cb24-44\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=a&quot;</span><span class=\"op\">(</span><span class=\"pp\">_ret</span><span class=\"op\">)</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-45\"><a href=\"#cb24-45\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg2</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg3</span><span class=\"op\">),</span><span class=\"pp\">        </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-46\"><a href=\"#cb24-46\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">          </span><span class=\"st\">&quot;0&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-47\"><a href=\"#cb24-47\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;rcx&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;r11&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">               </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-48\"><a href=\"#cb24-48\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                             </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-49\"><a href=\"#cb24-49\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _ret</span><span class=\"op\">;</span><span class=\"pp\">                                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb24-50\"><a href=\"#cb24-50\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span></code></pre></div>\n<p>In ARM64 (aarch64):</p>\n<div class=\"sourceCode\" id=\"cb25\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb25-1\"><a href=\"#cb25-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall1</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">,</span><span class=\"pp\"> arg1</span><span class=\"op\">)</span><span class=\"pp\">                       </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-2\"><a href=\"#cb25-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                                </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-3\"><a href=\"#cb25-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x8&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\">          </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-4\"><a href=\"#cb25-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x0&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg1</span><span class=\"op\">);</span><span class=\"pp\">   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-5\"><a href=\"#cb25-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-6\"><a href=\"#cb25-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-7\"><a href=\"#cb25-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-8\"><a href=\"#cb25-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">)</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-9\"><a href=\"#cb25-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">),</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-10\"><a href=\"#cb25-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">          </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-11\"><a href=\"#cb25-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-12\"><a href=\"#cb25-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-13\"><a href=\"#cb25-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _arg1</span><span class=\"op\">;</span><span class=\"pp\">                                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-14\"><a href=\"#cb25-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span>\n<span id=\"cb25-15\"><a href=\"#cb25-15\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb25-16\"><a href=\"#cb25-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall2</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">,</span><span class=\"pp\"> arg1</span><span class=\"op\">,</span><span class=\"pp\"> arg2</span><span class=\"op\">)</span><span class=\"pp\">                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-17\"><a href=\"#cb25-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                                </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-18\"><a href=\"#cb25-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x8&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\">          </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-19\"><a href=\"#cb25-19\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x0&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg1</span><span class=\"op\">);</span><span class=\"pp\">   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-20\"><a href=\"#cb25-20\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg2 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x1&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg2</span><span class=\"op\">);</span><span class=\"pp\">   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-21\"><a href=\"#cb25-21\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-22\"><a href=\"#cb25-22\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-23\"><a href=\"#cb25-23\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-24\"><a href=\"#cb25-24\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">)</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-25\"><a href=\"#cb25-25\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg2</span><span class=\"op\">),</span><span class=\"pp\">                     </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-26\"><a href=\"#cb25-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">          </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-27\"><a href=\"#cb25-27\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-28\"><a href=\"#cb25-28\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-29\"><a href=\"#cb25-29\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _arg1</span><span class=\"op\">;</span><span class=\"pp\">                                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-30\"><a href=\"#cb25-30\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span>\n<span id=\"cb25-31\"><a href=\"#cb25-31\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb25-32\"><a href=\"#cb25-32\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define syscall3</span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">,</span><span class=\"pp\"> arg1</span><span class=\"op\">,</span><span class=\"pp\"> arg2</span><span class=\"op\">,</span><span class=\"pp\"> arg3</span><span class=\"op\">)</span><span class=\"pp\">           </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-33\"><a href=\"#cb25-33\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">({</span><span class=\"pp\">                                                </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-34\"><a href=\"#cb25-34\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _num  asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x8&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">num</span><span class=\"op\">);</span><span class=\"pp\">          </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-35\"><a href=\"#cb25-35\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg1 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x0&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg1</span><span class=\"op\">);</span><span class=\"pp\">   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-36\"><a href=\"#cb25-36\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg2 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x1&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg2</span><span class=\"op\">);</span><span class=\"pp\">   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-37\"><a href=\"#cb25-37\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"dt\">register</span><span class=\"pp\"> </span><span class=\"dt\">long</span><span class=\"pp\"> _arg3 asm</span><span class=\"op\">(</span><span class=\"st\">&quot;x2&quot;</span><span class=\"op\">)</span><span class=\"pp\"> </span><span class=\"op\">=</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"dt\">long</span><span class=\"op\">)(</span><span class=\"pp\">arg3</span><span class=\"op\">);</span><span class=\"pp\">   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-38\"><a href=\"#cb25-38\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">                                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-39\"><a href=\"#cb25-39\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    asm </span><span class=\"dt\">volatile</span><span class=\"pp\"> </span><span class=\"op\">(</span><span class=\"pp\">                                  </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-40\"><a href=\"#cb25-40\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"st\">&quot;svc #0</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"pp\">                                    </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-41\"><a href=\"#cb25-41\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;=r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">)</span><span class=\"pp\">                                 </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-42\"><a href=\"#cb25-42\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg1</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg2</span><span class=\"op\">),</span><span class=\"pp\"> </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_arg3</span><span class=\"op\">),</span><span class=\"pp\">         </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-43\"><a href=\"#cb25-43\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">          </span><span class=\"st\">&quot;r&quot;</span><span class=\"op\">(</span><span class=\"pp\">_num</span><span class=\"op\">)</span><span class=\"pp\">                                   </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-44\"><a href=\"#cb25-44\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">        </span><span class=\"op\">:</span><span class=\"pp\"> </span><span class=\"st\">&quot;memory&quot;</span><span class=\"op\">,</span><span class=\"pp\"> </span><span class=\"st\">&quot;cc&quot;</span><span class=\"pp\">                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-45\"><a href=\"#cb25-45\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    </span><span class=\"op\">);</span><span class=\"pp\">                                              </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-46\"><a href=\"#cb25-46\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">    _arg1</span><span class=\"op\">;</span><span class=\"pp\">                                          </span><span class=\"op\">\\</span></span>\n<span id=\"cb25-47\"><a href=\"#cb25-47\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">})</span></span></code></pre></div>\n<p>Next, some definitions that the libc functions will use:</p>\n<div class=\"sourceCode\" id=\"cb26\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb26-1\"><a href=\"#cb26-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">int</span> pid_t<span class=\"op\">;</span></span>\n<span id=\"cb26-2\"><a href=\"#cb26-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">int</span> mode_t<span class=\"op\">;</span></span>\n<span id=\"cb26-3\"><a href=\"#cb26-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">int</span> <span class=\"dt\">ssize_t</span><span class=\"op\">;</span></span>\n<span id=\"cb26-4\"><a href=\"#cb26-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">typedef</span> <span class=\"dt\">unsigned</span> <span class=\"dt\">long</span> <span class=\"dt\">long</span> <span class=\"dt\">size_t</span><span class=\"op\">;</span></span>\n<span id=\"cb26-5\"><a href=\"#cb26-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb26-6\"><a href=\"#cb26-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define STDIN_FILENO  </span><span class=\"dv\">0</span></span>\n<span id=\"cb26-7\"><a href=\"#cb26-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define STDOUT_FILENO </span><span class=\"dv\">1</span></span>\n<span id=\"cb26-8\"><a href=\"#cb26-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define STDERR_FILENO </span><span class=\"dv\">2</span></span></code></pre></div>\n<p>And flags for calls to <code>open</code>:</p>\n<p>For x86-64:</p>\n<div class=\"sourceCode\" id=\"cb27\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb27-1\"><a href=\"#cb27-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_RDONLY            </span><span class=\"dv\">0</span></span>\n<span id=\"cb27-2\"><a href=\"#cb27-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_WRONLY            </span><span class=\"dv\">1</span></span>\n<span id=\"cb27-3\"><a href=\"#cb27-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_RDWR              </span><span class=\"dv\">2</span></span>\n<span id=\"cb27-4\"><a href=\"#cb27-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_CREAT          </span><span class=\"bn\">0x40</span></span>\n<span id=\"cb27-5\"><a href=\"#cb27-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_EXCL           </span><span class=\"bn\">0x80</span></span>\n<span id=\"cb27-6\"><a href=\"#cb27-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_NOCTTY        </span><span class=\"bn\">0x100</span></span>\n<span id=\"cb27-7\"><a href=\"#cb27-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_TRUNC         </span><span class=\"bn\">0x200</span></span>\n<span id=\"cb27-8\"><a href=\"#cb27-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_APPEND        </span><span class=\"bn\">0x400</span></span>\n<span id=\"cb27-9\"><a href=\"#cb27-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_NONBLOCK      </span><span class=\"bn\">0x800</span></span>\n<span id=\"cb27-10\"><a href=\"#cb27-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_DIRECTORY   </span><span class=\"bn\">0x10000</span></span></code></pre></div>\n<p>For Arm64 (aarch64):</p>\n<div class=\"sourceCode\" id=\"cb28\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb28-1\"><a href=\"#cb28-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_RDONLY            </span><span class=\"dv\">0</span></span>\n<span id=\"cb28-2\"><a href=\"#cb28-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_WRONLY            </span><span class=\"dv\">1</span></span>\n<span id=\"cb28-3\"><a href=\"#cb28-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_RDWR              </span><span class=\"dv\">2</span></span>\n<span id=\"cb28-4\"><a href=\"#cb28-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_CREAT          </span><span class=\"bn\">0x40</span></span>\n<span id=\"cb28-5\"><a href=\"#cb28-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_EXCL           </span><span class=\"bn\">0x80</span></span>\n<span id=\"cb28-6\"><a href=\"#cb28-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_NOCTTY        </span><span class=\"bn\">0x100</span></span>\n<span id=\"cb28-7\"><a href=\"#cb28-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_TRUNC         </span><span class=\"bn\">0x200</span></span>\n<span id=\"cb28-8\"><a href=\"#cb28-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_APPEND        </span><span class=\"bn\">0x400</span></span>\n<span id=\"cb28-9\"><a href=\"#cb28-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_NONBLOCK      </span><span class=\"bn\">0x800</span></span>\n<span id=\"cb28-10\"><a href=\"#cb28-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"pp\">#define O_DIRECTORY    </span><span class=\"bn\">0x4000</span></span></code></pre></div>\n<p>Finally, let\u2019s define the functions we\u2019ll use:</p>\n<div class=\"sourceCode\" id=\"cb29\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb29-1\"><a href=\"#cb29-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">ssize_t</span> close<span class=\"op\">(</span><span class=\"dt\">int</span> fd<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb29-2\"><a href=\"#cb29-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">return</span> syscall1<span class=\"op\">(</span>__NR_close<span class=\"op\">,</span> fd<span class=\"op\">);</span></span>\n<span id=\"cb29-3\"><a href=\"#cb29-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb29-4\"><a href=\"#cb29-4\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb29-5\"><a href=\"#cb29-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> fsync<span class=\"op\">(</span><span class=\"dt\">int</span> fd<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb29-6\"><a href=\"#cb29-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall1<span class=\"op\">(</span>__NR_fsync<span class=\"op\">,</span> fd<span class=\"op\">);</span></span>\n<span id=\"cb29-7\"><a href=\"#cb29-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb29-8\"><a href=\"#cb29-8\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb29-9\"><a href=\"#cb29-9\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">ssize_t</span> read<span class=\"op\">(</span><span class=\"dt\">int</span> fd<span class=\"op\">,</span> <span class=\"dt\">void</span> <span class=\"op\">*</span>buf<span class=\"op\">,</span> <span class=\"dt\">size_t</span> count<span class=\"op\">)</span></span>\n<span id=\"cb29-10\"><a href=\"#cb29-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">{</span></span>\n<span id=\"cb29-11\"><a href=\"#cb29-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall3<span class=\"op\">(</span>__NR_read<span class=\"op\">,</span> fd<span class=\"op\">,</span> buf<span class=\"op\">,</span> count<span class=\"op\">);</span></span>\n<span id=\"cb29-12\"><a href=\"#cb29-12\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb29-13\"><a href=\"#cb29-13\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb29-14\"><a href=\"#cb29-14\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> open<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>path<span class=\"op\">,</span> <span class=\"dt\">int</span> flags<span class=\"op\">,</span> mode_t mode<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb29-15\"><a href=\"#cb29-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall3<span class=\"op\">(</span>__NR_open<span class=\"op\">,</span> path<span class=\"op\">,</span> flags<span class=\"op\">,</span> mode<span class=\"op\">);</span></span>\n<span id=\"cb29-16\"><a href=\"#cb29-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span>\n<span id=\"cb29-17\"><a href=\"#cb29-17\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb29-18\"><a href=\"#cb29-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">ssize_t</span> write<span class=\"op\">(</span><span class=\"dt\">int</span> fd<span class=\"op\">,</span> <span class=\"dt\">const</span> <span class=\"dt\">void</span> <span class=\"op\">*</span>buf<span class=\"op\">,</span> <span class=\"dt\">size_t</span> count<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb29-19\"><a href=\"#cb29-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> syscall3<span class=\"op\">(</span>__NR_write<span class=\"op\">,</span> fd<span class=\"op\">,</span> buf<span class=\"op\">,</span> count<span class=\"op\">);</span></span>\n<span id=\"cb29-20\"><a href=\"#cb29-20\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And a helper function, <code>strlen</code>:</p>\n<div class=\"sourceCode\" id=\"cb30\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb30-1\"><a href=\"#cb30-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">size_t</span> strlen<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>str<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb30-2\"><a href=\"#cb30-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"dt\">size_t</span> len<span class=\"op\">;</span></span>\n<span id=\"cb30-3\"><a href=\"#cb30-3\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb30-4\"><a href=\"#cb30-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">for</span> <span class=\"op\">(</span>len <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span> str<span class=\"op\">[</span>len<span class=\"op\">];</span> len<span class=\"op\">++)</span></span>\n<span id=\"cb30-5\"><a href=\"#cb30-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>        asm<span class=\"op\">(</span><span class=\"st\">&quot;&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb30-6\"><a href=\"#cb30-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">return</span> len<span class=\"op\">;</span></span>\n<span id=\"cb30-7\"><a href=\"#cb30-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Finally, we can start writing a main function that uses this\ncode:</p>\n<div class=\"sourceCode\" id=\"cb31\"><pre class=\"sourceCode c\"><code class=\"sourceCode c\"><span id=\"cb31-1\"><a href=\"#cb31-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb31-2\"><a href=\"#cb31-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">char</span><span class=\"op\">*</span> text <span class=\"op\">=</span> <span class=\"st\">&quot;hello world</span><span class=\"sc\">\\n</span><span class=\"st\">&quot;</span><span class=\"op\">;</span> <span class=\"co\">// text to write</span></span>\n<span id=\"cb31-3\"><a href=\"#cb31-3\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write<span class=\"op\">(</span>STDOUT_FILENO<span class=\"op\">,</span> text<span class=\"op\">,</span> strlen<span class=\"op\">(</span>text<span class=\"op\">));</span> <span class=\"co\">// write text to stdout</span></span>\n<span id=\"cb31-4\"><a href=\"#cb31-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  fsync<span class=\"op\">(</span>STDOUT_FILENO<span class=\"op\">);</span> <span class=\"co\">// flush stdout</span></span>\n<span id=\"cb31-5\"><a href=\"#cb31-5\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb31-6\"><a href=\"#cb31-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">char</span><span class=\"op\">*</span> file_text <span class=\"op\">=</span> <span class=\"st\">&quot;Hello from file&quot;</span><span class=\"op\">;</span> <span class=\"co\">// text to write to file</span></span>\n<span id=\"cb31-7\"><a href=\"#cb31-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">int</span> fd <span class=\"op\">=</span> open<span class=\"op\">(</span><span class=\"st\">&quot;hello.txt&quot;</span><span class=\"op\">,</span> O_CREAT <span class=\"op\">|</span> O_TRUNC <span class=\"op\">|</span> O_RDWR<span class=\"op\">,</span> <span class=\"bn\">0666</span><span class=\"op\">);</span> <span class=\"co\">// open, truncate, create file hello.txt</span></span>\n<span id=\"cb31-8\"><a href=\"#cb31-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write<span class=\"op\">(</span>fd<span class=\"op\">,</span> file_text<span class=\"op\">,</span> strlen<span class=\"op\">(</span>file_text<span class=\"op\">));</span> <span class=\"co\">// write the file text to file</span></span>\n<span id=\"cb31-9\"><a href=\"#cb31-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  fsync<span class=\"op\">(</span>fd<span class=\"op\">);</span> <span class=\"co\">// flush hello.txt</span></span>\n<span id=\"cb31-10\"><a href=\"#cb31-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close<span class=\"op\">(</span>fd<span class=\"op\">);</span> <span class=\"co\">// close hello.txt</span></span>\n<span id=\"cb31-11\"><a href=\"#cb31-11\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb31-12\"><a href=\"#cb31-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>  fd <span class=\"op\">=</span> open<span class=\"op\">(</span><span class=\"st\">&quot;hello.txt&quot;</span><span class=\"op\">,</span> O_RDONLY<span class=\"op\">,</span> <span class=\"bn\">0666</span><span class=\"op\">);</span> <span class=\"co\">// open the file hello.txt for reading</span></span>\n<span id=\"cb31-13\"><a href=\"#cb31-13\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb31-14\"><a href=\"#cb31-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"dt\">char</span> read_from_file<span class=\"op\">[</span>strlen<span class=\"op\">(</span>file_text<span class=\"op\">)</span> <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"op\">];</span> <span class=\"co\">// the buffer to read into</span></span>\n<span id=\"cb31-15\"><a href=\"#cb31-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>  read<span class=\"op\">(</span>fd<span class=\"op\">,</span> <span class=\"op\">(</span><span class=\"dt\">void</span> <span class=\"op\">*)</span>read_from_file<span class=\"op\">,</span> strlen<span class=\"op\">(</span>file_text<span class=\"op\">));</span> <span class=\"co\">// read from hello.txt to the buffer</span></span>\n<span id=\"cb31-16\"><a href=\"#cb31-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>  read_from_file<span class=\"op\">[</span>strlen<span class=\"op\">(</span>file_text<span class=\"op\">)]</span> <span class=\"op\">=</span> <span class=\"ch\">&#39;</span><span class=\"sc\">\\n</span><span class=\"ch\">&#39;</span><span class=\"op\">;</span> <span class=\"co\">// add a new line to the buffer</span></span>\n<span id=\"cb31-17\"><a href=\"#cb31-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>  write<span class=\"op\">(</span>STDOUT_FILENO<span class=\"op\">,</span> read_from_file<span class=\"op\">,</span> strlen<span class=\"op\">(</span>read_from_file<span class=\"op\">));</span> <span class=\"co\">// write the buffer to stdout</span></span>\n<span id=\"cb31-18\"><a href=\"#cb31-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>  fsync<span class=\"op\">(</span>STDOUT_FILENO<span class=\"op\">);</span> <span class=\"co\">// flush stdout</span></span>\n<span id=\"cb31-19\"><a href=\"#cb31-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>  close<span class=\"op\">(</span>fd<span class=\"op\">);</span> <span class=\"co\">// close hello.txt</span></span>\n<span id=\"cb31-20\"><a href=\"#cb31-20\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>After compiling it as above, you should have the following text:</p>\n<div class=\"sourceCode\" id=\"cb32\"><pre\nclass=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb32-1\"><a href=\"#cb32-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">hello</span> world</span>\n<span id=\"cb32-2\"><a href=\"#cb32-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">Hello</span> from file</span></code></pre></div>\n<p>With <code>hello.txt</code> containing\n<code>Hello from file</code>.</p>\n<p>Writing some simple libc code isn\u2019t that hard!</p>\n</section>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-02-16T21:05:35+00:00"
		},
		{
			"id": "gen/a-guide-to-rss.html",
			"url": "gen/a-guide-to-rss.html",
			"title": "A Guide to RSS",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>A Guide to RSS</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">A Guide to RSS</h1>\n<p class=\"byline\">2023-02-08T08:15:00-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#setup\" id=\"toc-setup\">Setup</a></li>\n<li><a href=\"#reading-older-rss-posts\"\nid=\"toc-reading-older-rss-posts\">Reading Older RSS Posts</a></li>\n<li><a href=\"#what-about-atom\" id=\"toc-what-about-atom\">What about\nAtom?</a></li>\n<li><a href=\"#rendering-more-content-with-morss\"\nid=\"toc-rendering-more-content-with-morss\">Rendering more content with\nmorss</a></li>\n</ul>\n</nav>\n<p>At the start of the year I decided to read more quality stuff instead\nof mindlessly doom scrolling the internet. An internet diet. I believe\nin discussing tools + methods to solve problems, so here are some\nfindings I had setting up an RSS feed, reading from it, and some of the\nchallenges along the way.</p>\n<section id=\"setup\" class=\"level2\">\n<h2>Setup</h2>\n<p>If you\u2019re like me, you want a few things:</p>\n<ol type=\"1\">\n<li>Offline reading</li>\n<li>Syncing</li>\n<li>Caching</li>\n<li>Mobile + Terminal + Web + Desktop clients</li>\n</ol>\n<p>To feasibly implement syncing across multiple devices, we\u2019ll need a\nserver to host our RSS feed. I self-host <a\nhref=\"https://github.com/FreshRSS/FreshRSS\">FreshRSS</a>, which acts as\nboth a web client and the server. It allows for syncing from many\nclients, which is great, and it has an easy docker-compose file to pull\nin all necessary dependencies. FreshRSS exposes an API as well as a\nGoogle Reader compatible API, which most clients support. This supports\nauthentication, which is a nice feature for locking down your\nserver.</p>\n<p>Finally, we\u2019ll need clients that implement offline reading and heavy\ncaching for good performance, for mobile, the terminal, and the\ndesktop.</p>\n<p>I use an Samsung S10 as my phone, which runs android. The app I use\non mobile is FeedMe, hooked up to my FreshRSS server through the Google\nReader API. This heavily caches and works well offline, so on the go I\ncan read some feeds.</p>\n<p>For a desktop client, I run a linux laptop, so I use Newsflash.\nNewsflash is similar to FeedMe, with support for the Google Reader API,\nand good offline capabilities. I tried a few other services, but they\ncouldn\u2019t parse my large RSS feed.</p>\n<p>For a terminal client, I use newsboat. Newsboat is a curses-based\ntext only feed, so RSS feeds that don\u2019t send over the full article\ncontent are a bad reading experience on newsboat. To deal with this, I\nuse <code>morss</code>, which scrapes the link provided by the RSS feed,\nand then generates a new RSS feed with the content of the blog\nincluded.</p>\n<p><a href=\"https://github.com/pictuga/morss\">morss</a> can be\ndownloaded with <code>pip</code>.</p>\n<p>Now you should have everything set up, and can add some feeds to your\nserver, pull them down to your clients, and are ready to go.</p>\n<p>But what if you\u2019re new to this RSS game, and want to read some older\nposts?</p>\n</section>\n<section id=\"reading-older-rss-posts\" class=\"level2\">\n<h2>Reading Older RSS Posts</h2>\n<p>Did you know that RSS can support older posts, and that blog\nplatforms like wordpress, blogger, and blogspot have those capabilities\nbuilt in? For example, let\u2019s say I wanted to read James Clear\u2019s old\nposts. His current feed, located at\n<code>https://jamesclear.com/feed</code> has 10 of his most recent blog\nposts. But he\u2019s published 300 more.</p>\n<p>His blog actually has those old posts in RSS form for us, we just\nhave to find it.</p>\n<p>Some blog sites\u2019 RSS supports the <code>paged</code> query parameter.\n<code>paged=1</code> means the first page, and <code>paged=2</code>\nmeans the second page. In Jamesclear\u2019s case, we just have to binary\nsearch to find the last RSS feed supported by the website.</p>\n<p>We could start out at\n<code>https://jamesclear.com/feed?paged=100</code>, realize that doesn\u2019t\nwork, try <code>https://jamesclear.com/feed?paged=50</code>, realize\nthat doesn\u2019t work, go to\n<code>https://jamesclear.com/feed?paged=25</code>, see that works, and\nthen figure out the last page, which as of now is page 30.</p>\n<p>We can then download all of those rss feeds with a handy dandy bash\nscript:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">#!/usr/bin/env bash</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> num <span class=\"kw\">in</span> <span class=\"va\">$(</span><span class=\"fu\">seq</span> 1 30<span class=\"va\">)</span><span class=\"kw\">;</span> <span class=\"cf\">do</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">wget</span> <span class=\"st\">&quot;https://jamesclear.com/feed?paged=</span><span class=\"va\">$num</span><span class=\"st\">&quot;</span> <span class=\"at\">-O</span> <span class=\"va\">$num</span>.rss</span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">done</span></span></code></pre></div>\n<p>And then we can download the 30 rss feeds.</p>\n<p>We now have 30 rss feeds that have the content we want to read. But\nhaving to add 30 entries to our RSS client is a bit of a pain: let\u2019s\naggregate them.</p>\n<p>I wrote a little script that would batch these into feeds with 150\nposts each, using <code>feedgen</code> and <code>feedparser</code>.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode python\"><code class=\"sourceCode python\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">#!/usr/bin/env python3</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"im\">import</span> feedparser</span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"im\">from</span> feedgen.feed <span class=\"im\">import</span> FeedGenerator</span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"im\">from</span> glob <span class=\"im\">import</span> glob</span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>files <span class=\"op\">=</span> glob(<span class=\"st\">&#39;*.rss&#39;</span>)</span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>file_count <span class=\"op\">=</span> <span class=\"bu\">len</span>(files)</span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>file_generators <span class=\"op\">=</span> []</span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> i <span class=\"kw\">in</span> <span class=\"bu\">range</span>((file_count <span class=\"op\">//</span> <span class=\"dv\">15</span>) <span class=\"op\">+</span> <span class=\"dv\">1</span>):</span>\n<span id=\"cb2-12\"><a href=\"#cb2-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg <span class=\"op\">=</span> FeedGenerator()</span>\n<span id=\"cb2-13\"><a href=\"#cb2-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.<span class=\"bu\">id</span>(<span class=\"st\">&#39;https://jamesclear.com/&#39;</span>)</span>\n<span id=\"cb2-14\"><a href=\"#cb2-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.title(<span class=\"ss\">f&#39;James Clear Page </span><span class=\"sc\">{</span>file_count <span class=\"op\">//</span> <span class=\"dv\">15</span> <span class=\"op\">-</span> i <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"sc\">}</span><span class=\"ss\">&#39;</span>)</span>\n<span id=\"cb2-15\"><a href=\"#cb2-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.link(href<span class=\"op\">=</span><span class=\"st\">&#39;https://jamesclear.com/&#39;</span>)</span>\n<span id=\"cb2-16\"><a href=\"#cb2-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.author( {<span class=\"st\">&#39;name&#39;</span>:<span class=\"st\">&#39;James Clear&#39;</span>,<span class=\"st\">&#39;email&#39;</span>:<span class=\"st\">&#39;jamesclear@gmail.com&#39;</span>} )</span>\n<span id=\"cb2-17\"><a href=\"#cb2-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.link(href<span class=\"op\">=</span><span class=\"st\">&#39;https://jamesclear.com/&#39;</span>, rel<span class=\"op\">=</span><span class=\"st\">&#39;alternate&#39;</span> )</span>\n<span id=\"cb2-18\"><a href=\"#cb2-18\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.logo(<span class=\"st\">&#39;https://jamesclear.com/favicon.ico&#39;</span>)</span>\n<span id=\"cb2-19\"><a href=\"#cb2-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.subtitle(<span class=\"st\">&#39;An Easy &amp; Proven Way to Build Good Habits &amp; Break Bad Ones&#39;</span>)</span>\n<span id=\"cb2-20\"><a href=\"#cb2-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.link(href<span class=\"op\">=</span><span class=\"st\">&#39;https://jamesclear.com/feed&#39;</span>, rel<span class=\"op\">=</span><span class=\"st\">&#39;self&#39;</span> )</span>\n<span id=\"cb2-21\"><a href=\"#cb2-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.language(<span class=\"st\">&#39;en&#39;</span>)</span>\n<span id=\"cb2-22\"><a href=\"#cb2-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>    file_generators.append(fg)</span>\n<span id=\"cb2-23\"><a href=\"#cb2-23\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-24\"><a href=\"#cb2-24\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> index, file_name <span class=\"kw\">in</span> <span class=\"bu\">enumerate</span>(files):</span>\n<span id=\"cb2-25\"><a href=\"#cb2-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>    file_generator_index <span class=\"op\">=</span> index <span class=\"op\">//</span> <span class=\"dv\">15</span></span>\n<span id=\"cb2-26\"><a href=\"#cb2-26\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">with</span> <span class=\"bu\">open</span>(file_name) <span class=\"im\">as</span> f:</span>\n<span id=\"cb2-27\"><a href=\"#cb2-27\" aria-hidden=\"true\" tabindex=\"-1\"></a>        xml <span class=\"op\">=</span> f.read()</span>\n<span id=\"cb2-28\"><a href=\"#cb2-28\" aria-hidden=\"true\" tabindex=\"-1\"></a>        d <span class=\"op\">=</span> feedparser.parse(xml)</span>\n<span id=\"cb2-29\"><a href=\"#cb2-29\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">for</span> entry <span class=\"kw\">in</span> d.entries:</span>\n<span id=\"cb2-30\"><a href=\"#cb2-30\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe <span class=\"op\">=</span> file_generators[file_generator_index].add_entry()</span>\n<span id=\"cb2-31\"><a href=\"#cb2-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.<span class=\"bu\">id</span>(entry[<span class=\"st\">&#39;link&#39;</span>])</span>\n<span id=\"cb2-32\"><a href=\"#cb2-32\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.title(entry[<span class=\"st\">&#39;title&#39;</span>])</span>\n<span id=\"cb2-33\"><a href=\"#cb2-33\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.link(href<span class=\"op\">=</span>entry[<span class=\"st\">&#39;link&#39;</span>])</span>\n<span id=\"cb2-34\"><a href=\"#cb2-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.content(entry[<span class=\"st\">&#39;content&#39;</span>][<span class=\"dv\">0</span>][<span class=\"st\">&#39;value&#39;</span>])</span>\n<span id=\"cb2-35\"><a href=\"#cb2-35\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.description(entry[<span class=\"st\">&#39;summary&#39;</span>])</span>\n<span id=\"cb2-36\"><a href=\"#cb2-36\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.author(entry[<span class=\"st\">&#39;authors&#39;</span>][<span class=\"dv\">0</span>])</span>\n<span id=\"cb2-37\"><a href=\"#cb2-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.guid(entry[<span class=\"st\">&#39;link&#39;</span>])</span>\n<span id=\"cb2-38\"><a href=\"#cb2-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>            fe.pubDate(entry[<span class=\"st\">&#39;published&#39;</span>])</span>\n<span id=\"cb2-39\"><a href=\"#cb2-39\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-40\"><a href=\"#cb2-40\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> index, fg <span class=\"kw\">in</span> <span class=\"bu\">enumerate</span>(<span class=\"bu\">reversed</span>(file_generators)):</span>\n<span id=\"cb2-41\"><a href=\"#cb2-41\" aria-hidden=\"true\" tabindex=\"-1\"></a>    fg.rss_file(<span class=\"ss\">f&quot;../site/james-clear-</span><span class=\"sc\">{</span>index <span class=\"op\">+</span> <span class=\"dv\">1</span><span class=\"sc\">}</span><span class=\"ss\">.rss&quot;</span>)</span></code></pre></div>\n<p>We can then aggregate these rss feeds into two rss feeds, and then\nput them in a folder. I host my RSS feeds on the web using netlify,\n<code>https://takashis-rss.netlify.app/</code> so that my RSS server can\npull these feeds and get the content from them.</p>\n<p>You can use any web hosting service you like, or self-host it. It\u2019s\nup to you, it just needs to be online for the RSS server to be able to\npull down.</p>\n</section>\n<section id=\"what-about-atom\" class=\"level2\">\n<h2>What about Atom?</h2>\n<p>Not all feeds are RSS feeds, some are Atom feeds. Take\nhttps://blog.computationalcomplexity.org/ for example. Atom doesn\u2019t\nsupport the <code>paged</code> query parameter. But it supports\nsomething even better. We\u2019ll first download their feed at\nhttps://blog.computationalcomplexity.org/feeds/posts/default and open it\nup in a text editor. Inside, we should be able to find that it has 2980\narticles, and they can be queried with a different query paramter,\ncalled <code>start-index</code>.</p>\n<p>So\nhttps://blog.computationalcomplexity.org/feeds/posts/default?start-index=100\nfetches the 100th - 125th blog post. We want to do this until we hit the\n2980th article:</p>\n<p>To do that, we edit the previous script a bit:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">#!/usr/bin/env bash</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> num <span class=\"kw\">in</span> <span class=\"va\">$(</span><span class=\"fu\">seq</span> 1 25 2980<span class=\"va\">)</span><span class=\"kw\">;</span> <span class=\"cf\">do</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">wget</span> <span class=\"st\">&quot;https://blog.computationalcomplexity.org/feeds/posts/default?start-index=</span><span class=\"va\">$num</span><span class=\"st\">&quot;</span> <span class=\"at\">-O</span> <span class=\"va\">$num</span>.rss</span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">done</span></span></code></pre></div>\n<p>And we can fetch all the posts, and aggregate them much the same way\nas above.</p>\n</section>\n<section id=\"rendering-more-content-with-morss\" class=\"level2\">\n<h2>Rendering more content with morss</h2>\n<p>This is good enough for some feeds, but some feeds only show a little\nbit of content, which is undesirable for terminal readers like\n<code>newsboat</code>, which don\u2019t fetch the entire article, just the\nRSS content.</p>\n<p>We can download <code>morss</code> with <code>pip</code> and run this\nscript, which renders the feed with a web browser and scrapes it into an\nRSS feed.</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">#!/usr/bin/env bash</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> num <span class=\"kw\">in</span> <span class=\"va\">$(</span><span class=\"fu\">seq</span> 1 37<span class=\"va\">)</span><span class=\"kw\">;</span> <span class=\"cf\">do</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"va\">LIM_ITEM</span><span class=\"op\">=</span>-1 <span class=\"va\">MAX_ITEM</span><span class=\"op\">=</span>-1 <span class=\"ex\">morss</span> <span class=\"st\">&quot;https://travelfreak.com/feed?paged=</span><span class=\"va\">$num</span><span class=\"st\">&quot;</span> <span class=\"op\">&gt;</span> <span class=\"va\">$num</span>.rss</span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">done</span></span></code></pre></div>\n<p>This lets us get around those pesky feeds with no content and just a\nlink.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-02-08T13:15:00+00:00"
		},
		{
			"id": "gen/how-to-index-your-library.html",
			"url": "gen/how-to-index-your-library.html",
			"title": "How to index your library",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>How to index your library</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">How to index your library</h1>\n<p class=\"byline\">2023-01-23T08:34:32-05:00</p>\n</header>\n<p>Books are nice. They make transferring knowledge easy, and are a way\nto record things for the future. What\u2019s not nice is searching through\nthem. Who uses a glossary nowadays?</p>\n<p>Another problem: my collection of books is too large to put in my\ntiny apartment:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> find . <span class=\"at\">-type</span> f <span class=\"at\">-name</span> <span class=\"st\">&quot;*.pdf&quot;</span> <span class=\"kw\">|</span> <span class=\"fu\">wc</span> <span class=\"at\">-l</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">223</span></span></code></pre></div>\n<p>But if I have these books, I might as well index them, so I can\nsearch for them quickly:</p>\n<p>First, since pdfs are binary, we\u2019ll have to extract their textual\ncontent to a file:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\">#!/usr/bin/env bash</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">title_case()</span> <span class=\"kw\">{</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">sed</span> <span class=\"st\">&#39;s/.*/\\L&amp;/; s/[a-z]*/\\u&amp;/g&#39;</span> <span class=\"op\">&lt;&lt;&lt;</span> <span class=\"va\">$1</span> <span class=\"kw\">|</span> <span class=\"fu\">tr</span> <span class=\"st\">&#39;-&#39;</span> <span class=\"st\">&#39; &#39;</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"kw\">}</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">for</span> f <span class=\"kw\">in</span> <span class=\"va\">$(</span><span class=\"fu\">find</span> . <span class=\"at\">-type</span> f <span class=\"at\">-name</span> <span class=\"st\">&quot;*.pdf&quot;</span><span class=\"va\">)</span><span class=\"kw\">;</span> <span class=\"cf\">do</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"va\">based_name</span><span class=\"op\">=</span><span class=\"va\">$(</span><span class=\"fu\">basename</span> <span class=\"va\">$f</span> .pdf<span class=\"va\">)</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"va\">txt_name</span><span class=\"op\">=</span><span class=\"st\">&quot;</span><span class=\"va\">${f</span><span class=\"op\">%</span>.<span class=\"pp\">*</span><span class=\"va\">}</span><span class=\"st\">.txt&quot;</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">if</span> <span class=\"kw\">[[</span> <span class=\"ot\">-f</span> <span class=\"st\">&quot;</span><span class=\"va\">$txt_name</span><span class=\"st\">&quot;</span> <span class=\"kw\">]];</span> <span class=\"cf\">then</span></span>\n<span id=\"cb2-11\"><a href=\"#cb2-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"bu\">echo</span> <span class=\"st\">&quot;</span><span class=\"va\">$txt_name</span><span class=\"st\"> exists.&quot;</span></span>\n<span id=\"cb2-12\"><a href=\"#cb2-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">continue</span></span>\n<span id=\"cb2-13\"><a href=\"#cb2-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">fi</span></span>\n<span id=\"cb2-14\"><a href=\"#cb2-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"ex\">pdftotext</span> <span class=\"va\">$f</span></span>\n<span id=\"cb2-15\"><a href=\"#cb2-15\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"va\">title_cased_name</span><span class=\"op\">=</span><span class=\"va\">$(</span><span class=\"ex\">title_case</span> <span class=\"va\">$based_name)</span></span>\n<span id=\"cb2-16\"><a href=\"#cb2-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"bu\">echo</span> <span class=\"at\">-e</span> <span class=\"st\">&quot;</span><span class=\"va\">$title_cased_name</span><span class=\"st\">\\n\\n&quot;</span> <span class=\"kw\">|</span> <span class=\"fu\">cat</span> <span class=\"at\">-</span> <span class=\"va\">$txt_name</span> <span class=\"kw\">|</span> <span class=\"ex\">sponge</span> <span class=\"va\">$txt_name</span></span>\n<span id=\"cb2-17\"><a href=\"#cb2-17\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">done</span></span></code></pre></div>\n<p>Next, we have to index the actual content. To do that, we\u2019ll put our\ntext content into a search engine, like <a\nhref=\"https://github.com/valeriansaliou/sonic\">sonic</a>.</p>\n<p>Grab the binary and set it up.</p>\n<p>Next, we\u2019ll grab a client to pass data to sonic:</p>\n<p>Create a Gemfile in a directory:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode rb\"><code class=\"sourceCode ruby\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"></a>source <span class=\"vs\">&#39;https://rubygems.org&#39;</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"></a>gem <span class=\"vs\">&#39;sonic-ruby&#39;</span></span></code></pre></div>\n<p>Bundle install the gem:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> bundle install</span></code></pre></div>\n<p>Next, create a file called <code>ingest.rb</code>. This will ingest\nyour textual data:</p>\n<p>Since the client I\u2019m using right now doesn\u2019t have throttling, it\ncauses a panic caused by a buffer overflow on the search engine by\nshoving too much data too quickly. To fix this, I overwrite that method\nin the file and use it.</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode rb\"><code class=\"sourceCode ruby\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">require</span> <span class=\"vs\">&#39;sonic-ruby&#39;</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">module</span> <span class=\"dt\">Sonic</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">module</span> <span class=\"dt\">Channels</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"fu\">refine</span> <span class=\"dt\">Ingest</span> <span class=\"cf\">do</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">def</span> push(collection, bucket, object, text, lang <span class=\"kw\">=</span> <span class=\"dv\">nil</span>)</span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"fu\">puts</span> <span class=\"st\">&quot;processing </span><span class=\"sc\">#{</span>object<span class=\"sc\">}</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\" tabindex=\"-1\"></a>        text_size <span class=\"kw\">=</span> text<span class=\"at\">.size</span></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\" tabindex=\"-1\"></a>        text <span class=\"kw\">=</span> text<span class=\"at\">.encode</span>(<span class=\"vs\">&#39;UTF-8&#39;</span>, <span class=\"wa\">:invalid</span> <span class=\"kw\">=&gt;</span> <span class=\"wa\">:replace</span>, <span class=\"wa\">:undef</span> <span class=\"kw\">=&gt;</span> <span class=\"wa\">:replace</span>)</span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\" tabindex=\"-1\"></a>        right <span class=\"kw\">=</span> <span class=\"dv\">5000</span></span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>        left <span class=\"kw\">=</span> <span class=\"dv\">0</span></span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"fu\">loop</span> <span class=\"cf\">do</span></span>\n<span id=\"cb5-13\"><a href=\"#cb5-13\" aria-hidden=\"true\" tabindex=\"-1\"></a>          <span class=\"cf\">break</span> <span class=\"cf\">if</span> right <span class=\"kw\">&gt;</span> text_size</span>\n<span id=\"cb5-14\"><a href=\"#cb5-14\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-15\"><a href=\"#cb5-15\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-16\"><a href=\"#cb5-16\" aria-hidden=\"true\" tabindex=\"-1\"></a>          arr <span class=\"kw\">=</span> <span class=\"kw\">[</span>collection, bucket, object, quote(text<span class=\"kw\">[</span>left<span class=\"kw\">...</span>right<span class=\"kw\">]</span><span class=\"at\">.gsub</span>(<span class=\"ch\">&#39;&quot;&#39;</span>, <span class=\"vs\">&#39;&#39;</span>))<span class=\"kw\">]</span></span>\n<span id=\"cb5-17\"><a href=\"#cb5-17\" aria-hidden=\"true\" tabindex=\"-1\"></a>          arr <span class=\"kw\">&lt;&lt;</span> <span class=\"st\">&quot;LANG(</span><span class=\"sc\">#{</span>lang<span class=\"sc\">}</span><span class=\"st\">)&quot;</span> <span class=\"cf\">if</span> lang</span>\n<span id=\"cb5-18\"><a href=\"#cb5-18\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-19\"><a href=\"#cb5-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>          execute(<span class=\"vs\">&#39;PUSH&#39;</span>, <span class=\"kw\">*</span>arr)</span>\n<span id=\"cb5-20\"><a href=\"#cb5-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>          right <span class=\"kw\">+=</span> <span class=\"dv\">5000</span></span>\n<span id=\"cb5-21\"><a href=\"#cb5-21\" aria-hidden=\"true\" tabindex=\"-1\"></a>          left <span class=\"kw\">+=</span> <span class=\"dv\">5000</span></span>\n<span id=\"cb5-22\"><a href=\"#cb5-22\" aria-hidden=\"true\" tabindex=\"-1\"></a>        <span class=\"cf\">end</span></span>\n<span id=\"cb5-23\"><a href=\"#cb5-23\" aria-hidden=\"true\" tabindex=\"-1\"></a>      <span class=\"cf\">end</span></span>\n<span id=\"cb5-24\"><a href=\"#cb5-24\" aria-hidden=\"true\" tabindex=\"-1\"></a>    <span class=\"cf\">end</span></span>\n<span id=\"cb5-25\"><a href=\"#cb5-25\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"cf\">end</span></span>\n<span id=\"cb5-26\"><a href=\"#cb5-26\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">end</span></span>\n<span id=\"cb5-27\"><a href=\"#cb5-27\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-28\"><a href=\"#cb5-28\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">using</span> <span class=\"dt\">Sonic</span><span class=\"kw\">::</span><span class=\"dt\">Channels</span></span>\n<span id=\"cb5-29\"><a href=\"#cb5-29\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-30\"><a href=\"#cb5-30\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># Connect to the Sonic server on localhost:1491</span></span>\n<span id=\"cb5-31\"><a href=\"#cb5-31\" aria-hidden=\"true\" tabindex=\"-1\"></a>client <span class=\"kw\">=</span> <span class=\"dt\">Sonic</span><span class=\"kw\">::</span><span class=\"dt\">Client</span><span class=\"at\">.new</span>(<span class=\"vs\">&#39;localhost&#39;</span>, <span class=\"dv\">1491</span>, <span class=\"vs\">&#39;SecretPassword&#39;</span>)</span>\n<span id=\"cb5-32\"><a href=\"#cb5-32\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-33\"><a href=\"#cb5-33\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># Connect to the ingest channel</span></span>\n<span id=\"cb5-34\"><a href=\"#cb5-34\" aria-hidden=\"true\" tabindex=\"-1\"></a>ingest <span class=\"kw\">=</span> client<span class=\"at\">.channel</span>(<span class=\"wa\">:ingest</span>)</span>\n<span id=\"cb5-35\"><a href=\"#cb5-35\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb5-36\"><a href=\"#cb5-36\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"dt\">Dir</span><span class=\"at\">.glob</span>(<span class=\"st\">&quot;$PATH_TO_FILES/**/*.txt&quot;</span>) <span class=\"cf\">do</span> <span class=\"kw\">|</span>f<span class=\"kw\">|</span></span>\n<span id=\"cb5-37\"><a href=\"#cb5-37\" aria-hidden=\"true\" tabindex=\"-1\"></a>  pdf_name <span class=\"kw\">=</span> f<span class=\"kw\">[</span><span class=\"dv\">0</span><span class=\"kw\">..-</span><span class=\"dv\">3</span><span class=\"kw\">]</span> <span class=\"kw\">+</span> <span class=\"vs\">&#39;pdf&#39;</span></span>\n<span id=\"cb5-38\"><a href=\"#cb5-38\" aria-hidden=\"true\" tabindex=\"-1\"></a>  text <span class=\"kw\">=</span> <span class=\"cn\">IO</span><span class=\"at\">.read</span>(f)</span>\n<span id=\"cb5-39\"><a href=\"#cb5-39\" aria-hidden=\"true\" tabindex=\"-1\"></a>  ingest<span class=\"at\">.push</span>(<span class=\"vs\">&#39;books&#39;</span>, <span class=\"vs\">&#39;all&#39;</span>, pdf_name, text)</span>\n<span id=\"cb5-40\"><a href=\"#cb5-40\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">end</span></span></code></pre></div>\n<p>Run that script with:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">ruby</span> ingest.rb</span></code></pre></div>\n<p>And then lets get searching! Create this file as\n<code>search.rb</code>:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode rb\"><code class=\"sourceCode ruby\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">require</span> <span class=\"vs\">&#39;sonic-ruby&#39;</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">if</span> <span class=\"cn\">ARGV</span><span class=\"at\">.length</span> !<span class=\"kw\">=</span> <span class=\"dv\">1</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">puts</span> <span class=\"st\">&quot;Too many names ... or not enough name?&quot;</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">exit</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">else</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\" aria-hidden=\"true\" tabindex=\"-1\"></a>  name <span class=\"kw\">=</span> <span class=\"cn\">ARGV</span><span class=\"kw\">[</span><span class=\"dv\">0</span><span class=\"kw\">]</span></span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">end</span></span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># Connect to the Sonic server on localhost:1491</span></span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\" aria-hidden=\"true\" tabindex=\"-1\"></a>client <span class=\"kw\">=</span> <span class=\"dt\">Sonic</span><span class=\"kw\">::</span><span class=\"dt\">Client</span><span class=\"at\">.new</span>(<span class=\"vs\">&#39;localhost&#39;</span>, <span class=\"dv\">1491</span>, <span class=\"vs\">&#39;SecretPassword&#39;</span>)</span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># Connect to the search channel</span></span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\" aria-hidden=\"true\" tabindex=\"-1\"></a>search <span class=\"kw\">=</span> client<span class=\"at\">.channel</span>(<span class=\"wa\">:search</span>)</span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-16\"><a href=\"#cb7-16\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"fu\">puts</span> <span class=\"st\">&quot;searching for </span><span class=\"sc\">#{</span>name<span class=\"sc\">}</span><span class=\"st\">&quot;</span></span>\n<span id=\"cb7-17\"><a href=\"#cb7-17\" aria-hidden=\"true\" tabindex=\"-1\"></a></span>\n<span id=\"cb7-18\"><a href=\"#cb7-18\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"co\"># Search for a matching name and return ID</span></span>\n<span id=\"cb7-19\"><a href=\"#cb7-19\" aria-hidden=\"true\" tabindex=\"-1\"></a>search<span class=\"at\">.query</span>(<span class=\"vs\">&#39;books&#39;</span>, <span class=\"vs\">&#39;all&#39;</span>, name, <span class=\"dv\">100</span>)<span class=\"at\">.split</span>(<span class=\"ch\">&#39; &#39;</span>)<span class=\"at\">.each</span> <span class=\"cf\">do</span> <span class=\"kw\">|</span>doc<span class=\"kw\">|</span></span>\n<span id=\"cb7-20\"><a href=\"#cb7-20\" aria-hidden=\"true\" tabindex=\"-1\"></a>  <span class=\"fu\">puts</span> doc</span>\n<span id=\"cb7-21\"><a href=\"#cb7-21\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"cf\">end</span></span></code></pre></div>\n<p>And then run a search:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre class=\"sourceCode sh\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">$</span> ruby search.rb <span class=\"st\">&quot;Oysters&quot;</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">searching</span> for Oysters</span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">/books/programming-languages/python/effective-python.pdf</span></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">/books/math/probability-theory-the-logic-of-science.pdf</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\" aria-hidden=\"true\" tabindex=\"-1\"></a><span class=\"ex\">/books/algorithms/programming-pearls.pdf</span></span></code></pre></div>\n<p>And that\u2019s it. How to index your books in 15 minutes or less,\nguaranteed or your money back.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-01-23T13:34:32+00:00"
		},
		{
			"id": "gen/recommended-resources.html",
			"url": "gen/recommended-resources.html",
			"title": "Recommended Resources",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Recommended Resources</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Recommended Resources</h1>\n<p class=\"byline\">2023-01-18T21:39:20-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#papers\" id=\"toc-papers\">Papers</a></li>\n<li><a href=\"#links\" id=\"toc-links\">Links</a></li>\n<li><a href=\"#courses\" id=\"toc-courses\">Courses</a></li>\n<li><a href=\"#books\" id=\"toc-books\">Books</a></li>\n<li><a href=\"#utilities\" id=\"toc-utilities\">Utilities</a></li>\n</ul>\n</nav>\n<p>Here\u2019s a list of resources I enjoyed, with a few comments.</p>\n<section id=\"papers\" class=\"level2\">\n<h2>Papers</h2>\n<ul>\n<li><a\nhref=\"https://www.cs.utexas.edu/users/mckinley/papers/asplos-2000.pdf\">Hoard:\nA Scalable Memory Allocator for Multithreaded Applications</a>: Hoard is\na parallel memory allocator that avoids fragmentation and false sharing\nby hoarding memory from the single-threaded system memory allocators and\ngiving it out in parallel for better performance.</li>\n<li><a href=\"https://dl.acm.org/doi/pdf/10.1145/358549.358561\">The\nEmperor\u2019s Old Clothes</a>: Hoare, of quicksort and ALGOL fame, explains\nwhy simplicitly is a virtue, and how a committee can destroy a language.\nHe mentions how bounds checking was implemented in ALGOL, and\ncomposition allowed it to grow to become a simple yet powerful\nlanguage.</li>\n<li><a\nhref=\"https://www.cs.virginia.edu/~evans/cs655/readings/steele.pdf\">Growing\na Language</a>: A paper about how to build a language to grow \u2013 a\nlanguage should be flexible, have a welcoming community, have generics\nand operator overloading, and worse is better.</li>\n<li><a\nhref=\"http://alexander.shen.free.fr/library/Kolmogorov65_Three-Approaches-to-Information.pdf\">Three\nApproaches to the Quantitative Definition of Information</a>: This paper\nformulates what\u2019s now called Kolmogorov complexity, which states that\nthe entropy of an object is determined by the smallest possible\nprogramming language that can express said information. This explains\ncompression, signal processing, and many other things in CS in just 5\npages.</li>\n<li><a href=\"https://cseweb.ucsd.edu/~wgg/smli_ps-1.pdf\">Technology and\nCourage</a>: A paper by technology pioneer, Ivan Sutherland, who was on\nthe team at MIT who built the first tablet. This paper goes into his\nhigh level thoughts about business, software, and life.</li>\n<li><a\nhref=\"https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf\">Reflections\non Trusting Trust</a>: A classic paper on how software isn\u2019t really\ntrustable unless you examine both the tools to build it and the code\nitself. This paper was surprisngly prescient, given the security\nproblems we have now with software.</li>\n<li><a href=\"https://ieeexplore.ieee.org/document/1291819\">Hazard\nPointers: Safe Memory Reclamation for Lock-Free Objects</a>: It was\nthought for a long time that garbage collection was a prerequisite to\nfast concurrent data structures, due to the lack of efficient\nbookkeeping for when to free parts of a data structure correctly. This\npaper discusses hazard pointers, a way to mark parts of a data structure\nas freeable even without garbage collection.</li>\n<li><a\nhref=\"https://people.csail.mit.edu/shanir/publications/Lazy_Concurrent.pdf\">A\nLazy Concurrent List-Based Set Algorithm</a>: This paper details\nconcurrent Skip Lists, which was implemented in the java collections\nlibrary in Java 1.6.</li>\n<li><a\nhref=\"http://www.usenix.org/events/hotos03/tech/full_papers/candea/candea.pdf\">Crash\nOnly Software</a>: A paper on explaining why crash-only software is\ngood, and a classification of such software.</li>\n<li><a href=\"https://arxiv.org/pdf/1603.06549.pdf\">Better bitmap\nperformance with Roaring bitmaps</a>: Roaring bitmaps, a faster data\nstructure and more storage efficient data structure for bitmaps, by\nusing both run-length encoding and array packing.</li>\n<li><a href=\"https://hypirion.com/pdf/RMTrees.pdf\">RRB-Trees: Efficient\nImmutable Vectors</a>: RRB-Trees, the Relaxed Radix Balanced Tree, is a\npurely functional data structure that is an improved version of the\nHAMT, the Hash Array Mapped Trie, which is the vector data structure in\nScala and Clojure.</li>\n<li><a href=\"https://people.csail.mit.edu/rivest/pubs/BFPRT73.pdf\">Time\nBounds for Selection</a>: A paper that explains the <code>PICK</code>\nselection algorithm, which can select the ith smallest of n numbers in\nO(n) time. This algorithm is more commonly known as quickselect.</li>\n<li><a\nhref=\"https://academic.oup.com/comjnl/article-pdf/5/1/10/1111445/050010.pdf\">Quicksort</a>:\nA paper that explains the classic quicksort algorithm, the first O(n log\nn) sorting algorithm that took sublinear memory.</li>\n<li><a\nhref=\"https://web.mit.edu/Saltzer/www/publications/endtoend/endtoend.pdf\">End\nto End Arguments in System Design</a>: A paper on a design principle,\nthe \u201cEnd to End\u201d argument, that explains why having functionality at the\nlower levels of a system may be redundant or useless compared to putting\nthem at a higher level of a system.</li>\n<li><a href=\"https://arxiv.org/abs/2106.05123\">Pattern Defeating\nQuicksort</a>: A sorting algorithm for the Dutch National flag problem,\nwhich can solve it in O(nk) time. This is the current unstable sort\nalgorithm in rust, with an ~5-10% better performance over the current\nrust stable sort, timsort.</li>\n</ul>\n</section>\n<section id=\"links\" class=\"level2\">\n<h2>Links</h2>\n<ul>\n<li><a href=\"https://beej.us/guide/bgnet/html/\">Beej\u2019s Guide to Network\nProgramming</a> Learn how to program network sockets in C.</li>\n</ul>\n</section>\n<section id=\"courses\" class=\"level2\">\n<h2>Courses</h2>\n<ul>\n<li><a\nhref=\"https://ocw.mit.edu/courses/6-172-performance-engineering-of-software-systems-fall-2018/\">MIT\nPerformance Engineering of Software Systems</a>: A good course to learn\nmore about computer architecture and what\u2019s going on under the hood when\nyou execute code.</li>\n<li><a\nhref=\"https://www.cs.umd.edu/class/fall2022/cmsc430/index.html\">Design\nand Implementation of Programming Languages</a>: A course that\nincrementally introduces compilers, by implementing a compiler that\nemits x86 assembly.</li>\n<li><a href=\"https://web.stanford.edu/class/cs168/index.html\">The Modern\nAlgorithmic Toolbox</a>: A course that thoroughly explains useful\nalgorithms and what they can be used for, with lots of real world\nexamples.</li>\n<li><a\nhref=\"https://15445.courses.cs.cmu.edu/fall2019/schedule.html\">Database\nSystems</a>: A course all about databases, explaining algorithms and\ndata structures for indexes, storage, logging, locking, and concurrency\nprotocols, like MVCC and 2PL.</li>\n</ul>\n</section>\n<section id=\"books\" class=\"level2\">\n<h2>Books</h2>\n<ul>\n<li><a\nhref=\"https://www.amazon.com/ARM-System-Developers-Guide-Architecture/dp/1558608745\">ARM\nSystem Developer\u2019s Guide</a>: Details the ARM ISA. A bit dated at this\npoint, but covers the fundamentals.</li>\n<li><a\nhref=\"https://www.amazon.com/Algorithms-Data-Structures-Massive-Datasets/dp/1617298034\">Algorithms\nand Data Structures for Massive Datasets</a>: Algorithms and data\nstructures that scale to meet the demands of large datasets.</li>\n<li><a href=\"https://en.algorithmica.org/hpc/\">Algorithms for Modern\nHardware</a>: A great resource for learning about performance\nengineering.</li>\n<li><a\nhref=\"https://www.amazon.com/Antifragile-Things-That-Disorder-Incerto/dp/0812979680\">Antifragile</a>:\nA sequel to the Black Swan, focusing on things that get stronger when\nput under stress, and how to build systems that do the same.</li>\n<li><a\nhref=\"https://www.amazon.com/Behind-Deep-Blue-Building-Computer/dp/0691118183\">Behind\nDeep Blue</a>: A book about the team that built deep blue, the first\ncomputer to defeat the world chess champion.</li>\n<li><a\nhref=\"https://www.amazon.com/Algorithms-Data-Structures-Massive-Datasets/dp/1617298034\">Computational\nGeometry</a>: a book that looks at algorithms geometrically. There\u2019s\nsections on calculating nearest neighbors, object collision, mapping\nalgorithms, dimension reduction, graphs, and even querying a database. I\ndidn\u2019t know computational geometry had so many applications!</li>\n<li><a href=\"https://craftinginterpreters.com/\">Crafting\nInterpreters</a>: Learn about compilers by implementing two interpreters\nfor a full featured language named lox.</li>\n<li><a href=\"https://www.databass.dev/\">Database Internals: A Deep\nDive</a>: A book that teaches databases in two parts: storage engines,\nand then as distributed databases.</li>\n<li><a\nhref=\"https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321\">Designing\nData Driven Databases</a>: The best book for learning about distributed\nsystems.</li>\n<li><a href=\"https://gameprogrammingpatterns.com/\">Game Programming\nPatterns</a>: A book about Design Patterns for game development. The\nexamples are in C++, and focused on games, but can be applied to many\ndomains outside of it.</li>\n<li><a\nhref=\"https://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/1449314287\">High\nPerformance MySQL</a>: Learn about how to use and deploy MySQL, while\nsqueezing as much performance as possible while dodging pitfalls.</li>\n<li><a\nhref=\"http://www.irrationalexuberance.com/main.html?src=%2F\">Irrational\nExuberance</a>: A book about economic bubbles and regression to the\nmean.</li>\n<li><a\nhref=\"https://www.amazon.com/Kill-Fire-Manage-Computer-Systems/dp/1718501188\">Kill\nit with Fire</a>: explains how to maintain and extend legacy systems,\nwith notes on leading teams and driving change.</li>\n<li><a href=\"http://learnyouahaskell.com/\">Learn you a Haskell for Great\nGood!</a>: An introduction to haskell, a statically and strongly typed\nfunctional programming language.</li>\n<li><a href=\"https://learnyousomeerlang.com/\">Learn you some Erlang for\nGreat Good!</a>: An introductory book to Erlang/OTP, a functional\nprogramming language with lots of libraries suited for web\nprogramming.</li>\n<li><a\nhref=\"https://www.amazon.com/Kill-Fire-Manage-Computer-Systems/dp/1718501188\">Meditations</a>:\nA classic book by Marcus Aurelius on the stoic philosophy, with gems\nthat still ring true today.</li>\n<li><a href=\"https://pages.cs.wisc.edu/~remzi/OSTEP/\">Operating Systems,\nThree Easy Pieces</a>: A book that tackles teaching operating systems in\nthree pieces: virtualization, concurrency, and persistence.</li>\n<li><a\nhref=\"https://www.amazon.com/Probabilistic-Data-Structures-Algorithms-Applications/dp/3748190484\">Probabilistic\nData Structures and Algorithms for Big Data Applications</a>: A book on\nprobabilistic data structures that are useful for big data. The six\nchapters cover many data structures for each problem.</li>\n<li><a\nhref=\"https://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880\">Programming\nPearls</a>: Algorithms and data structures that Jon Bentely, the creator\nof kd-trees explains in succint prose. There\u2019s a lot of great exercises\nand the author\u2019s storytelling makes the book an entertaining and fast\nread.</li>\n<li><a\nhref=\"https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321\">Proofs:\nA long form Mathematics Textbook</a>: An approachable book on proofs\nwith lots of problems and stories. Proofs and being able to read\nmathematical notation are much more useful than I would\u2019ve thought.</li>\n<li><a\nhref=\"https://www.amazon.com/Purely-Functional-Data-Structures-Okasaki/dp/0521663504\">Purely\nFunctional Data Structures</a>: A book on data structures for functional\nlanguages, like SML.</li>\n<li><a href=\"https://sql-performance-explained.com/\">SQL Performance\nExplained</a>: The book that made indexes click for me, with\naccompanying SQL code in many dialects of SQL, like SQL Server, Oracle,\nMySQL, and Postgres.</li>\n<li><a\nhref=\"https://www.amazon.com/Probabilistic-Data-Structures-Algorithms-Applications/dp/3748190484\">Seven\nConcurrency Models in Seven Weeks</a>: concurrency models in many\ndifferent languages, including java, clojure, and erlang, and how they\ndiffer, with quick explanations on the pros and cons of each.</li>\n<li><a\nhref=\"https://www.amazon.com/Probabilistic-Data-Structures-Algorithms-Applications/dp/3748190484\">Seven\nDatabases in Seven Weeks</a>: a whirlwind tour of some common NoSQL\ndatabases, like Redis, Neo4j, DynamoDB, and Hbase.</li>\n<li><a\nhref=\"https://www.brendangregg.com/blog/2020-07-15/systems-performance-2nd-edition.html\">Systems\nPerformance: Enterprise and the Cloud</a>: Learn how to profile and\nimprove performance and observability of systems. A must have for\nanybody learning in a big tech company.</li>\n<li><a\nhref=\"https://www.amazon.com/Art-Multiprocessor-Programming-Revised-Reprint/dp/0123973376\">The\nArt of Multiprocessor Programming</a>: A book that goes into great depth\nabout concurrent programming, with thorough exercises.</li>\n<li><a\nhref=\"https://www.amazon.com/Black-Swan-Improbable-Robustness-Fragility/dp/081297381X\">The\nBlack Swan</a>: An options trader explains why outlier events are\nactually quite common and hard to hedge against. I picked this up for\nthe nod to Popper, but stayed for the thoughts on the market.</li>\n<li><a\nhref=\"https://www.amazon.com/Innovators-Dilemma-Revolutionary-Change-Business/dp/0062060244\">The\nInnovator\u2019s Dilemma</a>: How companies adjust (and don\u2019t adjust) to\nchange, and how incumbents lose market share to new competitors.</li>\n<li><a href=\"https://man7.org/tlpi/\">The Linux Programming\nInterface</a>: a book on the linux OS, glibc, and system calls. Waiting\nfor a second edition soemday to cover io_uring, cgroups, and other\nthings.</li>\n<li><a\nhref=\"https://www.amazon.com/Kill-Fire-Manage-Computer-Systems/dp/1718501188\">The\nLittle Book of Semaphores</a>: A gentle introduction to mutual exclusion\nby introducing semaphores, the basis of almost all concurrent\nalgorithms.</li>\n</ul>\n</section>\n<section id=\"utilities\" class=\"level2\">\n<h2>Utilities</h2>\n<ul>\n<li><a href=\"https://fishshell.com/\">fish</a>: A shell with completions\nand sane scripting</li>\n<li><a href=\"https://github.com/CloudCannon/pagefind\">pagefind</a>:\nStatic search that works offline without needing to run a local\nserver</li>\n<li><a href=\"https://pandoc.org/\">pandoc</a>: A universal document\nconverter</li>\n<li><a href=\"https://github.com/clulab/pdf2txt\">pdf2txt</a>: Reading\npdfs as plain text</li>\n<li><a href=\"https://github.com/BurntSushi/ripgrep\">ripgrep</a>: Grep\nbut faster</li>\n<li><a href=\"https://github.com/plasma-umass/scalene\">scalene</a>: To\ndiagnose python performance problems</li>\n<li><a href=\"https://termux.dev/en/\">termux</a>: Run a unix terminal on\nyour android phone</li>\n<li><a href=\"https://github.com/panamax-rs/panamax\">panamax</a>: Mirror\ncrates.io locally</li>\n</ul>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2023-01-19T02:39:20+00:00"
		},
		{
			"id": "gen/the-agora-and-the-hivemind.html",
			"url": "gen/the-agora-and-the-hivemind.html",
			"title": "The agora and the hivemind",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>The agora and the hivemind</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">The agora and the hivemind</h1>\n<p class=\"byline\">2022-06-11T19:53:26-05:00</p>\n</header>\n<p>Have you ever felt like there\u2019s so much to do, but you never make any\nprogress? When I worked as an office worker, my manager drilled it into\nus that to remain competitive in an increasingly connected global\neconomy, workers would have to be able to multitask \u2013 handle many\nrequests in flight concurrently and work on them in parallel, bringing\ntogether stakeholders to build consensus.</p>\n<p>As a line cook in a restaurant, it was expected that cooks would be\nable to do any role in the restaurant \u2013 order ingredients, clean dishes,\nserve customers, prep ingredients, the whole shebang, especially in\nparallel.</p>\n<p>As a warehouse worker, we were expected to be able to handle a larger\nnumber of requests every month, with the same or smaller team, mentally\njuggling many POs at the same time to meet tighter deadlines for the\nsake of efficiency.</p>\n<p>As a tech worker, we were expected to exceed for our customers \u2013\nanswer pings at 3 a.m, make sure our service was free of security\ndefects, make a bi-weekly \u201cagile\u201d show and tell, and work on our project\nwhile having 7 hours of meetings a day.</p>\n<p>All these jobs had disastrous consequences \u2013 the office workers\nbecame so unproductive that they quit in droves, many of the line cooks\nsuffered physical injury, including losing a finger, and the warehouse\nworkers, well, many of them had to go on disability. Many of the tech\nworkers quit as well, tired of being unproductive and overworked.</p>\n<p>I could pontificate about how shareholder capitalism is at odds with\nlabor, but I\u2019ll leave that for another time. Instead, I\u2019ll talk about\nhow overstimulation via the internet is leading to an increase in\nmultitasking, crippling our one true superpower \u2013 the ability to\nconcentrate.</p>\n<p>Lots has been said about increasing productivity in the workplace\n(it\u2019s been a hot topic for over a century now), but I\u2019ve noticed in\nmyself and others that we can\u2019t concentrate as well as we used to. We\nturn to our phones for diet entertainment, forgoing the relaxation and\nconcentration of past times.</p>\n<p>Sustenance farmers did it best, I think. When I lived on a farm, the\nschedule was simple \u2013 wake up at 5 or so, before the sun rises to get\nwashed up, eat a small meal, and dressed to tackle the day\u2019s work.</p>\n<p>You\u2019d work slowly, maybe handling some maintenance tasks like setting\nup a net so the animals don\u2019t eat your crops, or patching holes in rice\npaddies so those dang beavers don\u2019t drain all the water from your patch.\nIn the summer, it\u2019d get too hot by 11 or so, so you\u2019d retire back home,\neat a small lunch, and take a nap \u2013 four, five hours.</p>\n<p>After that, you\u2019d set out again after the heat cooled off, finishing\noff your tasks for the day, maybe leaving some tools outside for\ntomorrow, taking note of what needs to be done, before retiring to eat\ndinner, wash up and sleep for the next day.</p>\n<p>Sometimes you needed your plots to lay fallow, or sometimes the other\npeople in your village would share tools, or maybe someone needed to be\na substitute teacher for the little ones because the only teacher in\ntown had a family emergency. You wouldn\u2019t think of things in terms of\nmoney \u2013 you\u2019d repay each other with favors and do the right thing (most\nof the time). You could borrow someone else\u2019s plot that hasn\u2019t been used\nin a while, maybe in exchange for something like crops or tools or a\nservice, like fixing up their house\u2019s roof. We\u2019d congregate at the town\ncenter, asking for favors, doing favors, and building up the shared\ncommunity. People were happy, for the most part.</p>\n<p>Most of us used to lead that kind of life, until the businesspeople\nlured us over to factories with the promise of <em>wages</em> and\n<em>benefits</em>, promising us milk and honey but leaving us with\nregrets and sadness.</p>\n<p>Thanks for nothing, capitalists.</p>\n<p>Industrialization was one game changer, but the internet was another.\nInstead of having a set of town centers, one for each town or\nthereabouts, we can now have a town center in our own houses (or pocket,\nwith cell phones).</p>\n<p>With this kind of super power, we should be able to use it to our own\nbenefit. And we did, kind of. There\u2019s lots of nice services these days\nthat make our lives easier, but they don\u2019t make our lives more\nfulfilling.</p>\n<p>And in exchange, we\u2019ve lost our ability to focus, robbing us of one\nof the paths to fulfillment.</p>\n<p>We\u2019ve all become part of the hivemind.</p>\n<p>It\u2019s impossible to have all of us disconnect. There will only be a\nfew people who want to build their own house off the grid and grow their\nown crops and maintain a solar panel for electricity.</p>\n<p>For the rest of us, we can only set boundaries \u2013 but I implore you to\nthink about the agora model \u2013 where we only go to town a few days out of\nthe week at most. We don\u2019t always have to be connected. A slower pace of\nlife isn\u2019t bad.</p>\n<p>For me, as a programmer, that means downloading the resources I need\nto work offline. On my personal computer, I have a copy of the\ndocumentation of all the tools I work with, books, papers, and\nsyllabuses for courses I\u2019d like to learn from, and offline copies of\ninteresting websites that I could learn a lot from (mainly in the form\nof rss, but a recursive wget does the trick for sites that don\u2019t have an\nrss feed), copies of music I like listening to.</p>\n<p>I only need to go online sometimes, since I\u2019ll always have something\nto enjoy.</p>\n<p>One side effect is that you won\u2019t hate the airplane as much \u2013 I just\nopen up a paper I\u2019ve wanted to read, a textbook, a course, and jump\nright in. It\u2019s a wonderful way to pass the time and really feel\nproductive by the end.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2022-06-12T00:53:26+00:00"
		},
		{
			"id": "gen/learn-computer-science.html",
			"url": "gen/learn-computer-science.html",
			"title": "Learn Computer Science",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Learn Computer Science</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Learn Computer Science</h1>\n<p class=\"byline\">2022-06-11T19:50:29-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#programming\" id=\"toc-programming\">Programming</a>\n<ul>\n<li><a href=\"#textbooks\" id=\"toc-textbooks\">Textbooks</a></li>\n<li><a href=\"#courses\" id=\"toc-courses\">Courses</a></li>\n<li><a href=\"#papers\" id=\"toc-papers\">Papers</a></li>\n<li><a href=\"#projects\" id=\"toc-projects\">Projects</a></li>\n</ul></li>\n<li><a href=\"#discrete-math\" id=\"toc-discrete-math\">Discrete Math</a>\n<ul>\n<li><a href=\"#textbooks-1\" id=\"toc-textbooks-1\">Textbooks</a></li>\n</ul></li>\n<li><a href=\"#linear-algebra\" id=\"toc-linear-algebra\">Linear Algebra</a>\n<ul>\n<li><a href=\"#textbooks-2\" id=\"toc-textbooks-2\">Textbooks</a></li>\n</ul></li>\n<li><a href=\"#statistics\" id=\"toc-statistics\">Statistics</a>\n<ul>\n<li><a href=\"#textbooks-3\" id=\"toc-textbooks-3\">Textbooks</a></li>\n</ul></li>\n<li><a href=\"#theory-of-computation\"\nid=\"toc-theory-of-computation\">Theory of Computation</a>\n<ul>\n<li><a href=\"#textbooks-4\" id=\"toc-textbooks-4\">Textbooks</a></li>\n</ul></li>\n<li><a href=\"#computer-architecture\"\nid=\"toc-computer-architecture\">Computer Architecture</a>\n<ul>\n<li><a href=\"#textbooks-5\" id=\"toc-textbooks-5\">Textbooks</a></li>\n<li><a href=\"#resources\" id=\"toc-resources\">Resources</a></li>\n</ul></li>\n<li><a href=\"#algorithms-and-data-structures\"\nid=\"toc-algorithms-and-data-structures\">Algorithms and Data\nStructures</a>\n<ul>\n<li><a href=\"#textbooks-6\" id=\"toc-textbooks-6\">Textbooks</a></li>\n</ul></li>\n<li><a href=\"#operating-systems\" id=\"toc-operating-systems\">Operating\nSystems</a>\n<ul>\n<li><a href=\"#textbooks-7\" id=\"toc-textbooks-7\">Textbooks</a></li>\n</ul></li>\n<li><a href=\"#networking\" id=\"toc-networking\">Networking</a>\n<ul>\n<li><a href=\"#textbooks-8\" id=\"toc-textbooks-8\">Textbooks</a></li>\n<li><a href=\"#projects-1\" id=\"toc-projects-1\">Projects</a></li>\n</ul></li>\n<li><a href=\"#databases\" id=\"toc-databases\">Databases</a>\n<ul>\n<li><a href=\"#textbooks-9\" id=\"toc-textbooks-9\">Textbooks</a></li>\n<li><a href=\"#projects-2\" id=\"toc-projects-2\">Projects</a></li>\n</ul></li>\n<li><a href=\"#compilers\" id=\"toc-compilers\">Compilers</a>\n<ul>\n<li><a href=\"#textbooks-10\" id=\"toc-textbooks-10\">Textbooks</a></li>\n<li><a href=\"#resources-1\" id=\"toc-resources-1\">Resources</a></li>\n</ul></li>\n<li><a href=\"#distributed-systems\"\nid=\"toc-distributed-systems\">Distributed Systems</a>\n<ul>\n<li><a href=\"#textbooks-11\" id=\"toc-textbooks-11\">Textbooks</a></li>\n</ul></li>\n</ul>\n</nav>\n<p>I have a confession to make. I, (and most of us) have been stuck on\nfad diets for CS. It\u2019s so nice to read easy books, like learn C++ in 21\ndays, or doing some leetcode problems. You learn a bit, feel that warm\nglow of getting smarter, and trick yourself into feeling productive.</p>\n<p>You\u2019re not really getting any better, without learning the\nfundamentals.</p>\n<p>I decided to cobble up a set of resources to go through, as a fusion\nof <a href=\"https://teachyourselfcs.com/\">Teach Yourself Computer\nScience</a> and <a\nhref=\"https://www.youtube.com/watch?v=Q4Y6ERYAwqw\">Steve Yegge</a>\u2019s\nrecommendations.</p>\n<p>Teach Yourself CS has a detailed list of good resources for the more\npractical aspects of CS, whereas Steve Yegge\u2019s recommendations focus\nmore on the mathematical side \u2013 the first four courses he recommends\nare: discrete math, linear algebra, statistics, and theory of\ncomputation.</p>\n<p>Steve Yegge\u2019s list omits Computer Architecture, which is a glaring\nomission \u2013 an Operating Systems course doesn\u2019t have enough time to cover\nall the interesting parts of concurrency, parallelism, and optimization\nthat a computer architecture course would.</p>\n<p>Teach Yourself CS doesn\u2019t mention Theory of Computation, and is\nlighter on the math background, giving one resource for math. Theory of\nComputation is a bit more dated (swallowed up by all the other fields),\nbut is still useful for its applications.</p>\n<p>To that end, I\u2019ve fused them both, and skimmed some resources to put\non this list.</p>\n<p>This list is incomplete and changing all the time, but hey, isn\u2019t\nthat what agile development is all about?</p>\n<section id=\"programming\" class=\"level2\">\n<h2>Programming</h2>\n<section id=\"textbooks\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Structure and Interpretation of Computer Programs</li>\n</ol>\n</section>\n<section id=\"courses\" class=\"level3\">\n<h3>Courses</h3>\n</section>\n<section id=\"papers\" class=\"level3\">\n<h3>Papers</h3>\n</section>\n<section id=\"projects\" class=\"level3\">\n<h3>Projects</h3>\n</section>\n</section>\n<section id=\"discrete-math\" class=\"level2\">\n<h2>Discrete Math</h2>\n<section id=\"textbooks-1\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Discrete Mathematics, an open introduction</li>\n</ol>\n</section>\n</section>\n<section id=\"linear-algebra\" class=\"level2\">\n<h2>Linear Algebra</h2>\n<section id=\"textbooks-2\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>No bullshit guide to linear Algebra, Savov</li>\n</ol>\n</section>\n</section>\n<section id=\"statistics\" class=\"level2\">\n<h2>Statistics</h2>\n<section id=\"textbooks-3\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Statistics fourth ed, Friedman et. al</li>\n<li>Think stats, Downey</li>\n<li>Think Bayes, Downey</li>\n</ol>\n</section>\n</section>\n<section id=\"theory-of-computation\" class=\"level2\">\n<h2>Theory of Computation</h2>\n<section id=\"textbooks-4\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Theory of Computation, Hefferon</li>\n<li>Computational Complexity, Arora and Barak</li>\n</ol>\n</section>\n</section>\n<section id=\"computer-architecture\" class=\"level2\">\n<h2>Computer Architecture</h2>\n<section id=\"textbooks-5\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Computer Architecture, a Programmers Perspective</li>\n<li>Computer Architecture, Patterson and Hennessey</li>\n</ol>\n</section>\n<section id=\"resources\" class=\"level3\">\n<h3>Resources</h3>\n<ol type=\"1\">\n<li>Some Assembly Required</li>\n</ol>\n</section>\n</section>\n<section id=\"algorithms-and-data-structures\" class=\"level2\">\n<h2>Algorithms and Data Structures</h2>\n<section id=\"textbooks-6\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>The Algorithm Design Manual, Skiena</li>\n<li>The Art of Multiprocessor programming</li>\n</ol>\n</section>\n</section>\n<section id=\"operating-systems\" class=\"level2\">\n<h2>Operating Systems</h2>\n<section id=\"textbooks-7\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Operating Systems, Three Easy Pieces</li>\n</ol>\n</section>\n</section>\n<section id=\"networking\" class=\"level2\">\n<h2>Networking</h2>\n<section id=\"textbooks-8\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Computer Networks, a Systems approach</li>\n</ol>\n</section>\n<section id=\"projects-1\" class=\"level3\">\n<h3>Projects</h3>\n<ol type=\"1\">\n<li>Chitcp</li>\n</ol>\n</section>\n</section>\n<section id=\"databases\" class=\"level2\">\n<h2>Databases</h2>\n<section id=\"textbooks-9\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Database Internals</li>\n</ol>\n</section>\n<section id=\"projects-2\" class=\"level3\">\n<h3>Projects</h3>\n<ol type=\"1\">\n<li>Chidb</li>\n</ol>\n</section>\n</section>\n<section id=\"compilers\" class=\"level2\">\n<h2>Compilers</h2>\n<section id=\"textbooks-10\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Crafting Interpreters</li>\n</ol>\n</section>\n<section id=\"resources-1\" class=\"level3\">\n<h3>Resources</h3>\n<ol type=\"1\">\n<li><a href=\"https://github.com/rui314/chibicc\">Chibicc</a></li>\n</ol>\n</section>\n</section>\n<section id=\"distributed-systems\" class=\"level2\">\n<h2>Distributed Systems</h2>\n<section id=\"textbooks-11\" class=\"level3\">\n<h3>Textbooks</h3>\n<ol type=\"1\">\n<li>Designing Data Intensive Applications</li>\n</ol>\n</section>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2022-06-12T00:50:29+00:00"
		},
		{
			"id": "gen/writing-compilers.html",
			"url": "gen/writing-compilers.html",
			"title": "Writing Compilers",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing Compilers</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing Compilers</h1>\n<p class=\"byline\">2022-01-10T17:48:22-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#a-plan-of-attack\" id=\"toc-a-plan-of-attack\">A Plan of\nAttack</a></li>\n<li><a href=\"#compiling-to-assembly-from-scratch\"\nid=\"toc-compiling-to-assembly-from-scratch\">Compiling to Assembly from\nScratch</a></li>\n<li><a href=\"#crafting-interpreters\"\nid=\"toc-crafting-interpreters\">Crafting Interpreters</a></li>\n<li><a href=\"#chibicc\" id=\"toc-chibicc\">ChibiCC</a></li>\n<li><a href=\"#conclusion\" id=\"toc-conclusion\">Conclusion</a></li>\n</ul>\n</nav>\n<p>In his post \u201cRich Programmer Food\u201d, Steve Yegge explains why you\nshould learn compilers:</p>\n<blockquote>\n<p>If you don\u2019t know how compilers work, then you don\u2019t know how\ncomputers work. If you\u2019re not 100% sure whether you know how compilers\nwork, then you don\u2019t know how they work.</p>\n</blockquote>\n<p>Throughout this post, Steve has some witticisms and some harsh\nrealizations:</p>\n<blockquote>\n<p>If you don\u2019t take compilers then you run the risk of forever being on\nthe programmer B-list: the kind of eager young architect who becomes a\nsaturnine old architect who spends a career building large systems and\nbeing damned proud of it.</p>\n</blockquote>\n<p>While I wouldn\u2019t say the article <strong>wholly</strong> convinced me\nto learn about compilers, I do agree that compilation problems are\neverywhere.</p>\n<p>In front-end work, where I started off, there\u2019s a glut of frameworks.\nReact, Angular, Vue, Svelte, with some tooling like webpack, parcel,\nesbuild, babel and browserify.</p>\n<p>What do they all have in common? They\u2019re all compilers. React takes\nJSX and turns it into HTML and JS.</p>\n<p>Angular launched Typescript, which is a language that compiles to\nJavascript.</p>\n<p>Vue has <code>.vue</code> templates, which compile to HTML, CSS, and\nJS.</p>\n<p>Svelte has its own <code>.svelte</code> files.</p>\n<p>All the other build tools I mentioned take javascript, minify it,\ntree-shake it (dead-code elimination) and bundle it for you so it can be\nserved on the internet.</p>\n<p>All of these are compiler problems.</p>\n<p>My favorite language, Rust, has a great deal of compiler work in the\ncore language and design tradeoffs to make it easy for new people to\nadopt and experienced people to enjoy.</p>\n<p>In Mobile, Kotlin and Swift, as well as many libraries, all reduce to\ncompiler problems \u2013 they end up manipulating ASTs to produce better\ncode, or compile to some bytecode that is executed on the target\nplatform.</p>\n<p>Compiler problems really are everywhere.</p>\n<p>Here\u2019s another quote from Ras Bodik:</p>\n<blockquote>\n<p>Don\u2019t be a boilerplate programmer. Instead, build tools for users and\nother programmers. Take historical note of textile and steel industries:\ndo you want to build machines and tools, or do you want to operate those\nmachines?</p>\n</blockquote>\n<p>Got the message? Compilers are really important. Or so I think. But\nhow does one learn compilers? Well, let\u2019s scour the internet.</p>\n<section id=\"a-plan-of-attack\" class=\"level2\">\n<h2>A Plan of Attack</h2>\n<p>There\u2019s no shortage of great materials on compilers on the internet,\nbut I want to focus on three resources I\u2019m currently using to learn\ncompilers, since I think they run the gamut: One\u2019s a great starting\nresource, another is a great medium level resource, and one is extremely\nhard but rewarding.</p>\n<p>The Resources:</p>\n<ol type=\"1\">\n<li><a href=\"https://keleshev.com/compiling-to-assembly-from-scratch/\"\nclass=\"uri\">https://keleshev.com/compiling-to-assembly-from-scratch/</a></li>\n<li><a href=\"https://craftinginterpreters.com/\"\nclass=\"uri\">https://craftinginterpreters.com/</a></li>\n<li><a href=\"https://github.com/rui314/chibicc\"\nclass=\"uri\">https://github.com/rui314/chibicc</a></li>\n</ol>\n</section>\n<section id=\"compiling-to-assembly-from-scratch\" class=\"level2\">\n<h2>Compiling to Assembly from Scratch</h2>\n<p>Compiling to Assembly from Scratch is the first resource I looked at\nto start my compiler writing journey. It\u2019s a short book on how to write\na small ARM32 emitting compiler in Typescript. It does this by parsing\nusing a parser combinator, and then emitting simple ARM32 code using the\nvisitor pattern.</p>\n<p>Parser combinators are a technique for parsing that\u2019s been picking up\nsteam recently. Because Typescript has first-class regex, this technique\nreally fits well here.</p>\n<p>The book also goes over basic ARM32 instructions, and at the end of\nthis pretty short book (~200 pages), you have a working compiler that\nturns a subset of javascript into ARM32.</p>\n<p>Worth every penny.</p>\n</section>\n<section id=\"crafting-interpreters\" class=\"level2\">\n<h2>Crafting Interpreters</h2>\n<p>Crafting Interpreters is a great book \u2013 the first half of the book\ncovers writing a tree-walk interpreter in Java, while the second half of\nthe book involves writing a bytecode VM in C for a non-trivial language\ncalled \u201cLox\u201d.</p>\n<p>Bob Nystrom really knows his stuff \u2013 the prose is clean, and every\nline of code written is well explained.</p>\n<p>That being said, for the first part, I didn\u2019t really want to write\nany Java (sorry Oracle), so I found a transcription of the first part of\nthe book\u2019s code in Rust <a href=\"https://github.com/jeschkies/lox-rs\"\nclass=\"uri\">https://github.com/jeschkies/lox-rs</a> and used that code\nas the basis for the first part of the book.</p>\n<p>At the end of the first part of the book, I really felt as though I\ngot the hang of the basics of compiler writing.</p>\n<p>I still need to go through the second part, but I\u2019m really enjoying\nit so far!</p>\n</section>\n<section id=\"chibicc\" class=\"level2\">\n<h2>ChibiCC</h2>\n<p>This resource is a bit different: It\u2019s a git repo by the creator of\nmold (the new LLVM linker) to create a C Compiler (CC) in C.</p>\n<p>This repository follows the paper \u201cAn Incremental Approach to\nCompiler Construction\u201d by Ghuloum, <a\nhref=\"http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf\"\nclass=\"uri\">http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf</a> which\nadvocates writing a simple compiler step by step and adding\nfunctionality little by little.</p>\n<p>Rui Ueyama, the author of this repo, writes clean C code for every\ncommit, and each message details adding a new feature to the C compiler.\nThere\u2019s no accompanying instructional material, so you\u2019re on your own to\nread the diffs and try to ascribe meaning to them, but it is important\nto read lots of code, and what better way to start than in such a\nstructured format?</p>\n</section>\n<section id=\"conclusion\" class=\"level2\">\n<h2>Conclusion</h2>\n<p>After going through a few resources for compiler construction, I\u2019m\nstarting to get a better understanding of compilers, and seeing those\nkinds of problems crop up all the time. Writing compilers has also\nmotivated me to read more code, and I\u2019m hoping to be able to read code\nfrom larger projects to write better code in the future!</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2022-01-10T22:48:22+00:00"
		},
		{
			"id": "gen/writing-portable-c.html",
			"url": "gen/writing-portable-c.html",
			"title": "Writing Portable C",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Writing Portable C</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Writing Portable C</h1>\n<p class=\"byline\">2021-11-15T18:06:09-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#posix-and-sus\" id=\"toc-posix-and-sus\">POSIX and\nSUS</a></li>\n<li><a href=\"#gcc-vs-musl\" id=\"toc-gcc-vs-musl\">GCC vs MUSL</a></li>\n<li><a href=\"#what-sacrifices-were-made\"\nid=\"toc-what-sacrifices-were-made\">What Sacrifices were made?</a>\n<ul>\n<li><a href=\"#how-do-you-make-static-binaries\"\nid=\"toc-how-do-you-make-static-binaries\">How do you make static\nbinaries?</a></li>\n<li><a href=\"#dont-name-your-functions-_init\"\nid=\"toc-dont-name-your-functions-_init\">Don\u2019t name your functions\n<code>_init</code></a></li>\n<li><a href=\"#getopt_long-doesnt-exist\"\nid=\"toc-getopt_long-doesnt-exist\"><code>getopt_long</code> doesn\u2019t\nexist</a></li>\n<li><a href=\"#sysctl-isnt-standard\" id=\"toc-sysctl-isnt-standard\">Sysctl\nisn\u2019t standard</a></li>\n<li><a href=\"#lstat-has-optional-fields\"\nid=\"toc-lstat-has-optional-fields\">lstat has optional fields</a></li>\n<li><a href=\"#ni_maxhost-isnt-defined\"\nid=\"toc-ni_maxhost-isnt-defined\"><code>NI_MAXHOST</code> isn\u2019t\ndefined</a></li>\n</ul></li>\n<li><a href=\"#getting-the-toolchains\"\nid=\"toc-getting-the-toolchains\">Getting the Toolchains</a></li>\n<li><a href=\"#in-short\" id=\"toc-in-short\">In Short</a></li>\n</ul>\n</nav>\n<p>On my free time I\u2019ve been hacking away on <a\nhref=\"https://github.com/Takashiidobe/unix-utils\">unix-utils</a>, a\nproject that implements some common unix utilities. In order to test how\nportable C really is for the average programmer, I decided to lean on\nopen source to see how many platforms I could target my C with. I wanted\nto write the most portable code I could (that meant targeting only\nPOSIX) functions and using a minimalistic stdlib that tried its best to\nadhere to the standards (musl). This let me write C code for about 50\ntargets. Let\u2019s go deeper into the background and how that was all\npossible:</p>\n<section id=\"posix-and-sus\" class=\"level2\">\n<h2>POSIX and SUS</h2>\n<p>In the 70s, C was made at AT&amp;T. In the 80s, it escaped, becoming\nmore popular, before eventually becoming standardized by ANSI (C89). But\nwhat about standards for Operating Systems? Enter POSIX (the Portable\nOperating System Interface), a standard for operating system interfaces.\nIn 1988, the first version of POSIX was released by the IEEE, which\ndetailed common interfaces, like Signals, pipes, and the C standard\nlibrary.</p>\n<p>The POSIX standards were fairly minimalistic in the 80s, adding some\nextensions (like real time programming) and thread extensions) in the\nearly 90s before being subsumed by the Austin Group, a committee that\ndesigned the Single Unix Specification. The Austin Group has steered the\nPOSIX standards since 1997, creating standards like (POSIX 1997/SUS v2),\n(POSIX 2001/SUS v3), and (POSIX 2008/SUS v4).</p>\n<p>Since 2008, there have been two minor corrections to the POSIX\nstandards (one in 2011 and 2017), but the two most common POSIX\nstandards in use are POSIX 2001 and 2008, which is where we\u2019ll be\ndirecting most of our attention to.</p>\n<p>POSIX compliance in particular ends up being extremely important,\nbecause most Operating Systems have at least some level of POSIX\ncompliance. Linux, the BSDs, Mac OS, and Windows all do to some extent.\nThat means that our C code can target all of them by following the\nstandards, which makes our code more flexible.</p>\n<p>This is so important that GCC (GNU\u2019s C Compiler) ended up\nimplementing a flag that checks for strict compliance to the POSIX\nstandard of your choice.</p>\n<p>In my Makefile, I have this line, which says to compile my code\nstrictly according to the standard.</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource make numberLines\"><code class=\"sourceCode\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a>CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200809L</span></code></pre></div>\n<p>Since I wrote the first draft of my utilities on a Mac OS computer\nwith no POSIX compatibility flags, you can imagine there was a lot of\nbreakage. As to why there was so much breakage, well, that requires\nanother history lesson.</p>\n</section>\n<section id=\"gcc-vs-musl\" class=\"level2\">\n<h2>GCC vs MUSL</h2>\n<p>In the 80s, the Free Software Foundation (FSF) wanted to create the\nideal \u201cFree\u201d programming environment. To do so, they were going to start\nfrom the top-down, by implementing the user space (a C compiler, a\nshell, the POSIX shell utilities, etc), and then build an OS kernel (GNU\nHurd). GNU succeeded at one part of their mission, by providing the most\ncommon userspace tools to date (GCC, Bash, and the GNU utils). However,\nGNU\u2019s kernel lost out to Linux, and the rest is history.</p>\n<p>Linux started out only supporting GCC tools for its userspace, but\nnow it can support a wide variety of C standard libraries (libc for\nshort). One of those ends up being Musl, the standard library of this\narticle.</p>\n<p>The choice of standard library would end up being entirely\ninconsequential if not for one detail: Musl supports static linking, and\nGCC does not.</p>\n<p>Sure GCC supports a lot of non-standard extensions, and sure GCC\nexecutables are more bloaty than their musl counterparts, but static\nlinking lets us execute our binaries without having installed a libc on\nthe platform.</p>\n<p>That means our code can reach even more users!</p>\n<p>Much blood has been spilt on static vs dynamic linking, so I will\nspare you the carnage by simply saying that static linking tends to be\nmore convenient for the end user (they require less dependencies on\ntheir side to run the code), which is good for us, the application\nbuilders.</p>\n</section>\n<section id=\"what-sacrifices-were-made\" class=\"level2\">\n<h2>What Sacrifices were made?</h2>\n<section id=\"how-do-you-make-static-binaries\" class=\"level3\">\n<h3>How do you make static binaries?</h3>\n<p>Going back to building some unix utilities, I downloaded a musl-gcc\ncompiler, logged into my linux VM and started compiling.</p>\n<p>The first issue I ran into was that musl-gcc didn\u2019t compile static\nbinaries.</p>\n<p>I added the flag <code>-static</code> to my build, but\n<code>file</code> and <code>ldd</code> ended up telling me that my\nbinary was still dynamically linked.</p>\n<p>I dug through troves of documentation. Eventually, I discovered that\nit wasn\u2019t enough just to provide the <code>-static</code> flag, because\nGCC can ignore it. You have to provide another flag,\n<code>--static</code> as well. Oh, and if that wasn\u2019t enough, that still\ndidn\u2019t compile static binaries. You had to disable <code>pie</code>, or\n<code>position independent executables</code> with the flag\n<code>-no-pie</code> as well.</p>\n<p>Finally, I had compiled a hello world binary statically. Time to move\non!</p>\n</section>\n<section id=\"dont-name-your-functions-_init\" class=\"level3\">\n<h3>Don\u2019t name your functions <code>_init</code></h3>\n<p>I then tried to compile my utilities. I wanted to decrease\nduplication so I wrote a header file with a function called\n<code>_init</code>. This ended up causing a duplicate symbol error (musl\ndefines this function in crti.o first).</p>\n<p>Of course, GCC never complained, so I had to rename this\nfunction.</p>\n</section>\n<section id=\"getopt_long-doesnt-exist\" class=\"level3\">\n<h3><code>getopt_long</code> doesn\u2019t exist</h3>\n<p>Next up, <code>getopt_long</code> (Get options with long flags) isn\u2019t\nPOSIX standard. Unshocking. POSIX only specifies the normal\n<code>getopt</code>, which supports short options only. Long options\nlike <code>--file</code> or <code>--color</code> are a GNUism.</p>\n<p>I ended up finding a copy of <code>getopt_long</code> online and\nrewriting my header file includes for my utilities.</p>\n</section>\n<section id=\"sysctl-isnt-standard\" class=\"level3\">\n<h3>Sysctl isn\u2019t standard</h3>\n<p>Next up, I had a compiler error where my implementation of\n<code>uptime</code> failed to compile. <code>&lt;sys/sysctl.h&gt;</code>\nis a Macism, and not part of POSIX. Linux offers it up in\n<code>&lt;linux/sysctl.h&gt;</code> for convenience, but as its name\nmight indicate, it\u2019s not portable.</p>\n<p>Next!</p>\n</section>\n<section id=\"lstat-has-optional-fields\" class=\"level3\">\n<h3>lstat has optional fields</h3>\n<p>In my implementation of stat, I used the functions\n<code>major</code>, <code>minor</code> and <code>ctime</code>, none of\nwhich are POSIX compliant. They\u2019re useful on mac os, so I can gate them\nbehind an <code>__APPLE__</code> macro, but that makes the code less\nsuccinct. Oh well.</p>\n</section>\n<section id=\"ni_maxhost-isnt-defined\" class=\"level3\">\n<h3><code>NI_MAXHOST</code> isn\u2019t defined</h3>\n<p>As an oddity, musl doesn\u2019t define <code>NI_MAXHOST</code> at all.\nThis is useful for <code>dig</code>, which returns the ip address for a\ngiven address. I ended up defining it if it wasn\u2019t already defined.</p>\n</section>\n</section>\n<section id=\"getting-the-toolchains\" class=\"level2\">\n<h2>Getting the Toolchains</h2>\n<p>With all these changes made, our code will now compile for Linux +\nmusl, thankfully. The next problem was actually getting our\ntoolchains.</p>\n<p>Luckily, after some googling, I found out about &lt;musl.cc&gt;, a\nwebsite which releases versions of musl-gcc toolchains.</p>\n<p>Now, since I didn\u2019t want to create an undue amount of load onto this\nwebsite, I created a mirror of it: <a\nhref=\"https://github.com/Takashiidobe/muslcc\"\nclass=\"uri\">https://github.com/Takashiidobe/muslcc</a>.</p>\n<p>Next, I had to create a github action that would fetch the compiler\nrequired, set it up properly, compile all of the binaries, strip the\ndebug information, tar them into one directory, and release them on a\npush to tags. Phew!</p>\n<p>This part turned out to be a lot of guesswork and letting it run, so\nI\u2019ll leave the final results here:</p>\n<p><a\nhref=\"https://github.com/Takashiidobe/unix-utils/blob/master/.github/workflows/release.yml\"\nclass=\"uri\">https://github.com/Takashiidobe/unix-utils/blob/master/.github/workflows/release.yml</a></p>\n<p>And the repo here:</p>\n<p><a href=\"https://github.com/Takashiidobe/unix-utils\"\nclass=\"uri\">https://github.com/Takashiidobe/unix-utils</a></p>\n</section>\n<section id=\"in-short\" class=\"level2\">\n<h2>In Short</h2>\n<p>It\u2019s amazing that you can write code that targets so many\narchitectures, and compile to them easily, all for free, with the power\nof open source (and Microsoft\u2019s wallet, thanks Github Actions).</p>\n<p>With this, I was able to build for 52 architectures and release code\nfor them (I ended up adding in support for x86_64 Darwin and arm64\nDarwin).</p>\n<p>Viva portable code.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-11-15T23:06:09+00:00"
		},
		{
			"id": "gen/building-rust-binaries-for-different-platforms.html",
			"url": "gen/building-rust-binaries-for-different-platforms.html",
			"title": "Building Rust binaries for different platforms",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Building Rust binaries for different platforms</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Building Rust binaries for different platforms</h1>\n<p class=\"byline\">2021-11-03T09:24:46-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#a-note-on-targets\" id=\"toc-a-note-on-targets\">A Note on\nTargets</a>\n<ul>\n<li><a href=\"#architectures\"\nid=\"toc-architectures\">Architectures</a></li>\n<li><a href=\"#vendors\" id=\"toc-vendors\">Vendors</a></li>\n<li><a href=\"#operating-systems\" id=\"toc-operating-systems\">Operating\nSystems</a></li>\n<li><a href=\"#environments\" id=\"toc-environments\">Environments</a></li>\n</ul></li>\n<li><a href=\"#building-binaries-for-30-targets\"\nid=\"toc-building-binaries-for-30-targets\">Building Binaries for ~30\nTargets</a>\n<ul>\n<li><a href=\"#checking-out-our-code\"\nid=\"toc-checking-out-our-code\">Checking out our code:</a></li>\n<li><a href=\"#downloading-the-c-compiler\"\nid=\"toc-downloading-the-c-compiler\">Downloading the C compiler</a></li>\n<li><a href=\"#installing-the-rust-toolchain\"\nid=\"toc-installing-the-rust-toolchain\">Installing the Rust\ntoolchain</a></li>\n<li><a href=\"#building-the-executable\"\nid=\"toc-building-the-executable\">Building the executable</a></li>\n<li><a href=\"#stripping-debug-information-from-binary\"\nid=\"toc-stripping-debug-information-from-binary\">Stripping debug\ninformation from binary</a></li>\n<li><a href=\"#and-uploading-to-github\"\nid=\"toc-and-uploading-to-github\">And uploading to Github</a></li>\n</ul></li>\n<li><a href=\"#results\" id=\"toc-results\">Results</a></li>\n</ul>\n</nav>\n<p>Rust has great support for cross compilation, with\n<code>cross</code>, you can install the required c toolchain + linker\nand cross compile your rust code to a binary that runs on your targeted\nplatform. Sweet!</p>\n<p>If you\u2019d like to look at the code and results, it\u2019s in this repo\nhere: <a\nhref=\"https://github.com/Takashiidobe/rust-build-binary-github-actions\"\nclass=\"uri\">https://github.com/Takashiidobe/rust-build-binary-github-actions</a></p>\n<p>Rust library writers use this feature to build and test for other\nplatforms than their own: <a\nhref=\"https://github.com/sharkdp/hyperfine/releases/tag/v1.12.0\">hyperfine</a>\nfor example builds for 11 different platforms.</p>\n<p>The <a\nhref=\"https://doc.rust-lang.org/stable/rustc/platform-support.html\">rustc\nbook</a> has a page on targets and tiers of support. Tier 1 supports 8\ntargets:</p>\n<table>\n<thead>\n<tr>\n<th>Tier 1</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>aarch64-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>i686-pc-windows-gnu</td>\n</tr>\n<tr>\n<td>i686-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>i686-pc-windows-msvc</td>\n</tr>\n<tr>\n<td>x86_64-apple-darwin</td>\n</tr>\n<tr>\n<td>x86_64-pc-windows-gnu</td>\n</tr>\n<tr>\n<td>x86_64-pc-windows-msvc</td>\n</tr>\n<tr>\n<td>x86_64-unknown-linux-gnu</td>\n</tr>\n</tbody>\n</table>\n<p>Tier 2 with Host tools supports 21 targets.</p>\n<table>\n<thead>\n<tr>\n<th>Tier 2</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>aarch64-apple-darwin</td>\n</tr>\n<tr>\n<td>aarch64-pc-windows-msvc</td>\n</tr>\n<tr>\n<td>aarch64-unknown-linux-musl</td>\n</tr>\n<tr>\n<td>arm-unknown-linux-gnueabi</td>\n</tr>\n<tr>\n<td>arm-unknown-linux-gnueabihf</td>\n</tr>\n<tr>\n<td>armv7-unknown-linux-gnueabihf</td>\n</tr>\n<tr>\n<td>mips-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>mips64-unknown-linux-gnuabi64</td>\n</tr>\n<tr>\n<td>mips64el-unknown-linux-gnuabi64</td>\n</tr>\n<tr>\n<td>mipsel-unknown-linux-gnuabi</td>\n</tr>\n<tr>\n<td>powerpc-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>powerpc64-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>powerpc64le-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>riscv64gc-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>s390x-unknown-linux-gnu</td>\n</tr>\n<tr>\n<td>x86_64-unknown-freebsd</td>\n</tr>\n<tr>\n<td>x86_64-unknown-illumos</td>\n</tr>\n<tr>\n<td>arm-unknown-linux-musleabihf</td>\n</tr>\n<tr>\n<td>i686-unknown-linux-musl</td>\n</tr>\n<tr>\n<td>x86_64-unknown-linux-musl</td>\n</tr>\n<tr>\n<td>x86_64-unknown-netbsd</td>\n</tr>\n</tbody>\n</table>\n<p>Let\u2019s try to build a binary for all 29 targets.</p>\n<section id=\"a-note-on-targets\" class=\"level2\">\n<h2>A Note on Targets</h2>\n<p>The Rust RFC for Target support: <a\nhref=\"https://rust-lang.github.io/rfcs/0131-target-specification.html\"\nclass=\"uri\">https://rust-lang.github.io/rfcs/0131-target-specification.html</a></p>\n<p>A target is defined in three or four parts:</p>\n<p><code>$architecture-$vendor-$os-$environment</code></p>\n<p>The environment is optional, so some targets have three parts and\nsome have four.</p>\n<p>Let\u2019s take <code>x86_64-apple-darwin</code> for example.</p>\n<ul>\n<li><code>x86_64</code> is the architecture</li>\n<li><code>apple</code> is the vendor</li>\n<li><code>darwin</code> is the os</li>\n</ul>\n<p>You\u2019ll notice here that there is no <code>$environment</code>. This\ntarget assumes the environment, which is most likely to be\n<code>gnu</code>.</p>\n<p>Let\u2019s take one with four parts:\n<code>i686-pc-windows-msvc</code>.</p>\n<ul>\n<li><code>i686</code> is the architecture</li>\n<li><code>pc</code> is the vendor</li>\n<li><code>windows</code> is the os</li>\n<li><code>msvc</code> is the environment</li>\n</ul>\n<p>In this target, the environment is specified as <code>msvc</code>,\nthe microsoft C compiler. This is the most popular compiler for windows,\nbut it need not be: if you look in the same tier 1 table, there\u2019s this\ntarget: <code>i686-pc-windows-gnu</code>.</p>\n<p>The only thing that\u2019s changed is the environment is now\n<code>gnu</code>. Windows can use <code>gcc</code> instead of\n<code>msvc</code>, so building for this target uses the <code>gcc</code>\ninstead of <code>msvc</code>.</p>\n<section id=\"architectures\" class=\"level3\">\n<h3>Architectures</h3>\n<table>\n<thead>\n<tr>\n<th>Architecture</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>aarch64</td>\n<td>ARM 64 bit</td>\n</tr>\n<tr>\n<td>i686</td>\n<td>Intel 32 bit</td>\n</tr>\n<tr>\n<td>x86_64</td>\n<td>Intel 64 bit</td>\n</tr>\n<tr>\n<td>arm</td>\n<td>ARM 32 bit</td>\n</tr>\n<tr>\n<td>armv7</td>\n<td>ARMv7 32 bit</td>\n</tr>\n<tr>\n<td>mips</td>\n<td>MIPS 32 bit</td>\n</tr>\n<tr>\n<td>mips64</td>\n<td>MIPS 64 bit</td>\n</tr>\n<tr>\n<td>mips64el</td>\n<td>MIPS 64 bit Little Endian</td>\n</tr>\n<tr>\n<td>mipsel</td>\n<td>MIPS 32 bit Little Endian</td>\n</tr>\n<tr>\n<td>powerpc</td>\n<td>IBM 32 bit</td>\n</tr>\n<tr>\n<td>powerpc64</td>\n<td>IBM 64 bit</td>\n</tr>\n<tr>\n<td>rsicv64gc</td>\n<td>RISC-V 64 bit</td>\n</tr>\n<tr>\n<td>s390x</td>\n<td>IBM Z 32 bit</td>\n</tr>\n</tbody>\n</table>\n</section>\n<section id=\"vendors\" class=\"level3\">\n<h3>Vendors</h3>\n<table>\n<thead>\n<tr>\n<th>Vendor</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>pc</td>\n<td>Microsoft</td>\n</tr>\n<tr>\n<td>apple</td>\n<td>Apple</td>\n</tr>\n<tr>\n<td>unknown</td>\n<td>Unknown</td>\n</tr>\n</tbody>\n</table>\n</section>\n<section id=\"operating-systems\" class=\"level3\">\n<h3>Operating Systems</h3>\n<table>\n<thead>\n<tr>\n<th>Operating System</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>darwin</td>\n<td>Apple\u2019s OS</td>\n</tr>\n<tr>\n<td>linux</td>\n<td>Linux OS</td>\n</tr>\n<tr>\n<td>windows</td>\n<td>Microsoft\u2019s OS</td>\n</tr>\n<tr>\n<td>freebsd</td>\n<td>FreeBSD OS</td>\n</tr>\n<tr>\n<td>netbsd</td>\n<td>NetBSD OS</td>\n</tr>\n<tr>\n<td>illumos</td>\n<td>Illumos OS, a Solaris derivative</td>\n</tr>\n</tbody>\n</table>\n</section>\n<section id=\"environments\" class=\"level3\">\n<h3>Environments</h3>\n<table>\n<thead>\n<tr>\n<th>Environment</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>musl</td>\n<td>Musl C library</td>\n</tr>\n<tr>\n<td>gnu</td>\n<td>GNU\u2019s C library</td>\n</tr>\n<tr>\n<td>msvc</td>\n<td>Microsoft Visual C library</td>\n</tr>\n<tr>\n<td>freebsd</td>\n<td>FreeBSD\u2019s C library</td>\n</tr>\n<tr>\n<td>netbsd</td>\n<td>NetBSD\u2019s C library</td>\n</tr>\n<tr>\n<td>illumos</td>\n<td>Illumos\u2019 C library</td>\n</tr>\n</tbody>\n</table>\n<p>When you go to the releases tab to download a particular binary,\nyou\u2019ll need to know these four things to download a binary that runs on\nyour system.</p>\n<p>Now, let\u2019s start building for all these systems.</p>\n</section>\n</section>\n<section id=\"building-binaries-for-30-targets\" class=\"level2\">\n<h2>Building Binaries for ~30 Targets</h2>\n<p>We\u2019re going to use Github Actions, a task runner on github.com to\nbuild our binaries. Our binary is a simple <code>hello world</code>\nbinary.</p>\n<p>If you\u2019d just like to look at the github actions file, it\u2019s located\nhere: <a\nhref=\"https://github.com/Takashiidobe/rust-build-binary-github-actions/blob/master/.github/workflows/release.yml\"\nclass=\"uri\">https://github.com/Takashiidobe/rust-build-binary-github-actions/blob/master/.github/workflows/release.yml</a></p>\n<p>Conceptually, we\u2019d like to do the following:</p>\n<ul>\n<li>Set up our target environments.</li>\n<li>Download the C compiler (environment) we need.</li>\n<li>Download a docker image of the OS we require.</li>\n<li>Download the rust toolchain onto docker container.</li>\n<li>Build the binary.</li>\n<li><em>Optionally</em> strip debug symbols.</li>\n<li>Publish it to the github releases tab.</li>\n</ul>\n<p>We\u2019ll first start out by defining our github action and setting up\nthe target environments:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> release</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a><span class=\"fu\">env</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a><span class=\"at\">  </span><span class=\"fu\">MIN_SUPPORTED_RUST_VERSION</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"st\">&quot;1.56.0&quot;</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a><span class=\"at\">  </span><span class=\"fu\">CICD_INTERMEDIATES_DIR</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"st\">&quot;_cicd-intermediates&quot;</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\"></a><span class=\"fu\">on</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\"></a><span class=\"at\">  </span><span class=\"fu\">push</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\"></a><span class=\"at\">    </span><span class=\"fu\">tags</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\"></a><span class=\"at\">      </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"st\">&#39;*&#39;</span></span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\"></a></span>\n<span id=\"cb1-12\"><a href=\"#cb1-12\"></a><span class=\"fu\">jobs</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-13\"><a href=\"#cb1-13\"></a><span class=\"at\">  </span><span class=\"fu\">build</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-14\"><a href=\"#cb1-14\"></a><span class=\"at\">    </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> ${{ matrix.job.target }} (${{ matrix.job.os }})</span></span>\n<span id=\"cb1-15\"><a href=\"#cb1-15\"></a><span class=\"at\">    </span><span class=\"fu\">runs-on</span><span class=\"kw\">:</span><span class=\"at\"> ${{ matrix.job.os }}</span></span>\n<span id=\"cb1-16\"><a href=\"#cb1-16\"></a><span class=\"at\">    </span><span class=\"fu\">strategy</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-17\"><a href=\"#cb1-17\"></a><span class=\"at\">      </span><span class=\"fu\">fail-fast</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">false</span></span>\n<span id=\"cb1-18\"><a href=\"#cb1-18\"></a><span class=\"at\">      </span><span class=\"fu\">matrix</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-19\"><a href=\"#cb1-19\"></a><span class=\"at\">        </span><span class=\"fu\">job</span><span class=\"kw\">:</span></span>\n<span id=\"cb1-20\"><a href=\"#cb1-20\"></a><span class=\"co\">          # Tier 1</span></span>\n<span id=\"cb1-21\"><a href=\"#cb1-21\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> aarch64-unknown-linux-gnu      </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-22\"><a href=\"#cb1-22\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> i686-pc-windows-gnu            </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> windows-2019                  </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-23\"><a href=\"#cb1-23\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> i686-unknown-linux-gnu         </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-24\"><a href=\"#cb1-24\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> i686-pc-windows-msvc           </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> windows-2019                  </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-25\"><a href=\"#cb1-25\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-apple-darwin            </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> macos-10.15                   </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-26\"><a href=\"#cb1-26\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-pc-windows-gnu          </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> windows-2019                  </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-27\"><a href=\"#cb1-27\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-pcwindows-msvc          </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> windows-2019                  </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-28\"><a href=\"#cb1-28\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-unknown-linux-gnu       </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04                  </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-29\"><a href=\"#cb1-29\"></a><span class=\"co\">          # Tier 2 with Host Tools</span></span>\n<span id=\"cb1-30\"><a href=\"#cb1-30\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> aarch64-apple-darwin           </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> macos-11.0                    </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-31\"><a href=\"#cb1-31\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> aarch64-pc-windows-msvc        </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> windows-2019                  </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-32\"><a href=\"#cb1-32\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> aarch64-unknown-linux-musl     </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-33\"><a href=\"#cb1-33\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> arm-unknown-linux-gnueabi      </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-34\"><a href=\"#cb1-34\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> arm-unknown-linux-gnueabihf    </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-35\"><a href=\"#cb1-35\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> armv7-unknown-linux-gnueabihf  </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-36\"><a href=\"#cb1-36\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> mips-unknown-linux-gnu         </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-37\"><a href=\"#cb1-37\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> mips64-unknown-linux-gnuabi64  </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-38\"><a href=\"#cb1-38\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> mips64el-unknown-linux-gnuabi64</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-39\"><a href=\"#cb1-39\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> mipsel-unknown-linux-gnu       </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-40\"><a href=\"#cb1-40\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> powerpc-unknown-linux-gnu      </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-41\"><a href=\"#cb1-41\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> powerpc64-unknown-linux-gnu    </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-42\"><a href=\"#cb1-42\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> powerpc64le-unknown-linux-gnu  </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-43\"><a href=\"#cb1-43\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> riscv64gc-unknown-linux-gnu    </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-44\"><a href=\"#cb1-44\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> s390x-unknown-linux-gnu        </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-45\"><a href=\"#cb1-45\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-unknown-freebsd         </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-46\"><a href=\"#cb1-46\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-unknown-illumos         </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-47\"><a href=\"#cb1-47\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> arm-unknown-linux-musleabihf   </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-48\"><a href=\"#cb1-48\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> i686-unknown-linux-musl        </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-49\"><a href=\"#cb1-49\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-unknown-linux-musl      </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span>\n<span id=\"cb1-50\"><a href=\"#cb1-50\"></a><span class=\"at\">          </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"kw\">{</span><span class=\"at\"> </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> x86_64-unknown-netbsd          </span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">os</span><span class=\"kw\">:</span><span class=\"at\"> ubuntu-20.04</span><span class=\"kw\">,</span><span class=\"at\"> </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span><span class=\"at\"> </span><span class=\"kw\">}</span></span></code></pre></div>\n<section id=\"checking-out-our-code\" class=\"level3\">\n<h3>Checking out our code:</h3>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"at\">    </span><span class=\"fu\">steps</span><span class=\"kw\">:</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Checkout source code</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a><span class=\"at\">      </span><span class=\"fu\">uses</span><span class=\"kw\">:</span><span class=\"at\"> actions/checkout@v2</span></span></code></pre></div>\n</section>\n<section id=\"downloading-the-c-compiler\" class=\"level3\">\n<h3>Downloading the C compiler</h3>\n<p>Most of the time, the C compiler we need is already installed, but in\nsome cases it\u2019ll be overriden by another compiler.</p>\n<p>We\u2019ll need to download the correct suitable C compiler in that case:\n(i686-pc-windows-gnu has gcc, but it\u2019s not on the $PATH).</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Install prerequisites</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a><span class=\"at\">      </span><span class=\"fu\">shell</span><span class=\"kw\">:</span><span class=\"at\"> bash</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a><span class=\"fu\">      run</span><span class=\"kw\">: </span><span class=\"ch\">|</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a>        case ${{ matrix.job.target }} in</span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a>          arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;</span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a>          aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;</span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\"></a>          i686-pc-windows-gnu) echo &quot;C:\\msys64\\mingw32\\bin&quot; &gt;&gt; $GITHUB_PATH</span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\"></a>        esac</span></code></pre></div>\n</section>\n<section id=\"installing-the-rust-toolchain\" class=\"level3\">\n<h3>Installing the Rust toolchain</h3>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Install Rust toolchain</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\"></a><span class=\"at\">      </span><span class=\"fu\">uses</span><span class=\"kw\">:</span><span class=\"at\"> actions-rs/toolchain@v1</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\"></a><span class=\"at\">      </span><span class=\"fu\">with</span><span class=\"kw\">:</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\"></a><span class=\"at\">        </span><span class=\"fu\">toolchain</span><span class=\"kw\">:</span><span class=\"at\"> stable</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\"></a><span class=\"at\">        </span><span class=\"fu\">target</span><span class=\"kw\">:</span><span class=\"at\"> ${{ matrix.job.target }}</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\"></a><span class=\"at\">        </span><span class=\"fu\">override</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"ch\">true</span></span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\"></a><span class=\"at\">        </span><span class=\"fu\">profile</span><span class=\"kw\">:</span><span class=\"at\"> minimal</span><span class=\"co\"> # minimal component installation (ie, no documentation)</span></span></code></pre></div>\n</section>\n<section id=\"building-the-executable\" class=\"level3\">\n<h3>Building the executable</h3>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Build</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a><span class=\"at\">      </span><span class=\"fu\">uses</span><span class=\"kw\">:</span><span class=\"at\"> actions-rs/cargo@v1</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a><span class=\"at\">      </span><span class=\"fu\">with</span><span class=\"kw\">:</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a><span class=\"at\">        </span><span class=\"fu\">use-cross</span><span class=\"kw\">:</span><span class=\"at\"> ${{ matrix.job.use-cross }}</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a><span class=\"at\">        </span><span class=\"fu\">command</span><span class=\"kw\">:</span><span class=\"at\"> build</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\"></a><span class=\"at\">        </span><span class=\"fu\">args</span><span class=\"kw\">:</span><span class=\"at\"> --locked --release --target=${{ matrix.job.target }}</span></span></code></pre></div>\n</section>\n<section id=\"stripping-debug-information-from-binary\" class=\"level3\">\n<h3>Stripping debug information from binary</h3>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Strip debug information from executable</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\"></a><span class=\"at\">      </span><span class=\"fu\">id</span><span class=\"kw\">:</span><span class=\"at\"> strip</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\"></a><span class=\"at\">      </span><span class=\"fu\">shell</span><span class=\"kw\">:</span><span class=\"at\"> bash</span></span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\"></a><span class=\"fu\">      run</span><span class=\"kw\">: </span><span class=\"ch\">|</span></span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\"></a>        # Figure out suffix of binary</span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\"></a>        EXE_suffix=&quot;&quot;</span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\"></a>        case ${{ matrix.job.target }} in</span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\"></a>          *-pc-windows-*) EXE_suffix=&quot;.exe&quot; ;;</span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\"></a>        esac;</span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\"></a>        # Figure out what strip tool to use if any</span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\"></a>        STRIP=&quot;strip&quot;</span>\n<span id=\"cb6-12\"><a href=\"#cb6-12\"></a>        case ${{ matrix.job.target }} in</span>\n<span id=\"cb6-13\"><a href=\"#cb6-13\"></a>          arm-unknown-linux-*) STRIP=&quot;arm-linux-gnueabihf-strip&quot; ;;</span>\n<span id=\"cb6-14\"><a href=\"#cb6-14\"></a>          aarch64-pc-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-15\"><a href=\"#cb6-15\"></a>          aarch64-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-16\"><a href=\"#cb6-16\"></a>          armv7-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-17\"><a href=\"#cb6-17\"></a>          mips-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-18\"><a href=\"#cb6-18\"></a>          mips64-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-19\"><a href=\"#cb6-19\"></a>          mips64el-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-20\"><a href=\"#cb6-20\"></a>          mipsel-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-21\"><a href=\"#cb6-21\"></a>          powerpc-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-22\"><a href=\"#cb6-22\"></a>          powerpc64-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-23\"><a href=\"#cb6-23\"></a>          powerpc64le-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-24\"><a href=\"#cb6-24\"></a>          riscv64gc-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-25\"><a href=\"#cb6-25\"></a>          s390x-unknown-*) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-26\"><a href=\"#cb6-26\"></a>          x86_64-unknown-freebsd) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-27\"><a href=\"#cb6-27\"></a>          x86_64-unknown-illumos) STRIP=&quot;&quot; ;;</span>\n<span id=\"cb6-28\"><a href=\"#cb6-28\"></a>        esac;</span>\n<span id=\"cb6-29\"><a href=\"#cb6-29\"></a>        # Setup paths</span>\n<span id=\"cb6-30\"><a href=\"#cb6-30\"></a>        BIN_DIR=&quot;${{ env.CICD_INTERMEDIATES_DIR }}/stripped-release-bin/&quot;</span>\n<span id=\"cb6-31\"><a href=\"#cb6-31\"></a>        mkdir -p &quot;${BIN_DIR}&quot;</span>\n<span id=\"cb6-32\"><a href=\"#cb6-32\"></a>        BIN_NAME=&quot;${{ env.PROJECT_NAME }}${EXE_suffix}&quot;</span>\n<span id=\"cb6-33\"><a href=\"#cb6-33\"></a>        BIN_PATH=&quot;${BIN_DIR}/${BIN_NAME}&quot;</span>\n<span id=\"cb6-34\"><a href=\"#cb6-34\"></a>        TRIPLET_NAME=&quot;${{ matrix.job.target }}&quot;</span>\n<span id=\"cb6-35\"><a href=\"#cb6-35\"></a>        # Copy the release build binary to the result location</span>\n<span id=\"cb6-36\"><a href=\"#cb6-36\"></a>        cp &quot;target/$TRIPLET_NAME/release/${BIN_NAME}&quot; &quot;${BIN_DIR}&quot;</span>\n<span id=\"cb6-37\"><a href=\"#cb6-37\"></a>        # Also strip if possible</span>\n<span id=\"cb6-38\"><a href=\"#cb6-38\"></a>        if [ -n &quot;${STRIP}&quot; ]; then</span>\n<span id=\"cb6-39\"><a href=\"#cb6-39\"></a>          &quot;${STRIP}&quot; &quot;${BIN_PATH}&quot;</span>\n<span id=\"cb6-40\"><a href=\"#cb6-40\"></a>        fi</span>\n<span id=\"cb6-41\"><a href=\"#cb6-41\"></a>        # Let subsequent steps know where to find the (stripped) bin</span>\n<span id=\"cb6-42\"><a href=\"#cb6-42\"></a>        echo ::set-output name=BIN_PATH::${BIN_PATH}</span>\n<span id=\"cb6-43\"><a href=\"#cb6-43\"></a>        echo ::set-output name=BIN_NAME::${BIN_NAME}</span></code></pre></div>\n</section>\n<section id=\"and-uploading-to-github\" class=\"level3\">\n<h3>And uploading to Github</h3>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource yml numberLines\"><code class=\"sourceCode yaml\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Create tarball</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a><span class=\"at\">      </span><span class=\"fu\">id</span><span class=\"kw\">:</span><span class=\"at\"> package</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a><span class=\"at\">      </span><span class=\"fu\">shell</span><span class=\"kw\">:</span><span class=\"at\"> bash</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a><span class=\"fu\">      run</span><span class=\"kw\">: </span><span class=\"ch\">|</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a>        PKG_suffix=&quot;.tar.gz&quot; ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=&quot;.zip&quot; ;; esac;</span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\"></a>        PKG_BASENAME=${PROJECT_NAME}-v${PROJECT_VERSION}-${{ matrix.job.target }}</span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\"></a>        PKG_NAME=${PKG_BASENAME}${PKG_suffix}</span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\"></a>        echo ::set-output name=PKG_NAME::${PKG_NAME}</span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\"></a>        PKG_STAGING=&quot;${{ env.CICD_INTERMEDIATES_DIR }}/package&quot;</span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\"></a>        ARCHIVE_DIR=&quot;${PKG_STAGING}/${PKG_BASENAME}/&quot;</span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\"></a>        mkdir -p &quot;${ARCHIVE_DIR}&quot;</span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\"></a>        mkdir -p &quot;${ARCHIVE_DIR}/autocomplete&quot;</span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\"></a>        # Binary</span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\"></a>        cp &quot;${{ steps.strip.outputs.BIN_PATH }}&quot; &quot;$ARCHIVE_DIR&quot;</span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\"></a>        # base compressed package</span>\n<span id=\"cb7-16\"><a href=\"#cb7-16\"></a>        pushd &quot;${PKG_STAGING}/&quot; &gt;/dev/null</span>\n<span id=\"cb7-17\"><a href=\"#cb7-17\"></a>        case ${{ matrix.job.target }} in</span>\n<span id=\"cb7-18\"><a href=\"#cb7-18\"></a>          *-pc-windows-*) 7z -y a &quot;${PKG_NAME}&quot; &quot;${PKG_BASENAME}&quot;/* | tail -2 ;;</span>\n<span id=\"cb7-19\"><a href=\"#cb7-19\"></a>          *) tar czf &quot;${PKG_NAME}&quot; &quot;${PKG_BASENAME}&quot;/* ;;</span>\n<span id=\"cb7-20\"><a href=\"#cb7-20\"></a>        esac;</span>\n<span id=\"cb7-21\"><a href=\"#cb7-21\"></a>        popd &gt;/dev/null</span>\n<span id=\"cb7-22\"><a href=\"#cb7-22\"></a>        # Let subsequent steps know where to find the compressed package</span>\n<span id=\"cb7-23\"><a href=\"#cb7-23\"></a>        echo ::set-output name=PKG_PATH::&quot;${PKG_STAGING}/${PKG_NAME}&quot;</span>\n<span id=\"cb7-24\"><a href=\"#cb7-24\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> </span><span class=\"st\">&quot;Artifact upload: tarball&quot;</span></span>\n<span id=\"cb7-25\"><a href=\"#cb7-25\"></a><span class=\"at\">      </span><span class=\"fu\">uses</span><span class=\"kw\">:</span><span class=\"at\"> actions/upload-artifact@master</span></span>\n<span id=\"cb7-26\"><a href=\"#cb7-26\"></a><span class=\"at\">      </span><span class=\"fu\">with</span><span class=\"kw\">:</span></span>\n<span id=\"cb7-27\"><a href=\"#cb7-27\"></a><span class=\"at\">        </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> ${{ steps.package.outputs.PKG_NAME }}</span></span>\n<span id=\"cb7-28\"><a href=\"#cb7-28\"></a><span class=\"at\">        </span><span class=\"fu\">path</span><span class=\"kw\">:</span><span class=\"at\"> ${{ steps.package.outputs.PKG_PATH }}</span></span>\n<span id=\"cb7-29\"><a href=\"#cb7-29\"></a></span>\n<span id=\"cb7-30\"><a href=\"#cb7-30\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Check for release</span></span>\n<span id=\"cb7-31\"><a href=\"#cb7-31\"></a><span class=\"at\">      </span><span class=\"fu\">id</span><span class=\"kw\">:</span><span class=\"at\"> is-release</span></span>\n<span id=\"cb7-32\"><a href=\"#cb7-32\"></a><span class=\"at\">      </span><span class=\"fu\">shell</span><span class=\"kw\">:</span><span class=\"at\"> bash</span></span>\n<span id=\"cb7-33\"><a href=\"#cb7-33\"></a><span class=\"fu\">      run</span><span class=\"kw\">: </span><span class=\"ch\">|</span></span>\n<span id=\"cb7-34\"><a href=\"#cb7-34\"></a>        unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE=&#39;true&#39; ; fi</span>\n<span id=\"cb7-35\"><a href=\"#cb7-35\"></a>        echo ::set-output name=IS_RELEASE::${IS_RELEASE}</span>\n<span id=\"cb7-36\"><a href=\"#cb7-36\"></a><span class=\"at\">    </span><span class=\"kw\">-</span><span class=\"at\"> </span><span class=\"fu\">name</span><span class=\"kw\">:</span><span class=\"at\"> Publish archives and packages</span></span>\n<span id=\"cb7-37\"><a href=\"#cb7-37\"></a><span class=\"at\">      </span><span class=\"fu\">uses</span><span class=\"kw\">:</span><span class=\"at\"> softprops/action-gh-release@v1</span></span>\n<span id=\"cb7-38\"><a href=\"#cb7-38\"></a><span class=\"at\">      </span><span class=\"fu\">if</span><span class=\"kw\">:</span><span class=\"at\"> steps.is-release.outputs.IS_RELEASE</span></span>\n<span id=\"cb7-39\"><a href=\"#cb7-39\"></a><span class=\"at\">      </span><span class=\"fu\">with</span><span class=\"kw\">:</span></span>\n<span id=\"cb7-40\"><a href=\"#cb7-40\"></a><span class=\"fu\">        files</span><span class=\"kw\">: </span><span class=\"ch\">|</span></span>\n<span id=\"cb7-41\"><a href=\"#cb7-41\"></a>          ${{ steps.package.outputs.PKG_PATH }}</span>\n<span id=\"cb7-42\"><a href=\"#cb7-42\"></a><span class=\"at\">      </span><span class=\"fu\">env</span><span class=\"kw\">:</span></span>\n<span id=\"cb7-43\"><a href=\"#cb7-43\"></a><span class=\"at\">        </span><span class=\"fu\">GITHUB_TOKEN</span><span class=\"kw\">:</span><span class=\"at\"> ${{ secrets.GITHUB_TOKEN }} </span></span></code></pre></div>\n<p>And after building this github actions file, we find that\u2026 3 targets\nfail to build.</p>\n<p><code>x86_64-unknown-freebsd</code>,\n<code>x86_64-unknown-illumos</code>,\n<code>powerpc-unknown-linux-gnu</code>.</p>\n<p>Luckily, the error message that cross provides gives us a clear\nindication of what to fix. Cross does not provide a proper image, so it\ngets confused, defaults to the toolchain it\u2019s running on (ubuntu 20.04),\nand the linker cannot find the proper libraries required. Easy to fix:\nAdd a <code>Cross.toml</code> file to the root of the project with\ndocker images for the particular targets, and build again.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode numberSource toml numberLines\"><code class=\"sourceCode toml\"><span id=\"cb8-1\"><a href=\"#cb8-1\"></a><span class=\"kw\">[target.x86_64-unknown-freebsd]</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\"></a><span class=\"dt\">image</span> <span class=\"op\">=</span> <span class=\"st\">&quot;svenstaro/cross-x86_64-unknown-freebsd&quot;</span></span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\"></a></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\"></a><span class=\"kw\">[target.powerpc64-unknown-linux-gnu]</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\"></a><span class=\"dt\">image</span> <span class=\"op\">=</span> <span class=\"st\">&quot;japaric/powerpc64-unknown-linux-gnu&quot;</span></span></code></pre></div>\n<p>You\u2019ll notice that illumos is missing here \u2013 I couldn\u2019t find a\nsuitable docker image to build it on docker hub, so I gave up. If you\nfind one, let me know and i\u2019ll update this article.</p>\n</section>\n</section>\n<section id=\"results\" class=\"level2\">\n<h2>Results</h2>\n<p>Out of the 29 architectures provided in Tier 1 and Tier 2 with host\ntools, it was easy enough to build a binary for 28 architectures (We\nonly need a solaris/illumos docker image to build for the last one).</p>\n<p>That\u2019s pretty good, given that this only took a couple of hours to\ntest out. I hope Rust continues to support this many architectures into\nthe future, and Github Actions keeps being a good platform to make\nreleases for.</p>\n<p>If you\u2019d like to take the repo for yourself to build rust binaries on\nreleases for 28 architectures, feel free to clone/fork the repo here: <a\nhref=\"https://github.com/Takashiidobe/rust-build-binary-github-actions\"\nclass=\"uri\">https://github.com/Takashiidobe/rust-build-binary-github-actions</a></p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-11-03T14:24:46+00:00"
		},
		{
			"id": "gen/offline-email.html",
			"url": "gen/offline-email.html",
			"title": "Offline e-mail in the terminal",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Offline e-mail in the terminal</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Offline e-mail in the terminal</h1>\n<p class=\"byline\">2021-10-27T09:44:59-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#setting-up-aerc\" id=\"toc-setting-up-aerc\">Setting up\nAerc</a></li>\n<li><a href=\"#offline-support\" id=\"toc-offline-support\">Offline\nSupport</a>\n<ul>\n<li><a href=\"#mbsync-for-reading-e-mail-offline\"\nid=\"toc-mbsync-for-reading-e-mail-offline\">Mbsync for reading e-mail\noffline</a></li>\n<li><a href=\"#sending-e-mail-offline\"\nid=\"toc-sending-e-mail-offline\">Sending E-mail offline</a></li>\n</ul></li>\n</ul>\n</nav>\n<p>I like putting stuff in the terminal. Let\u2019s roll back the clock 30\nyears and go back to terminal e-mail.</p>\n<p>Let\u2019s start with installing an e-mail client.</p>\n<p>I like <a href=\"https://aerc-mail.org/\">aerc</a>. I also use mac OS,\nso it can be installed with a simple <code>brew install aerc</code>.</p>\n<section id=\"setting-up-aerc\" class=\"level2\">\n<h2>Setting up Aerc</h2>\n<p>Here\u2019s another guide for that: <a\nhref=\"https://oren.github.io/articles/text-based-gmail/\">Text based\ngmail</a></p>\n<p>I personally use a gmail, so I had to create a gmail app password to\nprovide to aerc.</p>\n<p>On first startup, aerc has a startup wizard that helps you set up\nyour account. Nice! Put in your information and enjoy e-mail in the\nterminal.</p>\n<p>My <code>aerc/accounts.conf</code> looks something like this:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"ex\">[Personal]</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a><span class=\"bu\">source</span>        = imap://me@gmail.com:password@imap.gmail.com:993</span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a><span class=\"ex\">outgoing</span>      = smtp+plain://me@gmail.com:<span class=\"va\">$APP_PASSWORD_HERE</span>@smtp.gmail.com:587</span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a><span class=\"ex\">smtp-starttls</span> = yes</span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a><span class=\"ex\">from</span>          = Me <span class=\"op\">&lt;</span>me@gmail.com<span class=\"op\">&gt;</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a><span class=\"ex\">copy-to</span>       = Sent</span></code></pre></div>\n<p>As well, I wanted to change up some of the defaults:</p>\n<p>I set my <code>aerc/aerc.conf</code> like so: this sets my pager to\n<code>bat</code> instead of <code>less -R</code>, and prefers to display\nthe HTML portion of an email first if possible, then falling back to the\nplain text version.</p>\n<p>To be able to read HTML e-mail, I uncommented the line for text/html,\nand use the html filter that\u2019s provided by aerc. This requires\n<code>w3m</code> and <code>dante</code>, so I brew installed both:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"ex\">brew</span> install w3m</span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a><span class=\"ex\">brew</span> install dante</span></code></pre></div>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"ex\">[viewer]</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a><span class=\"va\">pager</span><span class=\"op\">=</span>/usr/local/bin/bat</span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a><span class=\"va\">alternatives</span><span class=\"op\">=</span>text/html,text/plain</span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a><span class=\"ex\">[filters]</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a><span class=\"ex\">subject,~^\\[PATCH=awk</span> <span class=\"at\">-f</span> @SHAREDIR@/filters/hldiff</span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\"></a><span class=\"ex\">text/html=bash</span> /usr/local/share/aerc/filters/html</span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\"></a><span class=\"ex\">text/*=awk</span> <span class=\"at\">-f</span> /usr/local/share/aerc/filters/plaintext</span></code></pre></div>\n<p>Great! Now we\u2019re all set up with aerc.</p>\n</section>\n<section id=\"offline-support\" class=\"level2\">\n<h2>Offline Support</h2>\n<p>This is great and all, but try to run <code>aerc</code> without\ninternet connection. It hangs. That\u2019s not acceptable! Let\u2019s fix\nthat.</p>\n<p>Drew DeVault, the original author of <code>aerc</code> published a\nguide on making <code>aerc</code> work offline <a\nhref=\"https://drewdevault.com/2021/05/17/aerc-with-mbsync-postfix.html\"\nclass=\"uri\">https://drewdevault.com/2021/05/17/aerc-with-mbsync-postfix.html</a>.\nWe\u2019ll follow this guide a bit, but I use gmail instead of\n<code>migadu</code>, and ended up using <code>msmtp</code> instead of\n<code>postfix</code>, so there\u2019ll be a few changes.</p>\n<section id=\"mbsync-for-reading-e-mail-offline\" class=\"level3\">\n<h3>Mbsync for reading e-mail offline</h3>\n<p>Let\u2019s start off installing <code>mbsync</code>. On Mac OS it is\nlisted as its previous name, <code>isync</code>. So run\n<code>brew install isync</code> to install it.</p>\n<p>We\u2019ll then set it up \u2013 the config file is at\n<code>~/.mbsyncrc</code>, so create that and fill it with this:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"ex\">IMAPStore</span> gmail-remote</span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\"></a><span class=\"ex\">Host</span> imap.gmail.com</span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\"></a><span class=\"ex\">AuthMechs</span> LOGIN</span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\"></a><span class=\"ex\">User</span> you@gmail.com</span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\"></a><span class=\"ex\">Pass</span> <span class=\"va\">$APP_PASSWORD_HERE</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\"></a><span class=\"ex\">SSLType</span> IMAPS</span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\"></a></span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\"></a><span class=\"ex\">MaildirStore</span> gmail-local</span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\"></a><span class=\"ex\">Path</span> ~/mail/gmail/</span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\"></a><span class=\"ex\">Inbox</span> ~/mail/gmail/INBOX</span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\"></a><span class=\"ex\">Subfolders</span> Verbatim</span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\"></a></span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\"></a><span class=\"ex\">Channel</span> gmail</span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\"></a><span class=\"ex\">Far</span> :gmail-remote:</span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\"></a><span class=\"ex\">Near</span> :gmail-local:</span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\"></a><span class=\"ex\">Expunge</span> Both</span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\"></a><span class=\"ex\">Patterns</span> <span class=\"pp\">*</span> !<span class=\"st\">&quot;[Gmail]/All Mail&quot;</span> !<span class=\"st\">&quot;[Gmail]/Important&quot;</span> !<span class=\"st\">&quot;[Gmail]/Starred&quot;</span> !<span class=\"st\">&quot;[Gmail]/Bin&quot;</span></span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\"></a><span class=\"ex\">SyncState</span> <span class=\"pp\">*</span></span></code></pre></div>\n<p>If you don\u2019t already have a <code>~/mail/gmail/INBOX</code> folder,\ncreate it with <code>mkdir -p ~/mail/gmail/INBOX</code>.</p>\n<p>Now, if you run <code>mbsync gmail</code>, all of your e-mail will be\nsynced to your <code>~/mail/gmail</code> folder.</p>\n<p>Now, we just need aerc to pull locally instead of from gmails\nservers.</p>\n<p>Go back to <code>aerc/accounts.conf</code>, and edit the source under\nthe [Personal] tag to point to <code>maildir://~/mail</code>. This will\nlet aerc read your e-mail locally instead of from gmail\u2019s servers.</p>\n<p>As well, set the default to <code>gmail/INBOX</code> to land in your\ninbox folder on start.</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"ex\">[Personal]</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a><span class=\"bu\">source</span>        = maildir://~/mail</span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a><span class=\"ex\">outgoing</span>      = smtp+plain://me@gmail.com:<span class=\"va\">$APP_PASSWORD_HERE</span>@smtp.gmail.com:587</span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a><span class=\"ex\">default</span>       = gmail/INBOX</span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a><span class=\"ex\">smtp-starttls</span> = yes</span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\"></a><span class=\"ex\">from</span>          = Me <span class=\"op\">&lt;</span>me@gmail.com<span class=\"op\">&gt;</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\"></a><span class=\"ex\">copy-to</span>       = Sent</span></code></pre></div>\n<p>Turn off your internet and run <code>aerc</code>. Now you can read\nyour e-mail offline! We\u2019ll want to always keep our mailbox in sync, so\nwe\u2019ll want to run <code>mbsync</code> frequently to keep our mailbox in\nsync.</p>\n<p>First, we\u2019ll need a program called <code>chronic</code>, which is\nprovided in <code>moreutils</code>. Download it with\n<code>brew install moreutils</code>.</p>\n<p>Run <code>crontab -e</code> to edit your local crontab, and put this\nin it.</p>\n<p>This will have cron execute <code>mbsync gmail</code> every minute,\nkeeping your mailbox in sync with google\u2019s servers.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"va\">MAILTO</span><span class=\"op\">=</span><span class=\"st\">&quot;&quot;</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\"></a><span class=\"va\">PATH</span><span class=\"op\">=</span>YOUR_PATH_HERE</span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\"></a><span class=\"ex\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> chronic mbsync gmail</span></code></pre></div>\n</section>\n<section id=\"sending-e-mail-offline\" class=\"level3\">\n<h3>Sending E-mail offline</h3>\n<p>If you try to send e-mail while offline on aerc currently, the e-mail\nwill never send. What we\u2019d like is some queue where the e-mail is sent\nimmediately if we\u2019re online, otherwise, to save that message in a queue,\nand send out all messages immediately as we regain connectivity.</p>\n<p>We\u2019ll use <code>msmtp</code> for that.</p>\n<p>Install it with <code>brew install msmtp</code>.</p>\n<p>msmtp\u2019s config file is called <code>~/.msmtprc</code>. Fill that file\nwith this:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"ex\">defaults</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a><span class=\"ex\">tls</span> on</span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a><span class=\"ex\">account</span> gmail</span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a><span class=\"ex\">auth</span> on</span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\"></a><span class=\"ex\">host</span> smtp.gmail.com</span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\"></a><span class=\"ex\">port</span> 587</span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\"></a><span class=\"ex\">user</span> me</span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\"></a><span class=\"ex\">from</span> me@gmail.com</span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\"></a><span class=\"ex\">password</span> APP_PASSWORD_HERE</span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\"></a></span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\"></a><span class=\"ex\">account</span> default: gmail</span></code></pre></div>\n<p>Now we can send e-mail from the command line. This isn\u2019t super useful\nyet, since aerc has this functionality already. Next, we need to\nimplement the queueing capability we discussed. You\u2019ll want to download\ntwo bash scripts that do this for us: <code>msmtpq</code> and\n<code>msmtp-queue</code>. These can be found here: <a\nhref=\"https://github.com/tpn/msmtp/tree/master/scripts/msmtpq\"\nclass=\"uri\">https://github.com/tpn/msmtp/tree/master/scripts/msmtpq</a>.\nMake them executable and place them somewhere on your path (I chose\n<code>/usr/local/bin</code>). This implements the queueing that be\ndiscussed.</p>\n<p>Finally, we\u2019ll have to hook up <code>aerc</code> to use this\ncapability in <code>accounts.conf</code>.</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\"></a><span class=\"ex\">[Personal]</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\"></a><span class=\"bu\">source</span>        = maildir://~/mail</span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\"></a><span class=\"ex\">outgoing</span>      = /usr/local/bin/msmtpq</span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\"></a><span class=\"ex\">default</span>       = gmail/INBOX</span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\"></a><span class=\"ex\">smtp-starttls</span> = yes</span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\"></a><span class=\"ex\">from</span>          = Me <span class=\"op\">&lt;</span>me@gmail.com<span class=\"op\">&gt;</span></span>\n<span id=\"cb8-7\"><a href=\"#cb8-7\"></a><span class=\"ex\">copy-to</span>       = Sent</span></code></pre></div>\n<p>Finally, we\u2019ll want to be able to execute the queueing functionality\nof <code>msmtpq</code> every minute as well. Edit your crontab to look\nlike this:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb9-1\"><a href=\"#cb9-1\"></a><span class=\"va\">MAILTO</span><span class=\"op\">=</span><span class=\"st\">&quot;&quot;</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\"></a><span class=\"va\">PATH</span><span class=\"op\">=</span>YOUR_PATH_HERE</span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\"></a><span class=\"ex\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> chronic mbsync gmail</span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\"></a><span class=\"ex\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> <span class=\"pp\">*</span> chronic msmtp-queue <span class=\"at\">-r</span></span></code></pre></div>\n<p>And with that, we\u2019re done! We can now read e-mail offline, which\nsyncs every minute when online, and send e-mail offline, which will get\nqueued, and sent as soon as we\u2019re back online again.</p>\n</section>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-10-27T14:44:59+00:00"
		},
		{
			"id": "gen/work-offline.html",
			"url": "gen/work-offline.html",
			"title": "Work Offline",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Work Offline</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Work Offline</h1>\n<p class=\"byline\">2021-10-07T20:43:45-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#tools-of-the-trade\" id=\"toc-tools-of-the-trade\">Tools of\nthe Trade</a>\n<ul>\n<li><a href=\"#git\" id=\"toc-git\">Git</a></li>\n<li><a href=\"#man-pages\" id=\"toc-man-pages\">Man Pages</a></li>\n<li><a href=\"#tldr\" id=\"toc-tldr\">Tldr</a></li>\n<li><a href=\"#zim-files\" id=\"toc-zim-files\">ZIM files</a></li>\n<li><a href=\"#devdocs\" id=\"toc-devdocs\">DevDocs</a></li>\n<li><a href=\"#e-books\" id=\"toc-e-books\">E-books</a></li>\n<li><a href=\"#papers\" id=\"toc-papers\">Papers</a></li>\n<li><a href=\"#rustup-cargo\" id=\"toc-rustup-cargo\">Rustup +\nCargo</a></li>\n</ul></li>\n<li><a href=\"#hardware\" id=\"toc-hardware\">Hardware</a></li>\n</ul>\n</nav>\n<p>In my last post, I discussed the tradeoffs of various languages with\nregards to software longevity \u2013 I wanted to pick a language to use that\nwould make long lasting software.</p>\n<p>In this post, I want to discuss working offline \u2013 why that\ninterleaves with the choice of language to use, and how to use tooling\nto make that accessible.</p>\n<p>Joe Nelson, of PostgREST fame, wrote a series of posts that resonated\nwith me \u2013 starting with <a\nhref=\"https://begriffs.com/posts/2015-04-20-going-write-only.html\">\u201cGoing\n\u2018Write Only\u2019\u201d</a> where he starts off with quoting Joey Hess, a person\nwho \u201cLives in a cabin and programs Haskell on a drastically\nunder-powered netbook\u201d, where he harvests all of his electricity from\nthe sun, and works using a distributed workflow, much like a git\nworkflow.</p>\n<p>He then goes on to explain his motivation of going \u201cwrite-only\u201d\nthusly:</p>\n<blockquote>\n<p>These people\u2019s thoughts are not idle for me. They contain a reproach,\na warning that one can be very busy and yet do unproductive things,\nhamartia. I want to focus on doing the right thing. Actually focus is\nthe wrong word. Focusing my thoughts would imply the same thoughts but\nsharper, whereas I want to change the way I think.</p>\n</blockquote>\n<p>He then went on to publish more blog posts focused on creating\nsoftware that lasts:</p>\n<ul>\n<li><a\nhref=\"https://begriffs.com/posts/2017-04-13-longterm-computing-reading.html\">Good\nbooks for deep hacks</a></li>\n<li><a\nhref=\"https://begriffs.com/posts/2019-01-19-inside-c-standard-lib.html\">Inside\nthe C Standard Library</a></li>\n<li><a\nhref=\"https://begriffs.com/posts/2020-08-31-portable-stable-software.html\">Tips\nfor stable and portable Software</a></li>\n<li><a\nhref=\"https://begriffs.com/posts/2021-07-04-shared-libraries.html\">Dynamic\nlinking best practices</a></li>\n</ul>\n<p>Which are all great reads, and inspired me to write this post about\nhow I work offline, and what I use to make that happen.</p>\n<section id=\"tools-of-the-trade\" class=\"level2\">\n<h2>Tools of the Trade</h2>\n<section id=\"git\" class=\"level3\">\n<h3><a href=\"https://git-scm.com/\">Git</a></h3>\n<p>It\u2019s a no-brainer to use git for this kind of workflow. You can go\noffline for weeks at a time, hacking away at your branch, and when\nyou\u2019re back online, merge back to the main branch, fetch what you\nmissed, and go back to hacking away offline. Since you have a copy of\nall the history of the repo on your hard disk, if you need to look at\nchanges from the past, you can do just that. Git enables this workflow,\nwhile other centralized systems require constant connectivity.</p>\n</section>\n<section id=\"man-pages\" class=\"level3\">\n<h3><a href=\"https://www.kernel.org/doc/man-pages/\">Man Pages</a></h3>\n<p>Man pages (and info pages) predate the internet, so of course they\nwork well offline. Unfortunately for Mac, Man pages are pretty sparse\n(basically scavenged off of old BSD manuals), and they aren\u2019t always the\nmost descriptive when it comes to using cli tools, so I tend to use\n<code>tldr</code> for that case.</p>\n<p>To pay it forward, I tend to bundle man pages with utilities that I\nmake, like <code>rvim</code> or <code>simplestats</code> on cargo, even\nthough rust docs are more common in rust land.</p>\n</section>\n<section id=\"tldr\" class=\"level3\">\n<h3><a href=\"https://github.com/tldr-pages/tldr\">Tldr</a></h3>\n<p>Ever remember how to use <code>tar</code>? Me neither. Tldr is a man\npages complement, offering examples for cli applications just by typing\n<code>tldr $keyword</code>. I personally really like it, because it\u2019s\nlike having a concise stackoverflow at your fingertips.</p>\n</section>\n<section id=\"zim-files\" class=\"level3\">\n<h3><a href=\"https://wiki.openzim.org/wiki/OpenZIM\">ZIM files</a></h3>\n<p>When I tell people about working offline, they ask \u201cbut what about X\nwebsite?\u201d. Well, if you want to look up a question on wikipedia or\nstackoverflow, you\u2019d surely need online access, right?</p>\n<p>That\u2019s where ZIM files come in \u2013 offline archives of whole websites.\nThe kiwix project (sponsored by wikipedia) offers downloads and torrents\nfor ZIM files for sites like wikipedia and stackoverflow, which you can\nwholesale download over an internet connection, and then search through\nto your hearts content. So if you ever forget how to reverse a linked\nlist in your favorite language, you can search through stackoverflow to\nfind out.</p>\n<ul>\n<li><a href=\"https://dumps.wikimedia.org/other/kiwix/zim/wikipedia/\"\nclass=\"uri\">https://dumps.wikimedia.org/other/kiwix/zim/wikipedia/</a></li>\n<li><a href=\"https://ftp.fau.de/kiwix/zim/stack_exchange/\"\nclass=\"uri\">https://ftp.fau.de/kiwix/zim/stack_exchange/</a></li>\n</ul>\n<p>You can also download wikipedia\u2019s own ZIM file archiver and archive\nother sites that you like.</p>\n</section>\n<section id=\"devdocs\" class=\"level3\">\n<h3><a href=\"https://devdocs.io/\">DevDocs</a></h3>\n<p>Not all languages/projects have offline documentation, but most of\nthem have documentation on the web. DevDocs is a project that allows you\nto download and search through that documentation in a convenient way\noffline. Every time you get back online, you can sync the documentation\nof the projects you like to follow. Nifty.</p>\n</section>\n<section id=\"e-books\" class=\"level3\">\n<h3>E-books</h3>\n<p>E-Books are really great too, in both PDF and epub format. You can\nkeep a copy of them on your hard disk and search through them too\nwithout going to the internet.</p>\n</section>\n<section id=\"papers\" class=\"level3\">\n<h3>Papers</h3>\n<p><a href=\"https://arxiv.org/\">Arxiv</a> is a repository of open access\narticles in the sciences and maths. You can download papers off there\nfor free, and read them at your leisure. There\u2019s a treasure trove of\npapers to read!</p>\n</section>\n<section id=\"rustup-cargo\" class=\"level3\">\n<h3><a href=\"https://www.rust-lang.org/learn\">Rustup + Cargo</a></h3>\n<p>Rust has a strong focus on offline work \u2013 cargo allows you to turn\ndocstring comments into HTML documentation with search, and\n<code>rustup</code> comes with its own offline documentation, by virtue\nof <code>rustup docs</code>.</p>\n<p>Cargo also allows one to force offline mode by adding the\n<code>--offline</code> command line flag \u2013 this forces cargo to use\ndownloaded crates instead of going to <code>crates.io</code>.</p>\n</section>\n</section>\n<section id=\"hardware\" class=\"level2\">\n<h2>Hardware</h2>\n<p>Currently, I work off of a Macbook pro 2017, which only has 128GB of\nhard disk space. If I want to supplant that with extra hard disk space,\nI have an external SSD that I carry around with me (with ZIM files for\noffline use). That being said, it is getting a bit old in 2022, and I\nmay replace it in the coming years for a <a\nhref=\"https://frame.work\">framework laptop</a>, as the company is very\ndevoted to right to repair.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-10-08T01:43:45+00:00"
		},
		{
			"id": "gen/software-that-lasts-offline.html",
			"url": "gen/software-that-lasts-offline.html",
			"title": "Software that lasts Offline",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Software that lasts Offline</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Software that lasts Offline</h1>\n<p class=\"byline\">2021-10-01T23:05:13-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#javascript\" id=\"toc-javascript\">Javascript</a></li>\n<li><a href=\"#typescript\" id=\"toc-typescript\">Typescript</a></li>\n<li><a href=\"#wasm\" id=\"toc-wasm\">WASM</a></li>\n<li><a href=\"#ruby\" id=\"toc-ruby\">Ruby</a></li>\n<li><a href=\"#python\" id=\"toc-python\">Python</a></li>\n<li><a href=\"#ocaml\" id=\"toc-ocaml\">OCaml</a></li>\n<li><a href=\"#jvm-languages-java-scala-clojure\"\nid=\"toc-jvm-languages-java-scala-clojure\">JVM languages (Java, Scala,\nClojure)</a></li>\n<li><a href=\"#clr-languages-c-f\" id=\"toc-clr-languages-c-f\">CLR\nlanguages (C#, F#)</a></li>\n<li><a href=\"#go\" id=\"toc-go\">Go</a></li>\n<li><a href=\"#c\" id=\"toc-c\">C++</a></li>\n<li><a href=\"#c-1\" id=\"toc-c-1\">C</a></li>\n<li><a href=\"#rust-every-day-for-3-years\"\nid=\"toc-rust-every-day-for-3-years\">Rust Every Day (For 3\nyears)</a></li>\n</ul>\n</nav>\n<p>It seems like every day software gets outdated. It\u2019s so hard to build\nsoftware that lasts for 3 years, let alone 30. Yet the houses we live in\nhave seen much longer lives, with just a bit of refurbishing here and\nthere. Why can\u2019t our software be the same way? _why the lucky stiff said\nsomething that resounds with me as a programmer as he left the\ninternet.</p>\n<blockquote>\n<p>To Program anymore was pointless.</p>\n<p>My programs would never live as long as the trial.</p>\n<p>A computer will never live as long as the trial.</p>\n<p>What if Amerika was only written for 32-bit power pc?</p>\n<p>Can an unfinished program be reconstructed??</p>\n<p>Can I write a program and go, \u201cAh, Well, You get the gist of it.\u201d</p>\n</blockquote>\n<p>Our software doesn\u2019t last as long as the written word. It\u2019s a very\ndefeating thing to think that most of our code doesn\u2019t last that long. I\nwondered if it had to be this way, or if it was something to do with how\nwe approached software writing. C code has lasted for a few decades, and\ncould last a few more \u2013 there\u2019s lots of COBOL and FORTRAN code in the\nwild that\u2019s 50 years old. Software that lasts is both high-level and\nlow-level at the same time \u2013 assembly would never last because it\u2019s tied\nto its platform.</p>\n<p>A higher-level language need not be tied to any specific\narchitecture. Yet the need for compatibility with architectures, past,\npresent, and future makes it so the language must only build off of\nlow-level primitives. A contradiction.</p>\n<p>I want a language that has offline documentation, that is robust, has\nwide compatibility in the past, present, and future, has standards, has\nmultiple implementations, is fast, and is easy to develop for. Here\u2019s a\nshort list of the languages I looked at, with some pros and cons for\neach in making software that lasts.</p>\n<section id=\"javascript\" class=\"level2\">\n<h2>Javascript</h2>\n<p>Javascript is well specified (by committee), with multiple\nimplementations, and a strong commitment to backwards compatibility \u2013\nbut that\u2019s about where the pros end. Even though I coded professionally\nin Javascript for a few years, things about the language still trip me\nup \u2013 I sometimes forget to check for nulls, or I get different types\nthan what I\u2019m expecting when I use the standard library. As well, I know\nthose things will never be fixed, because the web is the most popular\nfor programming. Therefore, fundamentally, the language will never be\nable to smooth out its warts.</p>\n</section>\n<section id=\"typescript\" class=\"level2\">\n<h2>Typescript</h2>\n<p>Typescript smooths out <em>most</em> of the usability issues of\nJavascript, and gives it static typing, generics, and new constructs\n(enums, interfaces, types). It compiles to Javascript quickly, and\nconsidering how accessible Javascript is, it shares most of its\naccessibility pros. That being said, Typescript has more lax backwards\ncompatibility requirements, but with its compatibility to Javascript,\nwon\u2019t be able to fix the language\u2019s warts.</p>\n</section>\n<section id=\"wasm\" class=\"level2\">\n<h2>WASM</h2>\n<p>Web Assembly is a new contender for web language of the future\n<em>TM</em>. It\u2019s a minimalistic language with S-expressions (like\nlisps) and is meant to be an easy compiler target. Go, C, C++, Rust, and\nothers can compile down to it, targeting the WASM capabilities of the\nbrowser. As well, WASI seems like a portable way to run sandboxed\napplications in the future.</p>\n<p>It\u2019s too low-level for productive use, but is an interesting foray\ninto fixing the kludge of the web.</p>\n</section>\n<section id=\"ruby\" class=\"level2\">\n<h2>Ruby</h2>\n<p>Ruby is the most OOP language I can think of \u2013 message passing,\neverything is an object, and GC pauses ad nauseum. It\u2019s a language with\na lot of expressiveness, and a lot of elegance. It has strong C\nbindings, so it has good interop with system libraries \u2013 and pretty good\nbackwards compatibility.</p>\n<p>That being said, it\u2019s slow and clunky to write. The philosophy of\nexpressiveness means that everybody writes ruby code differently, and\nthere\u2019s a huge divide between ruby programmers, who are more restrictive\nwith what functionality they use, and rails programmers, who are more\nkeen on monkey-patching everything they can find for usability reasons.\nNot to say one side is right, but the language\u2019s stewardship has been on\nappeasing many camps, and that leads to fragmentation.</p>\n</section>\n<section id=\"python\" class=\"level2\">\n<h2>Python</h2>\n<p>Python is also very OOP, but contrary to ruby, it even comes with its\nown Zen, which you can read by entering <code>import this</code> at the\nREPL.</p>\n<p>Beautiful is better than ugly. Explicit is better than implicit.\nSimple is better than complex. Complex is better than complicated. Flat\nis better than nested. Sparse is better than dense. Readability counts.\nThere should be one\u2013 and preferably only one \u2013obvious way to do it.</p>\n<p>Python prefers fewer ways to do one thing, but that zen has been\nwearing off, with a huge standard library, which makes it hard to commit\nto backwards compatibility. Python has some system dependencies that are\nless than stellar when it comes to backwards compatibility, and the\nlarge surface area can make it hard for the language to keep stable.</p>\n<p>Oh yeah, and remember Python3?</p>\n</section>\n<section id=\"ocaml\" class=\"level2\">\n<h2>OCaml</h2>\n<p>OCaml is an interesting language; it has a bytecode interpreter,\ncross compilation, and compilation to native, just like Haskell. It\u2019s\nrelatively fast to compile, but has issues with backwards compatibility\nand footguns. As well, the standard library has been reimplemented by\nmany, including by Jane Street, twice (Base and Core).</p>\n<p>It\u2019s a clear language with some baggage (Few people use the \u201cObject\nOriented\u201d or \u201cO\u201d features of \u201cOCaml\u201d). For loops and classes are often\nstruck down in code review as anti-patterns. Best to be functional, all\nthe time.</p>\n<p>It is relatively fast, with a good ecosystem (Dune makes building\nOCaml apps pretty nice in 2021) but it\u2019s still a relatively small\necosystem, fighting against Haskell to become Typed Functional\nProgramming\u2019s main language.</p>\n<p>Offline Documentation is great, and the standard library has few\nwants of its environment, but it lacks multicore support \u2013 in an\nincreasingly parallel world, that\u2019s a deal-breaker. It\u2019s looking like a\nreimplementation of the standard library with async might require a\nmajor version bump, to (5.X).</p>\n</section>\n<section id=\"jvm-languages-java-scala-clojure\" class=\"level2\">\n<h2>JVM languages (Java, Scala, Clojure)</h2>\n<p>JVM languages are pretty strong, with the JVM allowing users to\ntarget many platforms with their code (since the JVM runs on many\nthings). That being said, the JVM offers some penalty, because the\nruntimes can be quite hefty and difficult to port. It\u2019s not quite as\neasy as sending someone a binary and they can run it, or easy to\ncontainerize JVM apps, unlike those that offer native binaries.</p>\n</section>\n<section id=\"clr-languages-c-f\" class=\"level2\">\n<h2>CLR languages (C#, F#)</h2>\n<p>Same as the JVM languages, although I have to say that F# and C# are\npretty fun to program in.</p>\n</section>\n<section id=\"go\" class=\"level2\">\n<h2>Go</h2>\n<p>Go was the first <em>serious</em> language in the list I considered\nlearning \u2013 simple like C, with a strong standard library for the modern\nera with a focus on async + web programming. Sounds like a dream. Oh,\nand fast compile times and cross-compilation. Woah. Relatively small\nnative binaries that don\u2019t rely on libc? Doable in Go.</p>\n<p>Lots of big projects have been done in go, like most hashicorp stuff,\ndocker, kubernetes, and a wealth of devops/cloud tools. It\u2019s a\nproductive language, and one that nudges you to sane defaults.</p>\n<p>But it\u2019s not all sunshine and roses \u2013 the package managing story has\nbeen a nightmare, there are no generics (Hello casting to Interface{})\nand I don\u2019t understand why a GC\u2019ed language should have pointers and\nreferences explicitly? You get a lot for free, just by using Go, but you\npay for it with complexity \u2013 I rarely miss generics as an application\ndeveloper, until I\u2019m slapped with complexity because the library\ndeveloper decided to hand over the complexity to me. Go also has one\nstandard implementation and stewardship led by Google, which makes it a\nbit odd \u2013 Google has never been one for backwards compatibility, and it\nseems like Go might be due for a Go 2.0, which could be an ecosystem and\nbinary break for Go. Only time will tell if Go can survive the blow, or\nif it\u2019ll go with the route of holding onto the choices of the past.</p>\n</section>\n<section id=\"c\" class=\"level2\">\n<h2>C++</h2>\n<p>C++ is the first language on this list with no Garbage Collection, it\nhas a specification that\u2019s ISO standardized, with many committees, and\nwith many implementations. It has functionality for OOP, Functional\nProgramming, Generics, async, with the promise of being as fast as C\nwhile staying easier to use.</p>\n<p>It mostly capitalizes on that promise. With the advent of modern C++,\neven though C++ has added many features, it has had a strong promise\ntowards backwards compatibility (it keeps ABI compatibility for a long\ntime, only recently breaking ABI in C++11), and only removing clearly\nbroken functionality (auto_ptr, anyone?) But it can be hard to use \u2013\n(the iterator API is one frustrating example), and it can be hard to see\nthe runtime cost of the abstractions you use \u2013 Even though C++ follows\nthe \u201cZero-Cost Abstractions\u201d principle, where you don\u2019t pay for what you\ndon\u2019t use, and what you do use you couldn\u2019t hand-code any better, it\nbreaks down somewhat \u2013 <code>std::map</code> is extremely slow on\ncertain workloads, because it\u2019s just implemented incorrectly \u2013 and\nIterators are a good example of an API footgun (remember to always check\nfor <code>.end()</code>!).</p>\n<p>The complexity is never really ever paid off \u2013 you have to litter\nyour code with extra keywords like const to the left and right of your\nfunctions, along with noexcept, and final, and override. You have to\nremember what is and what isn\u2019t virtual, and use keywords accordingly,\nand you have to always generate move constructors, copy constructors,\nand remember which one is which \u2013 why are there so many ways to\ninitialize an object, and why are there so many things to remember when\nyou write your own class?</p>\n<p>Oh, and what\u2019s the difference between struct and class? Who\nknows?</p>\n<p>C++ is a language with lots of promises but it has run into the\nlimits of its promises \u2013 backwards compatibility, ease of use,\nperformance, and expressiveness are all in tension, and C++ is the\nlanguage you can see that in the most.</p>\n</section>\n<section id=\"c-1\" class=\"level2\">\n<h2>C</h2>\n<p>Meanwhile, C is much more minimalistic than C++. You get nothing \u2013 no\nexpanding arrays, no hashmaps, no trees, no graphs, no async, no\nunicode, nothing.</p>\n<p>It\u2019s a very bare language. That helps it with portability (C is the\nmost portable language on this list by far) but it pays that price by\ndoing almost nothing for you.</p>\n<p>It\u2019s a high-level language that makes few choices for you and leaves\nyou in a sandbox of your own creation. That can make code-sharing hard,\nsince it\u2019s bound to its environment \u2013 if you want to make a cross\nplatform library, you have to be careful about which libraries you use,\nsince different OSes have different system libraries.</p>\n<p>It has a static type system and is speedy, for sure \u2013 but it can be\nclunky and unsafe as well.</p>\n</section>\n<section id=\"rust-every-day-for-3-years\" class=\"level2\">\n<h2>Rust Every Day (For 3 years)</h2>\n<p>With all that being said, I\u2019ve decided to pick Rust as my language of\nchoice for the next 3 years for as many programming related tasks as I\ncan. Rust is pleasant to develop for, has pledged backwards\ncompatibility since 2015, targets a wide variety of architectures\n(thanks mainly to LLVM) and I\u2019m convinced is a language for the rest of\nmy career; it has a great team working on it, with a unique governance\nstructure that makes it resilient to being steered by one interest\ngroup.</p>\n<p>It\u2019s taken some great ideas from functional programming (Tagged\nUnions, Sum Types, iterators) while keeping the runtime promises of more\nimperative languages. It\u2019s a great language to learn for the future, and\none that I\u2019m sure will keep on growing, and for that, I\u2019m throwing my\nweight behind it.</p>\n<p>Rust every day. For 3 years. Then I\u2019ll revisit this and see what\u2019s\nchanged, but I\u2019d like to use Rust for the next 10 years, at least.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-10-02T04:05:13+00:00"
		},
		{
			"id": "gen/implementing-iterators.html",
			"url": "gen/implementing-iterators.html",
			"title": "Implementing Iterators",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Implementing Iterators</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Implementing Iterators</h1>\n<p class=\"byline\">2021-09-18T21:41:43-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#the-api\" id=\"toc-the-api\">The API</a></li>\n<li><a href=\"#why-use-iterators\" id=\"toc-why-use-iterators\">Why use\nIterators?</a></li>\n<li><a href=\"#next-steps\" id=\"toc-next-steps\">Next Steps</a></li>\n</ul>\n</nav>\n<p>Let\u2019s talk about implementing iterators: a way to visit every item in\na collection. We\u2019ll use C as an implementation language because it\u2019s\nsimpler than other languages, and we\u2019ll implement C++\u2019s iterator API.\nThis is the same in most mainstream programming languages, like Rust,\nC++, Python, Ruby, JavaScript, Java, C#, and PHP, with a few small\nimplementation differences.</p>\n<section id=\"the-api\" class=\"level2\">\n<h2>The API</h2>\n<p>The API we\u2019ll create is simple. A <code>int* next(int* it)</code>\nfunction that takes an iterator and returns its next element, or a\n<code>NULL</code> pointer if nothing comes next, and a\n<code>bool has_next(int* it)</code> that returns <code>true</code> if it\nhas a next item, or <code>false</code> if it does not.</p>\n<p>The C++ iterator API needs a few functions that give you an iterator\nto a collection. These are called <code>begin()</code> and\n<code>end()</code>, which return a pointer to the first item in the\ncollection, and one past the end of the collection. This is a dangerous\nAPI, since if we dereference <code>end()</code> we automatically cause\nUndefined Behavior, but our APIs become a bit cleaner. Tradeoffs, I\nguess.</p>\n<p>We\u2019ll elide the details of begin in our example and implement it\nourselves.</p>\n<p>Let\u2019s start by defining our collection: an array of ints from 1 -\n5.</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"dt\">int</span> items<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"dv\">1</span><span class=\"op\">,</span> <span class=\"dv\">2</span><span class=\"op\">,</span> <span class=\"dv\">3</span><span class=\"op\">,</span> <span class=\"dv\">4</span><span class=\"op\">,</span> <span class=\"dv\">5</span><span class=\"op\">};</span></span></code></pre></div>\n<p>Let\u2019s say we want to print them: no need for iterators, of\ncourse.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a><span class=\"dt\">int</span> items<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"dv\">1</span><span class=\"op\">,</span> <span class=\"dv\">2</span><span class=\"op\">,</span> <span class=\"dv\">3</span><span class=\"op\">,</span> <span class=\"dv\">4</span><span class=\"op\">,</span> <span class=\"dv\">5</span><span class=\"op\">};</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\"></a></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\"></a>    <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> i <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> <span class=\"dv\">5</span><span class=\"op\">;</span> i<span class=\"op\">++)</span> </span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\"></a>        printf<span class=\"op\">(</span><span class=\"st\">&quot;</span><span class=\"sc\">%d</span><span class=\"st\"> &quot;</span><span class=\"op\">,</span> items<span class=\"op\">[</span>i<span class=\"op\">]);</span>  </span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>But we have to initialize and increment a variable and use it as an\nindex to our collection\u2026 We want a clearer way of expressing a loop\nthrough all the items in a collection, and that\u2019s where iterators come\nin.</p>\n<p>Let\u2019s start by defining the begin and end iterators.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> begin <span class=\"op\">=</span> <span class=\"op\">&amp;</span>items<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">];</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> end <span class=\"op\">=</span> <span class=\"op\">&amp;</span>items<span class=\"op\">[</span><span class=\"dv\">5</span><span class=\"op\">];</span></span></code></pre></div>\n<p>Remember, the begin points to the first item of the collection, and\nend points to one past the end. We can\u2019t dereference end, so keep that\nin mind.</p>\n<p>Now, to create the <code>next()</code> function, we want to take an\niterator and move to the next item if we aren\u2019t already at the end\niterator.</p>\n<p>Let\u2019s do that:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> next<span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">*</span> it<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>it <span class=\"op\">!=</span> end<span class=\"op\">)</span> </span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\"></a>        <span class=\"cf\">return</span> it <span class=\"op\">+</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">);</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\"></a>    <span class=\"cf\">return</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Since we know that our iterator is an (int) pointer, we want to\nincrement the iterator four bytes (the result of sizeof(int) on my\ncomputer). This works, but there\u2019s a shorthand that most C compilers\nwill let you do, called pointer arithmetic. In this case, the compiler\nknows that this is an int pointer, and so it\u2019s overloaded additions and\nsubtractions to move forward and backwards by the sizeof an int.</p>\n<p>We can rewrite the above as:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> next<span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">*</span> it<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>it <span class=\"op\">!=</span> end<span class=\"op\">)</span> </span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a>        <span class=\"cf\">return</span> <span class=\"op\">++</span>it<span class=\"op\">;</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a>    <span class=\"cf\">return</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Next, we want to write <code>has_next</code>. <code>has_next</code>\nshould return a <code>bool</code> <code>true</code> if the iterator can\nbe incremented, or <code>false</code> if not. We know that an iterator\nhas a next item if it\u2019s not in the last item in the collection, which is\njust before the end pointer. Thus, we can define <code>has_next</code>\nthusly:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"dt\">int</span> has_next<span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">*</span> it<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\"></a>    <span class=\"cf\">return</span> it <span class=\"op\">!=</span> end <span class=\"op\">-</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Let\u2019s use our iterators thus far to traverse our collection:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a><span class=\"dt\">int</span> items<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"dv\">1</span><span class=\"op\">,</span> <span class=\"dv\">2</span><span class=\"op\">,</span> <span class=\"dv\">3</span><span class=\"op\">,</span> <span class=\"dv\">4</span><span class=\"op\">,</span> <span class=\"dv\">5</span><span class=\"op\">};</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> begin <span class=\"op\">=</span> <span class=\"op\">&amp;</span>items<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">];</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> end <span class=\"op\">=</span> <span class=\"op\">&amp;</span>items<span class=\"op\">[</span><span class=\"dv\">5</span><span class=\"op\">];</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\"></a></span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\"></a><span class=\"dt\">int</span><span class=\"op\">*</span> next<span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">*</span> it<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>it <span class=\"op\">!=</span> end<span class=\"op\">)</span> </span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\"></a>        <span class=\"cf\">return</span> <span class=\"op\">++</span>it<span class=\"op\">;</span></span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\"></a>    <span class=\"cf\">return</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\"></a><span class=\"op\">}</span></span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\"></a></span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\"></a><span class=\"dt\">int</span> has_next<span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">*</span> it<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\"></a>    <span class=\"cf\">return</span> it <span class=\"op\">!=</span> end <span class=\"op\">-</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb7-16\"><a href=\"#cb7-16\"></a><span class=\"op\">}</span></span>\n<span id=\"cb7-17\"><a href=\"#cb7-17\"></a></span>\n<span id=\"cb7-18\"><a href=\"#cb7-18\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-19\"><a href=\"#cb7-19\"></a>    puts<span class=\"op\">(</span><span class=\"st\">&quot;Printing forwards&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb7-20\"><a href=\"#cb7-20\"></a>    <span class=\"dt\">int</span><span class=\"op\">*</span> it <span class=\"op\">=</span> begin<span class=\"op\">;</span></span>\n<span id=\"cb7-21\"><a href=\"#cb7-21\"></a>    <span class=\"cf\">while</span> <span class=\"op\">(</span>it <span class=\"op\">!=</span> end<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-22\"><a href=\"#cb7-22\"></a>        printf<span class=\"op\">(</span><span class=\"st\">&quot;</span><span class=\"sc\">%d</span><span class=\"st\"> has next? &quot;</span><span class=\"op\">,</span> <span class=\"op\">*</span>it<span class=\"op\">);</span></span>\n<span id=\"cb7-23\"><a href=\"#cb7-23\"></a>        puts<span class=\"op\">(</span>has_next<span class=\"op\">(</span>it<span class=\"op\">)</span> <span class=\"op\">?</span> <span class=\"st\">&quot;true&quot;</span> <span class=\"op\">:</span> <span class=\"st\">&quot;false&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb7-24\"><a href=\"#cb7-24\"></a>        it <span class=\"op\">=</span> next<span class=\"op\">(</span>it<span class=\"op\">);</span></span>\n<span id=\"cb7-25\"><a href=\"#cb7-25\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb7-26\"><a href=\"#cb7-26\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This should print out:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode numberSource bash numberLines\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\"></a><span class=\"ex\">Printing</span> forwards</span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\"></a><span class=\"ex\">1</span> has next<span class=\"pp\">?</span> true</span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\"></a><span class=\"ex\">2</span> has next<span class=\"pp\">?</span> true</span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\"></a><span class=\"ex\">3</span> has next<span class=\"pp\">?</span> true</span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\"></a><span class=\"ex\">4</span> has next<span class=\"pp\">?</span> true</span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\"></a><span class=\"ex\">5</span> has next<span class=\"pp\">?</span> false</span></code></pre></div>\n</section>\n<section id=\"why-use-iterators\" class=\"level2\">\n<h2>Why use Iterators?</h2>\n<p>If this seems like a lot of ceremony for iterating through an array,\nit is. It\u2019s totally unnecessary. It gives us nothing more powerful than\nwhat a raw for loop would give us. But what happens if our collection\nisn\u2019t linear? What happens if we traverse a sorted map, or a graph?</p>\n<p>With a for loop, we must ask the caller to understand how the data\nstructure is implemented. With an iterator, we can provide a definition\nof next, and has next, and the user can call it without knowing\n<strong>anything about the underlying collection</strong> outside of the\nfact that it is iterable.</p>\n<p>This allows us to wrap graphs, trees, hash tables, ranges (finite and\ninfinite), and circular data structures in a friendly API for our\nusers.</p>\n<p>As well, language features allow us to reward usage of iterators by\nmaking syntax more terse: In C++, Rust, Java, C#, Ruby, Python, and\nJavaScript, if you implement the iterable API in each language, you can\ndo something along these lines:</p>\n<pre><code>for (item in collection)\n  do something to item</code></pre>\n<p>And the language takes care of the rest. In C, we can\u2019t do that, but\nin other languages, the language gives us some reward for doing so for\nour own types, as our types get to behave like library defined\ntypes.</p>\n</section>\n<section id=\"next-steps\" class=\"level2\">\n<h2>Next Steps</h2>\n<p>Now that we can implement iterators in C, try giving it a shot in\nyour favorite language and seeing what the iterator protocol is for it.\nIt\u2019s loads of fun, I swear.</p>\n<p>I tried it myself in C when writing a resizable array type too:</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb10-1\"><a href=\"#cb10-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">struct</span> Vector <span class=\"op\">{</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\"></a>  <span class=\"dt\">size_t</span> len<span class=\"op\">;</span></span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\"></a>  <span class=\"dt\">size_t</span> capacity<span class=\"op\">;</span></span>\n<span id=\"cb10-4\"><a href=\"#cb10-4\"></a>  <span class=\"dt\">int</span> <span class=\"op\">*</span>items<span class=\"op\">;</span></span>\n<span id=\"cb10-5\"><a href=\"#cb10-5\"></a><span class=\"op\">}</span> Vector<span class=\"op\">;</span></span>\n<span id=\"cb10-6\"><a href=\"#cb10-6\"></a></span>\n<span id=\"cb10-7\"><a href=\"#cb10-7\"></a><span class=\"co\">// Allow the user to set their own alloc/free</span></span>\n<span id=\"cb10-8\"><a href=\"#cb10-8\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> <span class=\"op\">*(*</span>__vector_malloc<span class=\"op\">)(</span><span class=\"dt\">size_t</span><span class=\"op\">)</span> <span class=\"op\">=</span> malloc<span class=\"op\">;</span></span>\n<span id=\"cb10-9\"><a href=\"#cb10-9\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> <span class=\"op\">*(*</span>__vector_realloc<span class=\"op\">)(</span><span class=\"dt\">void</span> <span class=\"op\">*,</span> <span class=\"dt\">size_t</span><span class=\"op\">)</span> <span class=\"op\">=</span> realloc<span class=\"op\">;</span></span>\n<span id=\"cb10-10\"><a href=\"#cb10-10\"></a><span class=\"dt\">static</span> <span class=\"dt\">void</span> <span class=\"op\">(*</span>__vector_free<span class=\"op\">)(</span><span class=\"dt\">void</span> <span class=\"op\">*)</span> <span class=\"op\">=</span> free<span class=\"op\">;</span></span>\n<span id=\"cb10-11\"><a href=\"#cb10-11\"></a></span>\n<span id=\"cb10-12\"><a href=\"#cb10-12\"></a><span class=\"dt\">void</span> vector_set_alloc<span class=\"op\">(</span><span class=\"dt\">void</span> <span class=\"op\">*(</span>malloc<span class=\"op\">)(</span><span class=\"dt\">size_t</span><span class=\"op\">),</span> <span class=\"dt\">void</span> <span class=\"op\">*(</span>realloc<span class=\"op\">)(</span><span class=\"dt\">void</span> <span class=\"op\">*,</span> <span class=\"dt\">size_t</span><span class=\"op\">),</span></span>\n<span id=\"cb10-13\"><a href=\"#cb10-13\"></a>                      <span class=\"dt\">void</span> <span class=\"op\">(*</span>free<span class=\"op\">)(</span><span class=\"dt\">void</span> <span class=\"op\">*))</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-14\"><a href=\"#cb10-14\"></a>  __vector_malloc <span class=\"op\">=</span> malloc<span class=\"op\">;</span></span>\n<span id=\"cb10-15\"><a href=\"#cb10-15\"></a>  __vector_realloc <span class=\"op\">=</span> realloc<span class=\"op\">;</span></span>\n<span id=\"cb10-16\"><a href=\"#cb10-16\"></a>  __vector_free <span class=\"op\">=</span> free<span class=\"op\">;</span></span>\n<span id=\"cb10-17\"><a href=\"#cb10-17\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-18\"><a href=\"#cb10-18\"></a></span>\n<span id=\"cb10-19\"><a href=\"#cb10-19\"></a>Vector <span class=\"op\">*</span>vector_new<span class=\"op\">(</span><span class=\"dt\">const</span> <span class=\"dt\">size_t</span> len<span class=\"op\">,</span> <span class=\"op\">...)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-20\"><a href=\"#cb10-20\"></a>  Vector <span class=\"op\">*</span>v <span class=\"op\">=</span> __vector_malloc<span class=\"op\">(</span><span class=\"kw\">sizeof</span><span class=\"op\">(</span>Vector<span class=\"op\">));</span></span>\n<span id=\"cb10-21\"><a href=\"#cb10-21\"></a>  <span class=\"dt\">int</span> capacity <span class=\"op\">=</span> <span class=\"dv\">8</span><span class=\"op\">;</span></span>\n<span id=\"cb10-22\"><a href=\"#cb10-22\"></a>  capacity <span class=\"op\">=</span> max<span class=\"op\">(</span>pow<span class=\"op\">(</span><span class=\"dv\">2</span><span class=\"op\">,</span> ceil<span class=\"op\">(</span>log<span class=\"op\">(</span>len<span class=\"op\">)</span> <span class=\"op\">/</span> log<span class=\"op\">(</span><span class=\"dv\">2</span><span class=\"op\">))),</span> capacity<span class=\"op\">);</span></span>\n<span id=\"cb10-23\"><a href=\"#cb10-23\"></a></span>\n<span id=\"cb10-24\"><a href=\"#cb10-24\"></a>  v<span class=\"op\">-&gt;</span>items <span class=\"op\">=</span> __vector_malloc<span class=\"op\">(</span><span class=\"kw\">sizeof</span><span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">)</span> <span class=\"op\">*</span> capacity<span class=\"op\">);</span></span>\n<span id=\"cb10-25\"><a href=\"#cb10-25\"></a>  v<span class=\"op\">-&gt;</span>len <span class=\"op\">=</span> len<span class=\"op\">;</span></span>\n<span id=\"cb10-26\"><a href=\"#cb10-26\"></a>  v<span class=\"op\">-&gt;</span>capacity <span class=\"op\">=</span> capacity<span class=\"op\">;</span></span>\n<span id=\"cb10-27\"><a href=\"#cb10-27\"></a></span>\n<span id=\"cb10-28\"><a href=\"#cb10-28\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">&gt;</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-29\"><a href=\"#cb10-29\"></a>    <span class=\"dt\">va_list</span> argp<span class=\"op\">;</span></span>\n<span id=\"cb10-30\"><a href=\"#cb10-30\"></a>    va_start<span class=\"op\">(</span>argp<span class=\"op\">,</span> len<span class=\"op\">);</span></span>\n<span id=\"cb10-31\"><a href=\"#cb10-31\"></a></span>\n<span id=\"cb10-32\"><a href=\"#cb10-32\"></a>    <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">size_t</span> i <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> len<span class=\"op\">;</span> i<span class=\"op\">++)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-33\"><a href=\"#cb10-33\"></a>      v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>i<span class=\"op\">]</span> <span class=\"op\">=</span> va_arg<span class=\"op\">(</span>argp<span class=\"op\">,</span> <span class=\"dt\">int</span><span class=\"op\">);</span></span>\n<span id=\"cb10-34\"><a href=\"#cb10-34\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb10-35\"><a href=\"#cb10-35\"></a></span>\n<span id=\"cb10-36\"><a href=\"#cb10-36\"></a>    va_end<span class=\"op\">(</span>argp<span class=\"op\">);</span></span>\n<span id=\"cb10-37\"><a href=\"#cb10-37\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb10-38\"><a href=\"#cb10-38\"></a></span>\n<span id=\"cb10-39\"><a href=\"#cb10-39\"></a>  <span class=\"cf\">return</span> v<span class=\"op\">;</span></span>\n<span id=\"cb10-40\"><a href=\"#cb10-40\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-41\"><a href=\"#cb10-41\"></a></span>\n<span id=\"cb10-42\"><a href=\"#cb10-42\"></a><span class=\"dt\">void</span> vector_free<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-43\"><a href=\"#cb10-43\"></a>  __vector_free<span class=\"op\">(</span>v<span class=\"op\">-&gt;</span>items<span class=\"op\">);</span></span>\n<span id=\"cb10-44\"><a href=\"#cb10-44\"></a>  __vector_free<span class=\"op\">(</span>v<span class=\"op\">);</span></span>\n<span id=\"cb10-45\"><a href=\"#cb10-45\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-46\"><a href=\"#cb10-46\"></a></span>\n<span id=\"cb10-47\"><a href=\"#cb10-47\"></a><span class=\"dt\">int</span> vector_get<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">,</span> <span class=\"dt\">size_t</span> index<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-48\"><a href=\"#cb10-48\"></a>  assert<span class=\"op\">(</span>index <span class=\"op\">&gt;=</span> <span class=\"dv\">0</span> <span class=\"op\">&amp;&amp;</span> index <span class=\"op\">&lt;</span> v<span class=\"op\">-&gt;</span>len<span class=\"op\">);</span></span>\n<span id=\"cb10-49\"><a href=\"#cb10-49\"></a>  <span class=\"cf\">return</span> v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>index<span class=\"op\">];</span></span>\n<span id=\"cb10-50\"><a href=\"#cb10-50\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-51\"><a href=\"#cb10-51\"></a></span>\n<span id=\"cb10-52\"><a href=\"#cb10-52\"></a><span class=\"dt\">void</span> vector_set<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">,</span> <span class=\"dt\">size_t</span> index<span class=\"op\">,</span> <span class=\"dt\">int</span> val<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-53\"><a href=\"#cb10-53\"></a>  assert<span class=\"op\">(</span>index <span class=\"op\">&gt;=</span> <span class=\"dv\">0</span> <span class=\"op\">&amp;&amp;</span> index <span class=\"op\">&lt;</span> v<span class=\"op\">-&gt;</span>len<span class=\"op\">);</span></span>\n<span id=\"cb10-54\"><a href=\"#cb10-54\"></a>  v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>index<span class=\"op\">]</span> <span class=\"op\">=</span> val<span class=\"op\">;</span></span>\n<span id=\"cb10-55\"><a href=\"#cb10-55\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-56\"><a href=\"#cb10-56\"></a></span>\n<span id=\"cb10-57\"><a href=\"#cb10-57\"></a><span class=\"dt\">int</span> vector_empty<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> v<span class=\"op\">-&gt;</span>len <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb10-58\"><a href=\"#cb10-58\"></a></span>\n<span id=\"cb10-59\"><a href=\"#cb10-59\"></a><span class=\"dt\">void</span> vector_push<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">,</span> <span class=\"dt\">int</span> val<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-60\"><a href=\"#cb10-60\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>v<span class=\"op\">-&gt;</span>len <span class=\"op\">==</span> v<span class=\"op\">-&gt;</span>capacity<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-61\"><a href=\"#cb10-61\"></a>    v<span class=\"op\">-&gt;</span>capacity <span class=\"op\">*=</span> <span class=\"dv\">2</span><span class=\"op\">;</span></span>\n<span id=\"cb10-62\"><a href=\"#cb10-62\"></a>    v<span class=\"op\">-&gt;</span>items <span class=\"op\">=</span> __vector_realloc<span class=\"op\">(</span>v<span class=\"op\">-&gt;</span>items<span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span><span class=\"dt\">int</span><span class=\"op\">)</span> <span class=\"op\">*</span> v<span class=\"op\">-&gt;</span>capacity<span class=\"op\">);</span></span>\n<span id=\"cb10-63\"><a href=\"#cb10-63\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb10-64\"><a href=\"#cb10-64\"></a>  v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>v<span class=\"op\">-&gt;</span>len<span class=\"op\">]</span> <span class=\"op\">=</span> val<span class=\"op\">;</span></span>\n<span id=\"cb10-65\"><a href=\"#cb10-65\"></a>  v<span class=\"op\">-&gt;</span>len<span class=\"op\">++;</span></span>\n<span id=\"cb10-66\"><a href=\"#cb10-66\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-67\"><a href=\"#cb10-67\"></a></span>\n<span id=\"cb10-68\"><a href=\"#cb10-68\"></a><span class=\"dt\">int</span> <span class=\"op\">*</span>vector_begin<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> <span class=\"op\">&amp;</span>v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">];</span> <span class=\"op\">}</span></span>\n<span id=\"cb10-69\"><a href=\"#cb10-69\"></a></span>\n<span id=\"cb10-70\"><a href=\"#cb10-70\"></a><span class=\"dt\">int</span> <span class=\"op\">*</span>vector_end<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">)</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> <span class=\"op\">&amp;</span>v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>v<span class=\"op\">-&gt;</span>len<span class=\"op\">];</span> <span class=\"op\">}</span></span>\n<span id=\"cb10-71\"><a href=\"#cb10-71\"></a></span>\n<span id=\"cb10-72\"><a href=\"#cb10-72\"></a><span class=\"dt\">int</span> <span class=\"op\">*</span>vector_next<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">,</span> <span class=\"dt\">int</span> <span class=\"op\">*</span>it<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-73\"><a href=\"#cb10-73\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>it <span class=\"op\">!=</span> vector_end<span class=\"op\">(</span>v<span class=\"op\">))</span></span>\n<span id=\"cb10-74\"><a href=\"#cb10-74\"></a>    <span class=\"cf\">return</span> <span class=\"op\">++</span>it<span class=\"op\">;</span></span>\n<span id=\"cb10-75\"><a href=\"#cb10-75\"></a>  <span class=\"cf\">return</span> NULL<span class=\"op\">;</span></span>\n<span id=\"cb10-76\"><a href=\"#cb10-76\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-77\"><a href=\"#cb10-77\"></a></span>\n<span id=\"cb10-78\"><a href=\"#cb10-78\"></a><span class=\"dt\">void</span> vector_for_each<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">,</span> <span class=\"dt\">int</span> <span class=\"op\">(*</span>fn<span class=\"op\">)(</span><span class=\"dt\">int</span><span class=\"op\">))</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-79\"><a href=\"#cb10-79\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> i <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> v<span class=\"op\">-&gt;</span>len<span class=\"op\">;</span> i<span class=\"op\">++)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-80\"><a href=\"#cb10-80\"></a>    v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>i<span class=\"op\">]</span> <span class=\"op\">=</span> <span class=\"op\">(*</span>fn<span class=\"op\">)(</span>v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>i<span class=\"op\">]);</span></span>\n<span id=\"cb10-81\"><a href=\"#cb10-81\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb10-82\"><a href=\"#cb10-82\"></a><span class=\"op\">}</span></span>\n<span id=\"cb10-83\"><a href=\"#cb10-83\"></a></span>\n<span id=\"cb10-84\"><a href=\"#cb10-84\"></a><span class=\"dt\">int</span> vector_pop<span class=\"op\">(</span>Vector <span class=\"op\">*</span>v<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-85\"><a href=\"#cb10-85\"></a>  assert<span class=\"op\">(</span>v<span class=\"op\">-&gt;</span>len <span class=\"op\">&gt;</span> <span class=\"dv\">0</span><span class=\"op\">);</span></span>\n<span id=\"cb10-86\"><a href=\"#cb10-86\"></a>  <span class=\"dt\">int</span> top <span class=\"op\">=</span> v<span class=\"op\">-&gt;</span>items<span class=\"op\">[</span>v<span class=\"op\">-&gt;</span>len <span class=\"op\">-</span> <span class=\"dv\">1</span><span class=\"op\">];</span></span>\n<span id=\"cb10-87\"><a href=\"#cb10-87\"></a>  v<span class=\"op\">-&gt;</span>len<span class=\"op\">--;</span></span>\n<span id=\"cb10-88\"><a href=\"#cb10-88\"></a>  <span class=\"cf\">return</span> top<span class=\"op\">;</span></span>\n<span id=\"cb10-89\"><a href=\"#cb10-89\"></a><span class=\"op\">}</span></span></code></pre></div>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-09-19T02:41:43+00:00"
		},
		{
			"id": "gen/desert-island-discs.html",
			"url": "gen/desert-island-discs.html",
			"title": "Desert Island Discs",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Desert Island Discs</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Desert Island Discs</h1>\n<p class=\"byline\">2021-09-06T22:47:22-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#an-operating-system\" id=\"toc-an-operating-system\">An\nOperating System</a></li>\n<li><a href=\"#a-c-compiler\" id=\"toc-a-c-compiler\">A C Compiler</a></li>\n<li><a href=\"#libc\" id=\"toc-libc\">Libc</a></li>\n<li><a href=\"#a-shell\" id=\"toc-a-shell\">A shell</a></li>\n<li><a href=\"#a-database\" id=\"toc-a-database\">A Database</a></li>\n<li><a href=\"#a-networking-stack\" id=\"toc-a-networking-stack\">A\nNetworking Stack</a></li>\n<li><a href=\"#unix-utils\" id=\"toc-unix-utils\">Unix Utils</a></li>\n<li><a href=\"#a-lisp-interpreter\" id=\"toc-a-lisp-interpreter\">A Lisp\nInterpreter</a></li>\n<li><a href=\"#a-text-editor\" id=\"toc-a-text-editor\">A Text\nEditor</a></li>\n</ul>\n</nav>\n<p>What would be the eight software programs you would take to a\ndeserted island? To me, I\u2019d need the following: an OS, libc, a C\ncompiler, a shell, a database, a networking stack, unix utils, a lisp\ninterpreter, and an editor. I\u2019ve decided to try my hand at writing these\nto get better at low-level programming, and learn the stack a bit\nbetter. It\u2019s a good challenge, but in the interest of time and sanity I\nwill be putting lots of asterisks next to each disc.</p>\n<section id=\"an-operating-system\" class=\"level2\">\n<h2>An Operating System</h2>\n<p>I\u2019m not going to write an OS. Maybe I\u2019ll write some signals and\nsystem calls, but that\u2019s about it.</p>\n</section>\n<section id=\"a-c-compiler\" class=\"level2\">\n<h2>A C Compiler</h2>\n<p>I\u2019ll write a C Compiler that implements <strong>most</strong> of C89,\nthat emits assembly of the computer I\u2019m working on.</p>\n</section>\n<section id=\"libc\" class=\"level2\">\n<h2>Libc</h2>\n<p>A limited subset of libc would be nice. Plauger has a good book on\nimplementing a C89 compliant libc, which I will most likely follow,\nalong with looking at some code from musl.</p>\n<p>As well, I\u2019ll be writing some crypto and data structures to help with\nother tasks down the road.</p>\n</section>\n<section id=\"a-shell\" class=\"level2\">\n<h2>A shell</h2>\n<p>Nothing like bash. I\u2019ve decided to write a small shell and relegate\nthe rest to the shell I\u2019m currently working on.</p>\n</section>\n<section id=\"a-database\" class=\"level2\">\n<h2>A Database</h2>\n<p>A simple serializable Key-Value database should suffice. Will need to\nlearn B-Trees, though.</p>\n</section>\n<section id=\"a-networking-stack\" class=\"level2\">\n<h2>A Networking Stack</h2>\n<p>I\u2019ll learn how to write an HTTP Client and Server using the sockets\nlibrary.</p>\n</section>\n<section id=\"unix-utils\" class=\"level2\">\n<h2>Unix Utils</h2>\n<p>I\u2019ll write some basic unix utils, striving for some partial POSIX\ncompliance.</p>\n</section>\n<section id=\"a-lisp-interpreter\" class=\"level2\">\n<h2>A Lisp Interpreter</h2>\n<p>Lisp, being one of the simplest languages, allows me to write a\nhigher level language from C. That makes it a great target for an\ninterpreter to learn from.</p>\n</section>\n<section id=\"a-text-editor\" class=\"level2\">\n<h2>A Text Editor</h2>\n<p>Vim is my text editor of choice; it\u2019d be nice to be able to write an\neditor with some similar functionality.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-09-07T03:47:22+00:00"
		},
		{
			"id": "gen/the-expression-problem-and-operations-on-matricies.html",
			"url": "gen/the-expression-problem-and-operations-on-matricies.html",
			"title": "The Expression Problem And Operations On Matricies",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>The Expression Problem And Operations On Matricies</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">The Expression Problem And Operations On\nMatricies</h1>\n<p class=\"byline\">2021-06-22T08:52:01-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#parsing\" id=\"toc-parsing\">Parsing</a></li>\n<li><a href=\"#the-problem\" id=\"toc-the-problem\">The problem</a></li>\n<li><a href=\"#naive-approach\" id=\"toc-naive-approach\">Naive\nApproach</a></li>\n<li><a href=\"#the-expression-problem\"\nid=\"toc-the-expression-problem\">The Expression problem</a>\n<ul>\n<li><a href=\"#improving-the-naive-approach\"\nid=\"toc-improving-the-naive-approach\">Improving the Naive\nApproach</a></li>\n<li><a href=\"#using-a-pair\" id=\"toc-using-a-pair\">Using a pair</a></li>\n<li><a href=\"#using-a-flag\" id=\"toc-using-a-flag\">Using a flag</a></li>\n<li><a href=\"#the-final-implementation\"\nid=\"toc-the-final-implementation\">The final implementation</a></li>\n<li><a href=\"#a-note-on-associativity\"\nid=\"toc-a-note-on-associativity\">A note on Associativity</a></li>\n<li><a href=\"#conclusion\" id=\"toc-conclusion\">Conclusion</a></li>\n</ul></li>\n</ul>\n</nav>\n<p>I\u2019ve heard the sentiment that technical interviews focus on the wrong\nthings; technical aptitude in data structures and algorithms isn\u2019t a\ngreat measure of people\u2019s on the job performance. I agree. That being\nsaid, there are some small problems where cursory knowledge in them can\nhelp you out.</p>\n<p>I\u2019m going to use an example I encountered recently, where I wanted to\naggregate my personal finances into monthly, quarterly, and yearly\nreports, with columns for earnings, spend, and cashflow (earnings -\nspend).</p>\n<p>I downloaded the relevant CSVs and went to work parsing them.</p>\n<section id=\"parsing\" class=\"level2\">\n<h2>Parsing</h2>\n<p>The first problem came with cleaning up some transactions that were\nunnecessary \u2013 banks tend to charge a maintenance fee, but they end up\ncrediting you if you meet certain criteria. Even though this balances\nout, I didn\u2019t want this to count in my earnings and spend, so I wrote a\n<code>sed</code> regex to delete these lines. Likewise, I wanted to\nremove some of my investments that I had made (I don\u2019t consider these to\nbe spending, and I wanted to track these another way). Another\n<code>sed</code> regex it is. Eventually this became a pain, so I made a\nbash function to combine the regexes in an array to parse the CSV. You\njust add regexes and it\u2019ll remove the related transactions. Easy\nenough.</p>\n</section>\n<section id=\"the-problem\" class=\"level2\">\n<h2>The problem</h2>\n<p>If you visualize the problem at hand, you\u2019ll get this matrix.</p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\"></th>\n<th style=\"text-align: center;\">Monthly</th>\n<th>Quarterly</th>\n<th>Yearly</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align: center;\">Earnings</td>\n<td style=\"text-align: center;\">Monthly Earnings</td>\n<td>Quarterly Earnings</td>\n<td>Yearly Earnings</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Spend</td>\n<td style=\"text-align: center;\">Monthly Spend</td>\n<td>Quarterly Spend</td>\n<td>Yearly Spend</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Cashflow</td>\n<td style=\"text-align: center;\">Monthly Cashflow</td>\n<td>Quarterly Cashflow</td>\n<td>Yearly Cashflow</td>\n</tr>\n</tbody>\n</table>\n<p>We have an (m * n) problem, where if we had a new row or column, we\nadd (m) or (n) more things we need to calculate.</p>\n<p>Let\u2019s get solving.</p>\n</section>\n<section id=\"naive-approach\" class=\"level2\">\n<h2>Naive Approach</h2>\n<p>The Naive approach is the O(m * n) solution, where you create a\nfunction that deals with a particular cell of this matrix. Take Monthly\nEarnings. You would write a function that does the logic for dividing\nthe CSV into months, and then applying the logic for Earnings to it.</p>\n<p>You would repeat this eight times, to get 9 different functions.</p>\n<p>When calling this logic, you would have a switch-case that would\nselect the logic required.</p>\n<p>This isn\u2019t very dry, and very tedious, even with only 9 cells. I\nwanted something better. This is due to the runtime of matricies.</p>\n</section>\n<section id=\"the-expression-problem\" class=\"level1\">\n<h1>The Expression problem</h1>\n<p>The <a\nhref=\"https://craftinginterpreters.com/representing-code.html#the-expression-problem\">expression\nproblem</a> is a fundamental problem in writing functions that work on\ntypes and vice versa.</p>\n<p>OOP Languages like Java make it easy to create new types that have\noperations on data. But let\u2019s say you want to add a new method to all\nyour classes. You now need to add a new method to all of your existing\nand future classes.</p>\n<p>ML type languages use pattern matching, which allows you to easily\nadd new operations to a function. But to apply that operation to all\nexisting types, you have to add a new case to all of the pattern\nmatches.</p>\n<p>Let\u2019s say I add a new time period, \u201cbi-yearly\u201d to denote half a year\nchunks. Well, if we go by the naive case, we\u2019d have to add new cases for\nbi-yearly + cashflow, bi-yearly + earnings, bi-yearly + spend. That\u2019s 3\nnew functions for one new time period. Ouch.</p>\n<p>Let\u2019s say I want a new category that only counts purchases that are\nlarger than $100, and call these \u201clarge purchases\u201d. If so, I would have\nto add logic to count for monthly, quarterly, bi-yearly, and yearly time\nperiods. That\u2019s 4 new functions for a new category.</p>\n<p>Let\u2019s say I want to add a new dimension. I want to split my purchases\nfor all of the above categories and time periods between my credit card\nand debit card. That\u2019s 4 * 4, or 16 new functions I\u2019d need to\nimplement.</p>\n<p>Big O notation would say this grows linearly with regards to the size\nof each dimension.</p>\n<p>If we have 4 monetary categories and 4 time periods, we have 4 * 4 or\n16 functions to implement. If we have 4 monetary categories, 4 time\nperiods, and 2 types of credit cards, we have 4 * 4 * 2, or 32 functions\nto implement.</p>\n<p>Our first proposed matrix is a 2D square, and we\u2019re calculating its\narea. A square with a length of four and a height of 4 has an area of\n16.</p>\n<p>Our second proposed matrix is a 3D square (a cube). To calculate the\narea of a cube, you multiply its length, width, and height. We have a\nlength of 4, a width of 4, and a height of 2, totalling 32.</p>\n<p>As we add new fields to our rows and columns, and new dimensions to\nour matrix, we\u2019ll soon see that this becomes untenable. (What happens if\nI also want to count my investment accounts, of which I have many? I\u2019d\nhave to add more and more dimensions, and the amount of functions to\nimplement increases quite a lot.</p>\n<section id=\"improving-the-naive-approach\" class=\"level2\">\n<h2>Improving the Naive Approach</h2>\n<p>In the interest of clean code, I wanted to create small composable\nfunctions that would calculate the each category.</p>\n<p>The Earnings function would only calculate transactions with a\npositive amount The Spend function would only calculate transactions\nwith a negative amount The Cashflow function would calculate all\ntransactions.</p>\n<p>The Monthly function would divide the CSV into months, and apply a\nfunction to each range. The Quarterly function would divide the CSV into\nquarters, and apply a function to each range. The Yearly function would\ndivide the CSV into years, and apply a function to each range.</p>\n<p>But the problem is how to set this up properly.</p>\n<p>We need some way to signal to the main function that we want to\ncalculate a row * column pairing (a cell). If we add a new dimension, we\ndon\u2019t want to break previous code.</p>\n</section>\n<section id=\"using-a-pair\" class=\"level2\">\n<h2>Using a pair</h2>\n<p>One way to signal this is to use a pair of enums that are captured in\na pair as (row, col). This works well enough if we stick to two\ndimensions. If we add a 3rd dimension, though, this will create\nincorrect code. If we\u2019re strict on requiring a pair, then we can\u2019t add\nthe 3rd dimension at all without breaking all of our existing code. If\nwe\u2019re looser (allow any tuple, and unpack the first, second and third\nvalues) this will work, but our code will be a bit confusing in order to\nmaintain backwards compatibility (some code will check the first and\nsecond fields of a 3-tuple, even though it should be checking all\nthree).</p>\n</section>\n<section id=\"using-a-flag\" class=\"level2\">\n<h2>Using a flag</h2>\n<p>Another way to signal this is to use a Flag enum. A flag enum is an\nenum that has values corresponding to powers of 2.</p>\n<p>For example:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">enum</span> Color <span class=\"op\">{</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a>  RED <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">,</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a>  GREEN <span class=\"op\">=</span> <span class=\"dv\">2</span><span class=\"op\">,</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a>  BLUE <span class=\"op\">=</span> <span class=\"dv\">4</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a><span class=\"op\">}</span> Color<span class=\"op\">;</span></span></code></pre></div>\n<p>(Some people prefer to write it like this, to be explicit that this\nis a flag):</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">enum</span> Color <span class=\"op\">{</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a>  RED <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"co\">// 1 </span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a>  GREEN <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">1</span><span class=\"op\">,</span> <span class=\"co\">// 2</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\"></a>  BLUE <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">2</span><span class=\"op\">,</span> <span class=\"co\">// 4</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\"></a><span class=\"op\">}</span> Color<span class=\"op\">;</span></span></code></pre></div>\n<p>This has the nice property that we can use bitwise or to denote more\nthan one state, and bitwise and to check if the enum is one or more or a\nparticular state.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a>Color color <span class=\"op\">=</span> RED <span class=\"op\">|</span> GREEN<span class=\"op\">;</span> <span class=\"co\">// this color is Red and Green</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a>Color Black <span class=\"op\">=</span> RED <span class=\"op\">|</span> GREEN <span class=\"op\">|</span> BLUE<span class=\"op\">;</span> <span class=\"co\">// this color, black, is all the colors</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a><span class=\"cf\">if</span> <span class=\"op\">(</span>color <span class=\"op\">&amp;</span> RED<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a>  <span class=\"co\">// this color has red, do some logic in the red case</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a><span class=\"op\">}</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\"></a><span class=\"cf\">if</span> <span class=\"op\">(</span>color <span class=\"op\">&amp;</span> GREEN<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\"></a>  <span class=\"co\">// this color has green, do some logic in the green case</span></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\"></a><span class=\"op\">}</span></span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\"></a><span class=\"cf\">if</span> <span class=\"op\">(</span>color <span class=\"op\">&amp;</span> BLUE<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\"></a>  <span class=\"co\">// this color has blue, do some logic in the blue case</span></span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>In C, since enums are stored as an unsigned int, you can store up to\n32 fields (rows + columns + dimensions, in our case). Sometimes this\nisn\u2019t enough, and you\u2019ll have to find another way, but in our case, it\nworks fine.</p>\n</section>\n<section id=\"the-final-implementation\" class=\"level2\">\n<h2>The final implementation</h2>\n<p>Finally to solve the problem, we want to provide a flag enum, and get\nthe CSV that we\u2019re applying it to. First, we want to slice the CSV into\nthe range provided, and then apply some category (Earning, Spend,\nCashflow) to it, and then save the CSV.</p>\n<p>That can be done something like this:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">enum</span> Categories <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\"></a>  MONTHLY <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">0</span><span class=\"op\">,</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\"></a>  QUARTERLY <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">1</span><span class=\"op\">,</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\"></a>  YEARLY <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">2</span><span class=\"op\">,</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\"></a>  EARNINGS <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">3</span><span class=\"op\">,</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\"></a>  SPEND <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">4</span><span class=\"op\">,</span></span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\"></a>  CASHFLOW <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">5</span><span class=\"op\">,</span></span>\n<span id=\"cb4-8\"><a href=\"#cb4-8\"></a><span class=\"op\">}</span> Categories<span class=\"op\">;</span></span>\n<span id=\"cb4-9\"><a href=\"#cb4-9\"></a></span>\n<span id=\"cb4-10\"><a href=\"#cb4-10\"></a><span class=\"dt\">void</span> generateCsvs<span class=\"op\">(</span>Category category<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-11\"><a href=\"#cb4-11\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> MONTHLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-12\"><a href=\"#cb4-12\"></a>    doMonthlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb4-13\"><a href=\"#cb4-13\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-14\"><a href=\"#cb4-14\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> QUARTERLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-15\"><a href=\"#cb4-15\"></a>    doQuarterlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb4-16\"><a href=\"#cb4-16\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-17\"><a href=\"#cb4-17\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> YEARLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-18\"><a href=\"#cb4-18\"></a>    doYearlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb4-19\"><a href=\"#cb4-19\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-20\"><a href=\"#cb4-20\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> EARNINGS<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-21\"><a href=\"#cb4-21\"></a>    doEarningsLogic<span class=\"op\">();</span></span>\n<span id=\"cb4-22\"><a href=\"#cb4-22\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-23\"><a href=\"#cb4-23\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> SPEND<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-24\"><a href=\"#cb4-24\"></a>    doSpendLogic<span class=\"op\">();</span></span>\n<span id=\"cb4-25\"><a href=\"#cb4-25\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-26\"><a href=\"#cb4-26\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> CASHFLOW<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-27\"><a href=\"#cb4-27\"></a>    doCashflowLogic<span class=\"op\">();</span></span>\n<span id=\"cb4-28\"><a href=\"#cb4-28\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb4-29\"><a href=\"#cb4-29\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>We can generate our CSVs just like that. Nice. If we add a new\ndimension, like Credit card vs debit card, all we have to do is add it\nto our enum and our main function. This only adds two new enums and two\nnew cases. We\u2019ve gone from adding (m * n) functions for our logic to\njust (m + n). Big O strikes again.</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">enum</span> Categories <span class=\"op\">{</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a>  MONTHLY <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">0</span><span class=\"op\">,</span></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a>  QUARTERLY <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">1</span><span class=\"op\">,</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a>  YEARLY <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">2</span><span class=\"op\">,</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a>  EARNINGS <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">3</span><span class=\"op\">,</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\"></a>  SPEND <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">4</span><span class=\"op\">,</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\"></a>  CASHFLOW <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">5</span><span class=\"op\">,</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\"></a>  CREDIT <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">6</span><span class=\"op\">,</span></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\"></a>  DEBIT <span class=\"op\">=</span> <span class=\"dv\">1</span> <span class=\"op\">&lt;&lt;</span> <span class=\"dv\">7</span><span class=\"op\">,</span></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\"></a><span class=\"op\">}</span> Categories<span class=\"op\">;</span></span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\"></a></span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\"></a><span class=\"dt\">void</span> generateCsvs<span class=\"op\">(</span>Categories category<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-13\"><a href=\"#cb5-13\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> CREDIT<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-14\"><a href=\"#cb5-14\"></a>    doCreditLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-15\"><a href=\"#cb5-15\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-16\"><a href=\"#cb5-16\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> DEBIT<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-17\"><a href=\"#cb5-17\"></a>    doDebitLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-18\"><a href=\"#cb5-18\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-19\"><a href=\"#cb5-19\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> MONTHLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-20\"><a href=\"#cb5-20\"></a>    doMonthlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-21\"><a href=\"#cb5-21\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-22\"><a href=\"#cb5-22\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> QUARTERLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-23\"><a href=\"#cb5-23\"></a>    doQuarterlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-24\"><a href=\"#cb5-24\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-25\"><a href=\"#cb5-25\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> YEARLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-26\"><a href=\"#cb5-26\"></a>    doYearlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-27\"><a href=\"#cb5-27\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-28\"><a href=\"#cb5-28\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> EARNINGS<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-29\"><a href=\"#cb5-29\"></a>    doEarningsLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-30\"><a href=\"#cb5-30\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-31\"><a href=\"#cb5-31\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> SPEND<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-32\"><a href=\"#cb5-32\"></a>    doSpendLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-33\"><a href=\"#cb5-33\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-34\"><a href=\"#cb5-34\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> CASHFLOW<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-35\"><a href=\"#cb5-35\"></a>    doCashflowLogic<span class=\"op\">();</span></span>\n<span id=\"cb5-36\"><a href=\"#cb5-36\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-37\"><a href=\"#cb5-37\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>If we wanted more than 31 categories, we could still do that using a\nstruct instead of an enum. This creates a struct where every member is a\nboolean flag, and we\u2019re checking if it\u2019s set in our generateCsvs\ncode.</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">struct</span> Categories <span class=\"op\">{</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\"></a>  <span class=\"dt\">int</span> MONTHLY <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\"></a>  <span class=\"dt\">int</span> QUARTERLY <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span> </span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\"></a>  <span class=\"dt\">int</span> YEARLY <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span> </span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\"></a>  <span class=\"dt\">int</span> EARNINGS <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span></span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\"></a>  <span class=\"dt\">int</span> SPEND <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span> </span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\"></a>  <span class=\"dt\">int</span> CASHFLOW <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span> </span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\"></a>  <span class=\"dt\">int</span> CREDIT <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span> </span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\"></a>  <span class=\"dt\">int</span> DEBIT <span class=\"op\">:</span> <span class=\"dv\">1</span><span class=\"op\">;</span> </span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\"></a><span class=\"op\">}</span> Categories<span class=\"op\">;</span></span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\"></a></span>\n<span id=\"cb6-12\"><a href=\"#cb6-12\"></a>Categories category <span class=\"op\">=</span> <span class=\"op\">{</span> <span class=\"dv\">1</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">0</span><span class=\"op\">,</span> <span class=\"dv\">1</span> <span class=\"op\">};</span> <span class=\"co\">// MONTHLY and EARNINGS are set, everything else is zero-initialized.</span></span>\n<span id=\"cb6-13\"><a href=\"#cb6-13\"></a></span>\n<span id=\"cb6-14\"><a href=\"#cb6-14\"></a><span class=\"co\">// or this:</span></span>\n<span id=\"cb6-15\"><a href=\"#cb6-15\"></a>Categories category <span class=\"op\">=</span> <span class=\"op\">{};</span></span>\n<span id=\"cb6-16\"><a href=\"#cb6-16\"></a>category<span class=\"op\">.</span>MONTHLY <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">;</span> <span class=\"co\">// set MONTHLY;</span></span>\n<span id=\"cb6-17\"><a href=\"#cb6-17\"></a>category<span class=\"op\">.</span>EARNINGS <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">;</span> <span class=\"co\">// set EARNINGS; </span></span>\n<span id=\"cb6-18\"><a href=\"#cb6-18\"></a></span>\n<span id=\"cb6-19\"><a href=\"#cb6-19\"></a><span class=\"dt\">void</span> generateCsvs<span class=\"op\">(</span>Categories category<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-20\"><a href=\"#cb6-20\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category<span class=\"op\">.</span>MONTHLY<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb6-21\"><a href=\"#cb6-21\"></a>    doMonthlyLogic<span class=\"op\">();</span></span>\n<span id=\"cb6-22\"><a href=\"#cb6-22\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb6-23\"><a href=\"#cb6-23\"></a>  <span class=\"co\">// etc.</span></span>\n<span id=\"cb6-24\"><a href=\"#cb6-24\"></a><span class=\"op\">}</span></span></code></pre></div>\n</section>\n<section id=\"a-note-on-associativity\" class=\"level2\">\n<h2>A note on Associativity</h2>\n<p>But wait, there\u2019s something we can improve upon in our solution:</p>\n<p>You might\u2019ve noticed that we\u2019re coupling our code based on time.\nSince we\u2019ve decided to cut up the CSV first by time and then calculate\nthe monetary category, you\u2019ve noticed that if we flip the order of them,\nwe might get a different result. This is bad, because refactoring tends\nto reorder things, and code that is coupled throughout time tends to\nlead to messier code.</p>\n<p>To improve this, we need to add a few restrictions.</p>\n<p>But first, a review on associativity and composition.</p>\n<p>Associativity means that the order a function is applied in doesn\u2019t\nmatter.</p>\n<p>Let\u2019s take the multiplication function. You\u2019ll notice that we can\napply them in any order and the function is still correct.</p>\n<blockquote>\n<p>4 * 3 * 2 == (4 * 3) * 2 == 4 * (3 * 2)</p>\n</blockquote>\n<p>Whereas division is not associative, because:</p>\n<blockquote>\n<p>(12 / 2) / 3 != 12 / (2 / 3).</p>\n</blockquote>\n<p>What we did above was like division, where we must apply the\nfunctions in some order, so they are coupled in time (the parentheses\ndenote this). What we really want is a mulitiplicative (associative)\nfunction, because no matter how many changes we make to the code, it\nwill only grow in complexity linearly, not polynomially.</p>\n<p>Thus, if we guarantee that our operations are associative, then we\ndon\u2019t have to worry about how we lay out our main function at all.</p>\n<p>To do this, we\u2019ll have to write our functions in a way that they take\na CSV and return a CSV after doing some to work them. These CSVs must\nwork on every other CSV that any other step in the main function can\nproduce. So, we\u2019ll change our main function to be like this, where every\nfunction takes the CSV and returns a CSV.</p>\n<p>We\u2019ll use the flag enum to make sure that we\u2019re applying just the\nfunctions that we want.</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"dt\">void</span> generateCsvs<span class=\"op\">(</span>Categories category<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a>  csv <span class=\"op\">=</span> <span class=\"op\">{};</span> </span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a>  <span class=\"co\">// assume the CSV is an array</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> CREDIT<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a>    csv <span class=\"op\">=</span> doCreditLogic<span class=\"op\">(</span>csv<span class=\"op\">);</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> DEBIT<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-8\"><a href=\"#cb7-8\"></a>    csv <span class=\"op\">=</span> doDebitLogic<span class=\"op\">(</span>csv<span class=\"op\">);</span></span>\n<span id=\"cb7-9\"><a href=\"#cb7-9\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb7-10\"><a href=\"#cb7-10\"></a>  <span class=\"co\">// etc</span></span>\n<span id=\"cb7-11\"><a href=\"#cb7-11\"></a>  writeToCsv<span class=\"op\">(</span>csv<span class=\"op\">);</span></span>\n<span id=\"cb7-12\"><a href=\"#cb7-12\"></a><span class=\"op\">}</span></span>\n<span id=\"cb7-13\"><a href=\"#cb7-13\"></a><span class=\"co\">// this is the same function </span></span>\n<span id=\"cb7-14\"><a href=\"#cb7-14\"></a><span class=\"dt\">void</span> generateCsvs<span class=\"op\">(</span>Categories category<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-15\"><a href=\"#cb7-15\"></a>  csv <span class=\"op\">=</span> <span class=\"op\">{};</span> </span>\n<span id=\"cb7-16\"><a href=\"#cb7-16\"></a>  <span class=\"co\">// We&#39;ve flipped the order, but it still works </span></span>\n<span id=\"cb7-17\"><a href=\"#cb7-17\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> DEBIT<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-18\"><a href=\"#cb7-18\"></a>    csv <span class=\"op\">=</span> doDebitLogic<span class=\"op\">(</span>csv<span class=\"op\">);</span></span>\n<span id=\"cb7-19\"><a href=\"#cb7-19\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb7-20\"><a href=\"#cb7-20\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>category <span class=\"op\">&amp;</span> CREDIT<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-21\"><a href=\"#cb7-21\"></a>    csv <span class=\"op\">=</span> doCreditLogic<span class=\"op\">(</span>csv<span class=\"op\">);</span></span>\n<span id=\"cb7-22\"><a href=\"#cb7-22\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb7-23\"><a href=\"#cb7-23\"></a>  <span class=\"co\">// etc</span></span>\n<span id=\"cb7-24\"><a href=\"#cb7-24\"></a>  writeToCsv<span class=\"op\">(</span>csv<span class=\"op\">);</span></span>\n<span id=\"cb7-25\"><a href=\"#cb7-25\"></a><span class=\"op\">}</span></span></code></pre></div>\n</section>\n<section id=\"conclusion\" class=\"level2\">\n<h2>Conclusion</h2>\n<p>We\u2019ve seen how we can use flag enums, combined with some logic, to\ncut down the amount of functions we have to write in order to calculate\nthe cell of a matrix. While I won\u2019t agree big tech interviews are the\nbest way to assess candidates, sometimes these problems crop up, and\npeople have been grappling with them for a long time (like the\nexpression problem).</p>\n</section>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-06-22T12:52:01+00:00"
		},
		{
			"id": "gen/write-rfcs.html",
			"url": "gen/write-rfcs.html",
			"title": "Write RFCs",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Write RFCs</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Write RFCs</h1>\n<p class=\"byline\">2021-06-03T21:00:10-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#defining-an-rfc\" id=\"toc-defining-an-rfc\">Defining an\nRFC</a></li>\n<li><a href=\"#benefits-of-rfcs\" id=\"toc-benefits-of-rfcs\">Benefits of\nRFCs</a></li>\n<li><a href=\"#implementing-rfcs\" id=\"toc-implementing-rfcs\">Implementing\nRFCs</a></li>\n<li><a href=\"#a-template-for-rfcs\" id=\"toc-a-template-for-rfcs\">A\nTemplate for RFCs</a></li>\n</ul>\n</nav>\n<p>RFCs are <code>Requests for Comments</code>, popularized by the\nInternet Engineering Task Force (IETF) which develops and promotes\nstandards for the internet.</p>\n<section id=\"defining-an-rfc\" class=\"level2\">\n<h2>Defining an RFC</h2>\n<p>Much has been said about RFCs (Including <a\nhref=\"https://datatracker.ietf.org/doc/html/rfc3\">RFC 3</a> which\noutlines how to write an RFC for the IETF), but let\u2019s read through the\nmain points of RFC 3.</p>\n<ul>\n<li>RFCs can be on thoughts, suggestions, etc. relating to the subject\n(The internet in this case)</li>\n<li>RFCs should be timely, rather than polished</li>\n<li>RFCs do not require examples</li>\n<li>RFCs can be as short or as long as needed</li>\n</ul>\n<p>According to RFC 3, RFCs should have the following information:</p>\n<ol type=\"1\">\n<li>\u201cNetwork Working Group Request for Comments:\u201d X (where X is the\nnumber of the RFC)</li>\n<li>Author and Affiliation</li>\n<li>Date</li>\n<li>Title (Does not need to be unique)</li>\n</ol>\n</section>\n<section id=\"benefits-of-rfcs\" class=\"level2\">\n<h2>Benefits of RFCs</h2>\n<p>According to <a\nhref=\"https://buriti.ca/6-lessons-i-learned-while-implementing-technical-rfcs-as-a-management-tool-34687dbf46cb\">6\nLessons I learned while implementing technical RFCs as a decision making\ntool</a>, After implementing RFCs in his organization, Juan Pablo\nBuritic\u00e1 picked RFCs for the following reasons:</p>\n<ul>\n<li>enable individual contributors to make decisions for systems they\u2019re\nresponsible for</li>\n<li>allow domain experts to have input in decisions when they\u2019re not\ndirectly involved in building a particular system</li>\n<li>manage the risk of decisions made</li>\n<li>include team members without it becoming design by committee</li>\n<li>have a snapshot of context for the future</li>\n<li>be asynchronous</li>\n<li>work on multiple projects in parallel</li>\n</ul>\n<p>In my company, RFCs allow us to propose ideas to improve processes,\ndevelopment experience, the product, with low risk of retribution and\nwithout the anxiety of giving a presentation. Q &amp; A is relaxed for\nboth the author of the RFC and those writing comments, as they are\nallowed to proceed asynchronously, without either party feeling\npressured to have all the answers right away. They\u2019re also a written\nrecord of the thoughts of the authors and reviewers throughout the\nlifecycle of the proposal, and serve as a historical artifact for\nreflection (if a proposal that sounded good didn\u2019t turn out so well, why\ndidn\u2019t it work out?)</p>\n</section>\n<section id=\"implementing-rfcs\" class=\"level2\">\n<h2>Implementing RFCs</h2>\n<p>Oxide Computer explained how they do RFCs (which they call RFDs,\nRequests for Discussions) here: <a\nhref=\"https://oxide.computer/blog/rfd-1-requests-for-discussion\">RFDs at\nOxide Computer</a></p>\n<p>At Oxide, RFDs are appropriate for the following cases:</p>\n<ul>\n<li>Add or change a company process</li>\n<li>An architectural or design decision for hardware or software</li>\n<li>Change to an API or command-line tool used by customers</li>\n<li>Change to an internal API or tool</li>\n<li>Change to an internal process</li>\n<li>A design for testing</li>\n</ul>\n<p>Oxide has a few twists, like adding a state as metadata (an RFD can\nbe in the Prediscussion, Ideation, Discussion, Published, Committed, or\nAbandoned state), and go into detail about integrating their RFD system\ninto git.</p>\n</section>\n<section id=\"a-template-for-rfcs\" class=\"level2\">\n<h2>A Template for RFCs</h2>\n<p>Following what Oxide did, I made a template repository for RFCs.</p>\n<p>You can find it here: <a\nhref=\"https://github.com/Takashiidobe/rfcs\">Template RFC\nRepository</a></p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-06-04T01:00:10+00:00"
		},
		{
			"id": "gen/learning-recursion.html",
			"url": "gen/learning-recursion.html",
			"title": "Learning Recursion",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Learning Recursion</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Learning Recursion</h1>\n<p class=\"byline\">2021-06-03T11:30:55-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#a-terminating-base-case\"\nid=\"toc-a-terminating-base-case\">A terminating base case</a></li>\n<li><a href=\"#continuing-the-recursion\"\nid=\"toc-continuing-the-recursion\">Continuing the Recursion</a></li>\n<li><a href=\"#making-progress-towards-the-base-case\"\nid=\"toc-making-progress-towards-the-base-case\">Making progress towards\nthe base case</a></li>\n<li><a href=\"#implementation\"\nid=\"toc-implementation\">Implementation</a></li>\n<li><a href=\"#finding-a-base-case\" id=\"toc-finding-a-base-case\">Finding\na base case</a></li>\n<li><a href=\"#continuing-the-recursion-1\"\nid=\"toc-continuing-the-recursion-1\">Continuing the Recursion</a></li>\n<li><a href=\"#making-progress\" id=\"toc-making-progress\">Making\nProgress</a></li>\n<li><a href=\"#appendix\" id=\"toc-appendix\">Appendix</a></li>\n</ul>\n</nav>\n<p>It\u2019s been said that the only way to learn recursion is to learn\nrecursion. So let\u2019s get started!</p>\n<p>Recursion is defined by the repeated application of a procedure.\nThere are three distinct parts to creating a recursive function:</p>\n<ol type=\"1\">\n<li>A terminating base case</li>\n<li>Continuing the recursion</li>\n<li>Making progress towards the base case</li>\n</ol>\n<p>Let\u2019s look at all of them while applying them to a problem:</p>\n<blockquote>\n<p>Given an array of integers, return the sum of their values.</p>\n</blockquote>\n<section id=\"a-terminating-base-case\" class=\"level2\">\n<h2>A terminating base case</h2>\n<p>We need a terminating base case, because otherwise a recursive\nfunction will continue forever.</p>\n<p>We\u2019ll start backwards (trying to find the case that terminates the\nalgorithm) and work our way from there.</p>\n<p>Let\u2019s say we have an empty array: well, that would look like this: If\nthe array is empty, then it makes sense that its sum is 0.</p>\n<p>Let\u2019s start writing some code to express that:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"dt\">int</span> sum_empty_arr<span class=\"op\">(</span><span class=\"dt\">int</span> arr<span class=\"op\">*,</span> <span class=\"dt\">size_t</span> len<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a>  <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a><span class=\"op\">}</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a><span class=\"dt\">int</span> sum<span class=\"op\">(</span><span class=\"dt\">int</span> arr<span class=\"op\">*,</span> <span class=\"dt\">size_t</span> len<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\"></a>    <span class=\"cf\">return</span> sum_empty_arr<span class=\"op\">(</span>arr<span class=\"op\">,</span> len<span class=\"op\">);</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\"></a>  <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\"></a>    <span class=\"co\">// In the next section!</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And hey, that\u2019s the only base case.</p>\n</section>\n<section id=\"continuing-the-recursion\" class=\"level2\">\n<h2>Continuing the Recursion</h2>\n<p>To continue the recursion, let\u2019s continue thinking: if we have a one\nitem array, what do we do?</p>\n<p>A one item array\u2019s sum can be expressed like this:</p>\n<p><code>arr[0] + 0</code>.</p>\n<p>Let\u2019s take <code>{1, 2}</code> as our array. Well, the sum of the\narray <code>{1, 2}</code> can be expressed like this:</p>\n<p><code>arr[0] + sum({2})</code></p>\n<p>Similarly, if we have a 3 item array like <code>{1, 2, 3}</code>, the\nsum of the array can be expressed like this:</p>\n<p><code>arr[0] + sum({2, 3})</code></p>\n<p>This formula works on arrays with any length.</p>\n<p>Our key insight here is to take the first item of the array, and sum\nit with the result of the sum of the rest of the items in the array.\nWe\u2019ve found a way to continue the recursion.</p>\n<p>Next, we\u2019ll have to think about how to make progress towards the base\ncase.</p>\n</section>\n<section id=\"making-progress-towards-the-base-case\" class=\"level2\">\n<h2>Making progress towards the base case</h2>\n<p>In our formula, we\u2019ve found a way to continue the recursion. But are\nwe making progress towards the base case?</p>\n<p>Our base case will terminate when it is provided an array with a\nlength of 0.</p>\n<p>In every recursive call, we reduce the length of the array we provide\nto <code>sum</code> by 1. Thus, as long as our array length is positive\n(which we can safely assume), we\u2019ll make progress towards the base case.\nNice! We won\u2019t recurse forever.</p>\n</section>\n<section id=\"implementation\" class=\"level2\">\n<h2>Implementation</h2>\n<p>We can turn our idea into code like so (I\u2019m doing a bit of pointer\narithmetic to move the pointer past the first item and decrementing the\nlength before calling <code>sum</code> again).</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"dt\">int</span> sum<span class=\"op\">(</span><span class=\"dt\">int</span> <span class=\"op\">*</span>arr<span class=\"op\">,</span> <span class=\"dt\">size_t</span> len<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a>        <span class=\"cf\">return</span> sum_empty_arr<span class=\"op\">(</span>arr<span class=\"op\">,</span> len<span class=\"op\">);</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\"></a>    <span class=\"op\">}</span>  <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\"></a>        <span class=\"dt\">int</span> head <span class=\"op\">=</span> arr<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">];</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\"></a>        len<span class=\"op\">--;</span> <span class=\"co\">// decrement the length</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\"></a>        arr<span class=\"op\">++;</span> <span class=\"co\">// move past the first item</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\"></a>        <span class=\"cf\">return</span> head <span class=\"op\">+</span> sum<span class=\"op\">(</span>arr<span class=\"op\">,</span> len<span class=\"op\">);</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And hey, if we run it:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a>    <span class=\"dt\">int</span> arr<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"dv\">1</span><span class=\"op\">,</span><span class=\"dv\">2</span><span class=\"op\">,</span><span class=\"dv\">3</span><span class=\"op\">,</span><span class=\"dv\">4</span><span class=\"op\">};</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a>    <span class=\"dt\">int</span> total <span class=\"op\">=</span> sum<span class=\"op\">(</span>arr<span class=\"op\">,</span> <span class=\"dv\">4</span><span class=\"op\">);</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a>    printf<span class=\"op\">(</span><span class=\"st\">&quot;</span><span class=\"sc\">%d\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> total<span class=\"op\">);</span> <span class=\"co\">// 10</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>And we get the correct result.</p>\n<p>We can clean this code up a bit:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"dt\">int</span> sum<span class=\"op\">(</span><span class=\"dt\">int</span> <span class=\"op\">*</span>arr<span class=\"op\">,</span> <span class=\"dt\">size_t</span> len<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>len <span class=\"op\">==</span> <span class=\"dv\">0</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\"></a>        <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb4-4\"><a href=\"#cb4-4\"></a>    <span class=\"op\">}</span>  <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb4-5\"><a href=\"#cb4-5\"></a>        <span class=\"cf\">return</span> arr<span class=\"op\">[</span><span class=\"dv\">0</span><span class=\"op\">]</span> <span class=\"op\">+</span> sum<span class=\"op\">(++</span>arr<span class=\"op\">,</span> <span class=\"op\">--</span>len<span class=\"op\">);</span></span>\n<span id=\"cb4-6\"><a href=\"#cb4-6\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb4-7\"><a href=\"#cb4-7\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Interestingly enough, even though python has a slicing operator, the\nimplementation is similar in length:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource py numberLines\"><code class=\"sourceCode python\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"kw\">def</span> list_sum(arr):</span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a>  <span class=\"cf\">if</span> <span class=\"bu\">len</span>(arr) <span class=\"op\">==</span> <span class=\"dv\">0</span>:</span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a>    <span class=\"cf\">return</span> <span class=\"dv\">0</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a>  <span class=\"cf\">else</span>:</span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a>    <span class=\"cf\">return</span> arr[<span class=\"dv\">0</span>] <span class=\"op\">+</span> list_sum(arr[<span class=\"dv\">1</span>:])</span></code></pre></div>\n<p>Similarly, in a language like OCaml, where recursion is the idiomatic\nway to express algorithms:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource ml numberLines\"><code class=\"sourceCode ocaml\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"kw\">let</span> <span class=\"kw\">rec</span> sum = <span class=\"kw\">function</span></span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\"></a>  | [] -&gt; <span class=\"dv\">0</span> <span class=\"co\">(* if the array is empty, return 0 *)</span></span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\"></a>  | h::t -&gt; h + (sum t) <span class=\"co\">(* otherwise, return the value of the head + sum of the rest of the elements. *)</span></span></code></pre></div>\n<p>Let\u2019s try another problem:</p>\n<blockquote>\n<p>Given a binary tree, calculate the sum of the values of all nodes in\nthe binary tree.</p>\n</blockquote>\n<p>Let\u2019s go through the steps again.</p>\n</section>\n<section id=\"finding-a-base-case\" class=\"level2\">\n<h2>Finding a base case</h2>\n<p>Let\u2019s ask ourselves what the possible cases are:</p>\n<p>If there is no node, because the node is null, clearly it shouldn\u2019t\ncount. Much like in the empty array case, let\u2019s return 0.</p>\n<p>If there is a node, let\u2019s return its value.</p>\n<p>Great, we\u2019ve got all our base cases covered. Let\u2019s express them\nbefore we continue on:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"dt\">int</span> sum<span class=\"op\">(</span>TreeNode <span class=\"op\">*</span>node<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>node <span class=\"op\">==</span> NULL<span class=\"op\">)</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a>    <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a>  <span class=\"cf\">else</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a>    <span class=\"cf\">return</span> node<span class=\"op\">-&gt;</span>val<span class=\"op\">;</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>But how do we continue the recursion?</p>\n</section>\n<section id=\"continuing-the-recursion-1\" class=\"level2\">\n<h2>Continuing the Recursion</h2>\n<p>To continue the recursion, we can apply the function we\u2019ve created to\nits left and right node. But how? Well, thinking back to the previous\nproblem, the sum of an array is the sum of the current value (the head)\n+ the rest of the items in the array. Likewise, for a binary tree, we\nneed to find the sum of the left items and the sum of the right\nitems.</p>\n<p>Since we know that a null node can\u2019t point to anything, we can leave\nthat case be, and express the sum of the binary tree as its current\nvalue + the sum of its left child + the sum of its right child.</p>\n<p>Let\u2019s do that:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb8-1\"><a href=\"#cb8-1\"></a><span class=\"dt\">int</span> sum<span class=\"op\">(</span>TreeNode <span class=\"op\">*</span>node<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>node <span class=\"op\">==</span> NULL<span class=\"op\">)</span></span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\"></a>    <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb8-4\"><a href=\"#cb8-4\"></a>  <span class=\"cf\">else</span></span>\n<span id=\"cb8-5\"><a href=\"#cb8-5\"></a>    <span class=\"cf\">return</span> node<span class=\"op\">-&gt;</span>val <span class=\"op\">+</span> sum<span class=\"op\">(</span>node<span class=\"op\">-&gt;</span>left<span class=\"op\">)</span> <span class=\"op\">+</span> sum<span class=\"op\">(</span>node<span class=\"op\">-&gt;</span>right<span class=\"op\">);</span></span>\n<span id=\"cb8-6\"><a href=\"#cb8-6\"></a><span class=\"op\">}</span></span></code></pre></div>\n</section>\n<section id=\"making-progress\" class=\"level2\">\n<h2>Making Progress</h2>\n<p>Are we making progress? We must be: for every node, we move onto its\nchild nodes. Child nodes (hopefully) eventually return null, in the case\nof a finite binary tree (of course, we can\u2019t calculate the sum of an\ninfinitely large binary tree).</p>\n<p>We did it! We can take this same idea and apply it to linked lists\nand graphs as well. That\u2019ll be an exercise for the reader, but the idea\nis very similar.</p>\n</section>\n<section id=\"appendix\" class=\"level2\">\n<h2>Appendix</h2>\n<p>Full code to sum of the nodes of a binary tree:</p>\n<p>In C:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb9-1\"><a href=\"#cb9-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\"></a></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">struct</span> TreeNode <span class=\"op\">{</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\"></a>  <span class=\"dt\">int</span> val<span class=\"op\">;</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\"></a>  <span class=\"kw\">struct</span> TreeNode <span class=\"op\">*</span>left<span class=\"op\">;</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\"></a>  <span class=\"kw\">struct</span> TreeNode <span class=\"op\">*</span>right<span class=\"op\">;</span></span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\"></a><span class=\"op\">}</span> TreeNode<span class=\"op\">;</span></span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\"></a></span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\"></a><span class=\"dt\">int</span> sum<span class=\"op\">(</span>TreeNode <span class=\"op\">*</span>node<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\"></a>  <span class=\"cf\">if</span> <span class=\"op\">(</span>node <span class=\"op\">==</span> NULL<span class=\"op\">)</span></span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\"></a>    <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\"></a>  <span class=\"cf\">else</span></span>\n<span id=\"cb9-13\"><a href=\"#cb9-13\"></a>    <span class=\"cf\">return</span> node<span class=\"op\">-&gt;</span>val <span class=\"op\">+</span> sum<span class=\"op\">(</span>node<span class=\"op\">-&gt;</span>left<span class=\"op\">)</span> <span class=\"op\">+</span> solve<span class=\"op\">(</span>node<span class=\"op\">-&gt;</span>right<span class=\"op\">);</span></span>\n<span id=\"cb9-14\"><a href=\"#cb9-14\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>In Java:</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode numberSource java numberLines\"><code class=\"sourceCode java\"><span id=\"cb10-1\"><a href=\"#cb10-1\"></a><span class=\"kw\">class</span> Solution <span class=\"op\">{</span></span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\"></a>  <span class=\"kw\">record</span> <span class=\"bu\">TreeNode</span><span class=\"op\">(</span><span class=\"dt\">int</span> val<span class=\"op\">,</span> <span class=\"bu\">TreeNode</span> left<span class=\"op\">,</span> <span class=\"bu\">TreeNode</span> right<span class=\"op\">)</span> <span class=\"op\">{}</span></span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\"></a></span>\n<span id=\"cb10-4\"><a href=\"#cb10-4\"></a>  <span class=\"kw\">public</span> <span class=\"dt\">int</span> <span class=\"fu\">sum</span><span class=\"op\">(</span><span class=\"bu\">TreeNode</span> node<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-5\"><a href=\"#cb10-5\"></a>    <span class=\"cf\">if</span> <span class=\"op\">(</span>node <span class=\"op\">==</span> <span class=\"kw\">null</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-6\"><a href=\"#cb10-6\"></a>      <span class=\"cf\">return</span> <span class=\"dv\">0</span><span class=\"op\">;</span></span>\n<span id=\"cb10-7\"><a href=\"#cb10-7\"></a>    <span class=\"op\">}</span> <span class=\"cf\">else</span> <span class=\"op\">{</span></span>\n<span id=\"cb10-8\"><a href=\"#cb10-8\"></a>      <span class=\"cf\">return</span> node<span class=\"op\">.</span><span class=\"fu\">val</span> <span class=\"op\">+</span> <span class=\"fu\">sum</span><span class=\"op\">(</span>node<span class=\"op\">.</span><span class=\"fu\">left</span><span class=\"op\">)</span> <span class=\"op\">+</span> <span class=\"fu\">sum</span><span class=\"op\">(</span>node<span class=\"op\">.</span><span class=\"fu\">right</span><span class=\"op\">);</span></span>\n<span id=\"cb10-9\"><a href=\"#cb10-9\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb10-10\"><a href=\"#cb10-10\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb10-11\"><a href=\"#cb10-11\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>In OCaml:</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre\nclass=\"sourceCode numberSource ml numberLines\"><code class=\"sourceCode ocaml\"><span id=\"cb11-1\"><a href=\"#cb11-1\"></a><span class=\"kw\">type</span> &#39;a tree =</span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\"></a>  | Node <span class=\"kw\">of</span> &#39;a tree * &#39;a * &#39;a tree</span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\"></a>  | Leaf;;</span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\"></a></span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\"></a><span class=\"kw\">let</span> <span class=\"kw\">rec</span> fold_tree f a t =</span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\"></a>    <span class=\"kw\">match</span> t <span class=\"kw\">with</span></span>\n<span id=\"cb11-7\"><a href=\"#cb11-7\"></a>      | Leaf -&gt; a</span>\n<span id=\"cb11-8\"><a href=\"#cb11-8\"></a>      | Node (l, x, r) -&gt; f x (fold_tree f a l) (fold_tree f a r);;</span></code></pre></div>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-06-03T15:30:55+00:00"
		},
		{
			"id": "gen/pack-enums-in-c.html",
			"url": "gen/pack-enums-in-c.html",
			"title": "Pack Enums in C",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Pack Enums in C</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Pack Enums in C</h1>\n<p class=\"byline\">2021-05-29T00:16:07-04:00</p>\n</header>\n<p>What\u2019s the default size of enums in C? Well it\u2019s int. We can see that\nby using <code>sizeof</code> in an example program:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">enum</span> Example <span class=\"op\">{</span></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a>    One <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">,</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a>    Two <span class=\"op\">=</span> <span class=\"dv\">2</span><span class=\"op\">,</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a><span class=\"op\">}</span> Example<span class=\"op\">;</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\"></a></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\"></a>    printf<span class=\"op\">(</span><span class=\"st\">&quot;The size of Example is: </span><span class=\"sc\">%d\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>Example<span class=\"op\">));</span></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Which prints out 4.</p>\n<p>This is noted by the standard: enums should be able to hold\n4-bytes.</p>\n<p>But 4 bytes seems wasteful, especially in this case: if we have an\nenum with two choices, we only need a bit to represent it.</p>\n<p>In GCC and Clang, there\u2019s support for <code>__attribute__</code>\nmodifiers. Let\u2019s use the <code>((__packed__))</code> modifier to tell\nthe compiler to use the smallest type it can for our enum.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">enum</span> Example <span class=\"op\">{</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\"></a>    One <span class=\"op\">=</span> <span class=\"dv\">1</span><span class=\"op\">,</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\"></a>    Two <span class=\"op\">=</span> <span class=\"dv\">2</span><span class=\"op\">,</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\"></a><span class=\"op\">}</span> __attribute__ <span class=\"op\">((</span>__packed__<span class=\"op\">))</span> Example<span class=\"op\">;</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\"></a></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\"></a>    printf<span class=\"op\">(</span><span class=\"st\">&quot;The size of Example is: </span><span class=\"sc\">%d\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>Example<span class=\"op\">));</span></span>\n<span id=\"cb2-10\"><a href=\"#cb2-10\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Which prints out 1. (our enum is now represented by an unsigned\nchar).</p>\n<p>If you want to make enums more dense in memory, this is the way to\ngo.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-05-29T04:16:07+00:00"
		},
		{
			"id": "gen/unix-environment-variables.html",
			"url": "gen/unix-environment-variables.html",
			"title": "Unix Environment Variables",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Unix Environment Variables</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Unix Environment Variables</h1>\n<p class=\"byline\">2021-05-24T18:58:40-04:00</p>\n</header>\n<p>Let\u2019s talk about some popular unix environment variables:</p>\n<ul>\n<li><code>$USER</code> - The current user</li>\n<li><code>$PAGER</code> - the program that accepts page by page input.\n<code>less</code> and <code>more</code> are good examples.</li>\n<li><code>$VISUAL</code> - A full screen editor (like <code>vi</code>,\n<code>emacs</code>, and <code>nano</code>).</li>\n<li><code>$EDITOR</code> - A line by line editor (<code>ed</code> or\n<code>ex</code> work).</li>\n<li><code>$PWD</code> - the current working directory</li>\n<li><code>$HOME</code> - the home directory</li>\n<li><code>$LANG</code> - the language you use, with an optional\nencoding.</li>\n<li><code>$MANPATH</code> - the list of directories to search for manual\npages.</li>\n<li><code>$MAIL</code> - where mail goes</li>\n<li><code>$SHELL</code> - path to shell binary you use\n(e.g.\u00a0<code>/bin/bash</code>, <code>/bin/ksh</code>,\n<code>/bin/sh</code>, <code>/bin/zsh</code>)</li>\n</ul>\n<p>The most important one is probably <code>$PATH</code>, which is where\nthe OS looks for binaries. It goes from the beginning to the end,\nexecuting the first binary it finds.</p>\n<p>Let\u2019s say my <code>$PATH</code> is like this:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource bash numberLines\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"ex\">/usr/local/bin:/usr/bin</span></span></code></pre></div>\n<p>Which instructs the OS to look into <code>/usr/local/bin</code> to\nfind a valid binary. Then <code>/usr/bin</code>.</p>\n<p>The <code>/bin</code> directory contains binaries for sysadmins and\nusers, but are required when there\u2019s no filesystem in use.</p>\n<p>The <code>/usr/bin</code> and was meant to contain executable\nprograms that were part of the OS</p>\n<p>and <code>/usr/local/bin</code> is for software that the user\ninstalls.</p>\n<p>There directories where superuser binaries should be located which\nfollow the same scheme:</p>\n<ul>\n<li><code>/sbin</code></li>\n<li><code>/usr/sbin</code></li>\n<li><code>/usr/local/sbin</code></li>\n</ul>\n<p>As well, <code>/usr/share/bin</code> is for binaries used for web\nservers and clients.</p>\n<p>If you find that a command doesn\u2019t work, double-check to make sure\nthat your <code>$PATH</code> is set up properly to find the correct\nbinary.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-05-24T22:58:40+00:00"
		},
		{
			"id": "gen/the-central-limit-theorem.html",
			"url": "gen/the-central-limit-theorem.html",
			"title": "The Central Limit Theorem",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>The Central Limit Theorem</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">The Central Limit Theorem</h1>\n<p class=\"byline\">2021-05-19T19:55:46-04:00</p>\n</header>\n<p>The central limit theory (CLT) states that when\n<strong>independent</strong> random variables are added, their properly\nnormalized sum tends toward a normal distribution (a bell curve) even if\nthe original variables themselves are not normally distributed. ~\nWikipedia</p>\n<p>One constraint is that we must have finite variance, as that lowers\nthe amount of outliers we see.</p>\n<p>Let\u2019s roll a dice 1000 times and see what that gets us:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"im\">from</span> collections <span class=\"im\">import</span> Counter</span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a><span class=\"im\">import</span> random</span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a><span class=\"kw\">def</span> r():</span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a>    <span class=\"cf\">return</span> random.randrange(<span class=\"dv\">1</span>, <span class=\"dv\">7</span>)</span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\"></a></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\"></a>rolls <span class=\"op\">=</span> Counter()</span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\"></a></span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\"></a><span class=\"cf\">for</span> _ <span class=\"kw\">in</span> <span class=\"bu\">range</span>(<span class=\"dv\">1000</span>):</span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\"></a>    rolls[r()] <span class=\"op\">+=</span> <span class=\"dv\">1</span></span>\n<span id=\"cb1-12\"><a href=\"#cb1-12\"></a></span>\n<span id=\"cb1-13\"><a href=\"#cb1-13\"></a>sorted_dict <span class=\"op\">=</span> {k: rolls[k] <span class=\"cf\">for</span> k <span class=\"kw\">in</span> <span class=\"bu\">sorted</span>(rolls)}</span></code></pre></div>\n<p>Running it I get this:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"ex\">{1:</span> 156, 2: 168, 3: 192, 4: 143, 5: 170, 6: 171}</span></code></pre></div>\n<ul>\n<li>1 was rolled 156 times</li>\n<li>2 was rolled 168 times</li>\n<li>3 was rolled 192 times</li>\n<li>4 was rolled 143 times</li>\n<li>5 was rolled 170 times</li>\n<li>6 was rolled 171 times</li>\n</ul>\n<figure>\n<img src=\"../assets/output.png\" alt=\"Output\" />\n<figcaption aria-hidden=\"true\">Output</figcaption>\n</figure>\n<p>You\u2019ll see that there\u2019s some variance, but we get a good enough\nresult.</p>\n<p>To test the central limit theorem, let\u2019s try to roll two dice at the\nsame time 1000 times and plot it.</p>\n<p>Change this line to this:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"cf\">for</span> _ <span class=\"kw\">in</span> <span class=\"bu\">range</span>(<span class=\"dv\">1000</span>):</span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a>    rolls[r() <span class=\"op\">+</span> r()] <span class=\"op\">+=</span> <span class=\"dv\">1</span></span></code></pre></div>\n<p>Here were the rolls:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"ex\">{2:</span> 22, 3: 59, 4: 81, 5: 110, 6: 149, 7: 174, 8: 144, 9: 101, 10: 77, 11: 53, 12: 30}</span></code></pre></div>\n<p>And here\u2019s the distribution:</p>\n<figure>\n<img src=\"../assets/two-dice.png\" alt=\"Two Dice Rolls\" />\n<figcaption aria-hidden=\"true\">Two Dice Rolls</figcaption>\n</figure>\n<p>You\u2019ll notice it\u2019s starting to converge on 6 and 7, but 2 and 12 were\nfairly unlikely.</p>\n<p>We\u2019re starting to get a normal distribution!</p>\n<p>Let\u2019s do 5 dice rolls.</p>\n<p>Change the line below:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"cf\">for</span> _ <span class=\"kw\">in</span> <span class=\"bu\">range</span>(<span class=\"dv\">1000</span>):</span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a>    rolls[r() <span class=\"op\">+</span> r() <span class=\"op\">+</span> r() <span class=\"op\">+</span> r() <span class=\"op\">+</span> r()] <span class=\"op\">+=</span> <span class=\"dv\">1</span></span></code></pre></div>\n<p>Here\u2019s the outcome:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"ex\">{7:</span> 2, 8: 8, 9: 8, 10: 14, 11: 33, 12: 35, 13: 54, 14: 72, 15: 61, 16: 85, 17: 94, 18: 93, 19: 108, 20: 88, 21: 82, 22: 65, 23: 37, 24: 22, 25: 17, 26: 11, 27: 8, 28: 2, 29: 1}</span></code></pre></div>\n<p>And the five dice rolls.</p>\n<figure>\n<img src=\"../assets/five-dice.png\" alt=\"Five Dice Rolls\" />\n<figcaption aria-hidden=\"true\">Five Dice Rolls</figcaption>\n</figure>\n<p>We get closer to a normal distribution.</p>\n<p>Let\u2019s do it a million times:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"cf\">for</span> _ <span class=\"kw\">in</span> <span class=\"bu\">range</span>(<span class=\"dv\">1000000</span>):</span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a>    rolls[r() <span class=\"op\">+</span> r() <span class=\"op\">+</span> r() <span class=\"op\">+</span> r() <span class=\"op\">+</span> r()] <span class=\"op\">+=</span> <span class=\"dv\">1</span></span></code></pre></div>\n<p>Here\u2019s the outcome:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\"></a><span class=\"ex\">{5:</span> 147, 6: 600, 7: 1890, 8: 4469, 9: 9147, 10: 16052, 11: 26310, 12: 39423, 13: 54070, 14: 69536, 15: 83228, 16: 94310, 17: 99997, 18: 100488, 19: 94484, 20: 83745, 21: 69777, 22: 53880, 23: 39506, 24: 26489, 25: 16144, 26: 9076, 27: 4547, 28: 1900, 29: 649, 30: 136}</span></code></pre></div>\n<p>And hey look, that looks like a normal distribution to me!</p>\n<figure>\n<img src=\"../assets/million-rolls.png\" alt=\"Million rolls\" />\n<figcaption aria-hidden=\"true\">Million rolls</figcaption>\n</figure>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-05-19T23:55:46+00:00"
		},
		{
			"id": "gen/file-io.html",
			"url": "gen/file-io.html",
			"title": "File Io",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>File Io</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">File Io</h1>\n<p class=\"byline\">2021-05-19T16:41:02-04:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#intuition\" id=\"toc-intuition\">Intuition</a></li>\n<li><a href=\"#suggestion-1\" id=\"toc-suggestion-1\">Suggestion 1:</a></li>\n<li><a href=\"#suggestion-2\" id=\"toc-suggestion-2\">Suggestion 2:</a></li>\n</ul>\n</nav>\n<p>File I/O is slow: but how slow is it really? Are there any ways we\ncan make it faster? Let\u2019s find out!</p>\n<p>First let\u2019s start out by writing the character <code>a</code> to a\nfile in python:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"im\">import</span> timeit</span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a><span class=\"kw\">def</span> test():</span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a>    <span class=\"cf\">with</span> <span class=\"bu\">open</span>(<span class=\"ss\">f&#39;output.txt&#39;</span>, <span class=\"st\">&#39;w+&#39;</span>) <span class=\"im\">as</span> f:</span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a>        f.write(<span class=\"st\">&#39;a&#39;</span>)</span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\"></a></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\"></a></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\"></a><span class=\"cf\">if</span> <span class=\"va\">__name__</span> <span class=\"op\">==</span> <span class=\"st\">&quot;__main__&quot;</span>:</span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\"></a>    <span class=\"bu\">print</span>(</span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\"></a>        <span class=\"ss\">f&#39;This took </span><span class=\"sc\">{</span>timeit<span class=\"sc\">.</span>timeit(<span class=\"st\">&quot;test()&quot;</span>, <span class=\"bu\">globals</span><span class=\"op\">=</span><span class=\"bu\">locals</span>(), number<span class=\"op\">=</span><span class=\"dv\">1</span>)<span class=\"sc\">}</span><span class=\"ss\"> seconds.&#39;</span>)</span></code></pre></div>\n<p>On my machine, this prints out:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"ex\">This</span> took 0.0002999180000000032 seconds.</span></code></pre></div>\n<p>Makes sense. Since it\u2019s hard to look at such small numbers, let\u2019s\nbump our number of repetitions up to <code>10000</code>.</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"im\">import</span> timeit</span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a><span class=\"kw\">def</span> test():</span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a>    <span class=\"cf\">with</span> <span class=\"bu\">open</span>(<span class=\"ss\">f&#39;output.txt&#39;</span>, <span class=\"st\">&#39;w+&#39;</span>) <span class=\"im\">as</span> f:</span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a>        f.write(<span class=\"st\">&#39;a&#39;</span>)</span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\"></a></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\"></a></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\"></a><span class=\"cf\">if</span> <span class=\"va\">__name__</span> <span class=\"op\">==</span> <span class=\"st\">&quot;__main__&quot;</span>:</span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\"></a>    <span class=\"bu\">print</span>(</span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\"></a>        <span class=\"ss\">f&#39;This took </span><span class=\"sc\">{</span>timeit<span class=\"sc\">.</span>timeit(<span class=\"st\">&quot;test()&quot;</span>, <span class=\"bu\">globals</span><span class=\"op\">=</span><span class=\"bu\">locals</span>(), number<span class=\"op\">=</span><span class=\"dv\">10000</span>)<span class=\"sc\">}</span><span class=\"ss\"> seconds.&#39;</span>)</span></code></pre></div>\n<p>On my machine, this prints out:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"ex\">This</span> took 4.582478715000001 seconds.</span></code></pre></div>\n<p>Let\u2019s try something similar but in memory. Let\u2019s add the string\n<code>a</code> to an empty string and return it:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"im\">import</span> timeit</span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a><span class=\"kw\">def</span> test():</span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a>    s <span class=\"op\">=</span> <span class=\"st\">&#39;&#39;</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\"></a>    s <span class=\"op\">+=</span> <span class=\"st\">&#39;a&#39;</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\"></a>    <span class=\"cf\">return</span> s</span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\"></a></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\"></a></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\"></a><span class=\"cf\">if</span> <span class=\"va\">__name__</span> <span class=\"op\">==</span> <span class=\"st\">&quot;__main__&quot;</span>:</span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\"></a>    <span class=\"bu\">print</span>(</span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\"></a>        <span class=\"ss\">f&#39;This took </span><span class=\"sc\">{</span>timeit<span class=\"sc\">.</span>timeit(<span class=\"st\">&quot;test()&quot;</span>, <span class=\"bu\">globals</span><span class=\"op\">=</span><span class=\"bu\">locals</span>(), number<span class=\"op\">=</span><span class=\"dv\">10000</span>)<span class=\"sc\">}</span><span class=\"ss\"> seconds.&#39;</span>)</span></code></pre></div>\n<p>On my machine, this prints out:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"ex\">This</span> took 0.0009243260000000031 seconds.</span></code></pre></div>\n<p>Doing some math, writing to a file 10000 times is 5000x slower than\nwriting to a string 10000 times in memory.</p>\n<p>So our intuition (and our Operating Systems textbooks) are correct.\nLet\u2019s dig deeper to see if we can find anything else.</p>\n<section id=\"intuition\" class=\"level2\">\n<h2>Intuition</h2>\n<p>Since all we\u2019re doing is opening a file, writing to it, closing the\nfile 10000 times, maybe there\u2019s some way to speed up this operation.</p>\n<p>Let\u2019s build a mental model for how python writes to a file:</p>\n<ol type=\"1\">\n<li>Open <code>output.txt</code>.</li>\n<li>Write the character <code>a</code> to <code>output.txt</code>.</li>\n<li>Close the file.</li>\n</ol>\n</section>\n<section id=\"suggestion-1\" class=\"level2\">\n<h2>Suggestion 1:</h2>\n<p>Since we\u2019re opening and closing the same file, what if we had some\nabstraction that represented the file? Let\u2019s say we had some integer\nthat would represent the file (a file descriptor) and we kept track of\nits state inside of our program. Whenever we need to save our changes to\ndisk, we notify the OS.</p>\n<p>So instead of doing:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource python numberLines\"><code class=\"sourceCode python\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a>repeat <span class=\"dv\">10000</span> times:</span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a>  <span class=\"bu\">open</span> `output.txt`</span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a>  clear the contents of `output.txt`</span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a>  write `a` to output.txt</span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a>  close `output.txt`</span></code></pre></div>\n<p>Which would require us to open the same file 10000 times:</p>\n<p>We try this:</p>\n<pre><code>file_contents = {}\nfile_contents[&#39;output.txt&#39;] = &#39;a&#39;\nopen file\nclear the contents of `output.txt`\nwrite file_contents[&#39;output.txt&#39;] to `output.txt`\nclose `output.txt`</code></pre>\n<p>Which would only require 1 call to the OS to open the file, 1 call to\nthe OS to write to the file, and 1 call to the OS to close the file.</p>\n<p>Python does this to some degree out of the box: the interpreter keeps\na dictionary of file_descriptor -&gt; changes and when it deems\nnecessary, it gives the file changes to the OS.</p>\n<p>To make python commit its buffer to the OS, use the\n<code>flush()</code> function.</p>\n</section>\n<section id=\"suggestion-2\" class=\"level2\">\n<h2>Suggestion 2:</h2>\n<p>What if the OS had a cache too? Since there are many processes trying\nto access the OS\u2019 resources, the OS has a chance to reconcile file\nwrites and batch them in a way that is more efficient.</p>\n<p>Let\u2019s say we ran the same python program twice at exactly the same\ntime. If we only employed caching at the python level, we\u2019d have to\nwrite to the same file twice with the character <code>a</code>. Of\ncourse, the OS can reconcile those changes and make it so there\u2019s only 1\nopen-write-close cycle required.</p>\n<p>It turns out both of these suggestions are implemented.</p>\n<p>To force the OS to propagate a change, you can use the\n<code>os.fsync(f.fileno())</code> function. When called, python asks the\nOS persist the changes in file descriptor <code>f</code> to disk.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-05-19T20:41:02+00:00"
		},
		{
			"id": "gen/const-correctness.html",
			"url": "gen/const-correctness.html",
			"title": "Const Correctness",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Const Correctness</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Const Correctness</h1>\n<p class=\"byline\">2021-05-17T19:32:39-04:00</p>\n</header>\n<p>Const correctness means marking all items you can <code>const</code>\nto prevent unwanted mutation. Let\u2019s say you want to grab a few options\nfrom a <code>settings</code> map that you\u2019ve created.</p>\n<p>Let\u2019s say you want the time to live value and the created at from a\nmap.</p>\n<p>Does this compile?</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource cpp numberLines\"><code class=\"sourceCode cpp\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"dt\">void</span> setTimeToLive<span class=\"op\">(</span><span class=\"dt\">int</span> ttl<span class=\"op\">)</span> <span class=\"op\">{</span><span class=\"co\">/* implementation here */</span><span class=\"op\">}</span></span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\"></a><span class=\"dt\">void</span> setCreatedAt<span class=\"op\">(</span><span class=\"dt\">int</span> createdAt<span class=\"op\">)</span> <span class=\"op\">{</span><span class=\"co\">/* implementation here */</span><span class=\"op\">}</span></span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\"></a></span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\"></a><span class=\"dt\">void</span> getOptions<span class=\"op\">(</span><span class=\"at\">const</span> <span class=\"bu\">std::</span>map<span class=\"op\">&lt;</span><span class=\"at\">const</span> <span class=\"dt\">char</span><span class=\"op\">*,</span> <span class=\"dt\">int</span><span class=\"op\">&gt;</span> <span class=\"op\">&amp;</span>m<span class=\"op\">)</span> <span class=\"kw\">noexcept</span> <span class=\"op\">{</span></span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\"></a>  <span class=\"at\">const</span> <span class=\"kw\">auto</span> ttl <span class=\"op\">=</span> m<span class=\"op\">[</span><span class=\"st\">&quot;ttl&quot;</span><span class=\"op\">];</span></span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\"></a>  <span class=\"at\">const</span> <span class=\"kw\">auto</span> createdAt <span class=\"op\">=</span> m<span class=\"op\">[</span><span class=\"st\">&quot;createdAt&quot;</span><span class=\"op\">];</span></span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\"></a>  setTimeToLive<span class=\"op\">(</span>ttl<span class=\"op\">);</span></span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\"></a>  setCreatedAt<span class=\"op\">(</span>createdAt<span class=\"op\">);</span></span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Nope: since <code>map[]</code> will insert in the case that it\ndoesn\u2019t find a matching key, this doesn\u2019t compile. We can\u2019t insert into\na map marked const.</p>\n<p>Let\u2019s say we didn\u2019t mark the map as <code>const</code>:</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource cpp numberLines\"><code class=\"sourceCode cpp\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"dt\">void</span> setTimeToLive<span class=\"op\">(</span><span class=\"dt\">int</span> ttl<span class=\"op\">)</span> <span class=\"op\">{</span><span class=\"co\">/* implementation here */</span><span class=\"op\">}</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a><span class=\"dt\">void</span> setCreatedAt<span class=\"op\">(</span><span class=\"dt\">int</span> createdAt<span class=\"op\">)</span> <span class=\"op\">{</span><span class=\"co\">/* implementation here */</span><span class=\"op\">}</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\"></a><span class=\"dt\">void</span> getOptions<span class=\"op\">(</span><span class=\"bu\">std::</span>map<span class=\"op\">&lt;</span><span class=\"at\">const</span> <span class=\"dt\">char</span><span class=\"op\">*,</span> <span class=\"dt\">int</span><span class=\"op\">&gt;</span> <span class=\"op\">&amp;</span>m<span class=\"op\">)</span> <span class=\"kw\">noexcept</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\"></a>  <span class=\"at\">const</span> <span class=\"kw\">auto</span> ttl <span class=\"op\">=</span> m<span class=\"op\">[</span><span class=\"st\">&quot;tttl&quot;</span><span class=\"op\">];</span> <span class=\"co\">// oops, typo</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\"></a>  <span class=\"at\">const</span> <span class=\"kw\">auto</span> createdAt <span class=\"op\">=</span> m<span class=\"op\">[</span><span class=\"st\">&quot;createdAt&quot;</span><span class=\"op\">];</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\"></a>  setTimeToLive<span class=\"op\">(</span>ttl<span class=\"op\">);</span></span>\n<span id=\"cb2-8\"><a href=\"#cb2-8\"></a>  setCreatedAt<span class=\"op\">(</span>createdAt<span class=\"op\">);</span></span>\n<span id=\"cb2-9\"><a href=\"#cb2-9\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This compiles now, but oh no, what\u2019s the value of ttl?\n<code>0</code>. When we access a map\u2019s key that doesn\u2019t exist, we get\nsome default value. In our case, a value of 0.</p>\n<p>So we\u2019re at a crossroads. We want our code to compile, be correct,\nand still allow the map to be <code>const</code>.</p>\n<p>Let\u2019s let that happen:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource cpp numberLines\"><code class=\"sourceCode cpp\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"dt\">void</span> setTimeToLive<span class=\"op\">(</span><span class=\"dt\">int</span> ttl<span class=\"op\">)</span> <span class=\"op\">{</span><span class=\"co\">/* implementation here */</span><span class=\"op\">}</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a><span class=\"dt\">void</span> setCreatedAt<span class=\"op\">(</span><span class=\"dt\">int</span> createdAt<span class=\"op\">)</span> <span class=\"op\">{</span><span class=\"co\">/* implementation here */</span><span class=\"op\">}</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a><span class=\"dt\">void</span> getOptions<span class=\"op\">(</span><span class=\"at\">const</span> <span class=\"bu\">std::</span>map<span class=\"op\">&lt;</span><span class=\"at\">const</span> <span class=\"dt\">char</span><span class=\"op\">*,</span> <span class=\"dt\">int</span><span class=\"op\">&gt;</span> <span class=\"op\">&amp;</span>m<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a>  <span class=\"at\">const</span> <span class=\"kw\">auto</span> ttl <span class=\"op\">=</span> m<span class=\"op\">.</span>at<span class=\"op\">(</span><span class=\"st\">&quot;tttl&quot;</span><span class=\"op\">);</span> <span class=\"co\">// oops, typo</span></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a>  <span class=\"at\">const</span> <span class=\"kw\">auto</span> createdAt <span class=\"op\">=</span> m<span class=\"op\">.</span>at<span class=\"op\">(</span><span class=\"st\">&quot;createdAt&quot;</span><span class=\"op\">);</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\"></a>  setTimeToLive<span class=\"op\">(</span>ttl<span class=\"op\">);</span></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\"></a>  setCreatedAt<span class=\"op\">(</span>createdAt<span class=\"op\">);</span></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>We replace <code>map::[]</code> with <code>map::at</code>.\n<code>map::at</code> does a checked get in the map. If it doesn\u2019t find\nthe key, it throws an exception.</p>\n<p>We remove our <code>noexcept</code> from the function because this\nfunction can throw and we move on with our lives.</p>\n<p>Const correctness saves lives.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-05-17T23:32:39+00:00"
		},
		{
			"id": "gen/virtual-functions.html",
			"url": "gen/virtual-functions.html",
			"title": "Virtual Functions",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Virtual Functions</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n  <style type=\"text/css\">\nhtml { -webkit-text-size-adjust: 100%; }\npre > code.sourceCode { white-space: pre; position: relative; }\npre > code.sourceCode > span { display: inline-block; line-height: 1.25; }\npre > code.sourceCode > span:empty { height: 1.2em; }\n.sourceCode { overflow: visible; }\ncode.sourceCode > span { color: inherit; text-decoration: inherit; }\ndiv.sourceCode { margin: 1em 0; }\npre.sourceCode { margin: 0; }\n@media screen {\ndiv.sourceCode { overflow: auto; }\n}\n@media print {\npre > code.sourceCode { white-space: pre-wrap; }\npre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }\n}\npre.numberSource code\n  { counter-reset: source-line 0; }\npre.numberSource code > span\n  { position: relative; left: -4em; counter-increment: source-line; }\npre.numberSource code > span > a:first-child::before\n  { content: counter(source-line);\n    position: relative; left: -1em; text-align: right; vertical-align: baseline;\n    border: none; display: inline-block;\n    -webkit-touch-callout: none; -webkit-user-select: none;\n    -khtml-user-select: none; -moz-user-select: none;\n    -ms-user-select: none; user-select: none;\n    padding: 0 4px; width: 4em;\n    color: #aaaaaa;\n  }\npre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }\ndiv.sourceCode\n  {   }\n@media screen {\npre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }\n}\ncode span.al { color: #ff0000; font-weight: bold; } /* Alert */\ncode span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */\ncode span.at { color: #7d9029; } /* Attribute */\ncode span.bn { color: #40a070; } /* BaseN */\ncode span.bu { color: #008000; } /* BuiltIn */\ncode span.cf { color: #007020; font-weight: bold; } /* ControlFlow */\ncode span.ch { color: #4070a0; } /* Char */\ncode span.cn { color: #880000; } /* Constant */\ncode span.co { color: #60a0b0; font-style: italic; } /* Comment */\ncode span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */\ncode span.do { color: #ba2121; font-style: italic; } /* Documentation */\ncode span.dt { color: #902000; } /* DataType */\ncode span.dv { color: #40a070; } /* DecVal */\ncode span.er { color: #ff0000; font-weight: bold; } /* Error */\ncode span.ex { } /* Extension */\ncode span.fl { color: #40a070; } /* Float */\ncode span.fu { color: #06287e; } /* Function */\ncode span.im { color: #008000; font-weight: bold; } /* Import */\ncode span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */\ncode span.kw { color: #007020; font-weight: bold; } /* Keyword */\ncode span.op { color: #666666; } /* Operator */\ncode span.ot { color: #007020; } /* Other */\ncode span.pp { color: #bc7a00; } /* Preprocessor */\ncode span.sc { color: #4070a0; } /* SpecialChar */\ncode span.ss { color: #bb6688; } /* SpecialString */\ncode span.st { color: #4070a0; } /* String */\ncode span.va { color: #19177c; } /* Variable */\ncode span.vs { color: #4070a0; } /* VerbatimString */\ncode span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */\n  </style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Virtual Functions</h1>\n<p class=\"byline\">2021-05-16T21:28:00-04:00</p>\n</header>\n<p>While learning Java, I came across this line of code:</p>\n<div class=\"sourceCode\" id=\"cb1\"><pre\nclass=\"sourceCode numberSource java numberLines\"><code class=\"sourceCode java\"><span id=\"cb1-1\"><a href=\"#cb1-1\"></a><span class=\"bu\">List</span><span class=\"op\">&lt;</span><span class=\"bu\">Integer</span><span class=\"op\">&gt;</span> array <span class=\"op\">=</span> <span class=\"kw\">new</span> <span class=\"bu\">ArrayList</span><span class=\"op\">();</span></span></code></pre></div>\n<p>As someone who knows C++, this is somewhat confusing \u2013\n<code>List</code> is an interface that <code>ArrayList</code>\nimplements. But if we treat <code>ArrayList</code> as a list, then when\nwe call <code>List.add()</code> we must use dynamic dispatch to find the\nright implementation, since the implementation of <code>add</code> isn\u2019t\non the list interface.</p>\n<p>That involves a <code>virtual</code> function lookup.</p>\n<p>In Java, most function calls are <code>virtual</code>, unless a\nmethod is declared as <code>final</code> (which means it cannot be\noverriden).</p>\n<p>By doing this, we get an advantage \u2013 if we decide to change our\n<code>array</code> variable from an <code>ArrayList</code> to another\n<code>List</code> interface conforming type, we can do so without\nbreaking any code.</p>\n<p>In exchange, we cannot use any <code>ArrayList</code> specific\nmethods without casting to <code>ArrayList</code>, which nullifies this\nbenefit.</p>\n<p>We have information that both ArrayList and LinkedList implement the\nList interface, so we can treat them as such in a collection.</p>\n<div class=\"sourceCode\" id=\"cb2\"><pre\nclass=\"sourceCode numberSource java numberLines\"><code class=\"sourceCode java\"><span id=\"cb2-1\"><a href=\"#cb2-1\"></a><span class=\"bu\">ArrayList</span><span class=\"op\">&lt;</span><span class=\"bu\">List</span><span class=\"op\">&gt;</span> lists <span class=\"op\">=</span> <span class=\"kw\">new</span> <span class=\"bu\">ArrayList</span><span class=\"op\">&lt;</span><span class=\"bu\">List</span><span class=\"op\">&gt;();</span></span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\"></a>lists<span class=\"op\">.</span><span class=\"fu\">add</span><span class=\"op\">(</span><span class=\"kw\">new</span> <span class=\"bu\">ArrayList</span><span class=\"op\">());</span></span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\"></a>lists<span class=\"op\">.</span><span class=\"fu\">add</span><span class=\"op\">(</span><span class=\"kw\">new</span> <span class=\"bu\">LinkedList</span><span class=\"op\">());</span></span>\n<span id=\"cb2-4\"><a href=\"#cb2-4\"></a></span>\n<span id=\"cb2-5\"><a href=\"#cb2-5\"></a><span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"bu\">List</span><span class=\"op\">&lt;</span><span class=\"bu\">Integer</span><span class=\"op\">&gt;</span> l <span class=\"op\">:</span> lists<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb2-6\"><a href=\"#cb2-6\"></a>    l<span class=\"op\">.</span><span class=\"fu\">add</span><span class=\"op\">(</span><span class=\"dv\">10</span><span class=\"op\">);</span> <span class=\"co\">// defer to each lists&#39; implementation for add</span></span>\n<span id=\"cb2-7\"><a href=\"#cb2-7\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Since we know that Java uses virtual functions for interface\nimplementations, everything works as expected. <code>l.add(10)</code>\ndefers to the implementation of <code>ArrayList</code> and\n<code>LinkedList</code>, and each list is added a <code>10</code>.</p>\n<p>A full example of virtual functions might look something like\nthis:</p>\n<div class=\"sourceCode\" id=\"cb3\"><pre\nclass=\"sourceCode numberSource java numberLines\"><code class=\"sourceCode java\"><span id=\"cb3-1\"><a href=\"#cb3-1\"></a><span class=\"kw\">public</span> <span class=\"kw\">class</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\"></a>  <span class=\"dt\">void</span> <span class=\"fu\">move</span><span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-3\"><a href=\"#cb3-3\"></a>    <span class=\"bu\">System</span><span class=\"op\">.</span><span class=\"fu\">out</span><span class=\"op\">.</span><span class=\"fu\">printf</span><span class=\"op\">(</span><span class=\"st\">&quot;walk </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> <span class=\"kw\">this</span><span class=\"op\">.</span><span class=\"fu\">name</span><span class=\"op\">());</span></span>\n<span id=\"cb3-4\"><a href=\"#cb3-4\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb3-5\"><a href=\"#cb3-5\"></a></span>\n<span id=\"cb3-6\"><a href=\"#cb3-6\"></a>  <span class=\"bu\">String</span> <span class=\"fu\">name</span><span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-7\"><a href=\"#cb3-7\"></a>    <span class=\"cf\">return</span> <span class=\"st\">&quot;Animal&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb3-8\"><a href=\"#cb3-8\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb3-9\"><a href=\"#cb3-9\"></a></span>\n<span id=\"cb3-10\"><a href=\"#cb3-10\"></a>  <span class=\"kw\">public</span> <span class=\"dt\">static</span> <span class=\"dt\">void</span> <span class=\"fu\">main</span><span class=\"op\">(</span><span class=\"bu\">String</span><span class=\"op\">[]</span> args<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-11\"><a href=\"#cb3-11\"></a>    Animal animals<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"kw\">new</span> <span class=\"fu\">Animal</span><span class=\"op\">(),</span> <span class=\"kw\">new</span> <span class=\"fu\">Bird</span><span class=\"op\">(),</span> <span class=\"kw\">new</span> <span class=\"fu\">Elephant</span><span class=\"op\">()};</span></span>\n<span id=\"cb3-12\"><a href=\"#cb3-12\"></a></span>\n<span id=\"cb3-13\"><a href=\"#cb3-13\"></a>    <span class=\"cf\">for</span> <span class=\"op\">(</span>Animal animal <span class=\"op\">:</span> animals<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-14\"><a href=\"#cb3-14\"></a>      animal<span class=\"op\">.</span><span class=\"fu\">move</span><span class=\"op\">();</span></span>\n<span id=\"cb3-15\"><a href=\"#cb3-15\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb3-16\"><a href=\"#cb3-16\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb3-17\"><a href=\"#cb3-17\"></a><span class=\"op\">}</span></span>\n<span id=\"cb3-18\"><a href=\"#cb3-18\"></a></span>\n<span id=\"cb3-19\"><a href=\"#cb3-19\"></a><span class=\"kw\">class</span> Bird <span class=\"kw\">extends</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb3-20\"><a href=\"#cb3-20\"></a>  <span class=\"at\">@Override</span></span>\n<span id=\"cb3-21\"><a href=\"#cb3-21\"></a>  <span class=\"dt\">void</span> <span class=\"fu\">move</span><span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-22\"><a href=\"#cb3-22\"></a>    <span class=\"bu\">System</span><span class=\"op\">.</span><span class=\"fu\">out</span><span class=\"op\">.</span><span class=\"fu\">printf</span><span class=\"op\">(</span><span class=\"st\">&quot;fly </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> <span class=\"kw\">this</span><span class=\"op\">.</span><span class=\"fu\">name</span><span class=\"op\">());</span></span>\n<span id=\"cb3-23\"><a href=\"#cb3-23\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb3-24\"><a href=\"#cb3-24\"></a></span>\n<span id=\"cb3-25\"><a href=\"#cb3-25\"></a>  <span class=\"at\">@Override</span></span>\n<span id=\"cb3-26\"><a href=\"#cb3-26\"></a>  <span class=\"bu\">String</span> <span class=\"fu\">name</span><span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-27\"><a href=\"#cb3-27\"></a>    <span class=\"cf\">return</span> <span class=\"st\">&quot;Bird&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb3-28\"><a href=\"#cb3-28\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb3-29\"><a href=\"#cb3-29\"></a><span class=\"op\">}</span></span>\n<span id=\"cb3-30\"><a href=\"#cb3-30\"></a></span>\n<span id=\"cb3-31\"><a href=\"#cb3-31\"></a><span class=\"kw\">class</span> Elephant <span class=\"kw\">extends</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb3-32\"><a href=\"#cb3-32\"></a>  <span class=\"at\">@Override</span></span>\n<span id=\"cb3-33\"><a href=\"#cb3-33\"></a>  <span class=\"bu\">String</span> <span class=\"fu\">name</span><span class=\"op\">()</span> <span class=\"op\">{</span></span>\n<span id=\"cb3-34\"><a href=\"#cb3-34\"></a>    <span class=\"cf\">return</span> <span class=\"st\">&quot;Elephant&quot;</span><span class=\"op\">;</span></span>\n<span id=\"cb3-35\"><a href=\"#cb3-35\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb3-36\"><a href=\"#cb3-36\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>Running this prints this out:</p>\n<div class=\"sourceCode\" id=\"cb4\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\"></a><span class=\"ex\">walk</span> Animal</span>\n<span id=\"cb4-2\"><a href=\"#cb4-2\"></a><span class=\"ex\">fly</span> Bird</span>\n<span id=\"cb4-3\"><a href=\"#cb4-3\"></a><span class=\"ex\">walk</span> Elephant</span></code></pre></div>\n<p>Here we create a base class, <code>Animal</code>, which has two\nmethods, <code>name</code> and <code>move</code>. This class is\ninstantiable because it has default implementations for both methods.\nThe Bird class overrides the move method, since it flies instead of\nwalks, and the Elephant only overrides the name. When we collect them\ninto an array and call the <code>move()</code> method on each animal as\nan animal, Java does the virtual function lookup and calls the correct\noverriden method as we expect.</p>\n<p>It turns out that not every language does this, mainly because there\nis a runtime cost in dynamic dispatch.</p>\n<p>In C++, you must designate a function as <code>virtual</code> which\nlabels a function as overridable by an inherited class.</p>\n<p>A roughly word for word translation of the above java program would\nlook like this:</p>\n<div class=\"sourceCode\" id=\"cb5\"><pre\nclass=\"sourceCode numberSource cpp numberLines\"><code class=\"sourceCode cpp\"><span id=\"cb5-1\"><a href=\"#cb5-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\"></a></span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\"></a><span class=\"kw\">struct</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\"></a>  <span class=\"kw\">virtual</span> <span class=\"at\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>name<span class=\"op\">()</span> <span class=\"at\">const</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> <span class=\"st\">&quot;Animal&quot;</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\"></a>  <span class=\"kw\">virtual</span> <span class=\"dt\">void</span> move<span class=\"op\">()</span> <span class=\"at\">const</span> <span class=\"op\">{</span> printf<span class=\"op\">(</span><span class=\"st\">&quot;walk </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> name<span class=\"op\">());</span> <span class=\"op\">}</span></span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\"></a>  <span class=\"kw\">virtual</span> <span class=\"op\">~</span>Animal<span class=\"op\">()</span> <span class=\"op\">{}</span></span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\"></a><span class=\"op\">};</span></span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\"></a></span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\"></a><span class=\"kw\">struct</span> Bird <span class=\"op\">:</span> <span class=\"kw\">public</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\"></a>  <span class=\"kw\">virtual</span> <span class=\"dt\">void</span> move<span class=\"op\">()</span> <span class=\"at\">const</span> <span class=\"kw\">override</span> <span class=\"op\">{</span> printf<span class=\"op\">(</span><span class=\"st\">&quot;fly </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> name<span class=\"op\">());</span> <span class=\"op\">}</span></span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\"></a>  <span class=\"kw\">virtual</span> <span class=\"at\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>name<span class=\"op\">()</span> <span class=\"at\">const</span> <span class=\"kw\">override</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> <span class=\"st\">&quot;Bird&quot;</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\"></a><span class=\"op\">};</span></span>\n<span id=\"cb5-13\"><a href=\"#cb5-13\"></a></span>\n<span id=\"cb5-14\"><a href=\"#cb5-14\"></a><span class=\"kw\">struct</span> Elephant <span class=\"op\">:</span> <span class=\"kw\">public</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb5-15\"><a href=\"#cb5-15\"></a>  <span class=\"kw\">virtual</span> <span class=\"at\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>name<span class=\"op\">()</span> <span class=\"at\">const</span> <span class=\"kw\">override</span> <span class=\"op\">{</span> <span class=\"cf\">return</span> <span class=\"st\">&quot;Elephant&quot;</span><span class=\"op\">;</span> <span class=\"op\">}</span></span>\n<span id=\"cb5-16\"><a href=\"#cb5-16\"></a><span class=\"op\">};</span></span>\n<span id=\"cb5-17\"><a href=\"#cb5-17\"></a></span>\n<span id=\"cb5-18\"><a href=\"#cb5-18\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-19\"><a href=\"#cb5-19\"></a>  <span class=\"at\">const</span> Animal <span class=\"op\">*</span>animals<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span><span class=\"kw\">new</span> Animal<span class=\"op\">(),</span> <span class=\"kw\">new</span> Bird<span class=\"op\">(),</span> <span class=\"kw\">new</span> Elephant<span class=\"op\">()};</span></span>\n<span id=\"cb5-20\"><a href=\"#cb5-20\"></a></span>\n<span id=\"cb5-21\"><a href=\"#cb5-21\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"at\">const</span> <span class=\"kw\">auto</span> <span class=\"op\">&amp;</span>animal <span class=\"op\">:</span> animals<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb5-22\"><a href=\"#cb5-22\"></a>    animal<span class=\"op\">-&gt;</span>move<span class=\"op\">();</span></span>\n<span id=\"cb5-23\"><a href=\"#cb5-23\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb5-24\"><a href=\"#cb5-24\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This returns:</p>\n<div class=\"sourceCode\" id=\"cb6\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\"></a><span class=\"ex\">walk</span> Animal</span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\"></a><span class=\"ex\">fly</span> Bird</span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\"></a><span class=\"ex\">walk</span> Elephant</span></code></pre></div>\n<p>In the Java version it isn\u2019t apparent to the programmer that there is\na runtime cost, but C++ puts it front and center. Since we used the\n<code>new</code> keyword, everything is placed on the heap. When we try\nto call the <code>move()</code> method, we have to do it with the\n<code>-&gt;</code> operator, which calls an object on the heap, rather\nthan on the stack.</p>\n<p>Let\u2019s say we don\u2019t use the <code>new</code> operator, and don\u2019t use a\npointer lookup:</p>\n<div class=\"sourceCode\" id=\"cb7\"><pre\nclass=\"sourceCode numberSource cpp numberLines\"><code class=\"sourceCode cpp\"><span id=\"cb7-1\"><a href=\"#cb7-1\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-2\"><a href=\"#cb7-2\"></a>  <span class=\"at\">const</span> Animal animals<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span>Animal<span class=\"op\">(),</span> Bird<span class=\"op\">(),</span> Elephant<span class=\"op\">()};</span></span>\n<span id=\"cb7-3\"><a href=\"#cb7-3\"></a></span>\n<span id=\"cb7-4\"><a href=\"#cb7-4\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"at\">const</span> <span class=\"kw\">auto</span> <span class=\"op\">&amp;</span>animal <span class=\"op\">:</span> animals<span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb7-5\"><a href=\"#cb7-5\"></a>    animal<span class=\"op\">.</span>move<span class=\"op\">();</span></span>\n<span id=\"cb7-6\"><a href=\"#cb7-6\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb7-7\"><a href=\"#cb7-7\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>This prints out:</p>\n<div class=\"sourceCode\" id=\"cb8\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\"></a><span class=\"ex\">walk</span> Animal</span>\n<span id=\"cb8-2\"><a href=\"#cb8-2\"></a><span class=\"ex\">walk</span> Animal</span>\n<span id=\"cb8-3\"><a href=\"#cb8-3\"></a><span class=\"ex\">walk</span> Animal</span></code></pre></div>\n<p>Since we are literally treating each animal as an <code>Animal</code>\ntype, <code>animal.move()</code> calls the default <code>Animal</code>\nimplementation of move. If we choose to have no runtime cost, we get\nless desirable behavior. But C++ gives you the choice upfront.</p>\n<p>Let\u2019s dig deeper.</p>\n<p>C doesn\u2019t have any language support for <code>virtual</code>\nfunctions, but we can still emulate them.</p>\n<p>A (very) rough translation of the java program might look like\nthis:</p>\n<div class=\"sourceCode\" id=\"cb9\"><pre\nclass=\"sourceCode numberSource c numberLines\"><code class=\"sourceCode c\"><span id=\"cb9-1\"><a href=\"#cb9-1\"></a><span class=\"pp\">#include </span><span class=\"im\">&lt;stdio.h&gt;</span></span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\"></a></span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\"></a><span class=\"kw\">typedef</span> <span class=\"kw\">struct</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">char</span> <span class=\"op\">*</span>name<span class=\"op\">;</span></span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\"></a>  <span class=\"dt\">void</span> <span class=\"op\">(*</span>move<span class=\"op\">)(</span><span class=\"dt\">const</span> <span class=\"kw\">struct</span> Animal <span class=\"op\">*);</span></span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\"></a><span class=\"op\">}</span> Animal_t<span class=\"op\">;</span></span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\"></a></span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\"></a><span class=\"dt\">void</span> fly<span class=\"op\">(</span><span class=\"dt\">const</span> Animal_t <span class=\"op\">*</span>a<span class=\"op\">)</span> <span class=\"op\">{</span> printf<span class=\"op\">(</span><span class=\"st\">&quot;fly </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> a<span class=\"op\">-&gt;</span>name<span class=\"op\">);</span> <span class=\"op\">}</span></span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\"></a><span class=\"dt\">void</span> walk<span class=\"op\">(</span><span class=\"dt\">const</span> Animal_t <span class=\"op\">*</span>a<span class=\"op\">)</span> <span class=\"op\">{</span> printf<span class=\"op\">(</span><span class=\"st\">&quot;walk </span><span class=\"sc\">%s\\n</span><span class=\"st\">&quot;</span><span class=\"op\">,</span> a<span class=\"op\">-&gt;</span>name<span class=\"op\">);</span> <span class=\"op\">}</span></span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\"></a><span class=\"dt\">void</span> animal_move<span class=\"op\">(</span><span class=\"dt\">const</span> Animal_t <span class=\"op\">*</span>a<span class=\"op\">)</span> <span class=\"op\">{</span> a<span class=\"op\">-&gt;</span>move <span class=\"op\">?</span> a<span class=\"op\">-&gt;</span>move<span class=\"op\">(</span>a<span class=\"op\">)</span> <span class=\"op\">:</span> walk<span class=\"op\">(</span>a<span class=\"op\">);</span> <span class=\"op\">}</span></span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\"></a></span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\"></a><span class=\"dt\">int</span> main<span class=\"op\">(</span><span class=\"dt\">void</span><span class=\"op\">)</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-13\"><a href=\"#cb9-13\"></a>  <span class=\"dt\">const</span> Animal_t animals<span class=\"op\">[]</span> <span class=\"op\">=</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-14\"><a href=\"#cb9-14\"></a>      <span class=\"op\">{.</span>name <span class=\"op\">=</span> <span class=\"st\">&quot;Animal&quot;</span><span class=\"op\">},</span> <span class=\"op\">{.</span>name <span class=\"op\">=</span> <span class=\"st\">&quot;Bird&quot;</span><span class=\"op\">,</span> <span class=\"op\">.</span>move <span class=\"op\">=</span> fly<span class=\"op\">},</span> <span class=\"op\">{.</span>name <span class=\"op\">=</span> <span class=\"st\">&quot;Elephant&quot;</span><span class=\"op\">}};</span></span>\n<span id=\"cb9-15\"><a href=\"#cb9-15\"></a>  <span class=\"dt\">const</span> <span class=\"dt\">size_t</span> animals_len <span class=\"op\">=</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>animals<span class=\"op\">)</span> <span class=\"op\">/</span> <span class=\"kw\">sizeof</span><span class=\"op\">(</span>Animal_t<span class=\"op\">);</span></span>\n<span id=\"cb9-16\"><a href=\"#cb9-16\"></a></span>\n<span id=\"cb9-17\"><a href=\"#cb9-17\"></a>  <span class=\"cf\">for</span> <span class=\"op\">(</span><span class=\"dt\">int</span> i <span class=\"op\">=</span> <span class=\"dv\">0</span><span class=\"op\">;</span> i <span class=\"op\">&lt;</span> animals_len<span class=\"op\">;</span> i<span class=\"op\">++)</span> <span class=\"op\">{</span></span>\n<span id=\"cb9-18\"><a href=\"#cb9-18\"></a>    <span class=\"dt\">const</span> Animal_t animal <span class=\"op\">=</span> animals<span class=\"op\">[</span>i<span class=\"op\">];</span></span>\n<span id=\"cb9-19\"><a href=\"#cb9-19\"></a>    animal_move<span class=\"op\">(&amp;</span>animal<span class=\"op\">);</span></span>\n<span id=\"cb9-20\"><a href=\"#cb9-20\"></a>  <span class=\"op\">}</span></span>\n<span id=\"cb9-21\"><a href=\"#cb9-21\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>C actually lets us do some interesting things here: It allows us to\nallocate our <code>animals</code> on the stack. As well, we create an\n<code>animal_move</code> function that asks the struct passed in if it\nhas a function pointer for <code>move</code>. If it does, then it defers\nto that, otherwise it calls a default implementation. If we do choose to\nuse a more specific version of <code>move</code>, then we do have the\npointer lookup cost, but if not, there is no cost.</p>\n<p>Predictably, this prints:</p>\n<div class=\"sourceCode\" id=\"cb10\"><pre\nclass=\"sourceCode numberSource sh numberLines\"><code class=\"sourceCode bash\"><span id=\"cb10-1\"><a href=\"#cb10-1\"></a><span class=\"ex\">walk</span> Animal</span>\n<span id=\"cb10-2\"><a href=\"#cb10-2\"></a><span class=\"ex\">fly</span> Bird</span>\n<span id=\"cb10-3\"><a href=\"#cb10-3\"></a><span class=\"ex\">walk</span> Elephant</span></code></pre></div>\n<p>Digging a little up, we find that Rust has a similar concept, but it\ndoes away with using keywords like <code>virtual</code> or\n<code>final</code> to designate dynamic dispatch.</p>\n<div class=\"sourceCode\" id=\"cb11\"><pre\nclass=\"sourceCode numberSource rs numberLines\"><code class=\"sourceCode rust\"><span id=\"cb11-1\"><a href=\"#cb11-1\"></a><span class=\"kw\">pub</span> <span class=\"kw\">trait</span> Animal <span class=\"op\">{</span></span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\"></a>    <span class=\"kw\">fn</span> name(<span class=\"op\">&amp;</span><span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">String</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\"></a>        <span class=\"st\">&quot;Animal&quot;</span><span class=\"op\">.</span>to_string()</span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\"></a>    <span class=\"kw\">fn</span> act(<span class=\"op\">&amp;</span><span class=\"kw\">self</span>) <span class=\"op\">{</span></span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\"></a>        <span class=\"pp\">println!</span>(<span class=\"st\">&quot;walk {}&quot;</span><span class=\"op\">,</span> <span class=\"kw\">self</span><span class=\"op\">.</span>name())<span class=\"op\">;</span></span>\n<span id=\"cb11-7\"><a href=\"#cb11-7\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-8\"><a href=\"#cb11-8\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-9\"><a href=\"#cb11-9\"></a></span>\n<span id=\"cb11-10\"><a href=\"#cb11-10\"></a><span class=\"kw\">struct</span> GenericAnimal <span class=\"op\">{}</span></span>\n<span id=\"cb11-11\"><a href=\"#cb11-11\"></a><span class=\"kw\">impl</span> Animal <span class=\"cf\">for</span> GenericAnimal <span class=\"op\">{}</span></span>\n<span id=\"cb11-12\"><a href=\"#cb11-12\"></a></span>\n<span id=\"cb11-13\"><a href=\"#cb11-13\"></a><span class=\"kw\">struct</span> Bird <span class=\"op\">{}</span></span>\n<span id=\"cb11-14\"><a href=\"#cb11-14\"></a><span class=\"kw\">impl</span> Animal <span class=\"cf\">for</span> Bird <span class=\"op\">{</span></span>\n<span id=\"cb11-15\"><a href=\"#cb11-15\"></a>    <span class=\"kw\">fn</span> name(<span class=\"op\">&amp;</span><span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">String</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-16\"><a href=\"#cb11-16\"></a>        <span class=\"st\">&quot;Bird&quot;</span><span class=\"op\">.</span>to_string()</span>\n<span id=\"cb11-17\"><a href=\"#cb11-17\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-18\"><a href=\"#cb11-18\"></a>    <span class=\"kw\">fn</span> act(<span class=\"op\">&amp;</span><span class=\"kw\">self</span>) <span class=\"op\">{</span></span>\n<span id=\"cb11-19\"><a href=\"#cb11-19\"></a>        <span class=\"pp\">println!</span>(<span class=\"st\">&quot;fly {}&quot;</span><span class=\"op\">,</span> <span class=\"kw\">self</span><span class=\"op\">.</span>name())<span class=\"op\">;</span></span>\n<span id=\"cb11-20\"><a href=\"#cb11-20\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-21\"><a href=\"#cb11-21\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-22\"><a href=\"#cb11-22\"></a></span>\n<span id=\"cb11-23\"><a href=\"#cb11-23\"></a><span class=\"kw\">struct</span> Elephant <span class=\"op\">{}</span></span>\n<span id=\"cb11-24\"><a href=\"#cb11-24\"></a><span class=\"kw\">impl</span> Animal <span class=\"cf\">for</span> Elephant <span class=\"op\">{</span></span>\n<span id=\"cb11-25\"><a href=\"#cb11-25\"></a>    <span class=\"kw\">fn</span> name(<span class=\"op\">&amp;</span><span class=\"kw\">self</span>) <span class=\"op\">-&gt;</span> <span class=\"dt\">String</span> <span class=\"op\">{</span></span>\n<span id=\"cb11-26\"><a href=\"#cb11-26\"></a>        <span class=\"st\">&quot;Elephant&quot;</span><span class=\"op\">.</span>to_string()</span>\n<span id=\"cb11-27\"><a href=\"#cb11-27\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-28\"><a href=\"#cb11-28\"></a><span class=\"op\">}</span></span>\n<span id=\"cb11-29\"><a href=\"#cb11-29\"></a></span>\n<span id=\"cb11-30\"><a href=\"#cb11-30\"></a></span>\n<span id=\"cb11-31\"><a href=\"#cb11-31\"></a><span class=\"kw\">fn</span> main() <span class=\"op\">{</span></span>\n<span id=\"cb11-32\"><a href=\"#cb11-32\"></a>    <span class=\"kw\">let</span> animals<span class=\"op\">:</span> <span class=\"dt\">Vec</span><span class=\"op\">&lt;&amp;</span><span class=\"kw\">dyn</span> Animal<span class=\"op\">&gt;</span> <span class=\"op\">=</span> <span class=\"pp\">vec!</span>[<span class=\"op\">&amp;</span>GenericAnimal<span class=\"op\">{},</span> <span class=\"op\">&amp;</span>Bird<span class=\"op\">{},</span> <span class=\"op\">&amp;</span>Elephant<span class=\"op\">{}</span>]<span class=\"op\">;</span></span>\n<span id=\"cb11-33\"><a href=\"#cb11-33\"></a>    <span class=\"cf\">for</span> animal <span class=\"kw\">in</span> animals <span class=\"op\">{</span></span>\n<span id=\"cb11-34\"><a href=\"#cb11-34\"></a>        animal<span class=\"op\">.</span>act()<span class=\"op\">;</span></span>\n<span id=\"cb11-35\"><a href=\"#cb11-35\"></a>    <span class=\"op\">}</span></span>\n<span id=\"cb11-36\"><a href=\"#cb11-36\"></a><span class=\"op\">}</span></span></code></pre></div>\n<p>We create a <code>trait</code> of animal (kind of like an interface,\nbut supercharged) and then we create an instantiable version of it\n(<code>GenericAnimal</code>) that just takes the default implementation.\nThen we implement our <code>Bird</code> and <code>Elephant</code> and we\ncollect them into a vector and properly call the method on them. The\ncompiler assumes that we want dynamic dispatch by default and does it\nfor us. If not, we can call the parent classes\u2019 method:</p>\n<div class=\"sourceCode\" id=\"cb12\"><pre\nclass=\"sourceCode numberSource rs numberLines\"><code class=\"sourceCode rust\"><span id=\"cb12-1\"><a href=\"#cb12-1\"></a><span class=\"pp\">Animal::</span>act(<span class=\"op\">&amp;</span>Bird)<span class=\"op\">;</span> <span class=\"co\">// this calls the Animal version of `act` with a bird.</span></span></code></pre></div>\n<p>This is similar to C++:</p>\n<div class=\"sourceCode\" id=\"cb13\"><pre\nclass=\"sourceCode numberSource cpp numberLines\"><code class=\"sourceCode cpp\"><span id=\"cb13-1\"><a href=\"#cb13-1\"></a><span class=\"at\">const</span> Bird<span class=\"op\">*</span> bird <span class=\"op\">=</span> <span class=\"kw\">new</span> Bird<span class=\"op\">();</span></span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\"></a>bird<span class=\"op\">-&gt;</span>Animal<span class=\"op\">::</span>move<span class=\"op\">();</span> <span class=\"co\">// calls Animal::move with bird.</span></span></code></pre></div>\n<p>In short, here\u2019s a history of virtual functions and their syntax,\nstarting from C and ending with Rust:</p>\n<p>In C, there\u2019s a rough way to emulate virtuals, but it takes some\neffort since it\u2019s not built into the language.</p>\n<p>In C++, virtual functions were deemed useful enough to be built into\nthe language. This led to a terser syntax for overriding, but led to\nmore cognitive load on the programmer, since they had to choose\n<code>virtual</code> or non-virtual implementations.</p>\n<p>In Java, most methods are by default virtual, so the implementation\ndetails are hidden from the programmer. Java allows you to declare\nnon-overridable methods as <code>final</code>, so <code>final</code>\nmethods have no runtime cost, and all <code>@Override</code> methods\nhave runtime cost, which is a fair tradeoff.</p>\n<p>In Rust, the compiler figures out if you want a <code>virtual</code>\nor normal method call through your trait implementations, but allows you\nto call the base method through a subclass if you so choose. This allows\nfor having even less cognitive load than in Java (no\n<code>@Override</code> or <code>final</code> necessary), but with an\nescape hatch to call the base class method in an overriden type (as C++\nallows).</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2021-05-17T01:28:00+00:00"
		},
		{
			"id": "gen/the-strong-force-and-weak-force-of-companies.html",
			"url": "gen/the-strong-force-and-weak-force-of-companies.html",
			"title": "The Strong Force and Weak Force of Companies",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>The Strong Force and Weak Force of Companies</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">The Strong Force and Weak Force of Companies</h1>\n<p class=\"byline\">2020-08-18T13:19:06-05:00</p>\n</header>\n<p>There are four fundamental interactions in physics; gravity,\nelectromagnetism, the strong force, and the weak force. Particles are\naffected by all four of these \u2013 hence why they are fundamental to\nunderstanding physics. The strong force holds the nucleus of an atom\ntogether. The weak force tries to tear the nucleus of an atom apart,\ncreating radioactivity.</p>\n<p>The strong force is a million times stronger than the weak force at\nsmall distances, up to 10 angstroms. However, as you add more protons\nand neutrons to the nucleus of an atom, the atom gets bigger - and the\nweak force becomes stronger and stronger, until eventually the nucleus\nof an atom is too big to be kept together by the strong force, and the\nweak force tears the atom apart, resulting in a radioactive atom.\nCompanies follow the same trajectory.</p>\n<p>Companies are a lot like atoms; at first, growth is key \u2013 you want to\nextend your revenue by having people buy the service you offer them. How\ndo you build a better service? By hiring. So you hire people to improve\nyour service. At first, this works excellently. Your first few hires\nhave great impact at the company, and they lay the foundation for hires\nin the future. Of course, it\u2019s not all roses \u2013 they make some mistakes,\nand put in guardrails to make sure future employees don\u2019t make the same\nmistakes. But at this point of the curve, it is worth way more to you as\na company to continue hiring, since each hire gives you more value than\nyou pay them. But as time passes and you hire more people, each hire has\nless impact. They\u2019re encumbered by the communication cost of talking to\nmultitudes of stakeholders, and the cost of checking all of the\nguardrails their predecessors laid down for them. Eventually work slides\nto a snail\u2019s pace, and it shows \u2013 the product doesn\u2019t improve very much,\nif at all \u2013 features that might take a few days take months at a time\nnow, and your revenue doesn\u2019t increase as much as it used to. You\u2019ve hit\nyour first slope. Your competitive advantage, your strong force is\nfading. Everyone else is coming for you. The weak force is\nstrengthening.</p>\n<p>You have a few ways of delaying the inevitable \u2013 maybe you find a\nnovel way to manage resources so you become better than the competition.\nMaybe you realize that some of the rules you\u2019ve enshrined don\u2019t do much\nfor you, so you cut excess baggage. Maybe you can\u2019t do the above, and\nyou cut excess resources in the form of employees. You\u2019ve managed to\nkeep the competition at bay, but your strong force weakens as you do\nthis. If you manage resources to become better than the competition,\nwhat stops the competition from copying you? If you cut excess baggage,\nyou run the risk of cutting out rules that were well-intentioned and\nprotected you from damage. You run the risk of plunging your company\ninto a dark age, where the employees have to rediscover the practices\nthat were purged from the annals of history to resume work. If you cut\nemployees, you risk the loss of morale that keeps your company churning.\nIf the company is willing to axe some people, what stops it from axing\nthe rest of them? Each time you do this, you come closer to your doom by\nthe hands of the weak force.</p>\n<p>A company that keeps delaying the inevitable soon falls to its own\nforces. It blows up, metaphorically. People stop wanting to work at the\nfirm because there\u2019s too much bureaucracy. The product stop dominating\nthe market, and revenues fall. The consumers drop you for your\ncompetition. Your company blows up, becoming a waste zone.</p>\n<p>Business is all about keeping the weak force away. As we\u2019ve made\nprogress in business, we\u2019ve learned how to do this better. Companies\nfind ways to make more revenue with fewer people, and do more with less.\nBut this too shall pass \u2013 the companies of yesteryear will soon be left\nin the dust. And so on and so forth. I wonder what the future of\norganization has in store for the rest of us?</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2020-08-18T18:19:06+00:00"
		},
		{
			"id": "gen/the-business-curve.html",
			"url": "gen/the-business-curve.html",
			"title": "The Business Curve",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>The Business Curve</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">The Business Curve</h1>\n<p class=\"byline\">2020-08-08T10:25:54-05:00</p>\n</header>\n<p>In <code>Zero to One</code>, Peter Thiel proclaims \u201cCompetition is\nfor losers.\u201d \u2013 if you can make a monopoly, you should, because you can\nextract far more profit from it than if you participated in an open\nmarket.</p>\n<p>In a free market, with perfect competition, you face this supply and\ndemand curve below. You have to sell the good at the price where supply\nmeets demand, and you can sell up to but not more than quantity where\ndemand meets supply. Assuming you\u2019re not the only seller of the good,\nyou have to settle for some chunk of the market.</p>\n<p><img src=\"../assets/supply-and-demand-curve.png\" /></p>\n<p>Assume there are 5 merchants, and the amount of revenue you can bring\nin is the square created by the area of where supply meets demand, you\nget something like this:</p>\n<p><img src=\"../assets/supply-and-demand-curve-for-firms.png\" /></p>\n<p>All of you split the market somewhat equally, and you make 0\n<em>economic</em> profit. Nobody can sell the good for more than it\u2019s\nworth (opportunity cost + cost of production), and nobody will buy the\ngood for more than it\u2019s worth (opportunity cost + cost of production).\nThe perfectly free market makes buyers and sellers equally well off.</p>\n<p><img src=\"../assets/utility-for-buyers-and-sellers.png\" /></p>\n<p>This assumes that the first few products that a firm sells on the\nopen market are the <em>cheapest</em> for it to produce, and that there\nare buyers that are willing to pay <em>more</em> for the product than\nothers, because it is inherently worth more to them. The firms get to\nsell the goods that cost less for them to make at a higher price, and\nthe buyers who would\u2019ve bought the good at a higher price to get to pay\nless for the good. Everyone wins a little bit.</p>\n<p>But firms want to make <em>economic</em> profit. This is where the\nreal money comes in. You can do this in many ways; organizations like\nOPEC (the Organization of the Petroleum Exporting Countries) band\ntogether every year and restrict the supply of oil on the open market.\nThis lets them charge more for their good (oil), since artificial\nscarcity drives up the price of oil.</p>\n<p>Because of this, the market for oil looks something like this:</p>\n<p><img src=\"../assets/opec-oil-curve.png\" /></p>\n<p>The utility that both sides get is:</p>\n<p><img src=\"../assets/opec-utility-gain.png\" /></p>\n<p>Nice! We\u2019ve made <em>economic</em> profit. What we\u2019ve done here is\ntaken a large slice of the pie for ourselves; the buyers lose some\nutility, but in exchange the sellers get more utility. However, we\u2019ve\nlost some <em>total</em> utility. The area to the right of the seller\u2019s\nutility gain is now white. That\u2019s utility that we\u2019ve <em>lost</em>. This\nis called <em>Deadweight Loss</em>, because OPEC has now made some\nutility inherent to the market unreachable. The market as a whole could\nbe better off and capture that white area if OPEC decided to sell oil at\nthe market competitive price.</p>\n<p>OPEC made the market better for the sellers, in exchange for hurting\nthe buyers, and worse for the economy as a whole.</p>\n<p>In this case, OPEC is an oligopoly, or a case where there are only a\nfew sellers of a good. A monopoly is when there\u2019s only one, and a\nduopoly is when there are only two. All of these traditionally generate\ndeadweight loss, generating less utility for the buyer and more for the\nseller(s). This is why you hear how monopolies and oligopolies are\n<em>bad</em> and should be broken up by the government.</p>\n<p>But OPEC isn\u2019t a maintainable oligopoly. Saudi Arabia doesn\u2019t trust\nthe other members of OPEC. Russia doesn\u2019t trust OPEC. In fact, OPEC\ndoesn\u2019t trust itself. The reason is simple: As a seller, you could make\nmore money if you undercut the market and sell more oil at a lower\nprice. If I sell oil at a lower price than the other countries, I get\nall of the profits. That entire red rhombus I had to share with the\nother sellers? All mine. And I expand it a little bit too. The rhombus\ngets fatter for me, at the expense of all of the other sellers.\nOligopolies have a cooperation problem \u2013 the economy cannot enforce its\nsellers to sell a good at a higher price than it values said good. So\nRussia, Venezuela, Saudi, and so forth go to each OPEC meeting wondering\nif this is the time the other countries backstab them and make off with\nall the gold. In OPEC\u2019s case, all of the countries have to be well armed\ntoo, because they don\u2019t know when the other countries might come to\ncapture their oil to increase their profits. Cooperation works worst\nwhen all parties are paranoid.</p>\n<p>The problem with this model of economics is that it only somewhat\napplies to some goods in some places. This assumes we have symmetric\ninformation \u2013 that sellers know just as much as buyers. This also\nassumes that our goods are private and no different than each other. But\nreally, every good is somewhat different; coke isn\u2019t exactly the same as\npepsi, even though they are similar products. This model also doesn\u2019t\ncount network effects, where making a good become more popular has\nbenefits to all of its users and its overall utility.</p>\n<p>If I wanted to buy some British soda, I would have to import that\nsoda to the US in order to buy it. That costs me both time and money;\nand so the soda costs more than it would if I simply wanted a coke. If I\nwanted a coke, I could just walk down the street since every grocery\nstore carries it, because of its popularity. Coke is cheaper than this\nBritish soda, Iron Bru.</p>\n<p>A service like Uber really wants a monopoly for that reason; because\nif it had a monopoly, it would be able to have all of the drivers on its\nplatform available to serve all of the riders, and thus be able to get\neconomic profit. Alas, Lyft exists; and so, there are only half the\navailable drivers on Uber and half the available riders on Uber. Uber\nand Lyft are then also forced to price their service lower and lower to\nbeat each other out and win the loyalty of their riders. Buyers win\nhere, but the sellers are engaged in a race to the bottom. And only one\nwill survive, a la highlander.</p>\n<p>If we assume that a monopoly is the only way to go to gain\nmonopolistic profits, we need to find a way to do so, without using\nforce (because that breeds paranoia). The only way out is by making a\nbetter product. If we make a better product, we can create a market that\ndidn\u2019t exist before, and gain monopolistic profits from that market. If\nthis product cannot be replicated, then there is no incentive to stop\nthe monopoly; because the market will only be worse off. Thus, no use of\nforce in any way can stop us from gaining monopoly profits. But building\nthe next Google is hard. Incredibly so.</p>\n<p>You can, however, build a product that has differentiation in some\nway. You must have a feature that is <em>hard</em> and <em>useful</em>,\nand you too can ride a smaller but also profitable monopoly curve for\nprofit.</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2020-08-08T15:25:54+00:00"
		},
		{
			"id": "gen/language-pessimism-and-optimism.html",
			"url": "gen/language-pessimism-and-optimism.html",
			"title": "Language Pessimism and Optimism",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Language Pessimism and Optimism</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Language Pessimism and Optimism</h1>\n<p class=\"byline\">2020-04-24T16:31:51-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#the-pessimists\" id=\"toc-the-pessimists\">The\nPessimists</a></li>\n<li><a href=\"#the-optimists\" id=\"toc-the-optimists\">The\nOptimists</a></li>\n<li><a href=\"#a-twist\" id=\"toc-a-twist\">A Twist</a></li>\n<li><a href=\"#choose-your-own-adventure\"\nid=\"toc-choose-your-own-adventure\">Choose your own adventure</a></li>\n<li><a href=\"#is-safety-preference\" id=\"toc-is-safety-preference\">Is\nSafety Preference?</a></li>\n</ul>\n</nav>\n<p>Let\u2019s talk languages. Not languages like Swahili or Latin, but\nlanguages like C or Java. Programming languages. I would argue that the\nprogramming language you use day to day is the most important tool you\nuse in programming \u2013 if you use a modern language, it offers a lot of\npunch compared to something like assembly. The programming languages of\ntoday are cross platform, which gives you <em>compatibility</em>,\nmeaning you don\u2019t have to worry about writing your code for every\nplatform or architecture, because your language takes care of it for\nyou. It gives you <em>abstraction</em>, because you can write code that\ntakes a different shape than the way the machine sees it. Machines can\u2019t\nunderstand for loops or if statements, or even really anything more than\n0s and 1s. We made up things like functions and classes and interfaces\nand stuff like that. And these abstractions are really good. I\u2019ve never\nwondered when a for loop or if statement didn\u2019t work as intended in the\nlanguage. Programming languages also give you <em>safety</em> \u2013 they\nprevent you from doing bad things with your program. If I try to cast to\na non-compatible type, my compiler might catch that \u2013 if I try to write\nto some memory I don\u2019t own, my language or Operating system will stop\nthat. And that\u2019s just scratching the surface \u2013 there\u2019s plenty more to\nlove about languages. Higher order functions! Algebraic Data Types!\nOptimizations! Syntactic Sugar! It\u2019s a joyride all the way down. But\nwe\u2019re not going to talk about the nitty-gritty type theory of languages,\nno, today we\u2019re going to be talking about how people view languages in\nprogramming, by doing everybody\u2019s favorite thing \u2013 dividing people into\ntwo kinds of people, the x\u2019s and the y\u2019s, or the pessimists and\noptimists.</p>\n<section id=\"the-pessimists\" class=\"level2\">\n<h2>The Pessimists</h2>\n<p>The pessimists tend to say something along these lines quite often:\n\u201cGood code can be written in any language, and bad code can be written\nin any language. It\u2019s all about discipline when writing code.\u201d COBOL is\nas good as Java. People made great systems in COBOL, just like they made\ngreat systems in Java. And it\u2019s true. Much underpinning financial\nsystems were written in COBOL. Many COBOL systems are still out in the\nwild running, decades after they were written. And to the pessimists\u2019\ncredit, they work just fine. After all, if a language is Turing\ncomplete, it is <em>as powerful</em> as any other language. Basically\nall popular languages are Turing complete, so they\u2019re theoretically\nequivalent in power. Some languages are just better at certain things,\nbut they can all <em>express</em> the same things.</p>\n</section>\n<section id=\"the-optimists\" class=\"level2\">\n<h2>The Optimists</h2>\n<p>The optimists might say that languages are different. An optimist\nmight say that they prefer C++ to C because it has collections and\nObject Orientation. An optimist might enjoy using smart pointers to aid\nin memory management. An optimist might like the way that python handles\niterable collections. These all aid in code readability, because the\nabstraction is easy to understand and encapsulates more functionality in\nfewer lines. Maybe an optimist likes static types, because they make it\nexplicit what types of data a function or method might return, or make\nit easier to understand the way data transforms throughout its\nlifecycle. In the optimists\u2019 eyes, there are abstractions which aid in\nthe expression of code, and since different languages choose different\nabstractions to make the expression of some types of programs harder and\nsome easier, there are some differences between languages. You can\nprogram in an object oriented style in C. You can program in a generic\nstyle in C. These are all far less compact than their equivalent C++.\nThere is an aesthetic difference, if not theoretical difference.</p>\n</section>\n<section id=\"a-twist\" class=\"level2\">\n<h2>A Twist</h2>\n<p>If you follow my points up above, I\u2019m promoting the idea that\nlanguage optimists prefer the aesthetics of a language, whereas the\nlanguage pessimists prefer the theoretical power of a language.\nTheoretical power of a language is not bounded by expressiveness,\nhowever. If it took you 100 lines of code to read from a file in a toy\nlanguage (let\u2019s call this language Airplane), but 1 line of code to read\nfrom a file in another language (let\u2019s call this language Ship), Ship\nand Airplane would be theoretically equal in power. But in practice,\nmost people would prefer to use Ship for reading files. 1 line of code\nis 100x less than 100. If this was the case for everything (let\u2019s say it\ntook 100x more lines to write any possible program in Airplane than in\nShip), you would probably prefer Ship. In terms of expressiveness, Ship\nis better than airplane.</p>\n<p>Ship is still not more <em>powerful</em> than Airplane; it is simply\nmore expressive.</p>\n<p>But that\u2019s still just aesthetics; what if there was a class of\nproblems that Ship did not suffer from that airplane suffered from.\nLet\u2019s say that Airplane and Ship are both Web programming languages, and\nif you fail to write \u201csafe\u201d Airplane code, you might allow some users to\nread information that belongs to another user\u2019s. Let\u2019s say in Ship, this\nproblem doesn\u2019t exist \u2013 Ship wouldn\u2019t let our code compile if it could\ndetect the possibility of this bug.</p>\n<p>Even with this added on, Ship is still not <em>theoretically</em>\nmore safe than Airplane; a correctly written Airplane program is <em>as\nsafe</em> as a Ship program that compiles. But I would say in this case,\nmost programmers would prefer Ship. Even though Airplane is\n<em>theoretically</em> <em>as safe</em> as Ship, a language that\nprovably lacks a class of errors is at least marginally better than a\nlanguage that may probabilistically have a class of errors.</p>\n<p>Now the twist is, is Ship in a different class of language compared\nto Airplane? Does safety matter?</p>\n</section>\n<section id=\"choose-your-own-adventure\" class=\"level2\">\n<h2>Choose your own adventure</h2>\n<p>It\u2019s up to you. Theoretically safety doesn\u2019t play a part in\nprogramming. God awful safety vulnerabilities and memory leaks don\u2019t\nmatter because, while they cause us and our users to be sad, and might\neven cause us to go to jail, they don\u2019t make our program any less\npowerful. A program doesn\u2019t care if you go to jail or not, actually, and\nneither does math. If you are concerned with this definition of power,\nthen Airplane and Ship are indeed equivalent. But maybe you have a more\npractical bent. If so, Ship is probably the better language \u2013 hey, you\ncan express yourself with 100x less code and it has more safety built in\nthat Airplane.</p>\n</section>\n<section id=\"is-safety-preference\" class=\"level2\">\n<h2>Is Safety Preference?</h2>\n<p>That leads me to my last point. Is Safety Preference? Is a safer\nlanguage a categorically different language than one that an unsafe\nlanguage? I would argue so. Most programmers these days will probably\nnever touch a memory unsafe language (C and C++ being the most popular\nof these). There\u2019s a whole extra class of errors to account for in these\ntwo languages, and when you choose a garbage collected language, most of\nthe time you don\u2019t have to worry about memory. That helps you out with\ndelivering better safe software. And that\u2019s great. It makes you more\nproductive. But maybe you need to have performance instead of safety,\nand this is where most people go for performance. Safety comes at some\ncost, and you can\u2019t always have safety. But if you can have safety, you\nmight as well buy into it, since it lessens your cognitive load.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2020-04-24T21:31:51+00:00"
		},
		{
			"id": "gen/performance-matters.html",
			"url": "gen/performance-matters.html",
			"title": "Performance Matters",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Performance Matters</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Performance Matters</h1>\n<p class=\"byline\">2020-03-29T13:51:41-05:00</p>\n</header>\n<p>Asking programmers about performance generally leads to two trains of\nthought. Either it doesn\u2019t matter, and there are other metrics to chase,\nor performance matters. Most of the time, those who think that\nperformance matters can be broken down into two different streams of\nthought. One group thinks that performance matters because it saves\nmoney \u2013 if your server costs are a million dollars a month and you make\nthe whole system 10% more efficient, you\u2019ve reduced server costs by\nabout a hundred thousand dollars. It\u2019s nice to save that money. The\nother group is more intense about it \u2013 performance is the only thing\nthat matters because it allows us to create programs that solve problems\nthat other (less efficient) programs would simply not allow us to.\nPlenty of hot-path code is written in low-level highly optimized\nlanguages.</p>\n<p>All three ways are true in sometimes: sometimes you don\u2019t need to\nlook at code under a microscope because the underlying runtime will\noptimize it, sometimes saving money may save the company, and sometimes\nperformance is the only thing that matters. But I\u2019m going to say that\nperformance has and always will matter because of the fact that hardware\nwill always get smaller, and we want to do more with less. It turns out\nthat there is a great analogue for this in chemistry already.</p>\n<p>In chemistry, atoms are held together by gravitational forces. But\nthere are two forces at work, the <code>strong</code> and\n<code>weak</code> force. The <code>strong force</code> keeps the nucleus\nof an atom together, whereas the <code>weak force</code> tries to\ndisperse the protons and neutrons of the atom. As you\u2019d expect, the\n<code>strong force</code> is stronger than the <code>weak force</code>\nfor smaller elements. But this begins to break down as atoms get bigger\n\u2013 the <code>strong force</code> is not asymptotically stronger than the\n<code>weak force</code>. As such, there are radioactive elements like\nUranium-235, where the <code>weak force</code> overpowers the\n<code>strong force</code> and causes the element to become radioactive.\nRadioactive elements eventually tear themselves apart, and split into\nsmaller elements at the end of their half-life.</p>\n<p>Hardware has historically (and I don\u2019t think this will change much)\nbeen the same way. At first, computers like the ENIAC were the size of a\nhouse, (wikipedia says 1,800 sq ft), and consumed 150kW of electricity\nto perform a whopping three square root operations per second. At first,\nthis is wholly insufficient for most of the work needed to be done on a\ncomputer. So research was done to optimize hardware to the point where\nit was able to be made smaller. That led to the micro-computer, a\ncomputer the size of a desk, which could do some interesting tasks like\nword processing or simple text games. Eventually we found that we had\nenough performance that we could stick a micro-computer into a smaller\ncomputer, one that was portable, and that was called a laptop. Then the\nhardware advanced to the point where it could fit into your pocket, and\nthat became the smart phone. Tablets branched out to be in the middle of\nsize (and therefore compute) of a laptop and a smart phone. Our need for\nsmaller and more efficient hardware has made it so we couldn\u2019t throw\nperformance by the wayside; every time performance was \u201cgood enough\u201d,\nthe hardware got smaller until performance mattered again.</p>\n<p>If you believe history will continue, then we\u2019ll have even smaller\ndevices with even more strict real time capabilities. Doctors have been\nasking for more efficient tools to treat patients with for a very long\ntime, for good reason. More portable and cheaper tools for doctors allow\nthem to treat more patients at less cost. More powerful tools allow for\ndoctors to find signs that they might\u2019ve missed with less powerful\ntools. A new generation of video gamers want to bring their games on the\ngo \u2013 as such, the mobile video game industry has blossomed apart from\nthe traditional console based games. VR headsets are now being used for\ntherapy, and this is extremely performance sensitive \u2013 if the program on\na VR headset is slow by even milliseconds, the user may become fatigued\nor nauseous, which defeats the purpose of the technology.</p>\n<p>History has always been about doing more with less, and I don\u2019t see\nthat changing for the near future. Maybe when Moore\u2019s law stops becoming\ntrue?</p>\n</article>\n</body>\n</html>\n",
			"date_published": "2020-03-29T18:51:41+00:00"
		},
		{
			"id": "gen/who-gets-stuff-done.html",
			"url": "gen/who-gets-stuff-done.html",
			"title": "Who Gets Stuff Done",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Who Gets Stuff Done</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Who Gets Stuff Done</h1>\n<p class=\"byline\">2020-03-12T11:52:45-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#the-hiring-bar\" id=\"toc-the-hiring-bar\">The Hiring\nBar</a></li>\n</ul>\n</nav>\n<p>Software developers are generalists. Ask the average software\ndeveloper questions about networking, databases, compilers, operating\nsystems, data structures, distributed systems, and 9 out of 10 will tell\nyou that they know something about them. But this generalist mentality\nbegins to break down once you acknowledge one of the most fundamental\nthings rules of life:</p>\n<ol type=\"1\">\n<li>Nobody can be an expert at everything.</li>\n</ol>\n<p>And if nobody can be an expert at everything, we eventually must have\nroles for our field. One mechanic alone cannot create a high performing\nand standards compliant car these days. It\u2019s just too hard. Likewise,\nsoftware development is too hard for any one person to keep the whole\nfield in their head. And that\u2019s a good thing. It means that we have\nroles for who does what, and that helps teams move quickly, without\ngetting bogged down in the minutae.</p>\n<p>So we have well defined roles for the work that we do on our teams,\nlike Front-End developer, Back-End developer, DevOps, SysAdmin,\nDesigner, Product Manager. All is dandy in the world. Well, all would be\ndandy if there wasn\u2019t a question of what makes an developer a\ndeveloper.</p>\n<p>Once a field becomes sufficiently mature, the practioners of the\ncraft, (the real intense ones anyway) start sharing a common idea of the\nideal practioner. First this starts out as vague and easy to achieve\nideals, like \u201ca real developer would be able to answer fizzbuzz in 30\nseconds\u201d, or \u201ca developer should be able to understand one programming\nlanguage well\u201d, which is all hunky dory. And soon, a regulatory body of\npractioners, filled with the people who subscribe to that ideal the best\nis borne, and they create norms and disseminate them to the rest of the\npracticing population. Psychologists in America have the APA, doctors to\npass a board certification, and lawyers have to pass the bar in each\nstate. I\u2019ll call the idea of the ideal practioner the \u201csoul\u201d of the\nfield, and the regulatory body (a la APA, bar, or other) the \u201cbody\u201d. If\nall is in harmony, the \u201cbody\u201d and \u201csoul\u201d are in alignment \u2013 the\npractioners agree with the higher ups on what should be taught, and what\nconstitutes a \u201creal\u201d practioner.</p>\n<p>The system I\u2019ve described above works great when \u201cbody\u201d and \u201csoul\u201d\nare in tune \u2013 there is buy-in from both sides of the table. But\nprogramming has never had that. And it\u2019s because the field is too\nvaried, one that should\u2019ve been split up (and probably will be) in the\ncoming decades. You see, development doesn\u2019t fit so neatly like other\nprofessions do in this model, because at large, there aren\u2019t two groups\nof programmers. There are three. Academics, Systems Programmers, and\nApplication Programmers.</p>\n<p>In computer science, academics do research on problems that are\nremarkably forward thinking \u2013 as you read this, papers are being\npublished for increasing the speed of low-level hardware, operating\nsystem calls, database reads and writes, distributed systems,\nprogramming langauges, AI, statistics, quantum computing, cryptography,\nwhat have you. These all have wide impact, maybe even decades later \u2013\nBarbara Liskov (of the Liskov substitution principle) was working on\nobject oriented languages in the 60s, some 30 years before they made it\nto the mainstream for practioners in the form of java. Liskov as well as\nLampert made long lasting contributions to distributed systems research,\nwhich has changed the way practioners have built their infrastructure,\nand has allowed companies like google and amazon to become global\ncompanies. RSA encryption, made in the 70s, is widely used today. There\nis a long tail of important and groundbreaking research, but you get the\ngist \u2013 Academics do important research.</p>\n<p>Systems Programmers are the ones who, when they see a reason to,\nimplement the academic\u2019s work. Linux implements some of the cutting edge\nof operating systems research. Zookeeper implements the consensus\nalgorithms that academics envisioned from the 70s. OpenSSL implements\nRSA encryption, and many others. System programmers transfer the\nabstract, theoretical world of theorems and proofs into libraries and\npackages for the rest of us to use.</p>\n<p>Application programmers are the ones who take the work of System\nProgrammers and create products and applications that are used by the\nworld at large (read: not tech-savvy people). They deal with the nitty\ngritty of presentation and User Experience, and find creative ways to\nuse the tools they have to make products that require very little\nin-depth knowledge of the product to use.</p>\n<p>With these three camps, it is impossible to have either a \u201csoul\u201d or\n\u201cbody\u201d for programmers. I\u2019ll list out the ideal \u201cbody\u201d and \u201csoul\u201d for\neach of the three camps.</p>\n<p>Academics:</p>\n<ul>\n<li>Body:\n<ul>\n<li>An academic body that tests developers on the rigor of their proofs\nand theoretical knowledge.</li>\n</ul></li>\n<li>Soul:\n<ul>\n<li>A practioner that thinks from first-principles to expand the rigor\nand breadth of the field.</li>\n</ul></li>\n<li>Education:\n<ul>\n<li>A higher education (Masters or PhD)</li>\n</ul></li>\n</ul>\n<p>Systems Programmers:</p>\n<ul>\n<li>Body:\n<ul>\n<li>A coalition of workers who stress low-level (in code) fundamentals,\nand tool building for performance.</li>\n</ul></li>\n<li>Soul:\n<ul>\n<li>A practioner who doesn\u2019t necessarily need to produce academic\nresearch, but can pick up academic works and translate them to libraries\nand packages.</li>\n</ul></li>\n<li>Education:\n<ul>\n<li>A degree in the field (Undergrad, Masters, or PhD)</li>\n</ul></li>\n</ul>\n<p>Application Programmers:</p>\n<ul>\n<li>Body:\n<ul>\n<li>A group of programmers who build products for the general\npopulation.</li>\n</ul></li>\n<li>Soul:\n<ul>\n<li>A practioner who can pick up a wide variety of tools, and knows how\nto use them to quickly create the required product.</li>\n</ul></li>\n<li>Education:\n<ul>\n<li>Varied.</li>\n</ul></li>\n</ul>\n<p>All three groups are in constant conflict, and this leads to the\nchaotic state of software development \u2013 at one end, the Academics aren\u2019t\neven implementing software \u2013 and at the other end, Application\nprogrammers stress a high-level knowledge of a variety of areas.\nAgreement isn\u2019t necessary in this case, but it is something that would\nbenefit largely in one area. Interviews.</p>\n<section id=\"the-hiring-bar\" class=\"level2\">\n<h2>The Hiring Bar</h2>\n<p>After being interviewed for days by Bell Labs, a young up-start\ncomputer scientist named Bjarne Stroustrup found a job at one of the\nmost coveted research labs in the nation.</p>\n<p>After being interviewed for weeks by an Unnamed Big Firm, a young\nup-start new graduate named ${GENERIC_NAME} found a job at one of the\nmost coveted firms in the nation.</p>\n<p>See any relation? You should, because I made it painfully obvious.\nBig firms subject prospective candidates to a brutal interview loop,\nconstituting of knowledge of low-level operating systems, compiler\ntheory, algorithms and data structures, distributed system design, and\nothers. This all makes sense if you want a software developer who will\nwork on all of these areas, but most firms do not actually need their\ncandidates to know this knowledge on the job \u2013 it is abstracted away\nfrom them by the work of Systems Programmers who provide (mainly) good\nlibraries to base work off of. Maybe Untitled Big Firm has does have\nproblems of scale \u2013 but your average start-up does not. And yet, the\nhiring process continues this way.</p>\n<p>The big firms might be justified for want of unicorn talent (after\nall, they\u2019re willing to pay for it), but most firms simply cannot afford\nto pay the compensation that these developers are worth these days. And\nyet, the hiring process continues, and I hear companies complain on\nLinkedIn about how hard it is to hire and retain good developer talent.\nTo those companies, I only have a few choice words: buck the norms, and\nfix your interview process.</p>\n<p>I\u2019ve heard countless stories of acquaintances not passing an\ninterview because they were asked questions that were outside of their\nspecialization, which matched the job. One acquaintance with an interest\nin robotics and hardware was asked about implementing a Todo CRUD app.\nHe failed. Another friend was asked about low-level disk write system\ncalls for a React position.</p>\n<p>I think this happens because companies have a mistaken perspective of\n\u201cwho gets stuff done\u201d, A.K.A \u201c10x engineers\u201d. They assume that to be a\n\u201cgreat\u201d developer, you must understand everything about your computer,\nand that translates to great code. That is not true. A good developer\nknows the appropriate level of abstraction for the task at hand. Asking\na systems programmer about application programming, or vice-versa, is a\nsurefire way to destroy your hiring pipeline. The best companies know\nthis, so they don\u2019t do that. They hire \u201c1x\u201d engineers, and make it to\nmarket \u201c10x\u201d as fast as the other firms. Those firms win. The product\npeople love the devs because they crank out bug-free code in record\ntime, and the customers love those companies because they make genuinely\ngood products.</p>\n<p>Always value getting stuff done.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2020-03-12T16:52:45+00:00"
		},
		{
			"id": "gen/10-predictions.html",
			"url": "gen/10-predictions.html",
			"title": "10 Predictions",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>10 Predictions</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">10 Predictions</h1>\n<p class=\"byline\">2019-12-26T19:56:17-05:00</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#self-driving-cars-will-still-be-two-years-out\"\nid=\"toc-self-driving-cars-will-still-be-two-years-out\">1. Self-driving\ncars will still be two years out</a></li>\n<li><a href=\"#rust-will-become-a-top-10-language-in-popularity\"\nid=\"toc-rust-will-become-a-top-10-language-in-popularity\">2. Rust will\nbecome a top 10 language in popularity</a></li>\n<li><a href=\"#webassembly-will-kill-javascript-and-desktop-apps\"\nid=\"toc-webassembly-will-kill-javascript-and-desktop-apps\">3.\nWebAssembly will kill JavaScript and Desktop Apps</a></li>\n<li><a href=\"#json-will-be-replaced-with-a-typed-transfer-protocol\"\nid=\"toc-json-will-be-replaced-with-a-typed-transfer-protocol\">4. JSON\nwill be replaced with a Typed Transfer Protocol</a></li>\n<li><a href=\"#functional-programming-will-finally-become-popular\"\nid=\"toc-functional-programming-will-finally-become-popular\">5.\nFunctional Programming will finally become popular</a></li>\n<li><a href=\"#microservice-hype-will-wear-off\"\nid=\"toc-microservice-hype-will-wear-off\">6. Microservice hype will wear\noff</a></li>\n<li><a href=\"#facebook-will-no-longer-be-a-top-10-company\"\nid=\"toc-facebook-will-no-longer-be-a-top-10-company\">7. Facebook will no\nlonger be a top 10 company</a></li>\n<li><a href=\"#an-ai-startup-will-become-this-decades-hottest-startup\"\nid=\"toc-an-ai-startup-will-become-this-decades-hottest-startup\">8. An AI\nstartup will become this decade\u2019s hottest startup</a></li>\n<li><a href=\"#blockchain-will-be-this-decades-beanie-babies\"\nid=\"toc-blockchain-will-be-this-decades-beanie-babies\">9. Blockchain\nwill be this decade\u2019s beanie babies</a></li>\n<li><a\nhref=\"#you-and-i-will-host-our-apps-on-a-new-cloud-provider-read.-not-aws\"\nid=\"toc-you-and-i-will-host-our-apps-on-a-new-cloud-provider-read.-not-aws\">10.\nYou and I will host our apps on a new cloud provider (read. not\nAWS)</a></li>\n</ul>\n</nav>\n<p>In a few more days, the 2010s will be over. Lots has changed in the\nprogramming world \u2013 Java is no longer king, but JavaScript, being the\nmost popular language (according to stack overflow) for 7 years\nstraight. NoSQL databases like MongoDB, Redis, and Cassandra have become\nexceedingly popular, as well as front end web technologies such as\nAngular, React, and Vue. Kotlin has become the preferred language for\nAndroid development, along with Swift for iOS. SaaS companies are\nubiquitous, and Marc Andreessen\u2019s prediction of \u201csoftware eating the\nworld\u201d rings even more true today.</p>\n<p>Let\u2019s hope that the 20s are an even wilder ride for software\ndevelopment, and to that end, here I\u2019ve decided to compile ten\npredictions for the next decade as a fun little exercise. As a reader of\nthis article, I encourage you to do the same (I\u2019m looking forward to\nseeing how our predictions are different or similar!)</p>\n<p>Most of these predictions will be wildly incorrect, but I think this\nis a good excuse to think about what could be coming in the future.</p>\n<section id=\"self-driving-cars-will-still-be-two-years-out\"\nclass=\"level2\">\n<h2>1. Self-driving cars will still be two years out</h2>\n<p>Before anyone asks, I\u2019m talking about level 5 meaning fully\nautonomous, you could take a nap in the backseat of the car with no\ndriver autonomous. There is a lot of interest in this space, and for\ngood reason \u2013 Large companies like Uber, Lyft, Waymo, and Tesla have\nbeen researching self driving cars for the good part of this decade.\nThere are many technical concerns regarding self-driving cars, but I\u2019m\nactually fairly sure they\u2019ll be solved this decade. Legality is a huge\ngray area. Should self-driving cars never have an accident? If that\nblocks general availability, self-driving cars will never make it on the\nroad. But if the government allows self-driving cars as long as they\nhave less accidents than human drivers, I think there\u2019s a shot they make\nit this decade. But I think the real problem is that regulation will be\nlagging behind.</p>\n</section>\n<section id=\"rust-will-become-a-top-10-language-in-popularity\"\nclass=\"level2\">\n<h2>2. Rust will become a top 10 language in popularity</h2>\n<p>According to 2019\u2019s Stack overflow\u2019s developer survey, the tenth most\npopular language is TypeScript, which has 21.2% of respondents\nprofessing usage. Right above that is C++ at 23.5%, and right below is C\nat 20.6%. Rust is currently at 3.2%, sitting just below Scala. Of the\nten languages, Typescript is the only one younger than a decade, but it\nhas already edged out C in popularity. Rust is the only language that\ncan save us from C and C++ supremacy in high performance computing. It\nhas a couple of famous backers (like Mozilla and Amazon), and it has won\nmost loved language for 4 years running on Stack Overflow. Allowing\naccess to low level computing without unsafe abstractions is a real\ntreat. Every generation of programmers flocks to a new way of doing\ncomputing \u2013 C saved us from assembly, and C++ followed to tack on object\noriented programming and RAII. Java popularized garbage collection, and\nlanguages such as Javascript, Python, and Ruby added higher level\nfunctional abstractions to the mainstream. I think this next decade will\nsee the rise of Swift, Kotlin, Go, and Rust to the top 10 of\nlanguages.</p>\n</section>\n<section id=\"webassembly-will-kill-javascript-and-desktop-apps\"\nclass=\"level2\">\n<h2>3. WebAssembly will kill JavaScript and Desktop Apps</h2>\n<p>I don\u2019t mean kill kill, like how C did away with Fortran. I expect to\nsee JavaScript as a top 5 language still by the end of this decade, but\nI think WASM is too much of a game changer to ignore. Applications with\nhigher performance requirements are gated from the web because\nJavaScript is the only front-end programming language \u2013 you simply can\u2019t\nhave a garbage collected interpreted language be high performance.\nWebAssembly changes all of that. Compile Rust, Go, C or C++ for the\nfront end. Games, exiled to desktops after the death of flash, can come\nback to the web. Developers with high CPU requirements (like AI/ML apps)\nwill most likely find their home on the web this decade. I expect\nsomething similar to npm popping up, but for all kinds of packages in\nall kinds of languages, widening the range of the web.</p>\n</section>\n<section id=\"json-will-be-replaced-with-a-typed-transfer-protocol\"\nclass=\"level2\">\n<h2>4. JSON will be replaced with a Typed Transfer Protocol</h2>\n<p>JSON has been around for 20 years \u2013 but I don\u2019t expect it to be\npopular for another 20. While I enjoy working with JSON APIs, I think\nthat choosing a JavaScript based transfer protocol is a double edged\nsword. Sure, it rose in popularity because it\u2019s just like Javascript,\nbut JavaScript is fast and loose, something not all programmers\nappreciate. Tools to facilitate typing and strictness have popped up for\nJSON, but sometimes it\u2019s better to start from the ground up. I expect\nsomething like YAML with strict typing becoming more of the standard by\n2030.</p>\n</section>\n<section id=\"functional-programming-will-finally-become-popular\"\nclass=\"level2\">\n<h2>5. Functional Programming will finally become popular</h2>\n<p>Programming in a functional style has become all the rage recently,\nbut people still haven\u2019t adopted functional languages into their\ntoolkit. Of the three tenets of functional programming, most mainstream\nlanguages have accepted two, functions as first class citizens, and\nstronger typing. Immutability is hard to implement if all of your data\nstructures are mutable, so that\u2019s a non-starter. I just want to be able\nto talk about algebraic data types at a meetup without being an outcast,\ndarn it!</p>\n</section>\n<section id=\"microservice-hype-will-wear-off\" class=\"level2\">\n<h2>6. Microservice hype will wear off</h2>\n<p>This one will probably seem crazy to half of the readers, and obvious\nto half of the readers. Microservices are great because they encourage\nlooser coupling. Unfortunately, looser coupling also requires more code.\nAnd the worst thing you could do to your codebase is increase the amount\nof code it has. If monoliths create tech debt gradually by entangling\neverything in their grasp, the sheer amount of code microservices\nintroduce will blanket your entire organization.</p>\n</section>\n<section id=\"facebook-will-no-longer-be-a-top-10-company\"\nclass=\"level2\">\n<h2>7. Facebook will no longer be a top 10 company</h2>\n<p>Facebook made one good product 15 years ago. The other two products\ndriving most of their profits, Instagram and WhatsApp were acquisitions.\nAmong the youth, Facebook is unhip and ancient. You know, just like\ncommodores are artifacts of a bygone epoch. Zuckerberg is smart, but I\ndon\u2019t think good acquisitions (which saved Facebook this decade) will\nsave them the next decade. We\u2019ll see though.</p>\n</section>\n<section id=\"an-ai-startup-will-become-this-decades-hottest-startup\"\nclass=\"level2\">\n<h2>8. An AI startup will become this decade\u2019s hottest startup</h2>\n<p>Last decade\u2019s hottest startups, like Uber, or Lyft, or AirBnB created\nthe gig economy. I expect AI to try to coax the gig economy into its\ncoffin.</p>\n</section>\n<section id=\"blockchain-will-be-this-decades-beanie-babies\"\nclass=\"level2\">\n<h2>9. Blockchain will be this decade\u2019s beanie babies</h2>\n<p>Blockchain has been gaining ubiquity as a secure new way to exchange\nfunds, but I don\u2019t see it taking off just yet - It strikes me as an idea\nthat is too early for its current decade.</p>\n</section>\n<section\nid=\"you-and-i-will-host-our-apps-on-a-new-cloud-provider-read.-not-aws\"\nclass=\"level2\">\n<h2>10. You and I will host our apps on a new cloud provider (read. not\nAWS)</h2>\n<p>AWS became <em>extremely</em> popular this decade - and I don\u2019t\nexpect the service to die this decade. While it\u2019s great for enterprise\nby thinning the IT department, it\u2019s not made for you and me. It\u2019s\nconfusing, for one, with configuration hiding behind every corner, ready\nto jump out and spook you. Oh yeah, and it costs a lot.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2019-12-27T00:56:17+00:00"
		},
		{
			"id": "gen/software-engineering.html",
			"url": "gen/software-engineering.html",
			"title": "Why are there so many Software Engineers?",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Why are there so many Software Engineers?</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Why are there so many Software Engineers?</h1>\n<p class=\"byline\">2019-04-14T20:56:58.198Z</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#hardware-vs.-software\"\nid=\"toc-hardware-vs.-software\">Hardware vs.\u00a0Software</a></li>\n<li><a href=\"#what-is-software\" id=\"toc-what-is-software\">What is\nSoftware</a></li>\n<li><a href=\"#what-is-hardware\" id=\"toc-what-is-hardware\">What is\nHardware</a></li>\n<li><a href=\"#why-software\" id=\"toc-why-software\">Why Software</a></li>\n<li><a href=\"#conclusion\" id=\"toc-conclusion\">Conclusion</a></li>\n</ul>\n</nav>\n<section id=\"hardware-vs.-software\" class=\"level2\">\n<h2>Hardware vs.\u00a0Software</h2>\n<p>Have you ever wondered why so many people are software developers\ninstead of hardware developers these days? I certainly have. And even if\nyou haven\u2019t, I\u2019ll go ahead and give you a cut and dry example of why\nthat is, and why software is considered to be the way of the future (for\nnow). I\u2019ve never studied anything about either hardware or software, to\nbe fair \u2013 hardware is black magic and software is a black box, so take\nmy narrative and reasoning with a grain of salt.</p>\n</section>\n<section id=\"what-is-software\" class=\"level2\">\n<h2>What is Software</h2>\n<p>First off, we\u2019ll have to define what software is. I really don\u2019t have\na great definition to give you, but I\u2019m sure you know what software is\nanyway \u2013 it\u2019s anything above hardware, and hardware is anything below\nsoftware. I jest, of course. Software is defined as operating\ninformation used by a computer. These days, any kind of programming that\nbuilds on an operating system (OS) is software programming. To me,\noperating systems are the proverbial line drawn in the sand between\nhardware and software \u2013 an OS takes your instructions and etches them\ninto the hardware. It turns software actions into hardware truth, a sort\nof bridge between hardware and software.</p>\n</section>\n<section id=\"what-is-hardware\" class=\"level2\">\n<h2>What is Hardware</h2>\n<p>This time I\u2019m better prepared to read out the definition of hardware!\nPut down your pitchforks. Ahem. Hardware is \u201cthe machines, wiring, and\nother physical components of a computer or other electronic system.\u201d\nSound good? Hardware is all around us. I\u2019m writing this article on a\nMacbook Pro, I ride the bus to and from work, and I even use a microwave\nfrom time to time (a lot of the time, actually). These are all examples\nof hardware with software interfaces that expose an interactive API.\nWhen I click the button to reheat my pizza, the microwave sends\ninstructions to the hardware of the microwave (turn on, use this much\nelectricity, start spinning, turn off, etc). Hardware is everywhere\naround us.</p>\n</section>\n<section id=\"why-software\" class=\"level2\">\n<h2>Why Software</h2>\n<p>Now that we have some definitions out of the way, let\u2019s take a trip\ndown memory lane. Long, long ago there were not that many computers and\nhardware was very expensive. One of the first popular programming\nlanguages was Fortran, which ran on the IBM 704 mainframe computer.\nComputers were the size of rooms back then, and this super computer\npacked a whopping punch. It had a jaw-dropping memory of about 18KB and\nweighed 10 tons. Whoo wee. We\u2019ve come a long way, haven\u2019t we? Anyway,\ngiven the cost of these computers and the amount of electricity they\nconsumed (thousands of dollars worth an hour), it made sense that it was\nimportant to optimize for hardware time, not programmer time. See, a\nteam at IBM had access to one of these. That means a team of smart,\ncapable individuals would all have to share one computer. They\u2019d fuss\nfor hours about making faster algorithms, because it mattered. A lot.\nMost people programmed in pure machine code in those days because a\ncompiler couldn\u2019t come close to the amount of optimization a team of\nsuper smart people would be able to do. Clearly, hardware was the\nconstraining factor here, not labor. And for many years that was true \u2013\ninterpreted languages (such as lisp) were looked over because they ran\nthousands of times slower than native machine code. Needless to say,\nmost everyone programmed in machine code, and that was the way things\nwere.</p>\n<p>But eventually, that changed. Think about Moore\u2019s law. The number of\ntransistors in a circuit doubles every two years. With the increase in\ncomputing power of hardware, programmers were freed from having to use\nmachine code for everything. Eventually they used assembly, and then\nhigher level languages like C, and nowadays, extremely high level\nlanguages like Python, Ruby, and Javascript have risen to prominence.\nSure, Javascript runs many orders of times slower than machine language\nor assembly, but with every passing year, higher level languages rise in\npopularity. Every year, our hardware gets better. That means every year,\nhardware costs less. Thus, programmers are freed from having to optimize\nevery facet of their program. Oddly enough, programmers are incredibly\ncheap to hire these days. Give them a $1500 computer, two monitors, a\nkeyboard and mouse, a chair and desk. That\u2019s about $3000 for all the\nhardware they need. But the company needs to pay their salary, which can\nrange quite heavily, but it sure costs a lot more than $3000 a year, let\nme tell you.</p>\n<p>So the trend is quite apparent for right now. Hardware costs less and\nless with each passing year, whereas software costs more and more.\nSoftware took over hardware as the restricting factor in development,\nand ever since then, there\u2019s been a boom in software jobs and more of a\nglut in hardware jobs. And it doesn\u2019t seem to be stopping anytime soon.\nSteve Jobs famously told Barack Obama to lower barriers in immigration\nbecause Apple just couldn\u2019t hire enough talented software engineers.\nSalaries have skyrocketed for software developers, and it looks like\nthey won\u2019t be falling back to earth soon, as long as companies have too\nmuch demand for software developers with far too little supply.</p>\n</section>\n<section id=\"conclusion\" class=\"level2\">\n<h2>Conclusion</h2>\n<p>So the trend seems to be that we\u2019ll need more and more software\nengineers, and maybe hardware won\u2019t grow as fast. Even with the\nexplosion in mobile devices in the past decade, there can be thousands\nof apps on one phone. That means there\u2019s one team of hardware engineers\nfor every thousand or so teams of software engineers. So, perhaps, the\ndirection from now on will be more software-oriented instead of\nhardware-oriented. Or, perhaps, there\u2019ll be another change. Maybe\nhardware will see a revival when we all become cyborgs in the near\nfuture. Who really knows?</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2019-04-14T20:56:58.198000+00:00"
		},
		{
			"id": "gen/progressing-in-programming.html",
			"url": "gen/progressing-in-programming.html",
			"title": "Progressing in Programming",
			"content_html": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n  <title>Progressing in Programming</title>\n  <style type=\"text/css\">code{white-space: pre;}</style>\n<link rel=\"icon\" href=\"data:,\">\n<style>html{ visibility: hidden; opacity:0; }</style>\n<link rel=\"stylesheet\" href=\"../new.css\">\n<style>html { visibility: visible; opacity: 1; }</style>\n  <!--[if lt IE 9]>\n    <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js\"></script>\n  <![endif]-->\n</head>\n<body>\n<article>\n<header>\n<h1 class=\"title\">Progressing in Programming</h1>\n<p class=\"byline\">2019-04-11T20:41:20.201Z</p>\n</header>\n<nav id=\"TOC\">\n<ul>\n<li><a href=\"#c-programming\" id=\"toc-c-programming\">C\nProgramming</a></li>\n<li><a href=\"#operating-systems\" id=\"toc-operating-systems\">Operating\nSystems</a></li>\n<li><a href=\"#compilers\" id=\"toc-compilers\">Compilers</a></li>\n<li><a href=\"#c-programming-1\" id=\"toc-c-programming-1\">C++\nProgramming</a></li>\n<li><a href=\"#java-programming\" id=\"toc-java-programming\">Java\nProgramming</a></li>\n<li><a href=\"#go-programming\" id=\"toc-go-programming\">Go\nProgramming</a></li>\n<li><a href=\"#python-programming\" id=\"toc-python-programming\">Python\nProgramming</a></li>\n<li><a href=\"#data-structures-and-algorithms\"\nid=\"toc-data-structures-and-algorithms\">Data Structures and\nAlgorithms</a></li>\n</ul>\n</nav>\n<p>I\u2019ve always wondered what the power of journaling was \u2013 I\u2019d never\nbeen the type to write all of my goals in a journal, and plan\nmeticulously about what I was going to do \u2013 I took everything at face\nvalue and jumped on every opportunity as it came. But no longer! It\u2019s\ntime to begin blogging about progress. We\u2019re going to make some gains.\n(Not of the gym kind, of course).</p>\n<p>Before we begin to do any growing, we have to know what to grow in!\nSo we take this big goal and shrink it down into bite-sized pieces. So\nmy goal is to become a better software developer by the end of the year.\nMy reasoning is that understanding more about the basics of programming\nlanguages will help me out on the day to day, helping me understand what\nI need to do in order to become a better software developer.</p>\n<p>So then, what is there to learn? Well, too much. But I\u2019d like to\nimprove at certain parts of programming that are ubiquitous in the\nfield.</p>\n<section id=\"c-programming\" class=\"level2\">\n<h2>C Programming</h2>\n<p>Ah, C. The language of Unix, the programming language that runs Unix,\nthe most influential Operating System of all time. Such a powerful\nlanguage, with just 32 reserved words, you too can build your own kernel\nin just a few thousand lines using this wildly expressive language. So C\npretty much is the de facto language for compilers and Operating Systems\n(since they\u2019re both built in C), and this makes it a great first\nlanguage to sink my teeth into. The way I\u2019ll do it is by reading through\nProgramming in C (4th edition), which should be coming in the mail soon.\nI\u2019ll be littering this blog with some tidbits I learn from that book,\nand summarizing the key concepts there.</p>\n</section>\n<section id=\"operating-systems\" class=\"level2\">\n<h2>Operating Systems</h2>\n<p>You\u2019ve noticed I\u2019ve mentioned operating systems in the section above.\nAnd of course, operating systems are invaluable to us. No one these days\ninteracts with a computer without an operating system. So of course,\nlearning about Operating systems should be a high priority \u2013 especially\nUnix based ones. For that, I\u2019ve picked up a copy of OSTEP (Operating\nSystems: Three Easy Pieces) to help aid in learning about virtualization\n(the act of taking the physical hardware and making a virtual API to\ninteract with it, like writing to files, or editing files, spawning\nprocesses), concurrency (the act of turning this single threaded\ncomputer into one that can run multiple processes at once), and\npersistence (finally saving our actions to a hard disk, so they won\u2019t be\noverwritten on next boot up). Operating systems are considered to be a\nhard topic, so I\u2019m looking forward to the challenge! Maybe as a final\nproject, it would be cool to make a small OS that could support file IO\nor do something like that.</p>\n</section>\n<section id=\"compilers\" class=\"level2\">\n<h2>Compilers</h2>\n<p>Next up is Compilers, that thing that compiles your code and turns it\ninto machine language. I don\u2019t know too much about compilers (hey, I\u2019m a\nJavaScript(JS) guy, I use an interpreter), but I\u2019ve always been keen on\ncompilers ever since Babel entered the scene. If you don\u2019t know what\nBabel is, you\u2019ll have to know a bit about front-end web development. One\nof the pain points of front-end development is that we, as front-end\ndevelopers, have to support fairly old browsers, and they support\ndifferent features of HTML, CSS, and JS. For example, IE8 supports\nHTML4, CSS 2.1 (that means no media queries) and ES3 (the version of\nJavaScript that was standardized in 1999\u2026). Currently, Google Chrome\nsupports HTML5, CSS3, and ES10 (the version of JavaScript that was\nstandardized in 2019). So of course, we could all painfully write our\nES5 JavaScript to be backwards compatible with IE8, or we could ditch\nbrowser support for IE8 (a lot of firms have), but there\u2019s still a large\nuser base that uses IE11, so it\u2019s a hard sell to drop support for that.\nIE11 supports HTML5, CSS3, and ES5, which is the 2009 standard of\nJavaScript. You get the idea. Lots of browsers to target, but to target\nthem all, we\u2019d have to use some subset of JavaScript from 10 years ago.\nNot very fun. Many years ago, a solution named Babel was released \u2013 it\ntakes the JavaScript that you write, and turns it into valid es5\nJavaScript code. It\u2019s a compiler for JavaScript, but really, it\u2019s\nperhaps the best open source project out there in the JavaScript\necosystem. And to understand Babel, you have to understand compilers.\nCue the JavaScript music (Babel actually has a theme song, a cover of\nJeff Buckley\u2019s Hallelujah). I\u2019d like to write my own small language too,\npreferably in C, so I can understand the nitty gritty of creating a\ncompiler, and getting closer to the metal, if you will.</p>\n</section>\n<section id=\"c-programming-1\" class=\"level2\">\n<h2>C++ Programming</h2>\n<p>Ah, C++. When you program in C++, every problem looks like your\nthumb, and every goto leads you to a black hole. I\u2019m kidding, by the\nway, I don\u2019t have any experience writing C++, so I can\u2019t tell you much\nabout the language. It\u2019s also very popular, with uses in pretty much all\nindustries, but especially in game development. It\u2019s an excellent way to\nlearn about Object Oriented Programming, something I\u2019m really lacking,\nand it has a wide standard library (again, something that JavaScript is\nsorely lacking), which handles plenty of use cases, such as\nstd::vector&lt;T, T&gt; for lists, and std::array&lt;T, T&gt; for\narrays. What more could you ask for?</p>\n</section>\n<section id=\"java-programming\" class=\"level2\">\n<h2>Java Programming</h2>\n<p>Java is the best and worst thing that\u2019s happened to programming in\nthe past 20 years. Any takers on that statement? Steve Yegge said it.\nBut it\u2019s interesting, you see, because when one refers to Java, it\u2019s\nkind of hard to see if someone\u2019s referring to Java or the Java Virtual\nMachine(JVM). Java has so many people who live and die by it (in more of\nthe metaphoric sense), it has so many zealots that swear by it and\nnothing else, and become exalted to memetic heights \u2013 the old timey\npeople used to tell me about how Java saved them from environment\ndependent variables and worrying about memory management and pointers.\nAnd it\u2019s true that Java, specifically the JVM is amazing at abstracting\naway all the stuff that we really shouldn\u2019t be managing anyway, but one\nconcern is that Java is just such a slow moving language \u2013 it was in the\nSun Microsystems days, and it still kind of is in the Oracle Days. But\nstill, Java is a key language to at least know the basics of, and I\nmyself still admire how forward thihnking the Sun Microsystems team were\nin developing both the JVM and Java. Truly wonderful. A+ Language\nindeed.</p>\n</section>\n<section id=\"go-programming\" class=\"level2\">\n<h2>Go Programming</h2>\n<p>Golang is the best programming language to come out in the past 10\nyears. How many takers do I have for that statement? Go reminds of C,\nbut brought into the 21st century \u2013 it has garbage collection (yay!), it\ncan be run or compiled (the best of both worlds), the compiler can\nassume what types you\u2019re using, so you can say <code>x := 5</code>\ninstead of the slightly more verbose <code>int x = 5;</code>, there are\nno semicolons (the compiler adds them at the end of each line for you),\nand it has a very small API, with a more modern standard library so that\nyou can do what you need to, without having to know every nook and\ncranny of some arcane language (see: C++, Java, JavaScript). And it has\na cute mascot. That\u2019s the real kicker, to be honest. Java\u2019s mascot, the\nJava Duke, looks like its from a 17th century sketchbook. Python doesn\u2019t\nhave a mascot, just like JavaScript or C. Chalk a win up for the boys\nand girls at Google, their marketing is superb.</p>\n</section>\n<section id=\"python-programming\" class=\"level2\">\n<h2>Python Programming</h2>\n<p>Python is one of the most loved languages these days \u2013 and I will say\nwithout a doubt, that it is an amazing language. Guido really outdid\nhimself. But one thing I don\u2019t get is why there\u2019s a fork in the\nlanguage. Why is there Python2 (which this Mac runs) and Python3 (which\nthis blogger uses)? And the syntax is a bit different from the usual C\nderivative language syntax, but I guess that\u2019s a good thing about\npython, it has so many great things about it (such as lambdas from\n1994), and comprehensions (everyone\u2019s favorite feature of functional\nprogramming), and a killer ecosystem (I instinctively etch\n<code>import numpy as np</code> for almost every .py file I write). And\nit\u2019s a scripting language that can automate everything from emails, to\nfile moving, to web development, to even cars. Why don\u2019t people like\nscripting languages more?</p>\n</section>\n<section id=\"data-structures-and-algorithms\" class=\"level2\">\n<h2>Data Structures and Algorithms</h2>\n<p>Data Structures and Algorithms are perhaps the most sought after\nconcept in interviews, which has led a lot of people to discount the\nprocess entirely, but you know, I don\u2019t blame tech firms for using data\nstructures and algorithms questions to hire applicants, and here\u2019s why.\nLet\u2019s say you want to hire for a back-end software engineer, and your\nstack is in python\u2019s django, for example. Almost no one will have prior\npython django programming experience, so you have two choices. Either\nyou hire and test all applicants for python django knowledge (which\ncould take your team a year to fill those three vacancies on your team)\nor you could simply test on concepts that are familiar to backend\ndevelopment \u2013 ask them questions like \u201cwhat does MVC mean? How would you\nhandle real time communication needs in an app?\u201d, or even easier, say\nyou don\u2019t even have to write any code, we\u2019ll test you on ideas. And\nthat\u2019s really the core of what the Data Structures and Algorithms\ntechnical interview does, it tests some common knowledge among all\ndevelopers. So you know, it\u2019s not so bad. To get better at Data\nStructures and Algorithms, I\u2019ve got Elements of Programming Interviews\n(EPI in Python), Daily Coding Problem, and Algorithms by Skiena all\nlined up and ready to go. Hopefully by the end of the year I\u2019ll be a\nbetter problem solver then.</p>\n<p>Well, those are the areas I\u2019ll be covering, and maybe documenting\nhere and there through this blog. Hopefully I\u2019ll be a better software\ndeveloper, and maybe I\u2019ve encouraged you to be a better developer.</p>\n</section>\n</article>\n</body>\n</html>\n",
			"date_published": "2019-04-11T20:41:20.201000+00:00"
		}
	]
}