#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"
#define ARENA(n, sz) Arena n; { static char arena_backarr[sz];\
n.beg = arena_backarr; n.end = arena_backarr + sizeof(arena_backarr);\
__asm("":"+r"(n.beg)); __asm("":"+r"(n.end)); }
int read_all(FILE *f, Str *buf, Arena *a) {
if (!f) return -1;
buf->s = a->beg;
buf->n = fread(a->beg, 1, (uintptr_t)(a->end - a->beg) - 1, f);
a->beg += buf->n;
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) {
#undef S
#define S(s) {s,sizeof(s)-1}
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