~strahinja/slweb

92a411ceec8bdb2c0b36444d99df81085cb1dcb8 — Страхиња Радић 6 months ago 26c681b v0.4.6
BOOL -> int; small adjustments
4 files changed, 352 insertions(+), 337 deletions(-)

A AUTHORS
M defs.h
M slweb.c
M uninstall.do
A AUTHORS => AUTHORS +1 -0
@@ 0,0 1,1 @@
Strahinya Radich <contact@strahinja.org>

M defs.h => defs.h +70 -78
@@ 23,61 23,52 @@
#include "utf8.h"

#define COPYRIGHTYEAR "2020, 2021, 2022"
#define MADEBY_URL    "https://strahinja.srht.site/slweb"
#define MADEBY_URL    "https://strahinja.srht.site/slweb/"

#define BUFSIZE       1024
#define KEYSIZE       256
#define BUFSIZE	      1024
#define KEYSIZE	      256
#define SMALL_ARGSIZE 256
#define DATEBUFSIZE   12

static const char timestamp_format[]     = "d.m.y";
static const char timestamp_format[]	 = "d.m.y";
static const char timestamp_output_ext[] = ".html";

static const char CMD_GIT_LOG[]          = "xargs";
static const char* CMD_GIT_LOG_ARGS[]    
    = { "xargs", "-I{}", "git", "log", "-1", 
        "--pretty=format:{} %h %ci (%cn) %d", NULL };
static const char CMD_GIT_LOG[]	      = "xargs";
static const char* CMD_GIT_LOG_ARGS[] = {"xargs", "-I{}", "git", "log", "-1",
	"--pretty=format:{} %h %ci (%cn) %d", NULL};

static const char CMD_KATEX[]               = "katex";
static const char* CMD_KATEX_INLINE_ARGS[]  = { "katex", NULL };
static const char* CMD_KATEX_DISPLAY_ARGS[] = { "katex", "-d", NULL };
static const char CMD_KATEX[]		    = "katex";
static const char* CMD_KATEX_INLINE_ARGS[]  = {"katex", NULL};
static const char* CMD_KATEX_DISPLAY_ARGS[] = {"katex", "-d", NULL};

static const char* CMD_IDENTIFY = 
	"identify %s | sed -e's/.* \\([0-9]\\+\\)x\\([0-9]\\+\\)"
		".*/width=\"\\1\" height=\"\\2\"/g'";

typedef enum
{
    FALSE = 0,
    TRUE  = 1
} BOOL;
static const char* CMD_IDENTIFY
	= "identify %s | sed -e's/.* \\([0-9]\\+\\)x\\([0-9]\\+\\)"
	  ".*/width=\"\\1\" height=\"\\2\"/g'";

#define ALL(var, mask) (((var) & (mask)) == (mask))
#define ANY(var, mask) (((var) & (mask)) != 0)
#define IN(var, mask) ALL(var, mask)
#define IN(var, mask)  ALL(var, mask)

#define MIN(a,b) ((a < b) ? (a) : (b))
#define MIN(a, b) ((a < b) ? (a) : (b))

typedef unsigned char      UBYTE;
typedef unsigned long      ULONG;
typedef unsigned char UBYTE;
typedef unsigned long ULONG;
typedef unsigned long long ULLONG;

typedef enum
{
    CMD_NONE,
    CMD_BODY_ONLY,
    CMD_BASEDIR,
    CMD_HELP,
    CMD_LINK_PREFIX,
    CMD_VERSION
typedef enum {
	CMD_NONE,
	CMD_BODY_ONLY,
	CMD_BASEDIR,
	CMD_HELP,
	CMD_LINK_PREFIX,
	CMD_VERSION
} Command;

typedef struct
{
    u8* key;
    u8* value;
    size_t   value_size;
    BOOL     seen;    /* for use with macros */
typedef struct {
	u8* key;
	u8* value;
	size_t value_size;
	int seen; /* for use with macros */
} KeyValue;

typedef int (*csv_callback_t)(FILE* output, u8** csv_header, u8** csv_register);


@@ 87,54 78,55 @@ typedef int (*tsv_callback_t)(FILE* output, u8** tsv_header, u8** tsv_register);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-const-variable"
#endif
#define MAX_HEADING_LEVEL  4
#define MAX_CSV_REGISTERS  9
#define MAX_TSV_REGISTERS  9

#define ST_NONE                0
#define ST_YAML                1
#define ST_YAML_VAL            ((ULLONG)1 << 1)
#define ST_PARA_OPEN           ((ULLONG)1 << 2)
#define ST_TAG                 ((ULLONG)1 << 3)
#define ST_HEADING             ((ULLONG)1 << 4)
#define ST_HEADING_TEXT        ((ULLONG)1 << 5)
#define ST_BOLD                ((ULLONG)1 << 6)
#define ST_ITALIC              ((ULLONG)1 << 7)
#define ST_PRE                 ((ULLONG)1 << 8)
#define ST_CODE                ((ULLONG)1 << 9)
#define ST_BLOCKQUOTE          ((ULLONG)1 << 10)
#define ST_LINK                ((ULLONG)1 << 11)
#define MAX_HEADING_LEVEL 4
#define MAX_CSV_REGISTERS 9
#define MAX_TSV_REGISTERS 9

#define ST_NONE		       0
#define ST_YAML		       1
#define ST_YAML_VAL	       ((ULLONG)1 << 1)
#define ST_PARA_OPEN	       ((ULLONG)1 << 2)
#define ST_TAG		       ((ULLONG)1 << 3)
#define ST_HEADING	       ((ULLONG)1 << 4)
#define ST_HEADING_TEXT	       ((ULLONG)1 << 5)
#define ST_BOLD		       ((ULLONG)1 << 6)
#define ST_ITALIC	       ((ULLONG)1 << 7)
#define ST_PRE		       ((ULLONG)1 << 8)
#define ST_CODE		       ((ULLONG)1 << 9)
#define ST_BLOCKQUOTE	       ((ULLONG)1 << 10)
#define ST_LINK		       ((ULLONG)1 << 11)
#define ST_LINK_SECOND_ARG     ((ULLONG)1 << 12)
#define ST_LINK_SECOND_ARG_END ((ULLONG)1 << 13)
#define ST_LINK_SPAN           ((ULLONG)1 << 14)
#define ST_LINK_MACRO          ((ULLONG)1 << 15)
#define ST_IMAGE               ((ULLONG)1 << 16)
#define ST_LINK_SPAN	       ((ULLONG)1 << 14)
#define ST_LINK_MACRO	       ((ULLONG)1 << 15)
#define ST_IMAGE	       ((ULLONG)1 << 16)
#define ST_IMAGE_SECOND_ARG    ((ULLONG)1 << 17)
#define ST_MACRO_BODY          ((ULLONG)1 << 18)
#define ST_CSV_BODY            ((ULLONG)1 << 19)
#define ST_TSV_BODY            ((ULLONG)1 << 20)
#define ST_HTML_TAG            ((ULLONG)1 << 21)
#define ST_KBD                 ((ULLONG)1 << 22)
#define ST_LIST                ((ULLONG)1 << 23)
#define ST_NUMLIST             ((ULLONG)1 << 24)
#define ST_FOOTNOTE            ((ULLONG)1 << 25)
#define ST_MACRO_BODY	       ((ULLONG)1 << 18)
#define ST_CSV_BODY	       ((ULLONG)1 << 19)
#define ST_TSV_BODY	       ((ULLONG)1 << 20)
#define ST_HTML_TAG	       ((ULLONG)1 << 21)
#define ST_KBD		       ((ULLONG)1 << 22)
#define ST_LIST		       ((ULLONG)1 << 23)
#define ST_NUMLIST	       ((ULLONG)1 << 24)
#define ST_FOOTNOTE	       ((ULLONG)1 << 25)
#define ST_FOOTNOTE_TEXT       ((ULLONG)1 << 26)
#define ST_INLINE_FOOTNOTE     ((ULLONG)1 << 27)
#define ST_FORMULA             ((ULLONG)1 << 28)
#define ST_FORMULA	       ((ULLONG)1 << 28)
#define ST_DISPLAY_FORMULA     ((ULLONG)1 << 29)
#define ST_TABLE_HEADER        ((ULLONG)1 << 30)
#define ST_TABLE_LINE          ((ULLONG)1 << 31)
#define ST_TABLE               ((ULLONG)1 << 32)
#define ST_STRIKE              ((ULLONG)1 << 33)

#define ST_CS_NONE          0
#define ST_CS_HEADER        1
#define ST_CS_REGISTER      (1 << 2)
#define ST_CS_QUOTE         (1 << 3)
#define ST_CS_COND          (1 << 4)
#define ST_TABLE_HEADER	       ((ULLONG)1 << 30)
#define ST_TABLE_LINE	       ((ULLONG)1 << 31)
#define ST_TABLE	       ((ULLONG)1 << 32)
#define ST_STRIKE	       ((ULLONG)1 << 33)
#define ST_ENT		       ((ULLONG)1 << 33)

#define ST_CS_NONE	    0
#define ST_CS_HEADER	    1
#define ST_CS_REGISTER	    (1 << 2)
#define ST_CS_QUOTE	    (1 << 3)
#define ST_CS_COND	    (1 << 4)
#define ST_CS_COND_NONEMPTY (1 << 5)
#define ST_CS_COND_EMPTY    (1 << 6)
#define ST_CS_ESCAPE        (1 << 7)
#define ST_CS_ESCAPE	    (1 << 7)
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

M slweb.c => slweb.c +280 -258
@@ 4,7 4,7 @@

static size_t lineno		      = 0;
static size_t colno		      = 1;
static BOOL output_firstcol	      = TRUE;
static int output_firstcol	      = 1;
static const char* input_filename     = NULL;
static char* input_dirname	      = NULL;
static char* basedir		      = NULL;


@@ 165,29 165,53 @@ slweb_cleanup()
	return 0;
}

int add_css(FILE* output, BOOL output_yaml);
int add_css(FILE* output, int output_yaml);
int simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
	KeyValue** pvars);
int slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
	const BOOL body_only, const BOOL read_yaml_macros_and_links);
	const int body_only, const int read_yaml_macros_and_links);

BOOL
int
startswith(const char* s, const char* what)
{
	if (!s || !what)
		return FALSE;
		return 0;

	do
	{
		if (*s++ != *what++)
			return FALSE;
			return 0;
	} while (*s && *what);

	return !*what;
}

int
endswith(const char* s, const char* what)
{
	const char* ps	  = s;
	const char* pwhat = what;

	if (!s || !what)
		return 0;

	if (!*what)
		return 1;

	while (*ps)
		ps++;
	while (*pwhat)
		pwhat++;

	while (ps != s && pwhat != what)
		if (*ps-- != *pwhat--)
			return 0;

	return *ps == *pwhat && pwhat == what;
}

u8*
get_value(KeyValue* list, const size_t list_count, const u8* key, BOOL* seen)
get_value(KeyValue* list, const size_t list_count, const u8* key, int* seen)
{
	if (!list)
		return NULL;


@@ 199,7 223,7 @@ get_value(KeyValue* list, const size_t list_count, const u8* key, BOOL* seen)
			if (seen)
			{
				*seen	    = plist->seen;
				plist->seen = TRUE;
				plist->seen = 1;
			}
			return plist->value;
		}


@@ 339,7 363,7 @@ print_output(FILE* output, const char* fmt, ...)

int
print_command(FILE* output, const char* command, const u8* pass_arguments[],
	const u8* pipe_arguments[], const BOOL strip_newlines)
	const u8* pipe_arguments[], const int strip_newlines)
{
	if (!command || !pass_arguments)
		exit(error(EINVAL, (u8*)"print_command: Invalid argument"));


@@ 406,7 430,7 @@ print_command(FILE* output, const char* command, const u8* pass_arguments[],
			strip_newlines ? "" : "\n");
	}
	if (!strip_newlines)
		output_firstcol = TRUE;
		output_firstcol = 1;
	free(cmd_output_line);

	fclose(cmd_output);


@@ 535,10 559,10 @@ process_git_log(FILE* output)

	print_output(output, "<div id=\"git-log\">\nPrevious commit:\n");
	result = print_command(output, CMD_GIT_LOG,
		(const u8**)CMD_GIT_LOG_ARGS, (const u8**)pipe_args, FALSE);
		(const u8**)CMD_GIT_LOG_ARGS, (const u8**)pipe_args, 0);

	print_output(output, "</div><!--git-log-->\n");
	output_firstcol = TRUE;
	output_firstcol = 1;

	free(basename);



@@ 546,7 570,7 @@ process_git_log(FILE* output)
}

int
process_stylesheet(FILE* output, const u8* css_filename, BOOL output_yaml)
process_stylesheet(FILE* output, const u8* css_filename, int output_yaml)
{
	if (output_yaml)
		print_output(output, "stylesheet: %s\n", css_filename);


@@ 554,12 578,12 @@ process_stylesheet(FILE* output, const u8* css_filename, BOOL output_yaml)
		print_output(output,
			"<link rel=\"stylesheet\" href=\"%s\" />\n",
			css_filename);
	output_firstcol = TRUE;
	output_firstcol = 1;
	return 0;
}

int
process_inline_stylesheet(FILE* output, const u8* css_filename, BOOL output_yaml)
process_inline_stylesheet(FILE* output, const u8* css_filename, int output_yaml)
{
	FILE* css		 = NULL;
	u8* bufline		 = NULL;


@@ 584,7 608,7 @@ process_inline_stylesheet(FILE* output, const u8* css_filename, BOOL output_yaml
	if (output_yaml)
	{
		print_output(output, "inline-stylesheet: %s\n", css_filename);
		output_firstcol = TRUE;
		output_firstcol = 1;
		goto process_inline_stylesheet_cleanup;
	}



@@ 598,7 622,7 @@ process_inline_stylesheet(FILE* output, const u8* css_filename, BOOL output_yaml
		print_output(output, "%s", bufline);
	}
	print_output(output, "</style>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;

process_inline_stylesheet_cleanup:
	free(css_pathname);


@@ 863,7 887,7 @@ read_tsv(FILE* output, const char* filename, tsv_callback_t callback)

int
process_tsv(FILE* output, const u8* arg_token,
	const BOOL read_yaml_macros_and_links, const BOOL end_tag)
	const int read_yaml_macros_and_links, const int end_tag)
{
	if (end_tag)
	{


@@ 1213,7 1237,7 @@ read_csv(FILE* output, const char* filename, csv_callback_t callback)

int
process_csv(FILE* output, const u8* arg_token,
	const BOOL read_yaml_macros_and_links, const BOOL end_tag)
	const int read_yaml_macros_and_links, const int end_tag)
{
	if (end_tag)
	{


@@ 1275,7 1299,7 @@ process_csv(FILE* output, const u8* arg_token,

int
process_include(FILE* output, const u8* token,
	const BOOL read_yaml_macros_and_links)
	const int read_yaml_macros_and_links)
{
	u8* ptoken		= (u8*)strchr((char*)token, ' ');
	char* include_filename	= NULL;


@@ 1388,9 1412,9 @@ process_include(FILE* output, const u8* token,
		state			= ST_NONE;

		/* First pass: read YAML, macros and links */
		result = slweb_parse(output, filename, buffer, TRUE, TRUE);
		result = slweb_parse(output, filename, buffer, 1, 1);

		add_css(child_output, TRUE);
		add_css(child_output, 1);
		if (result || read_yaml_macros_and_links)
			goto process_include_child_cleanup;



@@ 1399,7 1423,7 @@ process_include(FILE* output, const u8* token,
		current_inline_footnote = 0;

		/* Second pass: parse and output */
		result = slweb_parse(output, filename, buffer, TRUE, FALSE);
		result = slweb_parse(output, filename, buffer, 1, 0);

	process_include_child_cleanup:
		slweb_cleanup();


@@ 1435,10 1459,10 @@ process_list_item_end(FILE* output)
	{
		state &= ~ST_PARA_OPEN;
		fprintf(output, "</p>");
		output_firstcol = FALSE;
		output_firstcol = 0;
	}
	fprintf(output, "</li>");
	output_firstcol = FALSE;
	output_firstcol = 0;
	return 0;
}



@@ 1446,7 1470,7 @@ int
process_list_end(FILE* output)
{
	fprintf(output, "</ul>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;
	return 0;
}



@@ 1454,7 1478,7 @@ int
process_numlist_start(FILE* output)
{
	fprintf(output, "<ol>");
	output_firstcol = FALSE;
	output_firstcol = 0;
	return 0;
}



@@ 1462,7 1486,7 @@ int
process_numlist_end(FILE* output)
{
	fprintf(output, "</ol>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;
	return 0;
}



@@ 1525,7 1549,7 @@ int process_timestamp(FILE* output, const u8* link_prefix, const char* link,

int
process_incdir_subdir(FILE* output, const char* subdirname,
	const u8* link_prefix, const BOOL details_open, const u8* macro_body)
	const u8* link_prefix, const int details_open, const u8* macro_body)
{
	print_output(output, "<li>\n<details%s>\n<summary>",
		details_open ? " open" : "");


@@ 1603,8 1627,7 @@ process_incdir_subdir(FILE* output, const char* subdirname,
			state	    = ST_NONE;

			/* First pass: read YAML, macros and links */
			result = slweb_parse(output, filename, buffer, TRUE,
				TRUE);
			result = slweb_parse(output, filename, buffer, 1, 1);

			if (result)
			{


@@ 1623,8 1646,7 @@ process_incdir_subdir(FILE* output, const char* subdirname,
			current_inline_footnote = 0;

			/* Second pass: parse and output */
			result = slweb_parse(output, filename, buffer, TRUE,
				FALSE);
			result = slweb_parse(output, filename, buffer, 1, 0);

			state = saved_state;



@@ 1651,20 1673,17 @@ process_incdir_subdir(FILE* output, const char* subdirname,
	free(abs_subdirname);

	print_output(output, "</div>\n</details>\n</li>\n");
	output_firstcol = FALSE;
	output_firstcol = 0;
	return 0;
}

int
process_incdir(FILE* output, const u8* token, const u8* link_prefix,
	const BOOL read_yaml_macros_and_links)
	const int read_yaml_macros_and_links)
{
	if (read_yaml_macros_and_links)
		return 0;

	u8* saveptr = NULL;
	/* skipping the first token (incdir) */
	u8* arg		= (u8*)strtok_r((char*)token, " ", (char**)&saveptr);
	u8* arg		= NULL;
	size_t arg_len	= 0;
	long num	= 5;
	u8* macro_body	= NULL;


@@ 1672,8 1691,12 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
	struct dirent** namelist;
	struct dirent** pnamelist;
	long names_output;
	BOOL details_open = TRUE;
	int details_open = 1;

	if (read_yaml_macros_and_links)
		return 0;

	arg = (u8*)strtok_r((char*)token, " ", (char**)&saveptr);
	arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
	if (!arg)
		exit(error(1, (u8*)"incdir: Arguments required"));


@@ 1738,7 1761,7 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
	{
		process_incdir_subdir(output, (*pnamelist)->d_name, link_prefix,
			details_open, macro_body);
		details_open = FALSE;
		details_open = 0;
		pnamelist++;
		names_output++;
	}


@@ 1748,12 1771,12 @@ process_incdir(FILE* output, const u8* token, const u8* link_prefix,
	free(incdir);

	print_output(output, "</ul>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;

	return 0;
}

BOOL url_is_local(const char* url);
int url_is_local(const char* url);

int
process_timestamp(FILE* output, const u8* link_prefix, const char* link,


@@ 1804,7 1827,7 @@ process_timestamp(FILE* output, const u8* link_prefix, const char* link,
						  : "",
		link, permalink_macro ? (char*)permalink_macro : "",
		formatted_date);
	output_firstcol = TRUE;
	output_firstcol = 1;
process_timestamp_cleanup:

	free(formatted_date);


@@ 1816,14 1839,14 @@ process_timestamp_cleanup:

int
process_macro(FILE* output, const u8* token,
	const BOOL read_yaml_macros_and_links, const BOOL end_tag)
	const int read_yaml_macros_and_links, const int end_tag)
{
	if (!end_tag)
	{
		if (IN(state, ST_MACRO_BODY))
			exit(error(1, (u8*)"Macro undefined or nested"));

		BOOL seen      = FALSE;
		int seen       = 0;
		u8* macro_body = get_value(macros, macros_count, token + 1,
			read_yaml_macros_and_links ? NULL : &seen);



@@ 1869,7 1892,7 @@ process_macro(FILE* output, const u8* token,
					pmacros = macros + macros_count - 1;
				}
				CALLOC(pmacros->key, u8, KEYSIZE);
				pmacros->seen = FALSE;
				pmacros->seen = 0;
				strcpy((char*)pmacros->key, (char*)token + 1);
				pmacros->value	    = NULL;
				pmacros->value_size = 0;


@@ 1885,8 1908,7 @@ process_macro(FILE* output, const u8* token,

int
process_tag(FILE* output, const u8* token, const u8* link_prefix,
	const BOOL read_yaml_macros_and_links, BOOL* skip_eol,
	const BOOL end_tag)
	const int read_yaml_macros_and_links, int* skip_eol, const int end_tag)
{
	if (!token || strlen((char*)token) < 1)
		return warning(1, (u8*)"%s:%ld:%ld: Empty tag name",


@@ 1907,7 1929,7 @@ process_tag(FILE* output, const u8* token, const u8* link_prefix,
			"© %s Strahinya Radich.\n"
			"</small></p></div><!--made-by-->\n",
			MADEBY_URL, COPYRIGHTYEAR);
		output_firstcol = TRUE;
		output_firstcol = 1;
	}
	else if (startswith((char*)token, "csv")) /* {csv} */
		process_csv(output, token, read_yaml_macros_and_links, end_tag);


@@ 1916,19 1938,19 @@ process_tag(FILE* output, const u8* token, const u8* link_prefix,
	else if (startswith((char*)token, "include")) /* {include} */
	{
		process_include(output, token, read_yaml_macros_and_links);
		*skip_eol = TRUE;
		*skip_eol = 1;
	}
	else if (startswith((char*)token, "incdir")) /* {incdir} */
	{
		process_incdir(output, token, link_prefix,
			read_yaml_macros_and_links);
		*skip_eol = TRUE;
		*skip_eol = 1;
	}
	else if (*token == '=') /* {=macro} */
	{
		process_macro(output, token, read_yaml_macros_and_links,
			end_tag);
		*skip_eol = TRUE;
		*skip_eol = 1;
	}
	else if (!read_yaml_macros_and_links) /* general tags */
	{


@@ 1982,49 2004,49 @@ process_tag(FILE* output, const u8* token, const u8* link_prefix,
			}
		}
		print_output(output, ">");
		output_firstcol = FALSE;
		output_firstcol = 0;
	}

	return 0;
}

int
process_bold(FILE* output, const BOOL end_tag)
process_bold(FILE* output, const int end_tag)
{
	print_output(output, "<%sstrong>", end_tag ? "/" : "");
	return 0;
}

int
process_italic(FILE* output, const BOOL end_tag)
process_italic(FILE* output, const int end_tag)
{
	print_output(output, "<%sem>", end_tag ? "/" : "");
	return 0;
}

int
process_code(FILE* output, const BOOL end_tag)
process_code(FILE* output, const int end_tag)
{
	print_output(output, "<%scode>", end_tag ? "/" : "");
	return 0;
}

int
process_blockquote(FILE* output, const BOOL end_tag)
process_blockquote(FILE* output, const int end_tag)
{
	print_output(output, "<%sblockquote>", end_tag ? "/" : "");
	return 0;
}

int
process_kbd(FILE* output, const BOOL end_tag)
process_kbd(FILE* output, const int end_tag)
{
	print_output(output, "<%skbd>", end_tag ? "/" : "");
	return 0;
}

int
process_strike(FILE* output, const BOOL end_tag)
process_strike(FILE* output, const int end_tag)
{
	print_output(output, "<%ss>", end_tag ? "/" : "");
	return 0;


@@ 2054,7 2076,7 @@ process_table_header_end(FILE* output)
}

int
process_table_body_start(FILE* output, const BOOL start_row)
process_table_body_start(FILE* output, const int start_row)
{
	print_output(output, "<tbody>\n");
	if (start_row)


@@ 2090,7 2112,7 @@ process_table_end(FILE* output)
	return 0;
}

BOOL
int
url_is_local(const char* url)
{
	return !(startswith(url, "http://") || startswith(url, "https://")


@@ 2107,7 2129,7 @@ process_inline_link(FILE* output, const u8* link_text, const u8* link_prefix,
		link_prefix ? (const char*)link_prefix : "",
		link_url ? (char*)link_url : "",
		link_macro_body ? (char*)link_macro_body : "", link_text);
	output_firstcol = FALSE;
	output_firstcol = 0;

	return 0;
}


@@ 2153,7 2175,7 @@ print_image_dimensions(FILE* output, const u8* image_file_prefix, const u8* path
		*eol = 0;

	print_output(output, "%s", cmd_output_line);
	output_firstcol = FALSE;
	output_firstcol = 0;

print_dimensions_cleanup:
	pclose(cmd_output);


@@ 2164,7 2186,7 @@ print_dimensions_cleanup:
int
process_inline_image(FILE* output, const u8* image_text,
	const u8* image_file_prefix, const u8* link_prefix, const u8* image_url,
	const BOOL add_link, const BOOL add_figcaption)
	const int add_link, const int add_figcaption)
{
	if (add_figcaption)
		print_output(output, "<figure>\n");


@@ 2184,7 2206,7 @@ process_inline_image(FILE* output, const u8* image_text,
		print_image_dimensions(output, image_file_prefix, image_url);
	print_output(output, "%s/>", image_url ? " " : "");

	output_firstcol = FALSE;
	output_firstcol = 0;

	if (add_link)
		print_output(output, "</a>");


@@ 2193,15 2215,15 @@ process_inline_image(FILE* output, const u8* image_text,
	{
		print_output(output, "<figcaption>%s</figcaption>\n</figure>\n",
			image_text);
		output_firstcol = TRUE;
		output_firstcol = 1;
	}
	return 0;
}

int
process_image(FILE* output, const u8* image_text, const u8* image_file_prefix,
	const u8* link_prefix, const u8* image_id, const BOOL add_link,
	const BOOL add_figcaption)
	const u8* link_prefix, const u8* image_id, const int add_link,
	const int add_figcaption)
{
	u8* url = get_value(links, links_count, image_id, NULL);
	return process_inline_image(output, image_text, image_file_prefix,


@@ 2210,8 2232,8 @@ process_image(FILE* output, const u8* image_text, const u8* image_file_prefix,

int
process_line_start(FILE* output, const u8* line, const u8* link_prefix,
	const BOOL first_line_in_doc, const BOOL previous_line_blank,
	const BOOL read_yaml_macros_and_links, const BOOL list_para)
	const int first_line_in_doc, const int previous_line_blank,
	const int read_yaml_macros_and_links, const int list_para)
{
	if ((first_line_in_doc || previous_line_blank)
		&& !(ANY(state, ST_BLOCKQUOTE | ST_PRE)))


@@ 2244,7 2266,7 @@ process_line_start(FILE* output, const u8* line, const u8* link_prefix,
					&& (IN(state, ST_PARA_OPEN)))
				{
					print_output(output, "</p>\n");
					output_firstcol = TRUE;
					output_firstcol = 1;
				}
				state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN);
			}


@@ 2254,7 2276,7 @@ process_line_start(FILE* output, const u8* line, const u8* link_prefix,
			if (!read_yaml_macros_and_links)
			{
				print_output(output, "<p>");
				output_firstcol = FALSE;
				output_firstcol = 0;
			}
			state |= ST_PARA_OPEN;
		}


@@ 2264,10 2286,10 @@ process_line_start(FILE* output, const u8* line, const u8* link_prefix,

int
process_text_token(FILE* output, const u8* line, const u8* link_prefix,
	const BOOL first_line_in_doc, const BOOL previous_line_blank,
	const BOOL processed_start_of_line,
	const BOOL read_yaml_macros_and_links, const BOOL list_para, u8** token,
	u8** ptoken, size_t* token_size, const BOOL add_enclosing_paragraph)
	const int first_line_in_doc, const int previous_line_blank,
	const int processed_start_of_line, const int read_yaml_macros_and_links,
	const int list_para, u8** token, u8** ptoken, size_t* token_size,
	const int add_enclosing_paragraph)
{
	if (!(IN(state, ST_YAML)))
	{


@@ 2286,7 2308,7 @@ process_text_token(FILE* output, const u8* line, const u8* link_prefix,
					= *token + strlen((char*)*token) - eol
					> 0;
			else
				output_firstcol = FALSE;
				output_firstcol = 0;
		}
	}
	RESET_TOKEN(*token, *ptoken, *token_size);


@@ 2294,7 2316,7 @@ process_text_token(FILE* output, const u8* line, const u8* link_prefix,
}

int
process_inline_footnote(const u8* token, const BOOL read_yaml_macros_and_links,
process_inline_footnote(const u8* token, const int read_yaml_macros_and_links,
	FILE* output)
{
	current_inline_footnote++;


@@ 2330,15 2352,15 @@ process_inline_footnote(const u8* token, const BOOL read_yaml_macros_and_links,
			"id=\"inline-footnote-text-%d\"><sup>%d</sup></a>",
			current_inline_footnote, current_inline_footnote,
			current_inline_footnote);
		output_firstcol = FALSE;
		output_firstcol = 0;
	}

	return 0;
}

int
process_footnote(FILE* output, const u8* token, const BOOL footnote_definition,
	const BOOL footnote_output)
process_footnote(FILE* output, const u8* token, const int footnote_definition,
	const int footnote_output)
{
	current_footnote++;



@@ 2371,7 2393,7 @@ process_footnote(FILE* output, const u8* token, const BOOL footnote_definition,
			"<a href=\"#footnote-%d\" id=\"footnote-text-%d\">"
			"<sup>%d</sup></a>",
			current_footnote, current_footnote, current_footnote);
		output_firstcol = FALSE;
		output_firstcol = 0;
	}

	return 0;


@@ 2386,12 2408,12 @@ process_horizontal_rule(FILE* output)
	print_output(output, "<hr />\n");
	if (IN(state, ST_PARA_OPEN))
		print_output(output, "<p>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;
	return 0;
}

int
process_formula(FILE* output, const u8* token, const BOOL display_formula)
process_formula(FILE* output, const u8* token, const int display_formula)
{
	int result	      = 0;
	const u8* pipe_args[] = {token, NULL};


@@ 2399,13 2421,13 @@ process_formula(FILE* output, const u8* token, const BOOL display_formula)
	result = print_command(output, CMD_KATEX,
		display_formula ? (const u8**)CMD_KATEX_DISPLAY_ARGS
				: (const u8**)CMD_KATEX_INLINE_ARGS,
		(const u8**)pipe_args, TRUE);
		(const u8**)pipe_args, 1);

	if (result)
	{
		print_output(output, "%s$%s$%s", display_formula ? "$" : "",
			token, display_formula ? "$" : "");
		output_firstcol = FALSE;
		output_firstcol = 0;
	}

	return result;


@@ 2470,12 2492,12 @@ begin_html_and_head(FILE* output)
		"<meta name=\"viewport\" content=\"width=device-width,"
		" initial-scale=1\" />\n<meta name=\"generator\" "
		"content=\"slweb\" />\n");
	output_firstcol = TRUE;
	output_firstcol = 1;
	return 0;
}

int
add_css(FILE* output, BOOL output_yaml)
add_css(FILE* output, int output_yaml)
{
	if (!vars)
		return -1;


@@ 2496,16 2518,16 @@ int
end_head_start_body(FILE* output)
{
	print_output(output, "</head>\n<body>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;

	return 0;
}

int
begin_article(FILE* output, const char* source_filename, const u8* link_prefix,
	const BOOL add_article_header, const u8* author, const u8* title,
	const int add_article_header, const u8* author, const u8* title,
	const u8* header_text, const char* title_heading_level, u8* date,
	const BOOL ext_in_permalink, const char* permalink_url)
	const int ext_in_permalink, const char* permalink_url)
{
	if (author || date || header_text || title)
		print_output(output, "<header>\n");


@@ 2553,21 2575,21 @@ begin_article(FILE* output, const char* source_filename, const u8* link_prefix,
}

int
end_footnotes(FILE* output, BOOL add_footnote_div)
end_footnotes(FILE* output, int add_footnote_div)
{
	size_t footnote = 0;

	if (IN(state, ST_PARA_OPEN))
	{
		print_output(output, "</p>\n");
		output_firstcol = TRUE;
		output_firstcol = 1;
		state &= ~ST_PARA_OPEN;
	}

	if (add_footnote_div)
	{
		print_output(output, "<div class=\"footnotes\">\n");
		output_firstcol = TRUE;
		output_firstcol = 1;
	}

	process_horizontal_rule(output);


@@ 2580,7 2602,7 @@ end_footnotes(FILE* output, BOOL add_footnote_div)
			"%s</p>\n",
			footnote + 1, footnote + 1, footnote + 1,
			(char*)inline_footnotes[footnote]);
		output_firstcol = TRUE;
		output_firstcol = 1;
	}

	KeyValue* pfootnote = footnotes;


@@ 2592,7 2614,7 @@ end_footnotes(FILE* output, BOOL add_footnote_div)
			"<a href=\"#footnote-text-%d\">%d.</a> %s</p>\n",
			footnote + 1, footnote + 1, footnote + 1,
			(char*)pfootnote->value);
		output_firstcol = TRUE;
		output_firstcol = 1;
		pfootnote++;
		footnote++;
	}


@@ 2600,7 2622,7 @@ end_footnotes(FILE* output, BOOL add_footnote_div)
	if (add_footnote_div)
	{
		print_output(output, "</div><!--footnotes-->\n");
		output_firstcol = TRUE;
		output_firstcol = 1;
	}

	return 0;


@@ 2610,7 2632,7 @@ int
end_body_and_html(FILE* output)
{
	print_output(output, "</body>\n</html>\n");
	output_firstcol = TRUE;
	output_firstcol = 1;
	return 0;
}



@@ 2622,7 2644,7 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
	u8* ptoken	= NULL;
	u8* var_key	= NULL;
	const u8* pline = line;
	BOOL in_arg	= FALSE;
	int in_arg	= 0;

	if (!line || !vars || !vars_count || !pvars)
		exit(error(EINVAL,


@@ 2635,7 2657,7 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
	{
		if (!in_arg && *pline == ':')
		{
			in_arg	= TRUE;
			in_arg	= 1;
			*ptoken = 0;
			var_key = (u8*)strdup((char*)token);
			if (!var_key)


@@ 2655,7 2677,7 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
		*ptoken = 0;
	if (var_key && *var_key && *token)
	{
		BOOL found     = FALSE;
		int found      = 0;
		KeyValue* cvar = NULL;

		cvar = *vars;


@@ 2665,7 2687,7 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,
				&& cvar->value_size
				&& !strcmp((const char*)cvar->value,
					(const char*)token))
				found = TRUE;
				found = 1;
			cvar++;
		}
		if (!found)


@@ 2695,46 2717,46 @@ simple_parse_yaml_line(const u8* line, KeyValue** vars, size_t* vars_count,

int
slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
	const BOOL body_only, const BOOL read_yaml_macros_and_links)
	const int body_only, const int read_yaml_macros_and_links)
{
	u8* title			   = NULL;
	u8* title_heading_level		   = NULL;
	u8* header_text			   = NULL;
	u8* author			   = NULL;
	u8* date			   = NULL;
	u8* permalink_url		   = NULL;
	u8* ext_in_permalink		   = NULL;
	u8* var_add_article_header	   = NULL;
	u8* var_add_image_links		   = NULL;
	u8* var_add_figcaption		   = NULL;
	u8* var_add_footnote_div	   = NULL;
	u8* image_file_prefix		   = NULL;
	u8* link_prefix			   = NULL;
	const u8* pbuffer		   = NULL;
	u8* line			   = NULL;
	u8* pline			   = NULL;
	size_t line_len			   = 0;
	u8* token			   = NULL;
	u8* ptoken			   = NULL;
	size_t token_size		   = 0;
	u8* link_text			   = NULL;
	size_t link_size		   = 0;
	u8* link_macro			   = NULL;
	UBYTE heading_level		   = 0;
	ULONG heading_count		   = 0;
	BOOL end_tag			   = FALSE;
	BOOL first_line_in_doc		   = TRUE;
	BOOL skip_change_first_line_in_doc = FALSE;
	BOOL skip_eol			   = FALSE;
	BOOL keep_token			   = FALSE;
	BOOL previous_line_blank	   = FALSE;
	BOOL processed_start_of_line	   = FALSE;
	BOOL add_image_links		   = TRUE;
	BOOL add_figcaption		   = TRUE;
	BOOL add_footnote_div		   = FALSE;
	BOOL list_para			   = FALSE;
	BOOL footnote_at_line_start	   = FALSE;
	size_t pline_len		   = 0;
	u8* title			  = NULL;
	u8* title_heading_level		  = NULL;
	u8* header_text			  = NULL;
	u8* author			  = NULL;
	u8* date			  = NULL;
	u8* permalink_url		  = NULL;
	u8* ext_in_permalink		  = NULL;
	u8* var_add_article_header	  = NULL;
	u8* var_add_image_links		  = NULL;
	u8* var_add_figcaption		  = NULL;
	u8* var_add_footnote_div	  = NULL;
	u8* image_file_prefix		  = NULL;
	u8* link_prefix			  = NULL;
	const u8* pbuffer		  = NULL;
	u8* line			  = NULL;
	u8* pline			  = NULL;
	size_t line_len			  = 0;
	u8* token			  = NULL;
	u8* ptoken			  = NULL;
	size_t token_size		  = 0;
	u8* link_text			  = NULL;
	size_t link_size		  = 0;
	u8* link_macro			  = NULL;
	UBYTE heading_level		  = 0;
	ULONG heading_count		  = 0;
	int end_tag			  = 0;
	int first_line_in_doc		  = 1;
	int skip_change_first_line_in_doc = 0;
	int skip_eol			  = 0;
	int keep_token			  = 0;
	int previous_line_blank		  = 0;
	int processed_start_of_line	  = 0;
	int add_image_links		  = 1;
	int add_figcaption		  = 1;
	int add_footnote_div		  = 0;
	int list_para			  = 0;
	int footnote_at_line_start	  = 0;
	size_t pline_len		  = 0;

	if (!buffer)
		exit(error(1, (u8*)"Empty buffer"));


@@ 2778,7 2800,7 @@ slweb_parse(FILE* output, const char* source_filename, const u8* buffer,
	if (!read_yaml_macros_and_links && !body_only)
	{
		begin_html_and_head(output);
		add_css(output, FALSE);
		add_css(output, 0);
		end_head_start_body(output);
	}



@@ 2806,10 2828,10 @@ do_buffer:;

	lineno++;
	colno			= 1;
	output_firstcol		= TRUE;
	processed_start_of_line = FALSE;
	skip_eol		= FALSE;
	list_para		= FALSE;
	output_firstcol		= 1;
	processed_start_of_line = 0;
	skip_eol		= 0;
	list_para		= 0;

do_line:
	if (!pline || !*pline)


@@ 2827,7 2849,7 @@ do_line:
		else if (colno == 1 && strlen((char*)pline) > 2
			&& startswith((char*)pline, "---"))
		{
			skip_eol = TRUE;
			skip_eol = 1;

			if (!(IN(state, ST_YAML)) && lineno > 1
				&& !read_yaml_macros_and_links)


@@ 2839,7 2861,7 @@ do_line:
				else
					state &= ~ST_YAML;

				skip_change_first_line_in_doc = TRUE;
				skip_change_first_line_in_doc = 1;
			}
			pline = NULL;
		}


@@ 2865,8 2887,8 @@ do_line:
				state |= ST_PARA_OPEN;
			}

			processed_start_of_line = TRUE;
			skip_eol		= FALSE;
			processed_start_of_line = 1;
			skip_eol		= 0;

			state |= ST_LIST;



@@ 2966,8 2988,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3006,8 3028,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3047,8 3069,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3084,7 3106,7 @@ do_line:
					print_output(output, "<pre>");
				else
					print_output(output, "</pre>");
				output_firstcol = FALSE;
				output_firstcol = 0;
			}

			/* Skip the rest of the line (language) */


@@ 3119,8 3141,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state, ST_PRE | ST_HEADING)))


@@ 3225,8 3247,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3267,8 3289,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3316,8 3338,8 @@ do_line:
				state |= ST_PARA_OPEN;
			}

			processed_start_of_line = TRUE;
			skip_eol		= FALSE;
			processed_start_of_line = 1;
			skip_eol		= 0;

			state |= ST_LIST;



@@ 3355,7 3377,7 @@ do_line:
		else if (colno == 1 && pline_len > 2
			&& startswith((char*)pline, "***"))
		{
			skip_eol = TRUE;
			skip_eol = 1;
			if (!read_yaml_macros_and_links)
				process_horizontal_rule(output);
			pline = NULL;


@@ 3382,8 3404,8 @@ do_line:
				state |= ST_PARA_OPEN;
			}

			processed_start_of_line = TRUE;
			skip_eol		= FALSE;
			processed_start_of_line = 1;
			skip_eol		= 0;

			state |= ST_LIST;



@@ 3419,8 3441,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3462,8 3484,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3495,7 3517,7 @@ do_line:
				heading_count++;
				process_heading_start(output, heading_level,
					heading_count);
				output_firstcol = FALSE;
				output_firstcol = 0;
			}
			state |= ST_HEADING_TEXT;
			pline++;


@@ 3506,13 3528,13 @@ do_line:
		if (colno == 1 && strlen((char*)pline) > 1
			&& startswith((char*)pline, "  "))
		{
			list_para = TRUE;
			list_para = 1;
			process_text_token(output, line, link_prefix,
				first_line_in_doc, previous_line_blank,
				processed_start_of_line,
				read_yaml_macros_and_links, list_para, &token,
				&ptoken, &token_size, TRUE);
			processed_start_of_line = TRUE;
				&ptoken, &token_size, 1);
			processed_start_of_line = 1;
			while (*pline == ' ' || *pline == '\t')
			{
				pline++;


@@ 3527,7 3549,7 @@ do_line:
			*ptoken	      = 0;
			strcat((char*)ptoken, "<br />");
			ptoken += br_len;
			output_firstcol = FALSE;
			output_firstcol = 0;
			pline++;
			colno++;
		}


@@ 3560,7 3582,7 @@ do_line:
			*ptoken		 = 0;
			size_t token_len = strlen((char*)token);

			skip_eol = TRUE;
			skip_eol = 1;
			if (read_yaml_macros_and_links)
			{
				if (!macros)


@@ 3602,8 3624,8 @@ do_line:
				first_line_in_doc, previous_line_blank,
				processed_start_of_line,
				read_yaml_macros_and_links, list_para, &token,
				&ptoken, &token_size, FALSE);
			processed_start_of_line = TRUE;
				&ptoken, &token_size, 0);
			processed_start_of_line = 1;
		}

		state |= ST_TAG;


@@ 3625,7 3647,7 @@ do_line:

		if ((IN(state, ST_TAG)) && pline - 1 && *(pline - 1) == '{')
		{
			end_tag = TRUE;
			end_tag = 1;
			pline++;
		}
		else


@@ 3653,7 3675,7 @@ do_line:
				read_yaml_macros_and_links, &skip_eol, end_tag);

			RESET_TOKEN(token, ptoken, token_size);
			end_tag = FALSE;
			end_tag = 0;
		}

		pline++;


@@ 3700,8 3722,8 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
				processed_start_of_line = TRUE;
					&token, &ptoken, &token_size, 1);
				processed_start_of_line = 1;

				if (!read_yaml_macros_and_links
					&& !(ANY(state,


@@ 3710,7 3732,7 @@ do_line:
					state ^= ST_KBD;
					process_kbd(output,
						!(IN(state, ST_KBD)));
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
			}



@@ 3721,7 3743,7 @@ do_line:
		else if (!(IN(state, ST_PRE)) && colno == 1
			&& strlen((char*)pline) > 1 && *(pline + 1) == '@')
		{
			skip_eol = TRUE;
			skip_eol = 1;

			pline += 2;
			colno += 2;


@@ 3732,7 3754,7 @@ do_line:
				if (!read_yaml_macros_and_links)
				{
					process_table_start(output);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
				pline = NULL;
				break;


@@ 3747,8 3769,8 @@ do_line:
				state &= ~ST_TABLE_HEADER;
				if (!read_yaml_macros_and_links)
				{
					process_table_body_start(output, FALSE);
					output_firstcol = TRUE;
					process_table_body_start(output, 0);
					output_firstcol = 1;
				}
				pline = NULL;
				break;


@@ 3758,7 3780,7 @@ do_line:
				if (!read_yaml_macros_and_links)
				{
					process_table_body_row_start(output);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
				break;



@@ 3767,7 3789,7 @@ do_line:
				if (!read_yaml_macros_and_links)
				{
					process_table_end(output);
					output_firstcol = TRUE;
					output_firstcol = 1;
				}
				pline = NULL;
				break;


@@ 3780,7 3802,7 @@ do_line:
		}
		else if (!(IN(state, ST_PRE)) && colno == 1)
		{
			skip_eol = TRUE;
			skip_eol = 1;

			if (IN(state, ST_TABLE_HEADER))
			{


@@ 3796,8 3818,8 @@ do_line:
				state |= ST_TABLE;
				if (!read_yaml_macros_and_links)
				{
					process_table_body_start(output, TRUE);
					output_firstcol = FALSE;
					process_table_body_start(output, 1);
					output_firstcol = 0;
				}
			}
			else if (IN(state, ST_TABLE))


@@ 3805,7 3827,7 @@ do_line:
				if (!read_yaml_macros_and_links)
				{
					process_table_body_row_start(output);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
			}
			else


@@ 3814,7 3836,7 @@ do_line:
				if (!read_yaml_macros_and_links)
				{
					process_table_start(output);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
			}



@@ 3828,16 3850,16 @@ do_line:
			{
				print_output(output, "%s", token);
				if (*token)
					output_firstcol = FALSE;
					output_firstcol = 0;
				if (strlen((char*)pline) > 1)
				{
					process_table_header_cell(output);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
				else
				{
					process_table_header_end(output);
					output_firstcol = TRUE;
					output_firstcol = 1;
				}
			}
			RESET_TOKEN(token, ptoken, token_size);


@@ 3851,16 3873,16 @@ do_line:
			{
				print_output(output, "%s", token);
				if (*token)
					output_firstcol = FALSE;
					output_firstcol = 0;
				if (strlen((char*)pline) > 1)
				{
					process_table_body_cell(output);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
				else
				{
					process_table_body_row_end(output);
					output_firstcol = TRUE;
					output_firstcol = 1;
				}
			}
			RESET_TOKEN(token, ptoken, token_size);


@@ 3920,8 3942,8 @@ do_line:
			if (!read_yaml_macros_and_links
				&& !(IN(state, ST_BLOCKQUOTE)))
			{
				process_blockquote(output, FALSE);
				output_firstcol = FALSE;
				process_blockquote(output, 0);
				output_firstcol = 0;
			}

			state |= ST_BLOCKQUOTE;


@@ 3956,13 3978,13 @@ do_line:
				first_line_in_doc, previous_line_blank,
				processed_start_of_line,
				read_yaml_macros_and_links, list_para, &token,
				&ptoken, &token_size, FALSE);
			processed_start_of_line = TRUE;
				&ptoken, &token_size, 0);
			processed_start_of_line = 1;

			RESET_TOKEN(token, ptoken, token_size);

			state |= ST_IMAGE;
			keep_token = TRUE;
			keep_token = 1;
			pline += 2;
			colno += 2;
		}


@@ 4016,7 4038,7 @@ do_line:
				&& (IN(state, ST_PARA_OPEN)))
			{
				print_output(output, "</p>\n");
				output_firstcol = TRUE;
				output_firstcol = 1;
			}
			state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN);
		}


@@ 4032,9 4054,9 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
					&token, &ptoken, &token_size, 1);
			}
			processed_start_of_line = TRUE;
			processed_start_of_line = 1;

			RESET_TOKEN(token, ptoken, token_size);
			state |= ST_FOOTNOTE;


@@ 4051,13 4073,13 @@ do_line:
				first_line_in_doc, previous_line_blank,
				processed_start_of_line,
				read_yaml_macros_and_links, list_para, &token,
				&ptoken, &token_size, TRUE);
				&ptoken, &token_size, 1);
		}
		processed_start_of_line = TRUE;
		processed_start_of_line = 1;

		RESET_TOKEN(token, ptoken, token_size);
		state |= ST_LINK;
		keep_token  = TRUE;
		keep_token  = 1;
		*link_macro = 0;
		pline++;
		colno++;


@@ 4188,7 4210,7 @@ do_line:
			process_inline_footnote(token,
				read_yaml_macros_and_links, output);

			keep_token = FALSE;
			keep_token = 0;
			RESET_TOKEN(token, ptoken, token_size);
			state &= ~ST_INLINE_FOOTNOTE;
			pline++;


@@ 4196,7 4218,7 @@ do_line:
		}
		else if (IN(state, ST_FOOTNOTE))
		{
			BOOL footnote_definition = (strlen((char*)pline) > 1)
			int footnote_definition = (strlen((char*)pline) > 1)
				&& (*(pline + 1) == ':')
				&& footnote_at_line_start;



@@ 4208,7 4230,7 @@ do_line:

			RESET_TOKEN(token, ptoken, token_size);
			state &= ~ST_FOOTNOTE;
			footnote_at_line_start = FALSE;
			footnote_at_line_start = 0;
			pline++;
			colno++;
			if (footnote_definition)


@@ 4278,7 4300,7 @@ do_line:
					colno++;
				}
				RESET_TOKEN(token, ptoken, token_size);
				keep_token = FALSE;
				keep_token = 0;
				state |= ST_LINK_SECOND_ARG_END;
				break;



@@ 4300,7 4322,7 @@ do_line:
				pline += 2;
				colno += 2;
				RESET_TOKEN(token, ptoken, token_size);
				keep_token = FALSE;
				keep_token = 0;
				if (IN(state, ST_LINK))
					state |= ST_LINK_SECOND_ARG;
				else


@@ 4339,12 4361,12 @@ do_line:
				first_line_in_doc, previous_line_blank,
				processed_start_of_line,
				read_yaml_macros_and_links, list_para, &token,
				&ptoken, &token_size, TRUE);
			processed_start_of_line = TRUE;
				&ptoken, &token_size, 1);
			processed_start_of_line = 1;

			RESET_TOKEN(token, ptoken, token_size);
			state |= ST_INLINE_FOOTNOTE;
			keep_token = TRUE;
			keep_token = 1;
			pline += 2;
			colno += 2;
			break;


@@ 4406,22 4428,22 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
					&token, &ptoken, &token_size, 1);
			}
			processed_start_of_line = TRUE;
			processed_start_of_line = 1;

			state ^= ST_DISPLAY_FORMULA;

			if (IN(state, ST_DISPLAY_FORMULA))
				keep_token = TRUE;
				keep_token = 1;
			else
			{
				*ptoken = 0;

				if (!read_yaml_macros_and_links)
					process_formula(output, token, TRUE);
					process_formula(output, token, 1);

				keep_token = FALSE;
				keep_token = 0;
				RESET_TOKEN(token, ptoken, token_size);
			}



@@ 4442,22 4464,22 @@ do_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
					&token, &ptoken, &token_size, 1);
			}
			processed_start_of_line = TRUE;
			processed_start_of_line = 1;

			state ^= ST_FORMULA;

			if (IN(state, ST_FORMULA))
				keep_token = TRUE;
				keep_token = 1;
			else
			{
				*ptoken = 0;

				if (!read_yaml_macros_and_links)
					process_formula(output, token, FALSE);
					process_formula(output, token, 0);

				keep_token = FALSE;
				keep_token = 0;
				RESET_TOKEN(token, ptoken, token_size);
			}



@@ 4505,8 4527,8 @@ do_line:
				state |= ST_PARA_OPEN;
			}

			processed_start_of_line = TRUE;
			skip_eol		= FALSE;
			processed_start_of_line = 1;
			skip_eol		= 0;

			state |= ST_NUMLIST;



@@ 4595,7 4617,7 @@ done_line:
			size_t token_len = strlen((char*)token);
			if (IN(state, ST_MACRO_BODY))
			{
				skip_eol = TRUE;
				skip_eol = 1;
				if (!read_yaml_macros_and_links)
					goto skip_macro_read;
				if (!macros)


@@ 4633,7 4655,7 @@ done_line:
			}
			else if (IN(state, ST_FOOTNOTE_TEXT))
			{
				skip_eol = TRUE;
				skip_eol = 1;
				if (!read_yaml_macros_and_links)
					goto skip_footnote_read;
				if (!footnotes)


@@ 4701,9 4723,9 @@ done_line:
				{
					process_heading(output, token,
						heading_level);
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
				first_line_in_doc = FALSE;
				first_line_in_doc = 0;
				RESET_TOKEN(token, ptoken, token_size);
				heading_level = 0;
			}


@@ 4714,7 4736,7 @@ done_line:
					first_line_in_doc, previous_line_blank,
					processed_start_of_line,
					read_yaml_macros_and_links, list_para,
					&token, &ptoken, &token_size, TRUE);
					&token, &ptoken, &token_size, 1);
		}

		if (!ANY(state,


@@ 4727,10 4749,10 @@ done_line:
				if (!read_yaml_macros_and_links)
				{
					print_output(output, "</p>");
					output_firstcol = FALSE;
					output_firstcol = 0;
				}
				if (IN(state, ST_LIST))
					skip_eol = TRUE;
					skip_eol = 1;
				state &= ~ST_PARA_OPEN;
			}



@@ 4761,7 4783,7 @@ done_line:
				*ptoken		 = 0;
				size_t token_len = strlen((char*)token);

				skip_eol = TRUE;
				skip_eol = 1;
				if (!read_yaml_macros_and_links)
					goto skip_footnote_text_read;
				if (!footnotes)


@@ 4807,8 4829,8 @@ done_line:
			state &= ~ST_BLOCKQUOTE;
			if (!read_yaml_macros_and_links)
			{
				process_blockquote(output, TRUE);
				output_firstcol = FALSE;
				process_blockquote(output, 1);
				output_firstcol = 0;
			}
		}



@@ 4819,7 4841,7 @@ done_line:
			{
				warning(1, (u8*)"Malformed table");
				process_table_end(output);
				output_firstcol = TRUE;
				output_firstcol = 1;
			}
			state &= ~(ST_TABLE_HEADER | ST_TABLE_LINE);
		}


@@ 4829,12 4851,12 @@ done_line:
			if (!read_yaml_macros_and_links)
			{
				process_table_end(output);
				output_firstcol = TRUE;
				output_firstcol = 1;
			}
			state &= ~ST_TABLE;
		}

		previous_line_blank = FALSE;
		previous_line_blank = 0;
	}

	if (!skip_eol && !keep_token && !read_yaml_macros_and_links


@@ 4843,18 4865,18 @@ done_line:
				| ST_LINK_SECOND_ARG_END))
	{
		print_output(output, "\n");
		output_firstcol = TRUE;
		output_firstcol = 1;
	}

	if (!keep_token)
		RESET_TOKEN(token, ptoken, token_size);

	if (!skip_change_first_line_in_doc && !(IN(state, ST_YAML)))
		first_line_in_doc = FALSE;
		first_line_in_doc = 0;

	skip_change_first_line_in_doc = FALSE;
	skip_change_first_line_in_doc = 0;
	if (line_len == 0)
		previous_line_blank = TRUE;
		previous_line_blank = 1;

	/* Lasts until the end of line */
	state &= ~(ST_YAML_VAL | ST_IMAGE_SECOND_ARG | ST_LINK_SECOND_ARG


@@ 4882,9 4904,9 @@ int
main(const int argc, const char** argv)
{
	const char* arg;
	Command cmd    = CMD_NONE;
	BOOL body_only = FALSE;
	int result     = 0;
	Command cmd   = CMD_NONE;
	int body_only = 0;
	int result    = 0;

	basedir_size = 2;
	CALLOC(basedir, char, basedir_size);


@@ 4905,7 4927,7 @@ main(const int argc, const char** argv)
				else if (!strcmp(arg, "body-only"))
				{
					arg += strlen("body-only");
					body_only = TRUE;
					body_only = 1;
				}
				else if (startswith(arg, "basedir"))
				{


@@ 4940,7 4962,7 @@ main(const int argc, const char** argv)
				switch (c)
				{
				case 'b':
					body_only = TRUE;
					body_only = 1;
					break;
				case 'd':
					cmd = CMD_BASEDIR;


@@ 5046,7 5068,7 @@ main(const int argc, const char** argv)
	inline_footnote_count = 0;

	/* First pass: read YAML, macros and links */
	result = slweb_parse(output, input_filename, buffer, body_only, TRUE);
	result = slweb_parse(output, input_filename, buffer, body_only, 1);

	if (result)
	{


@@ 5060,7 5082,7 @@ main(const int argc, const char** argv)
	current_inline_footnote = 0;

	/* Second pass: parse and output */
	result = slweb_parse(output, input_filename, buffer, body_only, FALSE);
	result = slweb_parse(output, input_filename, buffer, body_only, 0);

	slweb_cleanup();
	free(buffer);

M uninstall.do => uninstall.do +1 -1
@@ 1,6 1,6 @@
#!/bin/sh
redo-always
PREFIX=/usr/local
PREFIX=${PREFIX:-/usr/local}
BINDIR=$PREFIX/bin
#DOCDIR=$PREFIX/share/doc/slweb
MANDIR=$PREFIX/share/man/man1