
\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{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.}
LI
\href{https://accu.org/journals/overload/20/108/ignatchenko_1926}{An anecdote about preprocessor-based website.}
LI
\href{https://www.reddit.com/r/C_Programming/comments/11at6d8/generate_html_in_c/}{One attempt to generate HTML with C,}
LI
\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://www.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.
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, <code>template/head</code>) 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|\#| 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!): <code><a href="#link-fragment">...</a></code>
\item Hash in HTML entities—you don't need it, because you have Unicode.
\end{itemize}
\endenv

\item[Unicode Chars]
GCC in particular is bad at it. It expands 😃 to <code>U0001f603</code>, 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{this-post-is-lisp}{my previous Lispy setup.}

You can review all of my build code here:
\begin{itemize}\item Makefile
\href{makefile}{Makefile that builds blog posts}.
\item Templates for page
\href{template/head.html}{head,}
\href{template/header.html}{header,}
\item and a
\href{template/footer.html}{copyright footer.}
\item And the exact source file for this page:
\href{this-post-is-cpp.h}{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}
