Static Site Generator

2021-08-10 20:00:00


I wanted a static website generator that could maintain the data using markdown, have the entries merge with a template and then upload them to one of the super cheap static http servers. I looked around at a few different options and just didn't really like anything. It felt silly downloading a ton of node packages for a process that I used to run in one shell loop piping the files to the original markdown perl script. I like to program though and I thought it would be good practice to write the whole thing as a single C program.

Memory System

I had this funny idea I wanted to try. Imagine that in C all string allocations were on a stack. You can keep appending to a string on the top of the stack, and when you needed a new string, you can just push and the top of the stack will have an empty string that you can start working with. No malloc or free. In our imaginary world the stack is infinite.

I'm not a fan of null terminated strings. Aside from all of the security concerns, you have this mental burden of stuff like "is the data on the socket null terminated" or "I'm concatenating these strings remember to subtract one", blah. I much prefer having the string contain the length as part of the data structure.

I refer to that type of string in this program as a Line.

typedef struct Line{
    char *s;
    int size;
} Line;

The stack has the following structure:

typedef struct StringStack{
    char *data;
    u32 totalSize;
    u32 used;
    u32 *lastUsed;
    u32 lastUsedIndex;
    u32 stackSize;
    u32 errors;
} StringStack;

Description of the fields:


Let's walk through the code that parses image tags. Specifically this input string ![Santa 6502 Demo](

case TT_BANG:
    char val = token.value;
    if (getToken(line, &token)){
        if (token.type == TT_LEFT_BRACKET){
            markdownInline(stringStack, line, token);
            Line altText = topStringStack(stringStack);
            getBetweenTokenTypes(stringStack, line, TT_LEFT_PAREN, TT_RIGHT_PAREN);
            Line url = topStringStack(stringStack);

            appendf(stringStack, "<img src=\"%l\" alt=\"%l\" />", &url, &altText);
            Line image = topStringStack(stringStack);

            //Unwind the stack
            popStringStack(stringStack); //url
            popStringStack(stringStack); //link text
            popStringStack(stringStack); //set to string before parsing
            appendLine(stringStack, &image);
        else {
            appendChar(stringStack, val);
        appendChar(stringStack, val);

The first thing that we want to do is save the token.value in case we are not dealing with an image tag and we just need to output the char. Let's focus on the interesting part when we get a left bracket.

First off we want to save whatever is on the stack before we start working. The filename currently being processed is at the top of the stack. Everything else in red is junk left over from a previous data file.


Next we make a recursive call to markdownInline to pickup the alt text. Once we have a reference to that string we push it for later use.


We go through a similar process for the href by grabbing the text between the left and right parentheses and pushing it onto the stack.


The variadic function appendf works on the top of the stack. The %l argument in this case is for the Line data type. After obtaining the reference this time, the stack is not pushed since we want to pop the references that are no longer needed.


In the final step the image tag is relocated to the top of the stack. This allows for the calling function to assume the results of parsing are always on the top of the stack. It uses top to get that information and write it to the html file.


Pros and Cons