docs(docs): built docs

Note for now much of the docs is LLM written. This was done to save time and focus on code development. The docs have been LOOSLEY reviewed. However, the code itself has been either fully written by hand or fully reviewed. Therefore, the docs should at the moment be seen as a loose resource rather than authoratiative (and this is on top of the general ability for docs to drift)
This commit is contained in:
2026-11-09 14:09:44 -05:00
parent d9c4919477
commit 6b57738330
32596 changed files with 4155414 additions and 0 deletions

View File

@@ -0,0 +1,348 @@
/*
* Doxygen documentation filter.
*
* Supports:
* @requires
* @contribution
* @true_if
*
* We have this as a C not a python file to avoid spinning up the python interpreter separately for every file.
* We have this as a C and not a C++ file to avoid large binaries for something as simple as documentation generation and so we can more easily generate portable binaries.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 240
typedef struct {
const char *name;
const char *title;
const char *cssClass;
} Command;
// To add additional custom sections to the documentation edit this, you may also want to edit
// the doxygen-extra.css file to customize the class styling
static const Command commands[] = {
{"@requires", "Requirements", "serif-requires"},
{"@contribution", "Equation Contributions", "serif-contribution"},
{"@true_if", "Compile Time True Type If", "serif-true-if"}
};
#define COMMAND_COUNT (sizeof(commands) / sizeof(commands[0]))
typedef struct {
char *text;
size_t length;
size_t prefixLength;
size_t contentStart;
size_t contentLength;
size_t newlineStart;
int commandIndex;
} Line;
typedef struct {
Line *data;
size_t count;
size_t capacity;
} LineArray;
static void *checked_realloc(void *ptr, size_t size) {
void *result = realloc(ptr, size);
if (!result) {
fprintf(stderr, "ERROR: Out of memory.\n");
exit(EXIT_FAILURE);
}
return result;
}
/* Read a complete line, including its newline. */
static int read_line(FILE *file, Line *line) {
size_t capacity = 256;
size_t length = 0;
char *buffer = checked_realloc(NULL, capacity);
int character;
while ((character = fgetc(file)) != EOF) {
if (length + 1 >= capacity) {
capacity *= 2;
buffer = checked_realloc(buffer, capacity);
}
buffer[length++] = (char)character;
if (character == '\n')
break;
}
if (length == 0) {
free(buffer);
return 0;
}
buffer[length] = '\0';
line->text = buffer;
line->length = length;
line->commandIndex = -1;
line->prefixLength = 0;
line->contentStart = 0;
line->contentLength = 0;
line->newlineStart = length;
while (line->newlineStart > 0 &&
(buffer[line->newlineStart - 1] == '\n' ||
buffer[line->newlineStart - 1] == '\r')) {
--line->newlineStart;
}
return 1;
}
/* Recognize the supported Doxygen commands. */
static void parse_line(Line *line) {
const char *text = line->text;
const size_t end = line->newlineStart;
size_t pos = 0;
while (pos < end && (text[pos] == ' ' || text[pos] == '\t'))
++pos;
if (pos == end || text[pos] != '*')
return;
++pos;
/* Require whitespace after the comment marker. */
if (pos == end || (text[pos] != ' ' && text[pos] != '\t'))
return;
while (pos < end && (text[pos] == ' ' || text[pos] == '\t'))
++pos;
for (size_t index = 0; index < COMMAND_COUNT; ++index) {
const Command *command = &commands[index];
size_t nameLength = strlen(command->name);
if (nameLength > end - pos)
continue;
if (strncmp(text + pos, command->name, nameLength) != 0)
continue;
size_t start = pos + nameLength;
if (start == end || !isspace((unsigned char)text[start]))
continue;
while (start < end && isspace((unsigned char)text[start]))
++start;
size_t contentEnd = end;
while (contentEnd > start &&
isspace((unsigned char)text[contentEnd - 1])) {
--contentEnd;
}
if (start == contentEnd)
continue;
line->commandIndex = (int)index;
line->prefixLength = pos;
line->contentStart = start;
line->contentLength = contentEnd - start;
return;
}
}
static void append_line(LineArray *lines, Line line) {
if (lines->count == lines->capacity) {
size_t capacity = lines->capacity ? lines->capacity * 2 : 128;
lines->data = checked_realloc(
lines->data,
capacity * sizeof(Line)
);
lines->capacity = capacity;
}
lines->data[lines->count++] = line;
}
static size_t generated_length(
const Line *line,
const Command *command,
int first,
int last
) {
size_t length = line->prefixLength +
strlen("<li></li>") +
line->contentLength;
if (first) {
length += strlen("<table class=\"\"><tr><th></th></tr><tr><td><ul>");
length += strlen(command->cssClass);
length += strlen(command->title);
}
if (last)
length += strlen("</ul></td></tr></table>");
return length;
}
static void write_original(const Line *line) {
fwrite(line->text, 1, line->length, stdout);
}
static void write_transformed(
const Line *line,
const Command *command,
int first,
int last
) {
fwrite(line->text, 1, line->prefixLength, stdout);
if (first) {
printf(
"<table class=\"%s\"><tr><th>%s</th></tr><tr><td><ul>",
command->cssClass,
command->title
);
}
fputs("<li>", stdout);
fwrite(
line->text + line->contentStart,
1,
line->contentLength,
stdout
);
fputs("</li>", stdout);
if (last)
fputs("</ul></td></tr></table>", stdout);
fwrite(
line->text + line->newlineStart,
1,
line->length - line->newlineStart,
stdout
);
}
static void transform(const LineArray *lines) {
size_t index = 0;
while (index < lines->count) {
const Line *line = &lines->data[index];
if (line->commandIndex < 0) {
write_original(line);
++index;
continue;
}
size_t start = index;
int commandIndex = line->commandIndex;
while (index < lines->count &&
lines->data[index].commandIndex == commandIndex) {
++index;
}
size_t end = index;
const Command *command = &commands[commandIndex];
int overflow = 0;
for (size_t item = start; item < end; ++item) {
size_t length = generated_length(
&lines->data[item],
command,
item == start,
item == end - 1
);
if (length > MAX_LINE_LENGTH) {
overflow = 1;
break;
}
}
if (overflow) {
fprintf(
stderr,
"WARNING: %s group at input line %zu exceeds "
"%d characters after transformation; "
"original text retained.\n",
command->name,
start + 1,
MAX_LINE_LENGTH
);
}
for (size_t item = start; item < end; ++item) {
if (overflow) {
write_original(&lines->data[item]);
} else {
write_transformed(
&lines->data[item],
command,
item == start,
item == end - 1
);
}
}
}
}
int main(int argc, char **argv) {
// Validation
if (argc != 2) {
fprintf(stderr, "Usage: %s <source-file>\n", argv[0]);
return EXIT_FAILURE;
}
FILE *file = fopen(argv[1], "rb");
if (!file) {
fprintf(stderr, "ERROR: Cannot open '%s'.\n", argv[1]);
return EXIT_FAILURE;
}
// Parsing
LineArray lines = {0};
Line line;
while (read_line(file, &line)) {
parse_line(&line);
append_line(&lines, line);
}
// Clean up file handles
if (ferror(file)) {
fprintf(stderr, "ERROR: Failed reading '%s'.\n", argv[1]);
fclose(file);
return EXIT_FAILURE;
}
fclose(file);
// Transformation and output
transform(&lines);
// Cleanup memory
for (size_t index = 0; index < lines.count; ++index)
free(lines.data[index].text);
free(lines.data);
return ferror(stdout) ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@@ -0,0 +1,2 @@
project('doxygen-custom-sections-serif', 'c', version : '1.0.0')
executable('serif-custom-sections', 'custom_sections.c')