<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>ingramj.net</title>
    <link>https://www.ingramj.net/post/</link>
    <description>Recent posts on ingramj.net</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <copyright>Copyright © 2014-2025 Jim Ingram</copyright>
    <lastBuildDate>Sat, 20 Oct 2018 16:44:42 -0500</lastBuildDate>
    
	<atom:link href="https://www.ingramj.net/post/feed.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>How I Think About THAC0</title>
      <link>https://www.ingramj.net/2018/10/how-i-think-about-thac0/</link>
      <pubDate>Sat, 20 Oct 2018 16:44:42 -0500</pubDate>
      
      <guid>https://www.ingramj.net/2018/10/how-i-think-about-thac0/</guid>
      <description>&lt;p&gt;THAC0 stands for &amp;ldquo;To Hit Armor Class 0,&amp;rdquo; and it&amp;rsquo;s one of the two ways we used back in the day to figure out if an attack succeeded or not. (The other way was looking it up in a table.) The AD&amp;amp;D 2nd Edition &lt;em&gt;Player&amp;rsquo;s Handbook&lt;/em&gt; says that &amp;ldquo;Using THAC0 speeds the play of combat greatly,&amp;rdquo; just before giving this description of how it works:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The first step in making an attack roll is to find the number needed to hit the target. Subtract the Armor Class of the target from the attacker&amp;rsquo;s THAC0. (Remember that if the Armor Class is a negative number, you &lt;em&gt;add&lt;/em&gt; it to the attacker&amp;rsquo;s THACO.) The character has to roll the resulting number, or higher, on 1d20 to hit the target.
[&amp;hellip;] THAC0 is modified by weapon bonuses, Strength bonuses, and the like [&amp;hellip;] Figure Strength and weapon modifiers, subtract the total from the base THAC0, and record this modified THACO with each weapon on the character sheet. Subtract the target&amp;rsquo;s Armor Class from this modified THAC0 when determining the hit roll.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I omitted some worked examples from that quote, but that is the official description of how attack rolls worked in 2nd edition.  If you find it confusing, you aren&amp;rsquo;t alone. Starting with the 3rd edition in 2000 (that&amp;rsquo;s right: D&amp;amp;D 3e is old enough to vote!), when they essentially made attack rolls the core mechanic, Wizards of the Coast also switched things around so that instead of using the defender&amp;rsquo;s armor class to calculate the target number, the armor class &lt;em&gt;is&lt;/em&gt; the target number. Roll a d20, apply any bonuses and penalties, and if you get a number greater than the target&amp;rsquo;s armor class, it&amp;rsquo;s a hit. A higher AC means you&amp;rsquo;re harder to hit. It ends up working out the same as the old system, but it&amp;rsquo;s simpler in theory, if not in practice.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the thing: I actually like descending armor class, and think THAC0 is a great idea. It&amp;rsquo;s just really poorly explained. Instead of adding and subtracting things from THAC0 to get a target number, as in the official description, I just add everything to the attack roll instead, &lt;em&gt;including the defender&amp;rsquo;s armor class&lt;/em&gt;. In some ways this is like the third edition method, which also has modifiers on the attack roll, but instead of the target number changing depending on what you&amp;rsquo;re swinging at, &lt;em&gt;the target number is always your THAC0&lt;/em&gt;. The defender&amp;rsquo;s armor class becomes just another modifier on the attack roll.&lt;/p&gt;
&lt;p&gt;If you think about it that way, then descending armor class makes a lot more sense. Instead of using a human in normal clothing&amp;rsquo;s 9 AC as the baseline, use an armor class of 0 as the baseline. Anything with less armor than that is easier to hit, granting a bonus on the attack roll. Attacking an unarmored target is very easy &amp;ndash; you get a whopping +9 on your roll! Going in the other direction, a negative armor class mean you&amp;rsquo;re very difficult to hit &amp;ndash; anyone taking a swing at you will get a penalty on their attack roll.&lt;/p&gt;
&lt;p&gt;The way this ends up working for the GM at the table is pretty simple. Make a note of all the PC&amp;rsquo;s armor classes and THACOs, just as you would for all your monsters&amp;rsquo; stat blocks. Whenever a PC attacks a monster, they&amp;rsquo;ll roll a d20 and add all the modifiers they know about from strength, enchanted weapons, etc. Then you add the monster&amp;rsquo;s armor class to that roll and compare it to the attacker&amp;rsquo;s THAC0 to decide if it&amp;rsquo;s a hit. When a monster attacks a PC, do the same thing: add the PC&amp;rsquo;s armor class to the roll, along with any other modifiers, and compare it to the monster&amp;rsquo;s THAC0. Done.&lt;/p&gt;
&lt;p&gt;Example time. Let&amp;rsquo;s say you have a level 1 fighter (THAC0 19, AC 5) attacking an orc (THAC0 18, AC 6). The player rolls a 12, and adds their +1 strength bonus for a total of 13. You add the orc&amp;rsquo;s 6 AC to that and get 19. That&amp;rsquo;s the figher&amp;rsquo;s THACO, so it&amp;rsquo;s a hit, but just barely! The orc takes a swing at the fighter, and rolls a 9. You add the fighter&amp;rsquo;s 5 AC to get a 14, which is less than the orc&amp;rsquo;s THAC0. It&amp;rsquo;s a miss! As long as you have the THAC0 and AC for everyone involved, running combat with descending armor class is easy.&lt;/p&gt;
&lt;p&gt;This is the way I&amp;rsquo;ve been using descending armor class and THAC0 for years, and it works well for me. Delta, from &lt;a href=&#34;https://deltasdnd.blogspot.com/&#34;&gt;Delta&amp;rsquo;s D&amp;amp;D Hotspot&lt;/a&gt; takes the &amp;ldquo;armor class is a modifier on the attack roll&amp;rdquo; idea a bit further. Instead of having a THAC0 that changes as characters level up, he came up with the &lt;a href=&#34;http://www.oedgames.com/target20/&#34;&gt;Target 20&lt;/a&gt; system, where the target number is always 20, and the attacker&amp;rsquo;s level joins the defender&amp;rsquo;s armor class as just another attack roll modifier.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Swords and Wizardry One Shot</title>
      <link>https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/</link>
      <pubDate>Thu, 05 Jul 2018 17:20:00 -0500</pubDate>
      
      <guid>https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/</guid>
      <description>&lt;p&gt;A couple of summers ago, I ran a &lt;a href=&#34;http://arsludi.lamemage.com/index.php/78/grand-experiments-west-marches/&#34;&gt;West
Marches&lt;/a&gt;-style
campaign for several of my coworkers called &amp;ldquo;Riverkeep&amp;rdquo;, using the &lt;a href=&#34;https://www.froggodgames.com/swords-wizardry-complete-rulebook&#34;&gt;Swords &amp;amp;
Wizardry
Complete&lt;/a&gt;
rules. There&amp;rsquo;s a lot of prep work for that sort of campaign, even if you fill
in most of the map with pre-existing modules as I did. On top of that, each
session had between 8 and 12 players, which is a lot of fun, but also
exhausting to run. As a result, the campaign only lasted a few months before
going on indefinite hiatus, due to &lt;a href=&#34;https://www.penny-arcade.com/comic/2010/12/13&#34;&gt;DM
fatigue&lt;/a&gt;. (Note: I don&amp;rsquo;t blame
the players at all. They were and are wonderful people.) A couple of weeks ago
the subject came up in conversation again, and I offered to do a one shot
session, unconnected to the previous campaign, for 3 to 6 players. I ended up
getting four takers: a couple of campaign veterans who were already familiar
with Swords &amp;amp; Wizardry; one guy who had played a bit of &lt;a href=&#34;https://rpg.stackexchange.com/questions/13212/what-are-the-big-differences-between-the-dd-editions&#34;&gt;4th and 5th Edition
D&amp;amp;D&lt;/a&gt;
and &lt;a href=&#34;http://www.dungeon-world.com/&#34;&gt;Dungeon World&lt;/a&gt;, but not any older rules;
and one guy who had never played a table top RPG before, and whom I&amp;rsquo;d promised
wouldn&amp;rsquo;t need to read any rules beforehand. We decided to play a single
session of about four hours, and in order to make the most of our time, I&amp;rsquo;d
bring several pregenerated characters for them to choose from.&lt;/p&gt;
&lt;h3 id=&#34;setting-up&#34;&gt;Setting up&lt;/h3&gt;
&lt;p&gt;Since I didn&amp;rsquo;t have much time / didn&amp;rsquo;t want to do too much prep work, I looked
around for a pre-existing module suitable for four characters of around level
three, and came across &lt;a href=&#34;http://basicfantasy.org/showcase.cgi?sid=46&#34;&gt;&lt;em&gt;Tomb of the Mummy
Priest&lt;/em&gt;&lt;/a&gt; at the &lt;a href=&#34;http://basicfantasy.org/index.html&#34;&gt;Basic Fantasy
RPG&lt;/a&gt; site, which has some fantastic
resources, even if you&amp;rsquo;re using a different set of old-school RPG rules. The
only conversion I needed to do was from BFRPG&amp;rsquo;s ascending AC values to S&amp;amp;W&amp;rsquo;s
descending system. That being done, I created a set of six characters for the
four players to choose from, so that they&amp;rsquo;d each have at least three
options. I made them a mix of classes, but avoided multiclass demihumans in
order to keep things simple. I ended up with two human clerics, a human
fighter, a dwarf fighter, a halfling thief, and a human magic-user. After
rolling their attributes and making a few adjustments, I gave each 5,500 XP
and added their prime requisite bonuses. That gave the clerics and the thief
enough experience for level four, and the fighters and the magic-user enough
for level three. Then I picked out equipment and spells, and was ready to
start filling out character sheets.&lt;/p&gt;
&lt;p&gt;I tried to find some existing form-fillable sheets, but couldn&amp;rsquo;t find any that
I liked, and I also didn&amp;rsquo;t want to fill six sheets out by hand. Instead, I
ended up creating the sheets using &lt;a href=&#34;https://www.apple.com/keynote/&#34;&gt;Keynote&lt;/a&gt;,
which has surprisingly decent page-layout features. The six characters fit on
three sheets of letter-sized paper, and then I used a fourth sheet for the
magic-user&amp;rsquo;s spellbook and scroll. I also printed them out smaller sized with
four characters to a page so I could keep track of them behind my DM&amp;rsquo;s screen
(a binder and a manila folder with some tables taped to the inside).&lt;/p&gt;




&lt;figure class=&#34;card&#34;&gt;
  &lt;a href=&#34;https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/pdf/characters.pdf&#34;&gt;
  &lt;img src=&#34;https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/img/characters.png&#34; class=&#34;u-max-full-width&#34; alt=&#34;Character sheets for a 3rd level Human Fighter and a 3rd level Human Magic-User.&#34; /&gt;
  &lt;/a&gt;
  
  &lt;figcaption&gt;
    &lt;p&gt;A couple of the characters.
      (&lt;a href=&#34;https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/pdf/characters.pdf&#34;&gt;Click for PDF&lt;/a&gt;)&lt;/p&gt;
  &lt;/figcaption&gt;
  
&lt;/figure&gt;


&lt;h3 id=&#34;the-session&#34;&gt;The session&lt;/h3&gt;
&lt;p&gt;One of the players offered to host the game at his house, so on game day
I headed over, binder, character sheets, dice, rule books&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, and 17&amp;quot; x
22&amp;quot; pad of grid paper&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; in tow. Once everyone had arrived, the players
chose their characters and gave them names, and the spell casters picked
their spells. I didn&amp;rsquo;t share the module name (&lt;em&gt;Tomb of the Mummy
Priest&lt;/em&gt;) with the players, but strongly hinted that they&amp;rsquo;d want at least
one cleric, and I sort of expected them to also take either two
fighters, or another cleric and a fighter, and either the thief or the
magic-user. Instead, the party consisted of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Jora Orcsbane the Human Fighter&lt;/em&gt;, played by one of the campaign veterans
who likes to keep it simple.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Zur III the Human Cleric&lt;/em&gt;, played by the other veteran, and named after his
two previous characters: Zur the Enchanter (a Ranger), and Zur&amp;rsquo;s Brother
(also a Ranger).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Xanders the Human Magic-User&lt;/em&gt;, played by the guy who&amp;rsquo;d only played newer
editions before, and named after Colonel Sanders because of the 11 secret
herbs and spices (spell components) I&amp;rsquo;d placed in his equipment list.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Sticky Fingers the Halfling Thief&lt;/em&gt;, played by the new guy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was a little worried about the two newer players playing relatively low-HP
specialists, but at least the magic-user had access to some decent spells, and
the thief had bonuses from high dexterity and constitution and an additional
+1 to hit with missiles. Not too shabby.&lt;/p&gt;
&lt;p&gt;Then we got started. There&amp;rsquo;s some lengthy session notes containing spoilers
ahead, so if you&amp;rsquo;d like to, you can &lt;a href=&#34;#conclusion&#34;&gt;skip to the end&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&#34;card&#34;&gt;
  &lt;style&gt;
   #session-label {
     display: inline-block;
     cursor: pointer;
     margin-bottom: 1.5rem;
   }
   #session-label::after { content: &#34;▶&#34;; color: #999 }
   #session-toggle:checked ~ #session-label::after {
     content: &#34;▼&#34;; color: #999
   }
   #session { display: none; }
   #session-toggle:checked ~ #session { display: block; }
  &lt;/style&gt;
  &lt;input type=&#34;checkbox&#34; id=&#34;session-toggle&#34; style=&#34;display:none;&#34;&gt;
  &lt;label id=&#34;session-label&#34; for=&#34;session-toggle&#34;&gt;
    Spoilers
  &lt;/label&gt;
  &lt;div id=&#34;session&#34;&gt;
    &lt;p&gt;I gave the players a bit of background on their characters&amp;rsquo; situation: They&amp;rsquo;d
recently been hired to escort a trade caravan on a route that took it through
the small village of Mudar, on the edge of a great desert. However, after a
misunderstanding between the characters and the caravan leader (something
about some coins and items that had gone missing), they&amp;rsquo;d been left in Mudar
while the caravan continued on without them. After overcoming the villages
initial distrust &lt;strike&gt;by blowing all their cash in the village
taverns&lt;/strike&gt; with their generosity and good natures, the players learned a
couple of things about the area: (1) there&amp;rsquo;s supposedly an old abandoned
temple of a long-dead water deity hidden in a canyon, full of treasure, and
just a few hours ride out in the desert; and (2) several villagers have gone
missing in the night recently, and no one knows what&amp;rsquo;s happened to them.&lt;/p&gt;
&lt;p&gt;Since we didn&amp;rsquo;t have a whole lot of time, we didn&amp;rsquo;t play out any of the town
scenes, the journey to the canyon, or finding the tomb. I just placed the
party at the entrance, and mentioned that they&amp;rsquo;d only found it because of all
of the footprints leading in and out. A full session report would make this
already lengthy post even longer, so here are some of the highlights:&lt;/p&gt;
&lt;figure &gt;
  &lt;img src=&#34;https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/img/areas_1_2.png&#34; class=&#34;u-max-full-width&#34; alt=&#34;Map of the entryway and main hall of the tomb.&#34; /&gt;
  &lt;figcaption&gt;
    &lt;p&gt;Entrance and main hall.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The thief entered first, staying close to the walls and trying to be quiet.
That&amp;rsquo;s how he noticed how all the footprints went around a section of floor
about 10&amp;rsquo; down the passageway (area 1 on the map). The party investigated a
bit, thinking it might have been a trigger for some sort of arrow trap, but
moved on before figuring out it was a pit trap, with a recently reanimated
corpse inside&lt;/p&gt;
&lt;p&gt;The searched the entire main hall (area 2), and a little bit down each
passageway before I rolled a 1 and the seven bandits arrived from the western
passage. The party won the surprise roll, and quickly set up an ambush. The
combat lasted only a couple of rounds, before they took the last surviving
bandit hostage and got some exposition out of him.&lt;/p&gt;
&lt;figure &gt;
  &lt;img src=&#34;https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/img/areas_3_through_7.png&#34; class=&#34;u-max-full-width&#34; alt=&#34;Map of the north-west section of the tomb, including burial chambers.&#34; /&gt;
  &lt;figcaption&gt;
    &lt;p&gt;Storage and burial chambers.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Buoyed by this early success, the party made it&amp;rsquo;s way down the western
passageway, through the now-abandoned sleeping quarters (area 3) and oil
storage room (area 4). As they entered area 6, three mummified crocodiles
emerged from their sarcophagi and attacked. This was a tougher fight than the
one with the bandits, and the party had a tough time with their attack rolls,
but eventually Zur managed to turn back the crocodiles, who retreated to the
far side of their chamber. Xanders and Sticky Fingers improvised a trap in the
entryway using a large jar of oil and a torch, reasoning that the crocodiles
weren&amp;rsquo;t intelligent, and would likely knock over the jar and set themselves on
fire if they tried coming after the party again.&lt;/p&gt;
&lt;p&gt;Still feeling pretty confident at this point, they entered the burial chamber
(area 7), where the module&amp;rsquo;s boss monster laid in wait. As they drew near the
sarcophagus to get a better look at its hieroglyphics, Kutan Tahkmet, the
titular Mummy Priest whose tomb the party were robbing, burst out and started
attacking Jora. The module actually boosted the mummy&amp;rsquo;s stats from what the
BFRPG manual lists, giving it &lt;em&gt;darkness&lt;/em&gt;, &lt;em&gt;cause fear&lt;/em&gt;, &lt;em&gt;hold person&lt;/em&gt;, and
&lt;em&gt;resist fire&lt;/em&gt; spells. I just went with the base mummy stats from the Swords &amp;amp;
Wizardry manual instead, figuring that would be challenge enough.&lt;/p&gt;
&lt;p&gt;It turns out I was right, because after a few rounds of combat, the characters
hadn&amp;rsquo;t managed to do very much damage to Kutan, but he&amp;rsquo;d reduced Jora to 0 hit
points (unconscious, but stable) and given him a bad case of mummy rot to
boot. After Zur&amp;rsquo;s &lt;em&gt;cure light wounds&lt;/em&gt; spell failed to heal Jora, they started
making escape plans. Xanders cast a &lt;em&gt;web&lt;/em&gt; spell at the mummy, while Zur and
Sticky Fingers pulled the comatose fighter to safety. They decided to head
back to town to get some help for Jora, which ended up costing them the only
treasure they&amp;rsquo;d found so far: a 600gp set of ruby earrings.&lt;/p&gt;
&lt;figure &gt;
  &lt;img src=&#34;https://www.ingramj.net/2018/07/swords-and-wizardry-one-shot/img/east_half.png&#34; class=&#34;u-max-full-width&#34; alt=&#34;Map of the eastern half of the tomb, including a dark pool and the ritual chamber.&#34; /&gt;
  &lt;figcaption&gt;
    &lt;p&gt;Down the eastern passageway.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;When the party returned to the tomb after a couple of days, they found that
the bodies of the bandits they had killed had been dragged from the main hall,
down the eastern passageway. Scouting ahead, Sticky Fingers saw that the trail
turned to the south, into area 8, where he noticed movement in the dark pool
from the balcony above. Assuming it was more crocodiles (it wasn&amp;rsquo;t), and not
seeing any obvious treasure, he decided to check to the north instead. In that
direction, he saw a lit chamber with a bearded man at an altar, preparing to
sacrifice a villager, and surrounded by robed figures.&lt;/p&gt;
&lt;p&gt;Since they had the element of surprise, Xanders cast a &lt;em&gt;sleep&lt;/em&gt; spell into the
ritual chamber from the intersection just north of the pool room, which worked
on seven of the twelve robed figures, and then the rest of the party rushed in
to battle the remaining acolytes and their leader, Aram. After just a few
rounds of combat, Aram was down to just 3 hit points and all of his followers
had been slain. He surrendered to the player characters, who bound him with a
rope, and were just about to start searching the room when Kutan Tahkmet made
his entrance though the secret passage between areas 7 and 9.&lt;/p&gt;
&lt;p&gt;The second battle with the mummy priest went only slightly better than the
first, Jora and Zur were both afflicted with mummy rot, but still standing.
Meanwhile, Xanders and Sticky Fingers tried to figure out a way to knock down
one of the large oil lanterns that hung from the ceiling on top of the
rampaging mummy, and they were all wondering just how many hit points it could
possibly have. (It was 25.) Aram started shouting at the PCs, trying to get
them to untie him so he could join the melee with his battleaxe +1, which they
eventually agreed to do.&lt;/p&gt;
&lt;p&gt;After a few more rounds, they managed to destroy Kutan, and the players all
gave a sigh of relief. Aram immediately tried to run away down the secret
passage to the burial chamber, Xanders hit him with a sleep spell before he
could get very far. They searched the room and found all the treasure that had
been stashed in the corners, and then discovered the five other prisoners
still chained up in area 10. After a bit of discussion about what to do with
Aram, they decided to turn him over to the captives, who dragged the
bandit-turned-cultist down to the pool in area 8 and threw him in. The bodies
he had been disposing of in the pool had returned to life, and tore Aram to
pieces as the party gathered up all the treasure they could carry and made
their exit.&lt;/p&gt;

  &lt;/div&gt;
&lt;/div&gt;


&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I hadn&amp;rsquo;t run &lt;em&gt;Tomb of the Mummy Priest&lt;/em&gt; before, and even though it&amp;rsquo;s a
relatively small, uncomplicated module, I was surprised that we made it all
the way through in about four hours. The Egyptian-themed setting was a nice
change of pace from the vaguely Medieval European default fantasy setting.  If
this adventure were part of a campaign instead of a one shot, then I&amp;rsquo;d be
tempted to use &lt;a href=&#34;http://hyboria.xoth.net/races/human_stygian.htm&#34;&gt;Stygia&lt;/a&gt; from
Robert Howard&amp;rsquo;s &lt;em&gt;Conan&lt;/em&gt; stories as the historical background for the tomb.&lt;/p&gt;
&lt;p&gt;The players all had fun, and they also did very well, including the new guy,
who by picking the thief had ended up with what is probably the the most
challenging class to play from original D&amp;amp;D his first time out. I always make
monster attack and damage rolls in the open, and I got a kick out of watching
their reactions, and also how quickly their cockiness faded after their first,
nearly disastrous run-in with the boss monster. Towards the end of the final,
climactic battle, I moved from my seat behind the DM&amp;rsquo;s screen to get closer to
the map that they were gathered around, and cheered along with them when they
finally brought down the mummy priest. They&amp;rsquo;d really earned it.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;As mentioned, Swords &amp;amp; Wizardry Complete (with cover art by &lt;a href=&#34;https://www.tor.com/2009/04/29/an-interview-with-fantasy-artist-erol-otus/&#34;&gt;Erol Otus&lt;/a&gt;!), and also my new print copy of &lt;a href=&#34;http://basicfantasy.org/buytherules.html&#34;&gt;Basic Fantasy RPG Core Rules&lt;/a&gt; to help me fill in some gaps in the S&amp;amp;W rules.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The players do their own mapping in my games, and the &amp;ldquo;double tabloid&amp;rdquo;-sized paper gives them plenty of room to make it big enough for everyone to see. This particular pad is from &lt;a href=&#34;https://www.speedballart.com/our-product-lines/bienfang-paper/bienfang-fine-art-paper/&#34;&gt;Bienfang&lt;/a&gt;, but while the 11&amp;quot; x 17&amp;quot; tabloid size is relatively easy to find, the 17&amp;quot; x 22&amp;quot; isn&amp;rsquo;t. I got lucky and found it at a local Office Depot, but it doesn&amp;rsquo;t seem to be listed on their website anymore.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
    </item>
    
    <item>
      <title>A 6502 assembly idiom in Excitebike</title>
      <link>https://www.ingramj.net/2017/12/a-6502-assembly-idiom-in-excitebike/</link>
      <pubDate>Sun, 10 Dec 2017 13:12:42 -0600</pubDate>
      
      <guid>https://www.ingramj.net/2017/12/a-6502-assembly-idiom-in-excitebike/</guid>
      <description>&lt;p&gt;Sometimes I like to disassemble ROM dumps for old NES games to figure out how
they work. It&amp;rsquo;s sort of like putting together a puzzle without knowing what
the picture will look like beforehand. You start disassembling opcodes at a
known entry point (the NES&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Ricoh_2A03&#34;&gt;6502-based
CPU&lt;/a&gt; will jump to the address stored
at $FFFC-$FFFD in the ROM cartridge when the machine resets) and follow the
control flow through the rest of the ROM. The puzzle isn&amp;rsquo;t the disassembly
itself, which is a purely mechanical process. It&amp;rsquo;s figuring out what the
assembly code is doing, and &lt;em&gt;why&lt;/em&gt; it&amp;rsquo;s doing it. And along the way you can
sometimes find interesting bits of code that are unlike what a modern
programmer would (or &lt;em&gt;could&lt;/em&gt;) write in a high level language. I found one such
bit of code in the initialization routines for
&lt;a href=&#34;https://en.wikipedia.org/wiki/Excitebike&#34;&gt;Excitebike&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This article isn&amp;rsquo;t about the details of &lt;a href=&#34;https://wiki.nesdev.com/w/index.php/Nesdev&#34;&gt;NES
programming&lt;/a&gt;, but there are a
couple of things worth mentioning before getting to the code. First, the NES
uses memory-mapped IO, so hardware is controlled by writing to certain memory
locations instead of by using special CPU instructions. Second, the NES has a
custom chip called the &lt;a href=&#34;https://wiki.nesdev.com/w/index.php/PPU&#34;&gt;Picture Processing Unit
(PPU)&lt;/a&gt; that can, among other things,
generate a non-maskable interrupt (NMI) at the begining of the vertical
blanking interval (or &amp;ldquo;vblank&amp;rdquo;). That&amp;rsquo;s the time between when the last line of
the screen is rendered and the first line of the next frame is started, when
input can be processed and sprites can be updated.&lt;/p&gt;
&lt;p&gt;When the NES starts up, the PPU disables NMIs until bit 7 of address $2000
(the &lt;a href=&#34;https://wiki.nesdev.com/w/index.php/PPU_registers#PPUCTRL&#34;&gt;PPUCTRL register&lt;/a&gt;) is set. That gives the game&amp;rsquo;s startup code time to
perform whatever initialization it requires - clearing RAM, setting up
hardware, etc. Once all that&amp;rsquo;s done, most games will enable NMIs and enter an
infinite loop that gets interrupted once per vblank to let the main game logic
run. Sometimes games need to disable NMIs again after that. Excitebike, for
example, jumps back into the reset handler after exiting the track editor so
it can restart at the main menu.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; And that brings us to the code fragment
that I wanted to talk about:&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ca65&#34; data-lang=&#34;ca65&#34;&gt;disable_nmi:
        lda $10         ; First load the cached value for PPUCTRL,
        and #$7f        ; then clear bit 7 (disable NMI), and continue to...
set_ppuctrl:
        sta $2000       ; First write the value to PPUCTRL register,
        sta $10         ; then cache it in the zero page,
        rts             ; and return to last jsr.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;rsquo;ll start with the second routine, &lt;code&gt;set_ppuctrl&lt;/code&gt;. This routine simply writes
the value in the CPU&amp;rsquo;s accumulator to the PPUCTRL register, and also caches it
in address $10 of &lt;a href=&#34;https://en.wikipedia.org/wiki/Zero_page&#34;&gt;the zero page&lt;/a&gt;
before returning. The value needs to be cached in RAM, because the PPUCTRL
register is read-only. If the value wasn&amp;rsquo;t also stored somewhere else, it
would be impossible to update individual bits. And that&amp;rsquo;s exactly what the
&lt;code&gt;disable_nmi&lt;/code&gt; routine does. It loads the cached value, clears bit 7 (the one
that controls NMIs), and then flows right into the &lt;code&gt;set_ppuctrl&lt;/code&gt; routine. That
is, the two routines overlap in memory. And why not? Duplicating the code
would be a waste, and since you have control over exactly where code exists in
memory when programming in assembly, you can arrange things so that you can
avoid an extra &lt;code&gt;jmp&lt;/code&gt; or &lt;code&gt;jsr&lt;/code&gt; instruction.&lt;/p&gt;
&lt;p&gt;But you can&amp;rsquo;t always arrange things so conveniently. There&amp;rsquo;s another routine
in Excitebike&amp;rsquo;s initialization code that needs to write a value to PPUCTRL,
but it can&amp;rsquo;t just let control fall though to &lt;code&gt;set_ppuctrl&lt;/code&gt;, because
&lt;code&gt;disable_nmi&lt;/code&gt; is in the way:&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ca65&#34; data-lang=&#34;ca65&#34;&gt;some_init_routine:
        ; I&amp;#39;ve omitted some irrelevant instructions here.
        sta $fc         ; Clear a flag in the 6502&amp;#39;s &amp;#34;zero page&amp;#34;.
        lda #$10        ; We also want to set PPUCTRL to a fixed value.
        bne set_ppuctrl ; This unconditionally skips over disable_nmi.
disable_nmi:
        ...             ; As before.
set_ppuctrl:
        ...             ; As before.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The 6502 instruction set doesn&amp;rsquo;t include an unconditional relative branch, so
this routine uses a &lt;code&gt;bne&lt;/code&gt; instruction that is always followed, because &lt;code&gt;lda&lt;/code&gt;
with a non-zero argument clears the CPU&amp;rsquo;s zero flag. So instead of using a
regular unconditional &lt;code&gt;jmp&lt;/code&gt; (3 bytes, 3 cycles), or a &lt;code&gt;jsr&lt;/code&gt; subroutine call (3
bytes, 6 cycles, and a bit of stack space) to get where it needs to go next,
this routine gets almost as much benefit from being near &lt;code&gt;set_ppuctrl&lt;/code&gt; as
&lt;code&gt;disable_nmi&lt;/code&gt; does, for just the cost of a single &amp;ldquo;unconditional&amp;rdquo; &lt;code&gt;bne&lt;/code&gt; (2
bytes, 3 cycles).&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;That&amp;rsquo;s also an interesting process. The reset handler checks for a couple of values that it sets at particular addresses in RAM to decide whether or not to clear the memory used by the track editor. That way it can behave differently if it&amp;rsquo;s jumped to than if there was an actual hardware reset.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The labels and comments are my own. I have no idea what the original programmer called these routines, so coming up with good names and comments is part of the disassembly puzzle.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I&amp;rsquo;m not actually sure what else the routine does, or why. This disassembly project is a work in progress.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
    </item>
    
    <item>
      <title>Substrings With Printf</title>
      <link>https://www.ingramj.net/2017/10/substrings-with-printf/</link>
      <pubDate>Sun, 29 Oct 2017 10:30:40 -0500</pubDate>
      
      <guid>https://www.ingramj.net/2017/10/substrings-with-printf/</guid>
      <description>&lt;p&gt;You can specify a precision with printf&amp;rsquo;s &lt;code&gt;%s&lt;/code&gt; conversion to limit how
many characters are printed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;greeting&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Hello, World!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%.5s&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;greeting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// prints &amp;#34;Hello\n&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what if you don&amp;rsquo;t know until runtime how many characters you need?&lt;/p&gt;
&lt;p&gt;From &lt;a href=&#34;https://linux.die.net/man/3/printf&#34;&gt;&lt;code&gt;man 3 printf&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Instead of a decimal digit string one may write &amp;ldquo;*&amp;rdquo; or &amp;ldquo;*m$&amp;rdquo; (for
some decimal integer m) to specify that the precision is given in the
next argument, or in the m-th argument, respectively, which must be
of type int.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is awesome for printing substrings. Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;// start of the token inside a source string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;           &lt;span class=&#34;c1&#34;&gt;// number of characters in the token
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;print_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FILE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;%.*s&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &amp;ldquo;*m$&amp;rdquo; syntax comes from &lt;a href=&#34;http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html&#34;&gt;a POSIX extension&lt;/a&gt;
to the C standard that lets you specify which argument to use for each
conversion. This is helpful if you want to use the same argument more
than once:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;print_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FILE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;%1$.*2$s&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; (%2$d characters)&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that you can&amp;rsquo;t mix numbered and unnumbered conversions in the same
format string, so if you use &lt;code&gt;*m$&lt;/code&gt; for the precision, you also need to
use &lt;code&gt;%m$&lt;/code&gt; for the conversion itself.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Building jlox with Gradle</title>
      <link>https://www.ingramj.net/2017/10/building-jlox-with-gradle/</link>
      <pubDate>Sat, 14 Oct 2017 05:15:21 -0500</pubDate>
      
      <guid>https://www.ingramj.net/2017/10/building-jlox-with-gradle/</guid>
      <description>&lt;p&gt;I just started following along with Bob Nystrom&amp;rsquo;s &lt;a href=&#34;http://www.craftinginterpreters.com&#34;&gt;Crafting
Interpreters&lt;/a&gt; book a few days ago,
and one of the first things I did was set up a
&lt;a href=&#34;https://gradle.org&#34;&gt;Gradle&lt;/a&gt; project for the &lt;a href=&#34;http://www.craftinginterpreters.com/a-tree-walk-interpreter.html&#34;&gt;jlox
interpreter&lt;/a&gt;. It&amp;rsquo;s
a simple Java application with no external dependencies, so the build
script is hardly interesting, except for one thing: starting in Chapter
5, there is a &lt;a href=&#34;http://www.craftinginterpreters.com/representing-code.html#metaprogramming-the-trees&#34;&gt;GenerateAst&lt;/a&gt;
&amp;ldquo;script&amp;rdquo; needs to be run before compiling, because it generates source
files. Turns out, it&amp;rsquo;s pretty easy to add a code generation task to a
Gradle build.&lt;/p&gt;
&lt;p&gt;The first step is to create a
&lt;a href=&#34;https://docs.gradle.org/current/userguide/organizing_build_logic.html#sec:build_sources&#34;&gt;buildSrc&lt;/a&gt;
directory, and move GenerateAst.java into it, following the normal
conventions for Java projects &amp;ndash; that is, put the source file in
buildSrc/src/main/java/com/craftinginterpreters/tool/. Now you can use
the &lt;code&gt;GenerateAst&lt;/code&gt; class from your build.gradle file, but its interface
isn&amp;rsquo;t really suited for being used programmatically. It has a standard
&lt;code&gt;main&lt;/code&gt; method that treats the first argument as a path to the output
directory, and it passes that path as a &lt;code&gt;String&lt;/code&gt; to the &lt;code&gt;defineAst&lt;/code&gt; method,
like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;throws&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IOException&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Usage: generate_ast &amp;lt;output directory&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;defineAst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Expr&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arrays&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;asList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// snip ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;defineAst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;baseName&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;types&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;throws&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IOException&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;baseName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.java&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;PrintWriter&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;writer&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PrintWriter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// snip ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since we&amp;rsquo;ll be using &lt;code&gt;GenerateAst&lt;/code&gt; from a Gradle script instead of from the
command line, we can just pass in a
&lt;a href=&#34;http://docs.oracle.com/javase/8/docs/api/java/io/File.html&#34;&gt;&lt;code&gt;File&lt;/code&gt;&lt;/a&gt; object
for the output directory, instead of using path strings. Then we can use
&lt;code&gt;File&lt;/code&gt;&amp;rsquo;s constructors and methods to create the subdirectories and files
that we need.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// this replaces main(String[] args)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;throws&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IOException&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;packageDir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;com/craftinginterpreters/lox&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;packageDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;mkdirs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;defineAst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packageDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Expr&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arrays&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;asList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// snip ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;defineAst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;baseName&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;types&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;throws&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IOException&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputFile&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outputDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;baseName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.java&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;PrintWriter&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;writer&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PrintWriter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;outputFile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// snip ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to call &lt;code&gt;GenerateAst.run&lt;/code&gt; from our build.gradle, and pass it
an appropriate output directory. The project&amp;rsquo;s build directory is a good
place for generated files, so we&amp;rsquo;ll use a subdirectory under that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generatedSrcDir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;buildDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;generated/src/main/java/&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;task&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generateAst&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;doLast&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;GenerateAst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generatedSrcDir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running the &lt;code&gt;generateAst&lt;/code&gt; task will create Expr.java under the
build/generated/src/main/java/ directory, so now we just need to add
that directory to the main source set, and run the new task before
compiling.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;compileJava&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;dependsOn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generateAst&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sourceSets&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;java&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;srcDirs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generatedSrcDir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s it. Now the code generator will run for every build. If you&amp;rsquo;re
using an IDE, then you&amp;rsquo;ll also want to run the &lt;code&gt;generateAst&lt;/code&gt; task manually
after making changes to GenerateAst.java, so the changes to the generated
classes will be visible.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A new home on the web</title>
      <link>https://www.ingramj.net/2017/09/a-new-home-on-the-web/</link>
      <pubDate>Sun, 10 Sep 2017 17:28:29 -0500</pubDate>
      
      <guid>https://www.ingramj.net/2017/09/a-new-home-on-the-web/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been a member of &lt;a href=&#34;http://sdf.org&#34;&gt;SDF Public Access UNIX System&lt;/a&gt; for
around fifteen years, at the &lt;a href=&#34;http://sdf.org/?join#arpa&#34;&gt;ARPA&lt;/a&gt; level for
most of that time. They provide a great service, and have hosted various
incarnations of my homepage since I first signed up. The most recent was
started in November of 2014 as a blog about programming, built with
&lt;a href=&#34;https://jekyllrb.com&#34;&gt;Jekyll&lt;/a&gt; and only lasting for a couple of posts
(which I have copied over to this site). Then life got busier, and my blog
fell by the wayside.&lt;/p&gt;
&lt;p&gt;Since 2014, I&amp;rsquo;ve helped build a &lt;a href=&#34;https://contentcontroller.scorm.com&#34;&gt;new
product&lt;/a&gt;, went through a &lt;a href=&#34;https://rusticisoftware.com/big-news-rustici-software/&#34;&gt;corporate
acquisiton&lt;/a&gt;, started
running (and stopped, and started again), bought a house, ran an &lt;a href=&#34;https://en.wikipedia.org/wiki/Dungeons_%26_Dragons_retro-clones#Swords_.26_Wizardry&#34;&gt;old-school
D&amp;amp;D-ish&lt;/a&gt;
campaign (now on hiatus&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;), learned how to ski (sort of), quit Facebook,&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
had my tenth wedding anniverary, rode in a &lt;a href=&#34;http://www.tnballoon.com/index.html&#34;&gt;hot air
balloon&lt;/a&gt;, saw &lt;a href=&#34;http://ironmaiden.com&#34;&gt;Iron
Maiden&lt;/a&gt; live, played a lot of video games (most
recently, Breath of the Wild), and grew and shaved off three beards. But I
didn&amp;rsquo;t do much programming for fun, so I didn&amp;rsquo;t have a whole lot to write
about for a site I&amp;rsquo;d named &amp;ldquo;A Programmer&amp;rsquo;s Homepage&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;row card&#34;&gt;
&lt;div class=&#34;six columns&#34;&gt;

&lt;figure &gt;
  
  &lt;img src=&#34;https://www.ingramj.net/img/balloon.jpg&#34; class=&#34;u-max-full-width&#34; alt=&#34;Inside of a hot air balloon in flight.&#34; /&gt;
  
  
&lt;/figure&gt;


&lt;/div&gt;
&lt;div class=&#34;six columns&#34;&gt;

&lt;figure &gt;
  
  &lt;img src=&#34;https://www.ingramj.net/img/ski.jpg&#34; class=&#34;u-max-full-width&#34; alt=&#34;Selfie on a mountain in a ski helmet.&#34; /&gt;
  
  
&lt;/figure&gt;


&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now it seems like a good time to start writing again, with a more general
scope. Even though I still like SDF, and have no intention of cancelling my
account there,&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; I decided a couple of weeks ago that it was finally time to
register my own domain, and find a host that provides easier deployments and
some more bells and whistles. So I registered
&lt;a href=&#34;https://www.ingramj.net&#34;&gt;ingramj.net&lt;/a&gt; (and its .com counterpart) and looked
at a few hosting and authoring options before settling on
&lt;a href=&#34;https://www.netlify.com&#34;&gt;Netlify&lt;/a&gt; and &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;. If you&amp;rsquo;re a
developer, using them is &lt;a href=&#34;https://gohugo.io/hosting-and-deployment/hosting-on-netlify/&#34;&gt;dead
simple&lt;/a&gt;. Put
your site in a repo on one of the big &lt;a href=&#34;https://git-scm.com&#34;&gt;Git&lt;/a&gt; hosting sites
(I went with &lt;a href=&#34;https://gitlab.com&#34;&gt;GitLab&lt;/a&gt;, but they also support
&lt;a href=&#34;https://github.com&#34;&gt;GitHub&lt;/a&gt; and &lt;a href=&#34;https://bitbucket.org&#34;&gt;Bitbucket&lt;/a&gt;), and with
a surprisingly small amount of configuration, you can deploy changes just by
pushing to your master branch.  It&amp;rsquo;s like &lt;a href=&#34;https://pages.github.com&#34;&gt;GitHub
pages&lt;/a&gt;, but with a lot more features, like one-click
SSL certificates for custom domains, form handling, and preview deploys.&lt;/p&gt;
&lt;p&gt;Now that I have a new home on the web, I have a few ideas that I&amp;rsquo;d like to
write about. We&amp;rsquo;ll see how it goes.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I learned that if you offer to run an RPG campaign at a software company, you&amp;rsquo;ll get a lot of takers. The largest session had a dozen players, two of whom were remote. It was fun, but crazy.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I was never going to top &amp;ldquo;When it comes to eating a lot of tacos, the trick is to get as many down as you can really quickly, before the self-loathing kicks in,&amp;rdquo; so it was time to move on. Also, it was really bumming me out.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I want to get a new &lt;a href=&#34;http://sdf.org/store/?3;sdf9&#34;&gt;t-shirt&lt;/a&gt;, since my old one wore out years ago.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
    </item>
    
    <item>
      <title>Unit tests for C, in two macros</title>
      <link>https://www.ingramj.net/2014/11/unit-tests-for-c-in-two-macros/</link>
      <pubDate>Sat, 29 Nov 2014 00:00:00 +0000</pubDate>
      
      <guid>https://www.ingramj.net/2014/11/unit-tests-for-c-in-two-macros/</guid>
      <description>&lt;p&gt;No, not the same two macros as &lt;a href=&#34;http://www.jera.com/techinfo/jtns/jtn002.html&#34;&gt;MinUnit&lt;/a&gt;.
These macros have a few more features, and thus require a bit more from
the runtime. Together, the two macros are used to define test functions
that run code in a new process, and that have consistent return values
to indicate whether the test succeeded, failed, or had an error. All of
the code in this post is available on &lt;a href=&#34;https://gist.github.com/ingramj/ba3fcd776591fa5d9bef&#34;&gt;GitHub&lt;/a&gt;,
under the terms of the &lt;a href=&#34;https://opensource.org/licenses/MIT&#34;&gt;MIT License&lt;/a&gt;.
What follows is a description of the code and how it works.&lt;/p&gt;
&lt;p&gt;The first macro is called &lt;code&gt;BEGIN_TEST&lt;/code&gt;, and it is used to begin a new
test definition:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define BEGIN_TEST(name)                        \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;    static int test_##name(void)                \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;    {                                           \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        pid_t pid = fork();                     \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        if (pid &amp;lt; 0) {                          \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            return -1;                          \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        }                                       \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        if (pid == 0) {                         \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            int failed = 0;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It starts by defining a new function, whose name is created using the
&lt;code&gt;##&lt;/code&gt; token pasting operator. The function is declared static, which
isn&amp;rsquo;t really necessary, but it fits in well with how I write tests: a
single &amp;ldquo;public&amp;rdquo; function that calls a set of related static test
functions and aggregates their results.&lt;/p&gt;
&lt;p&gt;The test function forks a new process, so that if the test code
segfaults, it won&amp;rsquo;t take the whole test harness down, and the
remaining tests can be run. Forking also allows us to test functions
that &lt;em&gt;should&lt;/em&gt; cause the process to exit. If the fork fails, then -1
is returned. This is the &amp;ldquo;error&amp;rdquo; return value, used to indicate that
something has gone wrong while running the test.&lt;/p&gt;
&lt;p&gt;The rest of the macro is the start of the child process code, which
is where the test code itself lives. The &lt;code&gt;failed&lt;/code&gt; variable is a flag,
which is provided for convenience. It works with the &lt;code&gt;END_TEST&lt;/code&gt; macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define END_TEST(expected)                                      \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            exit(failed ? !expected : expected);                \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        } else {                                                \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            int status;                                         \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            waitpid(pid, &amp;amp;status, 0);                           \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            if (WIFEXITED(status)) {                            \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;                return WEXITSTATUS(status) == expected ? 0 : 1; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            }                                                   \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            return -1;                                          \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        }                                                       \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;expected&lt;/code&gt; argument is expected exit status of the child process
after a successful run. By making this a parameter, things like the
popular &amp;ldquo;exit with an error status if &lt;code&gt;malloc&lt;/code&gt; returns &lt;code&gt;NULL&lt;/code&gt;&amp;rdquo;
pattern become testable. However, the most common case is for the
exit status to depend on the value of the failed variable, so that&amp;rsquo;s
what the call to &lt;code&gt;exit&lt;/code&gt; does. If &lt;code&gt;failed&lt;/code&gt; is still 0 by the time the
exit line is reached, then the expected exit status is used.
Otherwise, &lt;code&gt;!expected&lt;/code&gt; (the &amp;ldquo;unexpected&amp;rdquo; exit status) is used instead.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;else&lt;/code&gt; block is run in the parent process, and it calls &lt;code&gt;waitpid&lt;/code&gt;
on the child process&amp;rsquo;s PID, catching the exit status in a variable.
If the child process exits normally, then its exit status is compared
to the expected value. If they match, then the test function returns
0, which is the &amp;ldquo;success&amp;rdquo; value; otherwise, it returns 1, which is the
&amp;ldquo;failed&amp;rdquo; value. If the child process did not exit normally because was
killed by a signal, then -1 (the &amp;ldquo;error&amp;rdquo; value) is returned.&lt;/p&gt;
&lt;p&gt;The two macros are intended to be used with a block of code in
between, which defines a new scope for local variables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BEGIN_TEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contrived_example&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;END_TEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The preprocessor expands this to something like the following:&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;test_contrived_example&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pid_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;EXIT_SUCCESS&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;waitpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;WIFEXITED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WEXITSTATUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;EXIT_SUCCESS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;                      
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;enhancements&#34;&gt;Enhancements&lt;/h2&gt;
&lt;p&gt;Okay, so I lied a bit in the title. These two macros are sufficient
for creating a set of test functions, and once those are created, it&amp;rsquo;s
pretty easy to test their return values in some automated fashion. But
by themselves, they make for a pretty bare-bones testing framework.&lt;/p&gt;
&lt;p&gt;One easy enhancement is to define some macros for working with the
&lt;code&gt;failed&lt;/code&gt; variable inside the test blocks. I like &lt;code&gt;FAIL_IF&lt;/code&gt;, which sets
&lt;code&gt;failed&lt;/code&gt; to 1 if some condition holds, and &lt;code&gt;FAIL_UNLESS&lt;/code&gt;, which sets it
to 1 if the condition t hold:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define FAIL_IF(cond)     failed = (cond) ? 1 : failed;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define FAIL_UNLESS(cond) failed = (cond) ? failed : 1;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BEGIN_TEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_failure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FAIL_IF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FAIL_UNLESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;END_TEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These new macros are useful for writing tests, but what about running
them and gathering results? I use a struct and a macro for this.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;passed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;cm&#34;&gt;/* the number of passed tests */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;cm&#34;&gt;/* the number of failed tests */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;errors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;cm&#34;&gt;/* the number of errors       */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tests_summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define RUN_TEST(name, summary)                 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;    do {                                        \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        int ret;                                \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        printf(&amp;#34;%s: &amp;#34;, #name);                  \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        fflush(stdout);                         \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        ret = test_##name();                    \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        if (ret == 0) {                         \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            printf(&amp;#34;passed\n&amp;#34;);                 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            (summary).passed++;                 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        } else if (ret == 1) {                  \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            printf(&amp;#34;failed\n&amp;#34;);                 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            (summary).failed++;                 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        } else {                                \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            printf(&amp;#34;failed due to an error\n&amp;#34;); \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;            (summary).errors++;                 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;        }                                       \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;    } while (0)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;tests_summary&lt;/code&gt; struct just holds counts for the number of passed
and failed tests, and the number of errors that have occurred. The
&lt;code&gt;RUN_TEST&lt;/code&gt; macro takes a test name and a summary struct, runs the
named test, and increments the appropriate field in the summary struct
based on the s return value. Along the way, it prints some status
information. Using these, one can easily run a suite of related tests
and gather the aggregate results for reporting:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;run_test_suite&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;tests_summary&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;RUN_TEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contrived_example&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;RUN_TEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_failure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;failed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Oh no! Some tests failed!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I&amp;rsquo;ve left macros from the standard library unexpanded, and cleaned up the indentation.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Unlike the other macros in this post, &lt;code&gt;RUN_TEST&lt;/code&gt; could be replaced with an inline function. The (very slight) advantage of using a macro is that we can get the test function from just the name, instead of having to pass a string and a function pointer separately. One &lt;em&gt;could&lt;/em&gt; write a macro that calls the inline function with the appropriate arguments, but I&amp;rsquo;m not sure that really buys you much&amp;hellip;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
    </item>
    
    <item>
      <title>A Makefile template for simple C projects</title>
      <link>https://www.ingramj.net/2014/11/a-makefile-template-for-simple-c-projects/</link>
      <pubDate>Sun, 09 Nov 2014 00:00:00 +0000</pubDate>
      
      <guid>https://www.ingramj.net/2014/11/a-makefile-template-for-simple-c-projects/</guid>
      <description>&lt;p&gt;Large programming projects may require elaborate build systems, but
for a simple project consisting of a single executable target and
handful of C source files, a single
&lt;a href=&#34;http://en.wikipedia.org/wiki/Make_(software)&#34;&gt;Makefile&lt;/a&gt; is often all
that is necessary. If you use &lt;a href=&#34;http://www.gnu.org/software/make/&#34;&gt;GNU Make&lt;/a&gt;
and a C compiler capable of emitting dependency rules
(both &lt;a href=&#34;https://gcc.gnu.org/&#34;&gt;GCC&lt;/a&gt; and &lt;a href=&#34;http://clang.llvm.org/&#34;&gt;Clang&lt;/a&gt;
can do this, and no doubt others can as well), then a single generic
Makefile template can be used for multiple projects by changing only a
few variable definitions.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; Over time I&amp;rsquo;ve developed such a template,
which I present here with the hope that others will find it useful.&lt;/p&gt;
&lt;p&gt;At the top of the template are variables with project-specific values.
These are typically the only lines that need to be modified when
starting a new project. The &lt;code&gt;PROG&lt;/code&gt; variable holds the name of the
executable target to be built, and &lt;code&gt;SRCS&lt;/code&gt; holds the list of source
files needed to build it. Header files are not listed here, because
they are handled automatically. If an external library is needed, then
the &lt;code&gt;CFLAGS&lt;/code&gt; and &lt;code&gt;LDFLAGS&lt;/code&gt; variables can be modified as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROG&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; program
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;SRCS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; main.c util.c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CC&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; cc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CFLAGS&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; -Wall -Wextra -Werror
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;LDFLAGS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to build the executable target, all the source files need to
be compiled into object files, which are then linked together. The list
of object files can be created from the list of source files by using a
&lt;a href=&#34;http://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html&#34;&gt;substitution reference&lt;/a&gt;.
Keeping the list of object files in a variable makes it easy to write
the rule for the executable target, and also the rule for cleaning up
generated files. Another substitution reference is used to create a
list of &amp;ldquo;.d&amp;rdquo; files in the &lt;code&gt;DEPS&lt;/code&gt; variable. These files are created by
the compiler (with the &lt;code&gt;-MMD&lt;/code&gt; flag) alongside each object file, and
contain dependency information in the form of Makefile rules. The
dependencies include the C source file, along with any header files that
it includes. By getting this information directly from the compiler,
we&amp;rsquo;re spared from having to manually list dependencies for each file in
the project. This is the key to keeping the Makefile as generic as
possible.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OBJS&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;SRCS:.c&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;.o&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;DEPS&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;SRCS:.c&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;.d&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.PHONY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PROG&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;$(PROG)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;OBJS&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;CC&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -o &lt;span class=&#34;nv&#34;&gt;$@&lt;/span&gt; $^
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;%.o&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; %.&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;CC&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -MMD -c $&amp;lt; -o &lt;span class=&#34;nv&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;-include&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;DEPS&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;-include $(DEPS)&lt;/code&gt; line includes the dependency files that were
generated as a side effect of the &lt;code&gt;%.o: %.c&lt;/code&gt; rule used to compile the
object files. The first time the project is built, there won&amp;rsquo;t be any
dependency files to include, but that&amp;rsquo;s okay because every source file
will have to be compiled anyway. On subsequent runs, the dependency
information will be used to determine which object files are out of
date. And even better, when the object files are rebuilt, their
dependency files will also be updated for the &lt;em&gt;next&lt;/em&gt; run.&lt;/p&gt;
&lt;p&gt;The final section of the Makefile has targets for cleaning up all the
generated files. The &lt;code&gt;clean&lt;/code&gt; target removes object and dependency
files. The &lt;code&gt;cleaner&lt;/code&gt; target depends on &lt;code&gt;clean&lt;/code&gt; and also removes the
executable file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.PHONY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cleaner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;clean&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm -f &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;OBJS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;DEPS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;cleaner&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm -rf &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;PROG&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Below is the complete Makefile template, which I have placed in the
&lt;a href=&#34;http://unlicense.org/&#34;&gt;public domain&lt;/a&gt;. Feel free to modify and use it
for your own projects.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROG&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; program
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;SRCS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; main.c util.c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CC&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; cc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CFLAGS&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; -Wall -Wextra -Werror
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;LDFLAGS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OBJS&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;SRCS:.c&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;.o&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;DEPS&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;SRCS:.c&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;.d&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.PHONY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PROG&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;$(PROG)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;OBJS&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;CC&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;LDFLAGS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -o &lt;span class=&#34;nv&#34;&gt;$@&lt;/span&gt; $^
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;%.o&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; %.&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;CC&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;CFLAGS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -MMD -c $&amp;lt; -o &lt;span class=&#34;nv&#34;&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;-include&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;DEPS&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.PHONY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cleaner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;clean&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm -f &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;OBJS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;DEPS&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;cleaner&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	rm -rf &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;PROG&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;If you&amp;rsquo;re using BSD Make, things are &lt;a href=&#34;http://wiki.netbsd.org/bsd_make/&#34;&gt;even easier&lt;/a&gt;: you just have to define some variables and include &lt;code&gt;bsd.prog.make&lt;/code&gt;. The whole Makefile can be just 3 or 4 lines.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description>
    </item>
    
  </channel>
</rss>
