From 4af753d591e61a7380735e03a8658fb8949e0448 Mon Sep 17 00:00:00 2001
From: WormHeamer
Date: Sat, 8 Mar 2025 16:45:17 -0500
Subject: initial commit
---
main.c | 409 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 409 insertions(+)
create mode 100644 main.c
(limited to 'main.c')
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..8dc8a6e
--- /dev/null
+++ b/main.c
@@ -0,0 +1,409 @@
+#define _POSIX_C_SOURCE 200809L
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define ARENA_IMPL
+#include "str.h"
+#include "arena.h"
+#define ARGS_IMPL
+#include "args.h"
+
+int read_all(FILE *f, Str *buf, Arena *a) {
+ if (!f) return -1;
+ if (isatty(fileno(f))) {
+ buf->s = a->beg;
+ buf->n = fread(a->beg, 1, (uintptr_t)(a->end - a->beg) - 1, f);
+ a->beg += buf->n;
+ } else {
+ fseek(f, 0, SEEK_END);
+ long ofs = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf->n = ofs;
+ buf->s = new_arr(a, char, buf->n);
+ if ((isize)fread(buf->s, 1, buf->n, f) != buf->n) return -1;
+ }
+ return ferror(f) ? -1 : 0;
+}
+
+int next_line(Str *src, Str *line) {
+ if (src->n < 1) return 0;
+ line->s = src->s;
+ char *newln = memchr(src->s, '\n', src->n);
+ line->n = newln ? newln - src->s : src->n;
+ src->s += line->n + 1;
+ src->n -= line->n + 1;
+ return 1;
+}
+
+void str_putf(Str s, FILE *f) {
+ fwrite(s.s, 1, s.n, f);
+}
+
+void str_put(Str s) {
+ str_putf(s, stdout);
+}
+
+char to_xdigit(int x) {
+ if (x > 9) {
+ return 'A' + (x - 10);
+ } else {
+ return '0' + x;
+ }
+}
+
+void str_cat_uri(Str *s, Str uri, Arena *a) {
+ str_catc(s, '\'', a);
+ for (isize i = 0; i < uri.n; i++) {
+ char c = uri.s[i];
+ if (c == '\'' || c == '%') {
+ str_catc(s, '%', a);
+ str_catc(s, to_xdigit((c & 0xff) >> 4), a);
+ str_catc(s, to_xdigit(c & 0xf), a);
+ } else {
+ str_catc(s, c, a);
+ }
+ }
+ str_catc(s, '\'', a);
+}
+
+void str_cat_html(Str *s, Str uri, Arena *a) {
+ for (isize i = 0; i < uri.n; i++) {
+ char c = uri.s[i];
+ switch (c) {
+ case '&': str_cat(s, S("&"), a); break;
+ case '<': str_cat(s, S("<"), a); break;
+ case '>': str_cat(s, S(">"), a); break;
+ default: str_catc(s, c, a); break;
+ }
+ }
+}
+
+int is_ol_item(Str s) {
+ Str h = str_cut(s, '.').head;
+ if (h.n < 1) return 0;
+ for (isize i = 0; i < h.n; i++) {
+ if (!(h.s[i] >= '0' && h.s[i] <= '9')) return 0;
+ }
+ return 1;
+}
+
+typedef enum {
+ LINE_BLANK, LINE_PARA,
+ LINE_LINK, LINE_FIGURE,
+ LINE_UL, LINE_OL,
+ LINE_HDR1, LINE_HDR2, LINE_HDR3, LINE_CODE,
+ LINE_BQUOT,
+} LineMode;
+
+LineMode lm_chg(LineMode from, LineMode to, Str *out, Arena *a) {
+ static Str op[] = {
+ [LINE_BLANK] = S(""),
+ [LINE_PARA] = S(""),
+ [LINE_LINK] = S("
\n- "),
+ [LINE_FIGURE] = S(""),
+ [LINE_UL] = S("
\n- "),
+ [LINE_OL] = S("
\n- "),
+ [LINE_HDR1] = S("
"),
+ [LINE_HDR2] = S(""),
+ [LINE_HDR3] = S(""),
+ [LINE_CODE] = S(""),
+ [LINE_BQUOT] = S(""),
+ };
+ static Str cl[] = {
+ [LINE_BLANK] = S(""),
+ [LINE_PARA] = S("
"),
+ [LINE_LINK] = S("\n"),
+ [LINE_FIGURE] = S(""),
+ [LINE_UL] = S("\n"),
+ [LINE_OL] = S("\n"),
+ [LINE_HDR1] = S(""),
+ [LINE_HDR2] = S(""),
+ [LINE_HDR3] = S(""),
+ [LINE_CODE] = S(""),
+ [LINE_BQUOT] = S(""),
+ };
+ static Str cont[] = {
+ [LINE_BLANK] = S(""),
+ [LINE_PARA] = S("
\n"),
+ [LINE_FIGURE] = S("\n"),
+ [LINE_LINK] = S("\n"),
+ [LINE_UL] = S("\n"),
+ [LINE_OL] = S("\n"),
+ [LINE_HDR1] = S("\n