
\documentclass[12pt]{article}
\usepackage[T2A,OT1]{fontenc}
\usepackage[default]{cantarell}
\usepackage[a4paper, top=20mm, bottom=20mm, left=20mm, right=20mm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[russian, english]{babel}
\usepackage{tabu}
\usepackage{hyperref}
\usepackage{parskip}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage[normalem]{ulem}
\usepackage{float}
\floatstyle{boxed}
\restylefloat{figure}
\usepackage{setspace}
\onehalfspacing
\author{Artyom Bologov \href{mailto:this-post-is-cpp@aartaka.me}{(email)}}
\date{\today}
\title{I Generated This Post With C Preprocessor}
\makeatletter
\def\endenv{\expandafter\end\expandafter{\@currenvir}}
\makeatother
\begin{document}
\maketitle

It’s a new phase, so I’m re-evaluating my life and tech choices yet again.
This time, I identify as a C programmer.
I’m moving to C-based software and trying to script everything with C.
So why not move my website from Lisp to C too?
To C preprocessor, actually.

There are several inspirations for this idea:

\begin{itemize}\item \href{https://stackoverflow.com/a/1662202}{Quake hack for raw file injection}.
\item \href{https://accu.org/journals/overload/20/108/ignatchenko_1926}{An anecdote about preprocessor-based website}.
\item \href{https://reddit.com/r/C_Programming/comments/11at6d8/generate_html_in_c}{One attempt to generate HTML with C},
\item \href{https://github.com/aalmkainzi/htmc}{And another HTML generation library}.
\end{itemize}

So, technically, I’m not the first one to generate a website with C preprocessor
(let’s call it
\href{https://gnu.org/software/make/manual/html_node/Implicit-Variables.html}{CPP}.
But I’m up to the challenge of making it actually usable and pretty!
The page you’re looking at is generated with C preprocessor, so consider that a success.

\section*{C Preprocessor Is a Templating Engine, Actually} \label{cpp-is-templating-engine}

CPP is quite dumb: it operates on code that’s not even parsed yet.
Which is bad if you want to make Lisp-like macros.
And good if you want to embed some text or files into arbitrary text.
Even if this text is HTML.
So preprocessor is a templating engine of sorts.

But CPP possesses several advantages over tools like
\href{https://mustache.github.io}{Mustache}:

\begin{description}\item[Portability]
C compiler with a preprocessor is available for every OS and every toolset.
\item[Familiarity]
Every C programmer knows how CPP works. (Right?)
  Almost every programmer knows HTML.
  If they don’t, they can easily learn both preprocessor and HTML.
\item[Zero dependencies, no building]
Again, C compilers are everywhere.
  And you don’t need any third-party libraries to build a website with preprocessor.
\end{description}

Preprocessor also has built-in recursive file inclusion.
One can write HTML files with preprocessor directives in them.
Here’s how a template file (say, \verb|template/head|) might look like:

\begin{figure}[h!]\begin{verbatim}
<head>
  <title> PAGE_I Generated This Post With C Preprocessor </title>
#ifdef PAGE_Yes, you can use C preprocessor as a website generator.
  <meta name="description" content=PAGE_Yes, you can use C preprocessor as a website generator./>;
#endif
</head>
\end{verbatim}\caption{Hypothetical HTML file with preprocessor directives}\end{figure}

You can then \verb|#include "template/head"| from another file.

\section*{Problematic Chars} \label{problematic-chars}

Preprocessor, as any templating engine, has some special chars that you have to handle.
And preprocessor doesn’t make it easy to work with these.

\begin{description}\item[Hash Sign]
The most obvious preprocessor offender is the hash sign.
  Preprocessor interprets hash sign as a directive.
  And fails silently if it cannot interpret the directive properly.
\begin{itemize}\item If you use hash in plaintext content, just replace it with \verb|\&num;| and enjoy: \verb|safe hash sign: #|
\item If you need hash in element IDs/fragments, quote it as per HTML attribute syntax and it will be recognized as C quoted string (nice feature of the preprocessor!): \verb|<a href="#link-fragment">...</a>|
\item Hash in HTML entities—you don’t need it, because you have Unicode.
\end{itemize}
</dd>

\item[Unicode Chars]
GCC in particular is bad at it. It expands 😃 to \verb|U0001f603|, for example.
  That’s why I use Clang.

\item[Comments]
Compilation stages before preprocessor remove comments, unless you instruct preprocessor not to.
  You simply have to provide a \verb|-C| flag.
  GCC is making it hard again: it’s adding its own comments to the output.
  That’s why I use Clang.
\end{description}

\section*{Is That Worth It?} \label{worth-it}

Given all these problems with chars and the fact that preprocessor is scary, is it worth it?
Actually, yes.
The preprocessor-based setup abstracts away the repetitive parts, while keeping things simple and portable enough.
And, however painful it is to acknowledge, it’s simpler than
\href{run:this-post-is-lisp}{my previous Lispy setup}.

You can review all of my build code here:
\begin{itemize}\item Makefile
\href{https://makefile}{Makefile that builds blog posts}.
\item Templates for page
  \href{https://template/head}{head},
\href{https://template/header}{header},
\item and a
\href{https://template/footer}{copyright footer}.)
\item And the exact source file for this page:
\href{run:this-post-is-cpp}{this-post-is-cpp.h}
\end{itemize}

Update December 2024: I rewrote the whole thing in
\href{run:this-post-is-ed}{ed(1)}.


\par\noindent\rule{\textwidth}{0.4pt}
\href{https://creativecommons.org/licenses/by/4.0}{CC-BY 4.0} 2022-2026 by Artyom Bologov (aartaka,)
\href{https://codeberg.org/aartaka/pages/commit/a91befa}{with one commit remixing Claude-generated code}.
Any and all opinions listed here are my own and not representative of my employers; future, past and present.
\end{document}
