Skip to content

opensourcedoc/c-stack-mustache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Generic C Code with Mustache Templates

This project demonstrates how to bring generic programming into the C language by using Mustache, a lightweight logic-less template engine.

C lacks native support for generics. Instead of relying on macros or duplicating similar code for each data type, this approach uses Mustache templates to generate reusable, type-safe stack implementations in plain C.

The repository includes:

  • Mustache templates for .c and .h files of a stack structure.
  • A simple code generation pipeline using make.
  • Two test cases demonstrating usage with int and a custom wrapper type.

This project shows that even in a low-level language like C, meta-programming techniques can improve maintainability and reduce boilerplate — all without giving up performance or transparency.


Why Mustache?

C macros and conditional compilation can simulate some forms of generic code, but they often come with trade-offs:

  • 🧹 Complex syntax – Macro logic can quickly become unreadable and hard to debug.
  • 🚫 Limited flexibility – Features like conditional defaults or type-dependent expansion are hard to express.
  • 🧪 Poor tooling support – IDEs and linters usually struggle with macro-heavy code.

Using a template engine like Mustache provides a different approach:

  • Clear separation between code and logic – Templates stay readable and simple.
  • Flexible output – You can generate .c/.h files for any type combination with consistent formatting.
  • Static output – The generated code is plain C, fully transparent to compilers and debuggers.
  • Easy integration – Combine with make or shell scripts for reproducible, automated generation.

This method doesn’t replace C’s core mechanisms — it augments them through pre-processing. It’s especially useful when you want to maintain clean, consistent, reusable data structures across multiple types without relying on compiler extensions.


Usage Example

The following test demonstrates how to use a generated stack for a user-defined type int_obj_t. The type wraps an int value, and provides custom clone and free functions for memory safety.

// int_obj_t is a wrapper around int with malloc/free.
typedef struct {
    int data;
} int_obj_t;

Here's a minimal usage scenario:

#include "stack_obj.h"

int_obj_t * obj_new(int data);
void * obj_clone(void *obj);
void obj_free(void *obj);

int main(void)
{
    stack_t *s = stack_new((stack_params_t){
        .clone = obj_clone,
        .free = obj_free
    });

    int data[] = {3, 4, 5, 6};
    for (size_t i = 0; i < 4; i++) {
        stack_push(s, obj_new(data[i]));
        int_obj_t *top = stack_peek(s);
        assert(top->data == data[i]);
        obj_free(top);
    }

    // Pops: 6, 5, 4, 3
    for (int i = 3; i >= 0; i--) {
        int_obj_t *top = stack_pop(s);
        assert(top->data == data[i]);
        obj_free(top);
    }

    stack_free(s);
    return 0;
}

Build and Run

make                # Generates C code via Mustache and builds the test
./test_obj          # Runs the test program

This confirms that the generated stack works with non-primitive types and handles memory ownership safely via callbacks.


System Requirements

  • A modern C compiler
  • GNU Make
  • mustach (template processor)

License

Apache License 2.0 Copyright (c) 2019 ByteBard

About

No description or website provided.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published