2021-08-07 21:38:53 +00:00
|
|
|
#include <ctype.h>
|
2021-07-30 14:55:37 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
/* input/output streams */
|
|
|
|
FILE *IN;
|
|
|
|
FILE *OUT;
|
|
|
|
|
2021-07-30 14:55:37 +00:00
|
|
|
/* util */
|
|
|
|
void
|
|
|
|
die(char *msg)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s\n", msg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* header/footer */
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
write_file(char *input)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-07-30 15:47:55 +00:00
|
|
|
FILE *f = fopen(input, "r");
|
|
|
|
char c;
|
|
|
|
while ((c = fgetc(f)) != EOF)
|
2021-10-21 16:56:41 +00:00
|
|
|
fputc(c, OUT);
|
2021-07-30 15:47:55 +00:00
|
|
|
fclose(f);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
2021-08-06 18:48:54 +00:00
|
|
|
/* remove dangerous characters */
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_sanitized_char(char c)
|
2021-08-06 18:48:54 +00:00
|
|
|
{
|
|
|
|
switch (c) {
|
|
|
|
case '<':
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<");
|
2021-08-06 18:48:54 +00:00
|
|
|
break;
|
|
|
|
case '>':
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, ">");
|
2021-08-06 18:48:54 +00:00
|
|
|
break;
|
|
|
|
case '&':
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "&");
|
2021-08-06 18:48:54 +00:00
|
|
|
break;
|
|
|
|
case '\'':
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "'");
|
2021-08-06 18:48:54 +00:00
|
|
|
break;
|
|
|
|
case '\"':
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, """);
|
2021-08-06 18:48:54 +00:00
|
|
|
break;
|
|
|
|
default:
|
2021-10-21 16:56:41 +00:00
|
|
|
fputc(c, OUT);
|
2021-08-06 18:48:54 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-10-21 21:57:39 +00:00
|
|
|
void
|
|
|
|
emit_sanitized_string(char *str)
|
|
|
|
{
|
|
|
|
while (*str != '\0') {
|
|
|
|
emit_sanitized_char(*str);
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read n bytes from IN */
|
|
|
|
void
|
|
|
|
read_n_bytes(size_t n, char *buf)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
buf[i] = fgetc(IN);
|
|
|
|
buf[i] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove occurrences of c from the right side of buf */
|
|
|
|
void
|
|
|
|
rstrip(char *buf, char c)
|
|
|
|
{
|
|
|
|
size_t i = strlen(buf) - 1;
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
if (buf[i] == c)
|
|
|
|
buf[i] = '\0';
|
|
|
|
else if (i <= 0 || buf[i] != c)
|
|
|
|
break;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-30 14:55:37 +00:00
|
|
|
/* headings */
|
|
|
|
int
|
2021-10-21 16:56:41 +00:00
|
|
|
heading_level(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
|
|
|
int heading_level = 1;
|
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
while (fgetc(IN) == '*')
|
2021-07-30 14:55:37 +00:00
|
|
|
heading_level++;
|
|
|
|
|
|
|
|
return heading_level;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_heading(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
int level = heading_level();
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<h%d>", level);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
|
|
|
char c;
|
2021-10-21 16:56:41 +00:00
|
|
|
while ((c = fgetc(IN)) != '\n')
|
|
|
|
emit_sanitized_char(c);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "</h%d>", level);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
|
|
|
/* We want the newline we used to break the loop to be picked up by the
|
|
|
|
* formatter again. */
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1, SEEK_CUR);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* links */
|
|
|
|
bool
|
2021-10-21 16:56:41 +00:00
|
|
|
external_link_p(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
|
|
|
char buf[5] = {0};
|
2021-10-21 16:56:41 +00:00
|
|
|
fgets(buf, 5, IN);
|
|
|
|
fseek(IN, -4, SEEK_CUR);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
|
|
|
return !strcmp(buf, "http");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2021-10-21 16:56:41 +00:00
|
|
|
internal_implicit_link_p(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
while (1) {
|
2021-10-21 16:56:41 +00:00
|
|
|
char c = fgetc(IN);
|
2021-07-30 14:55:37 +00:00
|
|
|
if (c == EOF) {
|
|
|
|
die("End of file encountered while parsing link.");
|
|
|
|
}
|
|
|
|
else if (c == '}') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (c == ' ') {
|
|
|
|
ret = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, count, SEEK_CUR);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-07-31 15:37:42 +00:00
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
get_linkname(char *out)
|
2021-07-31 15:37:42 +00:00
|
|
|
{
|
|
|
|
char c;
|
2021-10-21 16:56:41 +00:00
|
|
|
while ((c = fgetc(IN)) != '}') {
|
2021-07-31 15:37:42 +00:00
|
|
|
if (c == EOF)
|
|
|
|
die("End of file encountered while parsing link name.");
|
|
|
|
else if (c == '\n')
|
|
|
|
c = ' ';
|
|
|
|
*(out++) = c;
|
|
|
|
}
|
|
|
|
*out = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
get_link(char *out)
|
2021-07-31 15:37:42 +00:00
|
|
|
{
|
|
|
|
char c;
|
2021-08-21 17:52:20 +00:00
|
|
|
|
|
|
|
/* some links add the initial { for some reason */
|
2021-10-21 16:56:41 +00:00
|
|
|
if (fgetc(IN) != '{')
|
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-08-21 17:52:20 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
while (((c = fgetc(IN)) != ' ') && c != '\n' && c != '}') {
|
2021-07-31 15:37:42 +00:00
|
|
|
if (c == EOF)
|
|
|
|
die("End of file encountered while parsing link.");
|
|
|
|
*(out)++ = c;
|
|
|
|
}
|
|
|
|
*out = '\0';
|
|
|
|
}
|
|
|
|
|
2021-07-30 14:55:37 +00:00
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_external_link(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-07-31 15:37:42 +00:00
|
|
|
char link[1024];
|
2021-10-21 16:56:41 +00:00
|
|
|
get_link(link);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-07-31 15:37:42 +00:00
|
|
|
char linkname[1024];
|
2021-10-21 16:56:41 +00:00
|
|
|
get_linkname(linkname);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<a href=\"%s\" rel=\"external\">%s</a>", link, linkname);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_internal_implicit_link(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1, SEEK_CUR);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-08-21 17:52:20 +00:00
|
|
|
char link[1024];
|
2021-07-31 15:37:42 +00:00
|
|
|
char page[1024];
|
2021-10-21 16:56:41 +00:00
|
|
|
get_link(link);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-08-21 17:52:20 +00:00
|
|
|
memcpy(page, link, 1024);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-08-21 17:52:20 +00:00
|
|
|
for (size_t i = 0; link[i] != '\0'; i++)
|
|
|
|
if (link[i] >= 'A' && link[i] <= 'Z') link[i] = link[i] + 32;
|
|
|
|
|
|
|
|
for (size_t i = 0; page[i] != '\0'; i++)
|
|
|
|
if (page[i] == '-') page[i] = ' ';
|
2021-07-31 16:01:59 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<a href=\"%s.html\">%s</a>", link, page);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
2021-07-31 17:43:05 +00:00
|
|
|
bool
|
|
|
|
explicit_link_extension(char *link)
|
|
|
|
{
|
|
|
|
while (*link != '\0') {
|
|
|
|
if (*link++ == '.')
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-07-30 14:55:37 +00:00
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_internal_explicit_link(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1, SEEK_CUR);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-07-31 15:37:42 +00:00
|
|
|
char page[1024];
|
2021-10-21 16:56:41 +00:00
|
|
|
get_link(page);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-07-31 15:37:42 +00:00
|
|
|
char linkname[1024];
|
2021-10-21 16:56:41 +00:00
|
|
|
get_linkname(linkname);
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-07-31 17:43:05 +00:00
|
|
|
if (explicit_link_extension(page))
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<a href=\"%s\">%s</a>", page, linkname);
|
2021-07-31 17:43:05 +00:00
|
|
|
else
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<a href=\"%s.html\">%s</a>", page, linkname);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_link(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
if (external_link_p())
|
|
|
|
emit_external_link();
|
|
|
|
else if (internal_implicit_link_p())
|
|
|
|
emit_internal_implicit_link();
|
2021-07-30 14:55:37 +00:00
|
|
|
else
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_internal_explicit_link();
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-31 11:58:18 +00:00
|
|
|
/* code blocks */
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_code_block(char firstc)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
char nextc = fgetc(IN);
|
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-08-06 22:49:23 +00:00
|
|
|
|
|
|
|
bool pre = firstc == '\n' && nextc =='\n';
|
|
|
|
|
2021-08-06 19:41:17 +00:00
|
|
|
/* if this code block is on a separate line, create a <pre>. otherwise, it
|
|
|
|
* is inlined in a paragraph and we want a <code>. */
|
2021-08-06 22:49:23 +00:00
|
|
|
if (pre)
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<pre>");
|
2021-08-06 19:41:17 +00:00
|
|
|
else
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<code>");
|
2021-08-06 18:48:54 +00:00
|
|
|
|
2021-08-06 21:47:28 +00:00
|
|
|
for (;;) {
|
2021-10-21 16:56:41 +00:00
|
|
|
char c = fgetc(IN);
|
2021-08-06 21:47:28 +00:00
|
|
|
|
|
|
|
if (c == '`') {
|
2021-10-21 16:56:41 +00:00
|
|
|
if (fgetc(IN) == '`')
|
2021-08-06 21:47:28 +00:00
|
|
|
break;
|
|
|
|
else
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-08-06 21:47:28 +00:00
|
|
|
}
|
|
|
|
|
2021-07-31 11:58:18 +00:00
|
|
|
if (c == EOF)
|
|
|
|
die("Unexpected EOF while converting code block.");
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_sanitized_char(c);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
2021-08-06 18:48:54 +00:00
|
|
|
|
2021-08-06 22:49:23 +00:00
|
|
|
if (pre)
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "</pre>");
|
2021-08-06 19:41:17 +00:00
|
|
|
else
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "</code>");
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
|
2021-08-06 18:48:54 +00:00
|
|
|
/* blockquotes */
|
2021-08-01 11:24:33 +00:00
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_blockquote(void)
|
2021-08-01 11:24:33 +00:00
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<blockquote>");
|
2021-08-06 18:48:54 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
char c = fgetc(IN), lastc = 'a';
|
2021-08-06 18:48:54 +00:00
|
|
|
for(;;) {
|
|
|
|
if (lastc == '\n' && c != '>')
|
|
|
|
break;
|
|
|
|
else if (lastc == '>' && c == ' ')
|
|
|
|
;
|
|
|
|
else if (lastc == '\n' && c == '>')
|
2021-10-21 16:56:41 +00:00
|
|
|
fputc(' ', OUT);
|
2021-08-06 18:48:54 +00:00
|
|
|
else if (c != '\n')
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_sanitized_char(c);
|
2021-08-06 18:48:54 +00:00
|
|
|
lastc = c;
|
2021-10-21 16:56:41 +00:00
|
|
|
c = fgetc(IN);
|
2021-08-01 11:24:33 +00:00
|
|
|
}
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-08-06 18:48:54 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "</blockquote>\n");
|
2021-08-01 11:24:33 +00:00
|
|
|
}
|
2021-07-31 11:58:18 +00:00
|
|
|
|
2021-08-07 21:38:53 +00:00
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_image(void)
|
2021-08-07 21:38:53 +00:00
|
|
|
{
|
|
|
|
char buf[80];
|
|
|
|
char *bufptr = buf;
|
|
|
|
|
|
|
|
for(;;) {
|
2021-10-21 16:56:41 +00:00
|
|
|
char c = fgetc(IN);
|
2021-08-07 21:38:53 +00:00
|
|
|
if (isspace(c))
|
|
|
|
break;
|
|
|
|
else if (c == EOF)
|
|
|
|
die("EOF encountered while parsing image filename.");
|
|
|
|
else
|
|
|
|
*(bufptr++) = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bufptr = '\0';
|
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "<img src=\"../resources/img/%s\" />", buf);
|
2021-08-07 21:38:53 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-08-07 21:38:53 +00:00
|
|
|
}
|
|
|
|
|
2021-10-21 21:57:39 +00:00
|
|
|
void
|
|
|
|
emit_table(void)
|
|
|
|
{
|
|
|
|
char buf[256] = {0};
|
|
|
|
char *bufptr = buf;
|
|
|
|
|
|
|
|
fprintf(OUT, "<table border=\"1\"><tbody>\n");
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
read_n_bytes(4, buf);
|
|
|
|
if (!strcmp("===\n", buf)) {
|
2021-10-22 18:21:59 +00:00
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-10-21 21:57:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fseek(IN, -4L, SEEK_CUR);
|
|
|
|
memset(buf, '\0', 256);
|
|
|
|
fprintf(OUT, "<tr>\n");
|
|
|
|
char c;
|
|
|
|
while ((c = fgetc(IN)) != '\n') {
|
|
|
|
if (c == '|') {
|
|
|
|
rstrip(buf, ' ');
|
|
|
|
fprintf(OUT, "<td>");
|
|
|
|
emit_sanitized_string(buf);
|
|
|
|
fprintf(OUT, "</td>\n");
|
|
|
|
memset(buf, '\0', 256);
|
|
|
|
bufptr = buf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*(bufptr++) = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rstrip(buf, ' ');
|
|
|
|
fprintf(OUT, "<td>");
|
|
|
|
emit_sanitized_string(buf);
|
|
|
|
fprintf(OUT, "</td>\n");
|
|
|
|
fprintf(OUT, "</tr>\n");
|
|
|
|
bufptr = buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(OUT, "</tbody></table>\n");
|
|
|
|
}
|
|
|
|
|
2021-07-30 14:55:37 +00:00
|
|
|
/* main formatter */
|
|
|
|
void
|
2021-10-21 16:56:41 +00:00
|
|
|
format(void)
|
2021-07-30 14:55:37 +00:00
|
|
|
{
|
|
|
|
char c, lastc = '\n';
|
|
|
|
|
2021-08-07 15:20:37 +00:00
|
|
|
char *em_tags[] = {"<em>", "</em>"};
|
|
|
|
int in_em = 0; /* boolean used as index, therefore it's an int */
|
2021-09-29 17:55:10 +00:00
|
|
|
bool last_was_paragraph = false;
|
2021-08-07 15:20:37 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
while ((c = fgetc(IN)) != EOF) {
|
2021-07-31 14:29:39 +00:00
|
|
|
if (c == '\\') { /* escaped character */
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_sanitized_char(fgetc(IN));
|
2021-07-31 11:58:18 +00:00
|
|
|
}
|
|
|
|
else if (c == '*' && lastc == '\n') { /* heading */
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_heading();
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
else if (c == '{') { /* link */
|
2021-09-29 17:55:10 +00:00
|
|
|
if (!last_was_paragraph && lastc == '\n')
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "\n<p>");
|
|
|
|
emit_link();
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
2021-08-07 21:38:53 +00:00
|
|
|
else if (c == '$') { /* maybe image */
|
|
|
|
char buf[5];
|
2021-10-21 21:57:39 +00:00
|
|
|
read_n_bytes(4, buf);
|
2021-08-07 21:38:53 +00:00
|
|
|
|
|
|
|
if (!strcmp(buf, "img ")) {
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_image();
|
2021-08-07 21:38:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -4L, SEEK_CUR);
|
|
|
|
emit_sanitized_char(c);
|
2021-08-07 21:38:53 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-07 15:20:37 +00:00
|
|
|
else if (c == '_') {
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "%s", em_tags[in_em]);
|
2021-08-07 15:20:37 +00:00
|
|
|
in_em = !in_em;
|
|
|
|
}
|
2021-08-06 21:47:28 +00:00
|
|
|
else if (c == '`') { /* code block */
|
2021-10-21 16:56:41 +00:00
|
|
|
if (fgetc(IN) == '`')
|
|
|
|
emit_code_block(lastc);
|
2021-08-06 21:47:28 +00:00
|
|
|
else
|
2021-10-21 16:56:41 +00:00
|
|
|
fseek(IN, -1L, SEEK_CUR);
|
2021-07-31 11:58:18 +00:00
|
|
|
}
|
2021-08-06 18:48:54 +00:00
|
|
|
else if (c == '>' && lastc == '\n') { /* quote */
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_blockquote();
|
2021-08-06 18:48:54 +00:00
|
|
|
}
|
2021-10-21 21:57:39 +00:00
|
|
|
else if (c == '=' && lastc == '\n') { /* maybe table */
|
|
|
|
char buf[4];
|
|
|
|
read_n_bytes(3, buf);
|
|
|
|
|
|
|
|
if (!strcmp(buf, "==\n")) {
|
|
|
|
emit_table();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fseek(IN, -3L, SEEK_CUR);
|
|
|
|
emit_sanitized_char(c);
|
|
|
|
}
|
|
|
|
}
|
2021-09-29 17:55:10 +00:00
|
|
|
else if (lastc == '\n' && c == '\n') { /* new paragraph */
|
2021-10-21 16:56:41 +00:00
|
|
|
fprintf(OUT, "\n<p>");
|
2021-09-29 17:55:10 +00:00
|
|
|
last_was_paragraph = true;
|
|
|
|
lastc = c;
|
|
|
|
continue;
|
2021-07-31 11:58:18 +00:00
|
|
|
}
|
2021-07-31 14:29:39 +00:00
|
|
|
else if (c == '\n') { /* just a new line, same paragraph */
|
2021-10-21 16:56:41 +00:00
|
|
|
fputc(' ', OUT);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
else {
|
2021-10-21 16:56:41 +00:00
|
|
|
emit_sanitized_char(c);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
lastc = c;
|
2021-09-29 17:55:10 +00:00
|
|
|
last_was_paragraph = false;
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
basename(char *in, char *out, char delim)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; in[i] != delim; i++)
|
|
|
|
out[i] = in[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* entrypoint */
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
2021-10-21 16:56:41 +00:00
|
|
|
if (argc < 2)
|
2021-07-30 14:55:37 +00:00
|
|
|
die("No filename provided, exiting.");
|
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
IN = fopen(argv[1], "r");
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-07-30 15:12:36 +00:00
|
|
|
if (argc == 2) {
|
|
|
|
char bn[80] = {0};
|
|
|
|
basename(argv[1], bn, '.');
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-08-01 19:46:06 +00:00
|
|
|
char out_name[85] = {0};
|
2021-07-30 15:12:36 +00:00
|
|
|
sprintf(out_name, "%s.html", bn);
|
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
OUT = fopen(out_name, "w");
|
2021-07-30 15:12:36 +00:00
|
|
|
}
|
|
|
|
else {
|
2021-10-21 16:56:41 +00:00
|
|
|
OUT = fopen(argv[2], "w");
|
2021-07-30 15:12:36 +00:00
|
|
|
}
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
write_file("resources/header.html");
|
|
|
|
format();
|
|
|
|
write_file("resources/footer.html");
|
2021-07-30 14:55:37 +00:00
|
|
|
|
2021-10-21 16:56:41 +00:00
|
|
|
fclose(IN);
|
|
|
|
fclose(OUT);
|
2021-07-30 14:55:37 +00:00
|
|
|
}
|