чување 042376a1d1e7bcb3af3c1ba380fb77613b25e022
родитељ c995f21f0a965431529127161692bfaa63aeca83
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Fri, 13 Aug 2021 14:55:35 +0200
Reformatted code using clang-format; using goto instead of while in places to decrease indentation
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | index.html | | | 2 | +- |
| M | slweb.c | | | 8049 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
измењених датотека: 2, додавања: 4128(+), брисања: 3923(-)
diff --git a/index.html b/index.html
@@ -152,7 +152,7 @@ this program. If not, see <<a href="https://www.gnu.org/licenses">https://www
<div id="git-log">
Previous commit:
-index.slw e0dbba5 2021-08-11 17:31:02 +0200 (Страхиња Радић) (HEAD -> master, origin/master, origin/HEAD)
+index.slw c995f21 2021-08-12 09:06:45 +0200 (Страхиња Радић) (HEAD -> master, origin/master, origin/HEAD)
</div><!--git-log-->
diff --git a/slweb.c b/slweb.c
@@ -2,4320 +2,4525 @@
#include "defs.h"
-static size_t lineno = 0;
-static size_t colno = 1;
-static BOOL output_firstcol = TRUE;
-static char* input_filename = NULL;
-static char* input_dirname = NULL;
-static char* basedir = NULL;
-static size_t basedir_size = 0;
-static char* incdir = NULL;
-static char* global_link_prefix = NULL;
+static size_t lineno = 0;
+static size_t colno = 1;
+static BOOL output_firstcol = TRUE;
+static char* input_filename = NULL;
+static char* input_dirname = NULL;
+static char* basedir = NULL;
+static size_t basedir_size = 0;
+static char* incdir = NULL;
+static char* global_link_prefix = NULL;
static size_t global_link_prefix_size = 0;
-static KeyValue* vars = NULL;
-static KeyValue* pvars = NULL;
-static size_t vars_count = 0;
-static KeyValue* macros = NULL;
-static KeyValue* pmacros = NULL;
-static size_t macros_count = 0;
-static KeyValue* links = NULL;
-static KeyValue* plinks = NULL;
-static size_t links_count = 0;
-static KeyValue* footnotes = NULL;
-static KeyValue* pfootnotes = NULL;
-static size_t footnote_count = 0;
-static size_t current_footnote = 0;
-static u8** inline_footnotes = NULL;
+static KeyValue* vars = NULL;
+static KeyValue* pvars = NULL;
+static size_t vars_count = 0;
+static KeyValue* macros = NULL;
+static KeyValue* pmacros = NULL;
+static size_t macros_count = 0;
+static KeyValue* links = NULL;
+static KeyValue* plinks = NULL;
+static size_t links_count = 0;
+static KeyValue* footnotes = NULL;
+static KeyValue* pfootnotes = NULL;
+static size_t footnote_count = 0;
+static size_t current_footnote = 0;
+static u8** inline_footnotes = NULL;
static size_t inline_footnote_count = 0;
static size_t current_inline_footnote = 0;
-static u8* csv_template = NULL;
-static size_t csv_template_size = 0;
-static char* csv_filename = NULL;
-static long csv_iter = 0;
-static ULLONG state = ST_NONE;
-
-#define CHECKEXITNOMEM(ptr) do { if (!ptr) exit(error(ENOMEM, \
- (u8*)"Memory allocation failed (out of memory?)")); } while (0)
-
-#define CALLOC(ptr, ptrtype, nmemb) do { ptr = calloc(nmemb, sizeof(ptrtype)); \
- CHECKEXITNOMEM(ptr); } while (0)
-
-#define REALLOC(ptr, ptrtype, newsize) do { ptrtype* newptr = realloc(ptr, newsize); \
- CHECKEXITNOMEM(newptr); \
- ptr = newptr; } while (0)
+static u8* csv_template = NULL;
+static size_t csv_template_size = 0;
+static char* csv_filename = NULL;
+static long csv_iter = 0;
+static ULLONG state = ST_NONE;
+
+#define CHECKEXITNOMEM(ptr) \
+ do \
+ { \
+ if (!ptr) \
+ exit(error(ENOMEM, \
+ (u8*)"Memory allocation failed (out of " \
+ "memory?)")); \
+ } while (0)
+
+#define CALLOC(ptr, ptrtype, nmemb) \
+ do \
+ { \
+ ptr = calloc(nmemb, sizeof(ptrtype)); \
+ CHECKEXITNOMEM(ptr); \
+ } while (0)
+
+#define REALLOC(ptr, ptrtype, newsize) \
+ do \
+ { \
+ ptrtype* newptr = realloc(ptr, newsize); \
+ CHECKEXITNOMEM(newptr); \
+ ptr = newptr; \
+ } while (0)
#define REALLOCARRAY(ptr, membtype, newcount) \
- REALLOC(ptr, membtype, sizeof(membtype) * newcount);
-
-#define CHECKCOPY(token, ptoken, token_size, pline) do { \
- if (ptoken + 2 > token + token_size) \
- { \
- size_t old_size = token_size; \
- token_size += BUFSIZE; \
- REALLOC(token, u8, token_size); \
- ptoken = token + old_size - 1; \
- } \
- *ptoken++ = *pline++; } while (0)
-
-#define RESET_TOKEN(token, ptoken, token_size) do { \
- token_size = BUFSIZE; \
- REALLOC(token, u8, token_size); \
- *token = 0; ptoken = token; } while (0)
-
-#define ALL(var, mask) ( ((var) & (mask)) == (mask) )
-#define ANY(var, mask) ( (var) & (mask) )
+ REALLOC(ptr, membtype, sizeof(membtype) * newcount);
+
+#define CHECKCOPY(token, ptoken, token_size, pline) \
+ do \
+ { \
+ if (ptoken + 2 > token + token_size) \
+ { \
+ size_t old_size = token_size; \
+ token_size += BUFSIZE; \
+ REALLOC(token, u8, token_size); \
+ ptoken = token + old_size - 1; \
+ } \
+ *ptoken++ = *pline++; \
+ } while (0)
+
+#define RESET_TOKEN(token, ptoken, token_size) \
+ do \
+ { \
+ token_size = BUFSIZE; \
+ REALLOC(token, u8, token_size); \
+ *token = 0; \
+ ptoken = token; \
+ } while (0)
+
+#define ALL(var, mask) (((var) & (mask)) == (mask))
+#define ANY(var, mask) ((var) & (mask))
int
version()
{
- printf("%s v%s\n", PROGRAMNAME, VERSION);
- return 0;
+ printf("%s v%s\n", PROGRAMNAME, VERSION);
+ return 0;
}
int
usage()
{
- printf("Usage: %s [-b|--body-only] [-d|--basedir <dir>] [-h|--help]"
- " [-v|--version] [filename]\n", PROGRAMNAME);
- return 0;
+ printf("Usage: %s [-b|--body-only] [-d|--basedir <dir>] [-h|--help]"
+ " [-v|--version] [filename]\n",
+ PROGRAMNAME);
+ return 0;
}
int
error(int code, u8* fmt, ...)
{
- char buf[BUFSIZE];
- va_list args;
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), (const char*)fmt, args);
- va_end(args);
- fprintf(stderr, "%s:%s:%lu:%lu: %s\n", PROGRAMNAME,
- input_filename ? input_filename : "(stdin)",
- lineno, colno, buf);
- return code;
+ char buf[BUFSIZE];
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), (const char*)fmt, args);
+ va_end(args);
+ fprintf(stderr, "%s:%s:%lu:%lu: %s\n", PROGRAMNAME,
+ input_filename ? input_filename : "(stdin)", lineno, colno,
+ buf);
+ return code;
}
int
warning(int code, u8* fmt, ...)
{
- char buf[BUFSIZE];
- va_list args;
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), (const char*)fmt, args);
- va_end(args);
- fprintf(stderr, "Warning: %s\n", buf);
- return code;
+ char buf[BUFSIZE];
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), (const char*)fmt, args);
+ va_end(args);
+ fprintf(stderr, "Warning: %s\n", buf);
+ return code;
}
int
free_keyvalue(KeyValue** list, size_t list_count)
{
- if (!list || !*list)
- return 1;
-
- for (size_t index = 0; index < list_count; index++)
- {
- KeyValue* current = *list + index;
- if (current->value)
- free(current->value);
- if (current->key)
- free(current->key);
- }
- return 0;
+ if (!list || !*list)
+ return 1;
+
+ for (size_t index = 0; index < list_count; index++)
+ {
+ KeyValue* current = *list + index;
+ if (current->value)
+ free(current->value);
+ if (current->key)
+ free(current->key);
+ }
+ return 0;
}
int
slweb_cleanup()
{
- if (basedir)
- free(basedir);
- free(input_dirname);
- while (inline_footnote_count--)
- free(inline_footnotes[inline_footnote_count]);
- if (inline_footnotes)
- free(inline_footnotes);
- free_keyvalue(&footnotes, footnote_count);
- free_keyvalue(&links, links_count);
- free_keyvalue(¯os, macros_count);
- free_keyvalue(&vars, vars_count);
- if (footnotes)
- free(footnotes);
- if (links)
- free(links);
- if (macros)
- free(macros);
- if (vars)
- free(vars);
-
- return 0;
+ if (basedir)
+ free(basedir);
+ free(input_dirname);
+ while (inline_footnote_count--)
+ free(inline_footnotes[inline_footnote_count]);
+ if (inline_footnotes)
+ free(inline_footnotes);
+ free_keyvalue(&footnotes, footnote_count);
+ free_keyvalue(&links, links_count);
+ free_keyvalue(¯os, macros_count);
+ free_keyvalue(&vars, vars_count);
+ if (footnotes)
+ free(footnotes);
+ if (links)
+ free(links);
+ if (macros)
+ free(macros);
+ if (vars)
+ free(vars);
+
+ return 0;
}
-int slweb_parse(u8* buffer, FILE* output, BOOL body_only,
- BOOL read_yaml_macros_and_links);
+int
+slweb_parse(u8* buffer, FILE* output, BOOL body_only,
+ BOOL read_yaml_macros_and_links);
BOOL
startswith(const char* s, const char* what)
{
- if (!s || !what)
- return FALSE;
+ if (!s || !what)
+ return FALSE;
- do
- {
- if (*s++ != *what++)
- return FALSE;
- }
- while (*s && *what);
+ do
+ {
+ if (*s++ != *what++)
+ return FALSE;
+ } while (*s && *what);
- return !*what;
+ return !*what;
}
u8*
get_value(KeyValue* list, size_t list_count, u8* key, BOOL* seen)
{
- KeyValue* plist = list;
- while (plist < list + list_count)
- {
- if (!strcmp((char*)plist->key, (char*)key))
- {
- if (seen)
- {
- *seen = plist->seen;
- plist->seen = TRUE;
- }
- return plist->value;
- }
- plist++;
- }
- return NULL;
+ KeyValue* plist = list;
+ while (plist < list + list_count)
+ {
+ if (!strcmp((char*)plist->key, (char*)key))
+ {
+ if (seen)
+ {
+ *seen = plist->seen;
+ plist->seen = TRUE;
+ }
+ return plist->value;
+ }
+ plist++;
+ }
+ return NULL;
}
int
set_basedir(char* arg, char** basedir, size_t* basedir_size)
{
- size_t basedir_len = 0;
- size_t arg_len = strlen(arg);
-
- if (arg_len < 1)
- exit(error(1, (u8*)"--basedir: Argument required"));
-
- if (arg_len + 1 > *basedir_size)
- {
- *basedir_size = arg_len+1;
- REALLOC(*basedir, char, *basedir_size);
- }
- strncpy(*basedir, arg, *basedir_size-1);
- *(*basedir + arg_len) = 0;
- basedir_len = strlen(*basedir);
- if (*(*basedir + basedir_len - 1) == '/')
- *(*basedir + basedir_len - 1) = 0;
-
- return 0;
+ size_t basedir_len = 0;
+ size_t arg_len = strlen(arg);
+
+ if (arg_len < 1)
+ exit(error(1, (u8*)"--basedir: Argument required"));
+
+ if (arg_len + 1 > *basedir_size)
+ {
+ *basedir_size = arg_len + 1;
+ REALLOC(*basedir, char, *basedir_size);
+ }
+ strncpy(*basedir, arg, *basedir_size - 1);
+ *(*basedir + arg_len) = 0;
+ basedir_len = strlen(*basedir);
+ if (*(*basedir + basedir_len - 1) == '/')
+ *(*basedir + basedir_len - 1) = 0;
+
+ return 0;
}
int
-set_global_link_prefix(char* arg, char** global_link_prefix,
- size_t* global_link_prefix_size)
+set_global_link_prefix(
+ char* arg, char** global_link_prefix, size_t* global_link_prefix_size)
{
- size_t arg_len = strlen(arg);
+ size_t arg_len = strlen(arg);
- if (arg_len < 1)
- exit(error(1, (u8*)"--global-link-prefix: Argument required"));
+ if (arg_len < 1)
+ exit(error(1, (u8*)"--global-link-prefix: Argument required"));
- if (arg_len + 1 > *global_link_prefix_size)
- {
- *global_link_prefix_size = arg_len+1;
- REALLOC(*global_link_prefix, char, *global_link_prefix_size);
- }
- strncpy(*global_link_prefix, arg, *global_link_prefix_size-1);
- *(*global_link_prefix + arg_len) = 0;
+ if (arg_len + 1 > *global_link_prefix_size)
+ {
+ *global_link_prefix_size = arg_len + 1;
+ REALLOC(*global_link_prefix, char, *global_link_prefix_size);
+ }
+ strncpy(*global_link_prefix, arg, *global_link_prefix_size - 1);
+ *(*global_link_prefix + arg_len) = 0;
- return 0;
+ return 0;
}
char*
strip_ext(const char* fn)
{
- char* newname = NULL;
- char* pnewname = NULL;
- const char* pfn = NULL;
- char* dot = NULL;
+ char* newname = NULL;
+ char* pnewname = NULL;
+ const char* pfn = NULL;
+ char* dot = NULL;
- dot = strrchr(fn, '.');
+ dot = strrchr(fn, '.');
- if (!dot)
- return NULL;
+ if (!dot)
+ return NULL;
- CALLOC(newname, char, strlen(fn)+1);
- pnewname = newname;
- pfn = fn;
+ CALLOC(newname, char, strlen(fn) + 1);
+ pnewname = newname;
+ pfn = fn;
- while (pfn != dot && *pfn)
- *pnewname++ = *pfn++;
+ while (pfn != dot && *pfn)
+ *pnewname++ = *pfn++;
- return newname;
+ return newname;
}
int
print_output(FILE* output, char* fmt, ...)
{
- char buf[BUFSIZE];
- va_list args;
-
- if (!output || !fmt)
- exit(error(EINVAL, (u8*)"print_output: Invalid argument"));
-
- va_start(args, fmt);
- if (state & ST_CSV_BODY)
- {
- size_t buf_len = 0;
- vsnprintf((char*)buf, BUFSIZE, fmt, args);
- buf_len = strlen(buf);
- if (!csv_template)
- {
- csv_template_size = BUFSIZE;
- CALLOC(csv_template, u8, csv_template_size);
- strncpy((char*)csv_template, buf, BUFSIZE-1);
- *(csv_template + buf_len) = 0;
- }
- else
- {
- if (strlen((char*)csv_template) + buf_len > csv_template_size)
- {
- csv_template_size += BUFSIZE;
- REALLOC(csv_template, u8, csv_template_size);
- }
- strncat((char*)csv_template, buf, csv_template_size
- - strlen((char*)csv_template) - 1);
- }
- }
- else
- vfprintf(output, fmt, args);
- va_end(args);
- return 0;
+ char buf[BUFSIZE];
+ va_list args;
+
+ if (!output || !fmt)
+ exit(error(EINVAL, (u8*)"print_output: Invalid argument"));
+
+ va_start(args, fmt);
+ if (state & ST_CSV_BODY)
+ {
+ size_t buf_len = 0;
+ vsnprintf((char*)buf, BUFSIZE, fmt, args);
+ buf_len = strlen(buf);
+ if (!csv_template)
+ {
+ csv_template_size = BUFSIZE;
+ CALLOC(csv_template, u8, csv_template_size);
+ strncpy((char*)csv_template, buf, BUFSIZE - 1);
+ *(csv_template + buf_len) = 0;
+ }
+ else
+ {
+ if (strlen((char*)csv_template) + buf_len
+ > csv_template_size)
+ {
+ csv_template_size += BUFSIZE;
+ REALLOC(csv_template, u8, csv_template_size);
+ }
+ strncat((char*)csv_template, buf,
+ csv_template_size - strlen((char*)csv_template)
+ - 1);
+ }
+ }
+ else
+ vfprintf(output, fmt, args);
+ va_end(args);
+ return 0;
}
-#define PIPE_READ_INDEX 0
+#define PIPE_READ_INDEX 0
#define PIPE_WRITE_INDEX 1
int
-print_command(const char* command,
- const u8* pass_arguments[], const u8* pipe_arguments[],
- FILE* output, BOOL strip_newlines)
+print_command(const char* command, const u8* pass_arguments[],
+ const u8* pipe_arguments[], FILE* output, BOOL strip_newlines)
{
- if (!command || !pass_arguments)
- exit(error(EINVAL, (u8*)"print_command: Invalid argument"));
-
- pid_t pid = 0;
- int arg_pipe_fds[2];
- int output_pipe_fds[2];
- int pstatus = 0;
-
- pipe(arg_pipe_fds);
- pipe(output_pipe_fds);
- pid = fork();
- if (pid == 0)
- {
- close(arg_pipe_fds[PIPE_WRITE_INDEX]);
- close(output_pipe_fds[PIPE_READ_INDEX]);
-
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-
- dup2(arg_pipe_fds[PIPE_READ_INDEX], STDIN_FILENO);
- dup2(output_pipe_fds[PIPE_WRITE_INDEX], STDOUT_FILENO);
-
- execvp(command, (char* const*)pass_arguments);
- exit(1);
- }
- else if (pid < 0)
- exit(error(errno, (u8*)"Fork failed"));
-
- /* Parent */
- close(arg_pipe_fds[PIPE_READ_INDEX]);
- close(output_pipe_fds[PIPE_WRITE_INDEX]);
- FILE* cmd_input = fdopen(arg_pipe_fds[PIPE_WRITE_INDEX], "w");
- FILE* cmd_output = fdopen(output_pipe_fds[PIPE_READ_INDEX], "r");
-
- if (!cmd_input || !cmd_output)
- exit(error(1, (u8*)"Cannot fdopen"));
-
- if (pipe_arguments)
- {
- const u8** ppipe_argument = pipe_arguments;
- while (ppipe_argument && *ppipe_argument)
- {
- fprintf(cmd_input, "%s\n", *ppipe_argument);
- ppipe_argument++;
- }
- }
- fclose(cmd_input);
-
- u8* cmd_output_line = NULL;
- CALLOC(cmd_output_line, u8, BUFSIZE);
- while (!feof(cmd_output))
- {
- if (!fgets((char*)cmd_output_line, BUFSIZE, cmd_output))
- continue;
-
- char* eol = strchr((char*)cmd_output_line, '\n');
- if (eol)
- *eol = 0;
-
- print_output(output, "%s%s", cmd_output_line,
- strip_newlines ? "" : "\n");
- }
- if (!strip_newlines)
- output_firstcol = TRUE;
- free(cmd_output_line);
-
- fclose(cmd_output);
-
- kill(pid, SIGKILL);
- pid_t wpid = waitpid(pid, &pstatus, 0);
- if (wpid < 0)
- warning(pstatus, (u8*)"Child returned nonzero status, errno = %d",
- errno);
- if (WIFEXITED(pstatus))
- return WEXITSTATUS(pstatus);
-
- return wpid;
+ if (!command || !pass_arguments)
+ exit(error(EINVAL, (u8*)"print_command: Invalid argument"));
+
+ pid_t pid = 0;
+ int arg_pipe_fds[2];
+ int output_pipe_fds[2];
+ int pstatus = 0;
+
+ pipe(arg_pipe_fds);
+ pipe(output_pipe_fds);
+ pid = fork();
+ if (pid == 0)
+ {
+ close(arg_pipe_fds[PIPE_WRITE_INDEX]);
+ close(output_pipe_fds[PIPE_READ_INDEX]);
+
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+
+ dup2(arg_pipe_fds[PIPE_READ_INDEX], STDIN_FILENO);
+ dup2(output_pipe_fds[PIPE_WRITE_INDEX], STDOUT_FILENO);
+
+ execvp(command, (char* const*)pass_arguments);
+ exit(1);
+ }
+ else if (pid < 0)
+ exit(error(errno, (u8*)"Fork failed"));
+
+ /* Parent */
+ close(arg_pipe_fds[PIPE_READ_INDEX]);
+ close(output_pipe_fds[PIPE_WRITE_INDEX]);
+ FILE* cmd_input = fdopen(arg_pipe_fds[PIPE_WRITE_INDEX], "w");
+ FILE* cmd_output = fdopen(output_pipe_fds[PIPE_READ_INDEX], "r");
+
+ if (!cmd_input || !cmd_output)
+ exit(error(1, (u8*)"Cannot fdopen"));
+
+ if (pipe_arguments)
+ {
+ const u8** ppipe_argument = pipe_arguments;
+ while (ppipe_argument && *ppipe_argument)
+ {
+ fprintf(cmd_input, "%s\n", *ppipe_argument);
+ ppipe_argument++;
+ }
+ }
+ fclose(cmd_input);
+
+ u8* cmd_output_line = NULL;
+ CALLOC(cmd_output_line, u8, BUFSIZE);
+ while (!feof(cmd_output))
+ {
+ if (!fgets((char*)cmd_output_line, BUFSIZE, cmd_output))
+ continue;
+
+ char* eol = strchr((char*)cmd_output_line, '\n');
+ if (eol)
+ *eol = 0;
+
+ print_output(output, "%s%s", cmd_output_line,
+ strip_newlines ? "" : "\n");
+ }
+ if (!strip_newlines)
+ output_firstcol = TRUE;
+ free(cmd_output_line);
+
+ fclose(cmd_output);
+
+ kill(pid, SIGKILL);
+ pid_t wpid = waitpid(pid, &pstatus, 0);
+ if (wpid < 0)
+ warning(pstatus,
+ (u8*)"Child returned nonzero status, errno = %d",
+ errno);
+ if (WIFEXITED(pstatus))
+ return WEXITSTATUS(pstatus);
+
+ return wpid;
}
int
-read_file_into_buffer(u8** buffer, size_t* buffer_size, char* input_filename,
- char** input_dirname, FILE** input)
+read_file_into_buffer(u8** buffer, size_t* buffer_size, char* input_filename,
+ char** input_dirname, FILE** input)
{
- struct stat fs;
- char* slash = NULL;
-
- *input = fopen(input_filename, "r");
- if (!*input)
- return error(ENOENT, (u8*)"No such file: %s", input_filename);
-
- fstat(fileno(*input), &fs);
- if (*buffer)
- free(*buffer);
- *buffer_size = fs.st_size+1;
- CALLOC(*buffer, u8, *buffer_size);
- fread((void*)*buffer, 1, *buffer_size, *input);
-
- if (*input_dirname)
- free(*input_dirname);
-
- slash = strrchr(input_filename, '/');
- if (slash)
- {
- CALLOC(*input_dirname, char, strlen(input_filename)+1);
- char* pinput_dirname = *input_dirname;
- char* pinput_filename = input_filename;
- while (pinput_filename && *pinput_filename
- && pinput_filename != slash)
- *pinput_dirname++ = *pinput_filename++;
- }
- else
- {
- CALLOC(*input_dirname, char, 2);
- **input_dirname = '.';
- }
-
- fclose(*input);
-
- return 0;
+ struct stat fs;
+ char* slash = NULL;
+
+ *input = fopen(input_filename, "r");
+ if (!*input)
+ return error(ENOENT, (u8*)"No such file: %s", input_filename);
+
+ fstat(fileno(*input), &fs);
+ if (*buffer)
+ free(*buffer);
+ *buffer_size = fs.st_size + 1;
+ CALLOC(*buffer, u8, *buffer_size);
+ fread((void*)*buffer, 1, *buffer_size, *input);
+
+ if (*input_dirname)
+ free(*input_dirname);
+
+ slash = strrchr(input_filename, '/');
+ if (slash)
+ {
+ CALLOC(*input_dirname, char, strlen(input_filename) + 1);
+ char* pinput_dirname = *input_dirname;
+ char* pinput_filename = input_filename;
+ while (pinput_filename && *pinput_filename
+ && pinput_filename != slash)
+ *pinput_dirname++ = *pinput_filename++;
+ }
+ else
+ {
+ CALLOC(*input_dirname, char, 2);
+ **input_dirname = '.';
+ }
+
+ fclose(*input);
+
+ return 0;
}
-int read_csv(FILE* output, const char* filename, csv_callback_t callback);
+int
+read_csv(FILE* output, const char* filename, csv_callback_t callback);
int
print_meta_var(FILE* output, u8** csv_header, u8** csv_register)
{
- if (*csv_register && *(csv_register+1))
- {
- u8* pvalue = *(csv_register+1);
- size_t value_len = strlen((char*)pvalue);
- if (*pvalue == '%' && *(pvalue+value_len-1) == '%')
- {
- u8* var_name = NULL;
- var_name = (u8*)strdup((char*)pvalue+1);
- *(var_name+value_len-2) = 0;
- u8* value = get_value(vars, vars_count, var_name, NULL);
-
- if (value)
- print_output(output, "<meta name=\"%s\" content=\"%s\" />\n",
- *csv_register, value);
-
- free(var_name);
- }
- else
- print_output(output, "<meta name=\"%s\" content=\"%s\" />\n",
- *csv_register, *(csv_register+1));
- }
- return 0;
+ if (!*csv_register || !*(csv_register + 1))
+ return 0;
+ u8* pvalue = *(csv_register + 1);
+ size_t value_len = strlen((char*)pvalue);
+ if (*pvalue == '%' && *(pvalue + value_len - 1) == '%')
+ {
+ u8* var_name = NULL;
+ var_name = (u8*)strdup((char*)pvalue + 1);
+ *(var_name + value_len - 2) = 0;
+ u8* value = get_value(vars, vars_count, var_name, NULL);
+
+ if (value)
+ print_output(output,
+ "<meta name=\"%s\" content=\"%s\" />\n",
+ *csv_register, value);
+
+ free(var_name);
+ }
+ else
+ print_output(output, "<meta name=\"%s\" content=\"%s\" />\n",
+ *csv_register, *(csv_register + 1));
+ return 0;
}
int
process_heading_start(FILE* output, UBYTE heading_level, ULONG heading_count)
{
- print_output(output, "<h%d id=\"heading-%lu\">", heading_level, heading_count);
- return 0;
+ print_output(output, "<h%d id=\"heading-%lu\">", heading_level,
+ heading_count);
+ return 0;
}
int
process_heading(u8* token, FILE* output, UBYTE heading_level)
{
- if (!token || strlen((char*)token) < 1)
- warning(1, (u8*)"Empty heading");
+ if (!token || strlen((char*)token) < 1)
+ warning(1, (u8*)"Empty heading");
- print_output(output, "%s</h%d>",
- token ? (char*)token : "", heading_level);
+ print_output(
+ output, "%s</h%d>", token ? (char*)token : "", heading_level);
- return 0;
+ return 0;
}
int
process_git_log(FILE* output)
{
- if (!input_filename)
- return warning(1, (u8*)"Cannot use 'git-log' in stdin");
+ if (!input_filename)
+ return warning(1, (u8*)"Cannot use 'git-log' in stdin");
- char* basename = NULL;
- size_t basename_size = strlen(input_filename)+1;
- CALLOC(basename, char, basename_size);
- char* slash = strrchr(input_filename, '/');
- pid_t result = 0;
+ char* basename = NULL;
+ size_t basename_size = strlen(input_filename) + 1;
+ CALLOC(basename, char, basename_size);
+ char* slash = strrchr(input_filename, '/');
+ pid_t result = 0;
- if (slash)
- strncpy(basename, slash+1, basename_size-1);
- else
- strncpy(basename, input_filename, basename_size-1);
+ if (slash)
+ strncpy(basename, slash + 1, basename_size - 1);
+ else
+ strncpy(basename, input_filename, basename_size - 1);
- u8* pipe_args[] = { (u8*)basename, NULL };
+ u8* pipe_args[] = {(u8*)basename, NULL};
- print_output(output, "<div id=\"git-log\">\nPrevious commit:\n");
- result = print_command(CMD_GIT_LOG,
- (const u8**)CMD_GIT_LOG_ARGS,
- (const u8**)pipe_args, output, FALSE);
+ print_output(output, "<div id=\"git-log\">\nPrevious commit:\n");
+ result = print_command(CMD_GIT_LOG, (const u8**)CMD_GIT_LOG_ARGS,
+ (const u8**)pipe_args, output, FALSE);
- print_output(output, "</div><!--git-log-->\n");
- output_firstcol = TRUE;
+ print_output(output, "</div><!--git-log-->\n");
+ output_firstcol = TRUE;
- free(basename);
+ free(basename);
- return result ? warning(result, (u8*)"git-log: Cannot run git") : 0;
+ return result ? warning(result, (u8*)"git-log: Cannot run git") : 0;
}
-#define PRINTIF(format, arg) do { \
- if ((ALL(csv_state, ST_CS_COND_NONEMPTY) \
- && *csv_register[conditional_index-1]) \
- || (ALL(csv_state, ST_CS_COND_EMPTY) \
- && !*csv_register[conditional_index-1]) \
- || !ANY(csv_state, ST_CS_COND_EMPTY | ST_CS_COND_NONEMPTY)) \
- { fprintf(output, format, arg); } } while (0)
+#define PRINTIF(format, arg) \
+ do \
+ { \
+ if ((ALL(csv_state, ST_CS_COND_NONEMPTY) \
+ && *csv_register[conditional_index - 1]) \
+ || (ALL(csv_state, ST_CS_COND_EMPTY) \
+ && !*csv_register[conditional_index - 1]) \
+ || !ANY(csv_state, \
+ ST_CS_COND_EMPTY | ST_CS_COND_NONEMPTY)) \
+ { \
+ fprintf(output, format, arg); \
+ } \
+ } while (0)
int
print_csv_row(FILE* output, u8** csv_header, u8** csv_register)
{
- u8* pcsv_template = csv_template;
- UBYTE csv_state = ST_CS_NONE;
- UBYTE num = 0;
- UBYTE conditional_index = 0;
-
- while (*pcsv_template)
- {
- if (csv_state & ST_CS_ESCAPE)
- {
- PRINTIF("%c", *pcsv_template);
- csv_state &= ~ST_CS_ESCAPE;
- pcsv_template++;
- continue;
- }
-
- switch (*pcsv_template)
- {
- case '\\':
- csv_state |= ST_CS_ESCAPE;
- pcsv_template++;
- break;
- case '$':
- if (csv_state & ST_CS_REGISTER)
- {
- PRINTIF("%c", '$');
- csv_state &= ~ST_CS_REGISTER;
- }
- else
- csv_state |= ST_CS_REGISTER;
- pcsv_template++;
- break;
- case '#':
- if (csv_state & ST_CS_HEADER)
- {
- error(1, (u8*)"csv: Invalid header register mark");
- csv_state &= ~(ST_CS_REGISTER | ST_CS_HEADER);
- }
- else if (csv_state & ST_CS_REGISTER)
- {
- csv_state &= ~ST_CS_REGISTER;
- csv_state |= ST_CS_HEADER;
- }
- else
- PRINTIF("%c", '#');
- pcsv_template++;
- break;
- case '?':
- if (csv_state & ST_CS_COND)
- {
- error(1, (u8*)"csv: Invalid conditional mark");
- csv_state &= ~ST_CS_COND;
- }
- else if (csv_state & ST_CS_REGISTER)
- {
- csv_state &= ~ST_CS_REGISTER;
- csv_state |= ST_CS_COND;
- }
- else
- PRINTIF("%c", '?');
- pcsv_template++;
- break;
- case '!':
- if (ALL(csv_state, ST_CS_COND | ST_CS_COND_NONEMPTY))
- {
- csv_state &= ~(ST_CS_COND | ST_CS_COND_NONEMPTY);
- csv_state |= ST_CS_COND_EMPTY;
- }
- else if (csv_state & ST_CS_COND)
- {
- error(1, (u8*)"Empty conditional before/without nonempty"
- " conditional");
- csv_state &= ~(ST_CS_COND | ST_CS_COND_EMPTY);
- }
- else
- PRINTIF("%c", '!');
- pcsv_template++;
- break;
- case '/':
- if (ALL(csv_state, ST_CS_COND | ST_CS_COND_EMPTY))
- csv_state &= ~(ST_CS_COND | ST_CS_COND_EMPTY);
- else if (ALL(csv_state, ST_CS_COND))
- csv_state &= ~(ST_CS_COND | ST_CS_COND_NONEMPTY);
- else
- PRINTIF("%c", '/');
- pcsv_template++;
- break;
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (csv_state & ST_CS_COND)
- {
- conditional_index = *pcsv_template - '0';
- csv_state &= ~ST_CS_COND;
- csv_state |= ST_CS_COND_NONEMPTY;
- }
- else if (csv_state & ST_CS_HEADER)
- {
- num = *pcsv_template - '0';
- PRINTIF("%s", csv_header[num-1]);
- csv_state &= ~ST_CS_HEADER;
- }
- else if (csv_state & ST_CS_REGISTER)
- {
- num = *pcsv_template - '0';
- PRINTIF("%s", csv_register[num-1]);
- csv_state &= ~ST_CS_REGISTER;
- }
- else
- PRINTIF("%c", *pcsv_template);
- pcsv_template++;
- break;
- default:
- if (csv_state & ST_CS_HEADER)
- {
- error(1, (u8*)"csv: Invalid header register mark");
- csv_state &= ~ST_CS_HEADER;
- }
- else if (csv_state & ST_CS_REGISTER)
- {
- error(1, (u8*)"csv: Invalid register mark");
- csv_state &= ~ST_CS_REGISTER;
- }
- else
- PRINTIF("%c", *pcsv_template);
- pcsv_template++;
- }
- }
- return 0;
+ u8* pcsv_template = csv_template;
+ UBYTE csv_state = ST_CS_NONE;
+ UBYTE num = 0;
+ UBYTE conditional_index = 0;
+
+csv_template_start:
+ if (!*pcsv_template)
+ goto csv_template_done;
+ if (csv_state & ST_CS_ESCAPE)
+ {
+ PRINTIF("%c", *pcsv_template);
+ csv_state &= ~ST_CS_ESCAPE;
+ pcsv_template++;
+ goto csv_template_start;
+ }
+
+ switch (*pcsv_template)
+ {
+ case '\\':
+ csv_state |= ST_CS_ESCAPE;
+ pcsv_template++;
+ break;
+ case '$':
+ if (csv_state & ST_CS_REGISTER)
+ {
+ PRINTIF("%c", '$');
+ csv_state &= ~ST_CS_REGISTER;
+ }
+ else
+ csv_state |= ST_CS_REGISTER;
+ pcsv_template++;
+ break;
+ case '#':
+ if (csv_state & ST_CS_HEADER)
+ {
+ error(1, (u8*)"csv: Invalid header register mark");
+ csv_state &= ~(ST_CS_REGISTER | ST_CS_HEADER);
+ }
+ else if (csv_state & ST_CS_REGISTER)
+ {
+ csv_state &= ~ST_CS_REGISTER;
+ csv_state |= ST_CS_HEADER;
+ }
+ else
+ PRINTIF("%c", '#');
+ pcsv_template++;
+ break;
+ case '?':
+ if (csv_state & ST_CS_COND)
+ {
+ error(1, (u8*)"csv: Invalid conditional mark");
+ csv_state &= ~ST_CS_COND;
+ }
+ else if (csv_state & ST_CS_REGISTER)
+ {
+ csv_state &= ~ST_CS_REGISTER;
+ csv_state |= ST_CS_COND;
+ }
+ else
+ PRINTIF("%c", '?');
+ pcsv_template++;
+ break;
+ case '!':
+ if (ALL(csv_state, ST_CS_COND | ST_CS_COND_NONEMPTY))
+ {
+ csv_state &= ~(ST_CS_COND | ST_CS_COND_NONEMPTY);
+ csv_state |= ST_CS_COND_EMPTY;
+ }
+ else if (csv_state & ST_CS_COND)
+ {
+ error(1,
+ (u8*)"Empty conditional before/without nonempty"
+ " conditional");
+ csv_state &= ~(ST_CS_COND | ST_CS_COND_EMPTY);
+ }
+ else
+ PRINTIF("%c", '!');
+ pcsv_template++;
+ break;
+ case '/':
+ if (ALL(csv_state, ST_CS_COND | ST_CS_COND_EMPTY))
+ csv_state &= ~(ST_CS_COND | ST_CS_COND_EMPTY);
+ else if (ALL(csv_state, ST_CS_COND))
+ csv_state &= ~(ST_CS_COND | ST_CS_COND_NONEMPTY);
+ else
+ PRINTIF("%c", '/');
+ pcsv_template++;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (csv_state & ST_CS_COND)
+ {
+ conditional_index = *pcsv_template - '0';
+ csv_state &= ~ST_CS_COND;
+ csv_state |= ST_CS_COND_NONEMPTY;
+ }
+ else if (csv_state & ST_CS_HEADER)
+ {
+ num = *pcsv_template - '0';
+ PRINTIF("%s", csv_header[num - 1]);
+ csv_state &= ~ST_CS_HEADER;
+ }
+ else if (csv_state & ST_CS_REGISTER)
+ {
+ num = *pcsv_template - '0';
+ PRINTIF("%s", csv_register[num - 1]);
+ csv_state &= ~ST_CS_REGISTER;
+ }
+ else
+ PRINTIF("%c", *pcsv_template);
+ pcsv_template++;
+ break;
+ default:
+ if (csv_state & ST_CS_HEADER)
+ {
+ error(1, (u8*)"csv: Invalid header register mark");
+ csv_state &= ~ST_CS_HEADER;
+ }
+ else if (csv_state & ST_CS_REGISTER)
+ {
+ error(1, (u8*)"csv: Invalid register mark");
+ csv_state &= ~ST_CS_REGISTER;
+ }
+ else
+ PRINTIF("%c", *pcsv_template);
+ pcsv_template++;
+ }
+ goto csv_template_start;
+csv_template_done:
+ return 0;
}
int
read_csv(FILE* output, const char* filename, csv_callback_t callback)
{
- if (!callback)
- exit(error(EINVAL, (u8*)"read_csv: Invalid callback argument"));
-
- FILE* csv = NULL;
- size_t csv_lineno = 0;
- u8* bufline = NULL;
- u8* pbufline = NULL;
- u8* token = NULL;
- u8* ptoken = NULL;
- size_t token_size = 0;
- UBYTE csv_state = ST_CS_NONE;
- u8* csv_header[MAX_CSV_REGISTERS];
- UBYTE current_header = 0;
- u8* csv_register[MAX_CSV_REGISTERS];
- UBYTE current_register = 0;
- u8* csv_delimiter = get_value(vars, vars_count,
- (u8*)"csv-delimiter", NULL);
-
- if (!(csv = fopen(filename, "rt")))
- exit(error(ENOENT, (u8*)"csv: No such file: %s", filename));
-
- CALLOC(bufline, u8, BUFSIZE);
- token_size = BUFSIZE;
- CALLOC(token, u8, token_size);
- for (UBYTE i = 0; i < MAX_CSV_REGISTERS; i++)
- CALLOC(csv_header[i], u8, BUFSIZE);
- for (UBYTE i = 0; i < MAX_CSV_REGISTERS; i++)
- CALLOC(csv_register[i], u8, BUFSIZE);
-
- while (!feof(csv) && (!csv_iter || csv_lineno <= csv_iter))
- {
- u8* eol = NULL;
- if (!fgets((char*)bufline, BUFSIZE, csv))
- break;
- eol = (u8*)strchr((char*)bufline, '\n');
- if (eol)
- *eol = 0;
-
- pbufline = bufline;
- RESET_TOKEN(token, ptoken, token_size);
- current_register = 0;
- while (*pbufline)
- {
- switch (*pbufline)
- {
- case '"':
- if (csv_state & ST_CS_QUOTE)
- csv_state &= ~ST_CS_QUOTE;
- else
- csv_state |= ST_CS_QUOTE;
- pbufline++;
- break;
- case ';':
- case ',':
- if (csv_state & ST_CS_QUOTE)
- CHECKCOPY(token, ptoken, token_size, pbufline);
- else
- {
- *ptoken = 0;
- if (csv_lineno > 0)
- {
- if (current_register < MAX_CSV_REGISTERS)
- strncpy((char*)csv_register[current_register++],
- (char*)token, BUFSIZE-1);
- }
- else
- {
- if (current_header < MAX_CSV_REGISTERS)
- strncpy((char*)csv_header[current_header++],
- (char*)token, BUFSIZE-1);
- }
- RESET_TOKEN(token, ptoken, token_size);
- pbufline++;
- }
- break;
- default:
- if (csv_state & ST_CS_QUOTE)
- CHECKCOPY(token, ptoken, token_size, pbufline);
- else
- {
- if (csv_delimiter && *pbufline == *csv_delimiter)
- {
- *ptoken = 0;
- if (csv_lineno > 0)
- {
- if (current_register < MAX_CSV_REGISTERS)
- strncpy((char*)csv_register[current_register++],
- (char*)token, BUFSIZE-1);
- }
- else
- {
- if (current_header < MAX_CSV_REGISTERS)
- strncpy((char*)csv_header[current_header++],
- (char*)token, BUFSIZE-1);
- }
- RESET_TOKEN(token, ptoken, token_size);
- pbufline++;
- }
- else
- CHECKCOPY(token, ptoken, token_size, pbufline);
- }
- }
- }
- *ptoken = 0;
- if (csv_lineno > 0)
- {
- if (current_register < MAX_CSV_REGISTERS)
- strncpy((char*)csv_register[current_register++],
- (char*)token, BUFSIZE-1);
- }
- else
- {
- if (current_header < MAX_CSV_REGISTERS)
- strncpy((char*)csv_header[current_header++],
- (char*)token, BUFSIZE-1);
- }
- RESET_TOKEN(token, ptoken, token_size);
-
- if (csv_lineno > 0 && pbufline != bufline)
- (*callback)(output, csv_header, csv_register);
-
- for (UBYTE i = 0; i < MAX_CSV_REGISTERS; i++)
- *csv_register[i] = 0;
- csv_lineno++;
- }
- fclose(csv);
- for (UBYTE i = MAX_CSV_REGISTERS; i > 0; i--)
- free(csv_register[i-1]);
- for (UBYTE i = MAX_CSV_REGISTERS; i > 0; i--)
- free(csv_header[i-1]);
- free(token);
- free(bufline);
-
- return 0;
+ if (!callback)
+ exit(error(EINVAL, (u8*)"read_csv: Invalid callback argument"));
+
+ FILE* csv = NULL;
+ size_t csv_lineno = 0;
+ u8* bufline = NULL;
+ u8* pbufline = NULL;
+ u8* token = NULL;
+ u8* ptoken = NULL;
+ size_t token_size = 0;
+ UBYTE csv_state = ST_CS_NONE;
+ u8* csv_header[MAX_CSV_REGISTERS];
+ UBYTE current_header = 0;
+ u8* csv_register[MAX_CSV_REGISTERS];
+ UBYTE current_register = 0;
+ u8* csv_delimiter
+ = get_value(vars, vars_count, (u8*)"csv-delimiter", NULL);
+
+ if (!(csv = fopen(filename, "rt")))
+ exit(error(ENOENT, (u8*)"csv: No such file: %s", filename));
+
+ CALLOC(bufline, u8, BUFSIZE);
+ token_size = BUFSIZE;
+ CALLOC(token, u8, token_size);
+ for (UBYTE i = 0; i < MAX_CSV_REGISTERS; i++)
+ CALLOC(csv_header[i], u8, BUFSIZE);
+ for (UBYTE i = 0; i < MAX_CSV_REGISTERS; i++)
+ CALLOC(csv_register[i], u8, BUFSIZE);
+
+ while (!feof(csv) && (!csv_iter || csv_lineno <= csv_iter))
+ {
+ u8* eol = NULL;
+ if (!fgets((char*)bufline, BUFSIZE, csv))
+ break;
+ eol = (u8*)strchr((char*)bufline, '\n');
+ if (eol)
+ *eol = 0;
+
+ pbufline = bufline;
+ RESET_TOKEN(token, ptoken, token_size);
+ current_register = 0;
+ csv_bufline_start:
+ if (!*pbufline)
+ goto csv_bufline_done;
+ switch (*pbufline)
+ {
+ case '"':
+ if (csv_state & ST_CS_QUOTE)
+ csv_state &= ~ST_CS_QUOTE;
+ else
+ csv_state |= ST_CS_QUOTE;
+ pbufline++;
+ break;
+ case ';':
+ case ',':
+ if (csv_state & ST_CS_QUOTE)
+ CHECKCOPY(token, ptoken, token_size, pbufline);
+ else
+ {
+ *ptoken = 0;
+ if (csv_lineno > 0
+ && current_register < MAX_CSV_REGISTERS)
+ strncpy((char*)csv_register
+ [current_register++],
+ (char*)token, BUFSIZE - 1);
+ else if (csv_lineno <= 0
+ && current_header < MAX_CSV_REGISTERS)
+ strncpy((char*)csv_header[current_header++],
+ (char*)token, BUFSIZE - 1);
+ RESET_TOKEN(token, ptoken, token_size);
+ pbufline++;
+ }
+ break;
+ default:
+ if (csv_state & ST_CS_QUOTE)
+ CHECKCOPY(token, ptoken, token_size, pbufline);
+ else if (csv_delimiter && *pbufline == *csv_delimiter)
+ {
+ *ptoken = 0;
+ if (csv_lineno > 0
+ && current_register < MAX_CSV_REGISTERS)
+ strncpy((char*)csv_register
+ [current_register++],
+ (char*)token, BUFSIZE - 1);
+ else if (csv_lineno <= 0
+ && current_header < MAX_CSV_REGISTERS)
+ strncpy((char*)csv_header[current_header++],
+ (char*)token, BUFSIZE - 1);
+ RESET_TOKEN(token, ptoken, token_size);
+ pbufline++;
+ }
+ else
+ CHECKCOPY(token, ptoken, token_size, pbufline);
+ }
+ goto csv_bufline_start;
+ csv_bufline_done:
+ *ptoken = 0;
+ if (csv_lineno > 0)
+ {
+ if (current_register < MAX_CSV_REGISTERS)
+ strncpy((char*)csv_register[current_register++],
+ (char*)token, BUFSIZE - 1);
+ }
+ else
+ {
+ if (current_header < MAX_CSV_REGISTERS)
+ strncpy((char*)csv_header[current_header++],
+ (char*)token, BUFSIZE - 1);
+ }
+ RESET_TOKEN(token, ptoken, token_size);
+
+ if (csv_lineno > 0 && pbufline != bufline)
+ (*callback)(output, csv_header, csv_register);
+
+ for (UBYTE i = 0; i < MAX_CSV_REGISTERS; i++)
+ *csv_register[i] = 0;
+ csv_lineno++;
+ }
+ fclose(csv);
+ for (UBYTE i = MAX_CSV_REGISTERS; i > 0; i--)
+ free(csv_register[i - 1]);
+ for (UBYTE i = MAX_CSV_REGISTERS; i > 0; i--)
+ free(csv_header[i - 1]);
+ free(token);
+ free(bufline);
+
+ return 0;
}
int
-process_csv(u8* arg_token, FILE* output, BOOL read_yaml_macros_and_links,
- BOOL end_tag)
+process_csv(u8* arg_token, FILE* output, BOOL read_yaml_macros_and_links,
+ BOOL end_tag)
{
- if (end_tag)
- {
- state &= ~ST_CSV_BODY;
-
- if (read_yaml_macros_and_links)
- return 0;
-
- read_csv(output, csv_filename, &print_csv_row);
-
- free(csv_filename);
- csv_filename = NULL;
- free(csv_template);
- csv_template = NULL;
- csv_template_size = 0;
- }
- else
- {
- if (state & ST_CSV_BODY)
- exit(error(1, (u8*)"Can't nest csv directives"));
-
- state |= ST_CSV_BODY;
-
- if (read_yaml_macros_and_links)
- return 0;
-
- csv_iter = 0;
- u8* saveptr = NULL;
- u8* args = (u8*)strtok_r((char*)arg_token, " ", (char**)&saveptr);
- args = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
- if (!args)
- exit(error(EINVAL, (u8*)"csv: Arguments required"));
- size_t args_len = strlen((char*)args);
- if (*args != '"' || *(args + args_len - 1) != '"')
- exit(error(EINVAL, (u8*)"csv: First argument must be a string"));
- if (!csv_filename)
- CALLOC(csv_filename, u8, BUFSIZE);
- u8* args_base = (u8*)strdup((char*)args+1);
- *(args_base + strlen((char*)args_base) - 1) = 0;
- snprintf(csv_filename, BUFSIZE, "%s/%s.csv", input_dirname, (char*)args_base);
- free(args_base);
- args = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
- if (args)
- {
- errno = 0;
- csv_iter = strtol((char*)args, NULL, 10);
- if (errno)
- exit(error(errno, (u8*)"csv: Invalid argument '%s'", args));
- }
- }
-
- return 0;
+ if (end_tag)
+ {
+ state &= ~ST_CSV_BODY;
+
+ if (read_yaml_macros_and_links)
+ return 0;
+
+ read_csv(output, csv_filename, &print_csv_row);
+
+ free(csv_filename);
+ csv_filename = NULL;
+ free(csv_template);
+ csv_template = NULL;
+ csv_template_size = 0;
+ }
+ else
+ {
+ if (state & ST_CSV_BODY)
+ exit(error(1, (u8*)"Can't nest csv directives"));
+
+ state |= ST_CSV_BODY;
+
+ if (read_yaml_macros_and_links)
+ return 0;
+
+ csv_iter = 0;
+ u8* saveptr = NULL;
+ u8* args = (u8*)strtok_r(
+ (char*)arg_token, " ", (char**)&saveptr);
+ args = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
+ if (!args)
+ exit(error(EINVAL, (u8*)"csv: Arguments required"));
+ size_t args_len = strlen((char*)args);
+ if (*args != '"' || *(args + args_len - 1) != '"')
+ exit(error(EINVAL,
+ (u8*)"csv: First argument must be a string"));
+ if (!csv_filename)
+ CALLOC(csv_filename, u8, BUFSIZE);
+ u8* args_base = (u8*)strdup((char*)args + 1);
+ *(args_base + strlen((char*)args_base) - 1) = 0;
+ snprintf(csv_filename, BUFSIZE, "%s/%s.csv", input_dirname,
+ (char*)args_base);
+ free(args_base);
+ args = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
+ if (args)
+ {
+ errno = 0;
+ csv_iter = strtol((char*)args, NULL, 10);
+ if (errno)
+ exit(error(errno,
+ (u8*)"csv: Invalid argument '%s'",
+ args));
+ }
+ }
+
+ return 0;
}
int
process_include(u8* token, FILE* output, BOOL read_yaml_macros_and_links)
{
- if (read_yaml_macros_and_links)
- return 0;
-
- if (!input_filename)
- return warning(1, (u8*)"Cannot use 'include' in stdin");
-
- u8* ptoken = (u8*)strchr((char*)token, ' ');
- char* include_filename = NULL;
- char* pinclude_filename = NULL;
-
- if (!ptoken)
- exit(error(1, (u8*)"Directive 'include' requires"
- " an argument"));
-
- fflush(output);
- pid_t pid = fork();
- int pstatus = 0;
-
- if (pid > 0)
- wait(&pstatus);
- else if (pid == 0)
- {
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-
- CALLOC(include_filename, char, BUFSIZE);
- pinclude_filename = include_filename;
- ptoken++;
- while (ptoken && *ptoken)
- if (*ptoken != '"')
- *pinclude_filename++ = *ptoken++;
- else
- ptoken++;
-
- if (!strcmp(basedir, "."))
- set_basedir(input_dirname, &basedir, &basedir_size);
-
- CALLOC(input_filename, char, BUFSIZE);
- snprintf(input_filename, BUFSIZE, "%s/%s.slw", basedir, include_filename);
- free(include_filename);
-
- FILE* input = NULL;
- FILE* output = stdout;
- u8* buffer = NULL;
- size_t buffer_size = 0;
- int result = 0;
- ULLONG saved_state = ST_NONE;
-
- read_file_into_buffer(&buffer, &buffer_size, input_filename,
- &input_dirname, &input);
-
- free_keyvalue(&links, links_count);
- free(links);
- links = NULL;
- links_count = 0;
-
- free_keyvalue(&footnotes, footnote_count);
- free(footnotes);
- footnotes = NULL;
- footnote_count = 0;
- current_footnote = 0;
-
- while (inline_footnote_count--)
- free(inline_footnotes[inline_footnote_count]);
- if (inline_footnotes)
- free(inline_footnotes);
- inline_footnotes = NULL;
- inline_footnote_count = 0;
- current_inline_footnote = 0;
-
- saved_state = state;
- state = ST_NONE;
-
- /* First pass: read YAML, macros and links */
- result = slweb_parse(buffer, output, TRUE, TRUE);
-
- if (result)
- {
- slweb_cleanup();
- free(buffer);
- return result;
- }
- state = ST_NONE;
- current_footnote = 0;
- current_inline_footnote = 0;
-
- /* Second pass: parse and output */
- result = slweb_parse(buffer, output, TRUE, FALSE);
-
- state = saved_state;
-
- slweb_cleanup();
- free(buffer);
- exit(result);
- }
- else
- exit(error(1, (u8*)"Fork failed"));
-
- return 0;
+ if (read_yaml_macros_and_links)
+ return 0;
+
+ if (!input_filename)
+ return warning(1, (u8*)"Cannot use 'include' in stdin");
+
+ u8* ptoken = (u8*)strchr((char*)token, ' ');
+ char* include_filename = NULL;
+ char* pinclude_filename = NULL;
+
+ if (!ptoken)
+ exit(error(1,
+ (u8*)"Directive 'include' requires"
+ " an argument"));
+
+ fflush(output);
+ pid_t pid = fork();
+ int pstatus = 0;
+
+ if (pid > 0)
+ wait(&pstatus);
+ else if (pid == 0)
+ {
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+
+ CALLOC(include_filename, char, BUFSIZE);
+ pinclude_filename = include_filename;
+ ptoken++;
+ while (ptoken && *ptoken)
+ if (*ptoken != '"')
+ *pinclude_filename++ = *ptoken++;
+ else
+ ptoken++;
+
+ if (!strcmp(basedir, "."))
+ set_basedir(input_dirname, &basedir, &basedir_size);
+
+ CALLOC(input_filename, char, BUFSIZE);
+ snprintf(input_filename, BUFSIZE, "%s/%s.slw", basedir,
+ include_filename);
+ free(include_filename);
+
+ FILE* input = NULL;
+ FILE* output = stdout;
+ u8* buffer = NULL;
+ size_t buffer_size = 0;
+ int result = 0;
+ ULLONG saved_state = ST_NONE;
+
+ read_file_into_buffer(&buffer, &buffer_size, input_filename,
+ &input_dirname, &input);
+
+ free_keyvalue(&links, links_count);
+ free(links);
+ links = NULL;
+ links_count = 0;
+
+ free_keyvalue(&footnotes, footnote_count);
+ free(footnotes);
+ footnotes = NULL;
+ footnote_count = 0;
+ current_footnote = 0;
+
+ while (inline_footnote_count--)
+ free(inline_footnotes[inline_footnote_count]);
+ if (inline_footnotes)
+ free(inline_footnotes);
+ inline_footnotes = NULL;
+ inline_footnote_count = 0;
+ current_inline_footnote = 0;
+
+ saved_state = state;
+ state = ST_NONE;
+
+ /* First pass: read YAML, macros and links */
+ result = slweb_parse(buffer, output, TRUE, TRUE);
+
+ if (result)
+ {
+ slweb_cleanup();
+ free(buffer);
+ return result;
+ }
+ state = ST_NONE;
+ current_footnote = 0;
+ current_inline_footnote = 0;
+
+ /* Second pass: parse and output */
+ result = slweb_parse(buffer, output, TRUE, FALSE);
+
+ state = saved_state;
+
+ slweb_cleanup();
+ free(buffer);
+ exit(result);
+ }
+ else
+ exit(error(1, (u8*)"Fork failed"));
+
+ return 0;
}
int
process_list_start(FILE* output)
{
- fprintf(output, "<ul>");
- return 0;
+ fprintf(output, "<ul>");
+ return 0;
}
int
process_list_item_start(FILE* output)
{
- fprintf(output, "%s<li><p>", output_firstcol ? "" : "\n");
- return 0;
+ fprintf(output, "%s<li><p>", output_firstcol ? "" : "\n");
+ return 0;
}
int
process_list_item_end(FILE* output)
{
- if (state & ST_PARA_OPEN)
- {
- state &= ~ST_PARA_OPEN;
- fprintf(output, "</p>");
- output_firstcol = FALSE;
- }
- fprintf(output, "</li>");
- output_firstcol = FALSE;
- return 0;
+ if (state & ST_PARA_OPEN)
+ {
+ state &= ~ST_PARA_OPEN;
+ fprintf(output, "</p>");
+ output_firstcol = FALSE;
+ }
+ fprintf(output, "</li>");
+ output_firstcol = FALSE;
+ return 0;
}
int
process_list_end(FILE* output)
{
- fprintf(output, "</ul>\n");
- output_firstcol = TRUE;
- return 0;
+ fprintf(output, "</ul>\n");
+ output_firstcol = TRUE;
+ return 0;
}
int
process_numlist_start(FILE* output)
{
- fprintf(output, "<ol>");
- output_firstcol = FALSE;
- return 0;
+ fprintf(output, "<ol>");
+ output_firstcol = FALSE;
+ return 0;
}
int
process_numlist_end(FILE* output)
{
- fprintf(output, "</ol>\n");
- output_firstcol = TRUE;
- return 0;
+ fprintf(output, "</ol>\n");
+ output_firstcol = TRUE;
+ return 0;
}
int
filter_subdirs(const struct dirent* node)
{
- if (!node || ((*node->d_name == '.')
- && (!*(node->d_name+1)
- || ((*(node->d_name+1) == '.')
- && !(*(node->d_name+2))))))
- return 0;
-
- struct stat st;
- char* nodename = NULL;
-
- CALLOC(nodename, char, BUFSIZE);
- snprintf(nodename, BUFSIZE, "%s/%s", incdir, node->d_name);
-
- if (lstat(nodename, &st) < 0 || !S_ISDIR(st.st_mode))
- {
- free(nodename);
- return 0;
- }
-
- free(nodename);
-
- return 1;
+ if (!node
+ || ((*node->d_name == '.')
+ && (!*(node->d_name + 1)
+ || ((*(node->d_name + 1) == '.')
+ && !(*(node->d_name + 2))))))
+ return 0;
+
+ struct stat st;
+ char* nodename = NULL;
+
+ CALLOC(nodename, char, BUFSIZE);
+ snprintf(nodename, BUFSIZE, "%s/%s", incdir, node->d_name);
+
+ if (lstat(nodename, &st) < 0 || !S_ISDIR(st.st_mode))
+ {
+ free(nodename);
+ return 0;
+ }
+
+ free(nodename);
+
+ return 1;
}
int
filter_slw(const struct dirent* node)
{
- if (!node || ((*node->d_name == '.')
- && (!*(node->d_name+1)
- || ((*(node->d_name+1) == '.')
- && !(*(node->d_name+2))))))
- return 0;
-
- size_t node_len = strlen(node->d_name);
- size_t slw_len = strlen(".slw");
-
- if (slw_len >= node_len)
- return 0;
- return !strcmp(node->d_name + strlen(node->d_name) - slw_len, ".slw");
+ if (!node
+ || ((*node->d_name == '.')
+ && (!*(node->d_name + 1)
+ || ((*(node->d_name + 1) == '.')
+ && !(*(node->d_name + 2))))))
+ return 0;
+
+ size_t node_len = strlen(node->d_name);
+ size_t slw_len = strlen(".slw");
+
+ if (slw_len >= node_len)
+ return 0;
+ return !strcmp(node->d_name + strlen(node->d_name) - slw_len, ".slw");
}
-int
+int
reverse_alphacompare(const struct dirent** a, const struct dirent** b)
{
- if (!a || !b)
- return 0;
+ if (!a || !b)
+ return 0;
- return -1 * strcmp((*a)->d_name, (*b)->d_name);
+ return -1 * strcmp((*a)->d_name, (*b)->d_name);
}
int
-process_timestamp(FILE* output, const u8* link_prefix, const char* link,
- u8* permalink_macro, u8* date);
+process_timestamp(FILE* output, const u8* link_prefix, const char* link,
+ u8* permalink_macro, u8* date);
int
process_incdir_subdir(const char* subdirname, const u8* link_prefix,
- FILE* output, BOOL details_open, u8* macro_body)
+ FILE* output, BOOL details_open, u8* macro_body)
{
- print_output(output, "<li>\n<details%s>\n<summary>",
- details_open ? " open" : "");
- if (macro_body)
- fprintf(stdout, "%s", macro_body);
- print_output(output, "%s</summary>\n<div>\n", subdirname);
-
- struct dirent** namelist;
- struct dirent** pnamelist;
- long names_total = 0;
- long names_output;
- char* abs_subdirname = NULL;
-
- CALLOC(abs_subdirname, char, BUFSIZE);
- snprintf(abs_subdirname, BUFSIZE, "%s/%s/%s", basedir, incdir, subdirname);
-
- if ((names_total = scandir(abs_subdirname, &namelist, &filter_slw,
- &reverse_alphacompare)) < 0)
- {
- perror("scandir");
- exit(error(errno, (u8*)"incdir_subdir: scandir '%s' error",
- abs_subdirname));
- }
-
- pnamelist = namelist;
- names_output = 0;
- while (names_output < names_total && pnamelist && *pnamelist)
- {
- int pstatus = 0;
- /*
- *char* basename = strip_ext((*pnamelist)->d_name);
- *char* link = NULL;
- *CALLOC(link, char, BUFSIZE);
- *snprintf(link, BUFSIZE, "%s/%s", subdirname, basename);
- */
-
- fflush(output);
- pid_t pid = fork();
-
- if (pid > 0)
- wait(&pstatus);
- else if (pid == 0)
- {
- set_basedir(abs_subdirname, &basedir, &basedir_size);
- snprintf(input_filename, BUFSIZE, "%s/%s", abs_subdirname,
- (*pnamelist)->d_name);
-
- FILE* input = NULL;
- FILE* output = stdout;
- u8* buffer = NULL;
- size_t buffer_size = 0;
- int result = 0;
- ULLONG saved_state = ST_NONE;
-
- read_file_into_buffer(&buffer, &buffer_size, input_filename,
- &input_dirname, &input);
-
- free_keyvalue(&links, links_count);
- free(links);
- links = NULL;
- links_count = 0;
-
- free_keyvalue(&footnotes, footnote_count);
- free(footnotes);
- footnotes = NULL;
- footnote_count = 0;
- current_footnote = 0;
-
- while (inline_footnote_count--)
- free(inline_footnotes[inline_footnote_count]);
- if (inline_footnotes)
- free(inline_footnotes);
- inline_footnotes = NULL;
- inline_footnote_count = 0;
- current_inline_footnote = 0;
-
- saved_state = state;
- state = ST_NONE;
-
- /* First pass: read YAML, macros and links */
- result = slweb_parse(buffer, output, TRUE, TRUE);
-
- if (result)
- {
- slweb_cleanup();
- free(buffer);
- free(abs_subdirname);
- while (names_total--)
- free(namelist[names_total]);
- free(namelist);
- return result;
- }
-
- state = ST_NONE;
- current_footnote = 0;
- current_inline_footnote = 0;
-
- /* Second pass: parse and output */
- result = slweb_parse(buffer, output, TRUE, FALSE);
-
- state = saved_state;
-
- fflush(output);
- slweb_cleanup();
- free(buffer);
- free(abs_subdirname);
- while (names_total--)
- free(namelist[names_total]);
- free(namelist);
- exit(result);
- }
- else
- exit(error(1, (u8*)"Fork failed"));
-
- pnamelist++;
- names_output++;
- }
-
- while (names_total--)
- free(namelist[names_total]);
- free(namelist);
- free(abs_subdirname);
-
- print_output(output, "</div>\n</details>\n</li>\n");
- output_firstcol = FALSE;
- return 0;
+ print_output(output, "<li>\n<details%s>\n<summary>",
+ details_open ? " open" : "");
+ if (macro_body)
+ fprintf(stdout, "%s", macro_body);
+ print_output(output, "%s</summary>\n<div>\n", subdirname);
+
+ struct dirent** namelist;
+ struct dirent** pnamelist;
+ long names_total = 0;
+ long names_output;
+ char* abs_subdirname = NULL;
+
+ CALLOC(abs_subdirname, char, BUFSIZE);
+ snprintf(abs_subdirname, BUFSIZE, "%s/%s/%s", basedir, incdir,
+ subdirname);
+
+ if ((names_total = scandir(abs_subdirname, &namelist, &filter_slw,
+ &reverse_alphacompare))
+ < 0)
+ {
+ perror("scandir");
+ exit(error(errno, (u8*)"incdir_subdir: scandir '%s' error",
+ abs_subdirname));
+ }
+
+ pnamelist = namelist;
+ names_output = 0;
+ while (names_output < names_total && pnamelist && *pnamelist)
+ {
+ int pstatus = 0;
+ /*
+ *char* basename = strip_ext((*pnamelist)->d_name);
+ *char* link = NULL;
+ *CALLOC(link, char, BUFSIZE);
+ *snprintf(link, BUFSIZE, "%s/%s", subdirname, basename);
+ */
+
+ fflush(output);
+ pid_t pid = fork();
+
+ if (pid > 0)
+ wait(&pstatus);
+ else if (pid == 0)
+ {
+ set_basedir(abs_subdirname, &basedir, &basedir_size);
+ snprintf(input_filename, BUFSIZE, "%s/%s",
+ abs_subdirname, (*pnamelist)->d_name);
+
+ FILE* input = NULL;
+ FILE* output = stdout;
+ u8* buffer = NULL;
+ size_t buffer_size = 0;
+ int result = 0;
+ ULLONG saved_state = ST_NONE;
+
+ read_file_into_buffer(&buffer, &buffer_size,
+ input_filename, &input_dirname, &input);
+
+ free_keyvalue(&links, links_count);
+ free(links);
+ links = NULL;
+ links_count = 0;
+
+ free_keyvalue(&footnotes, footnote_count);
+ free(footnotes);
+ footnotes = NULL;
+ footnote_count = 0;
+ current_footnote = 0;
+
+ while (inline_footnote_count--)
+ free(inline_footnotes[inline_footnote_count]);
+ if (inline_footnotes)
+ free(inline_footnotes);
+ inline_footnotes = NULL;
+ inline_footnote_count = 0;
+ current_inline_footnote = 0;
+
+ saved_state = state;
+ state = ST_NONE;
+
+ /* First pass: read YAML, macros and links */
+ result = slweb_parse(buffer, output, TRUE, TRUE);
+
+ if (result)
+ {
+ slweb_cleanup();
+ free(buffer);
+ free(abs_subdirname);
+ while (names_total--)
+ free(namelist[names_total]);
+ free(namelist);
+ return result;
+ }
+
+ state = ST_NONE;
+ current_footnote = 0;
+ current_inline_footnote = 0;
+
+ /* Second pass: parse and output */
+ result = slweb_parse(buffer, output, TRUE, FALSE);
+
+ state = saved_state;
+
+ fflush(output);
+ slweb_cleanup();
+ free(buffer);
+ free(abs_subdirname);
+ while (names_total--)
+ free(namelist[names_total]);
+ free(namelist);
+ exit(result);
+ }
+ else
+ exit(error(1, (u8*)"Fork failed"));
+
+ pnamelist++;
+ names_output++;
+ }
+
+ while (names_total--)
+ free(namelist[names_total]);
+ free(namelist);
+ free(abs_subdirname);
+
+ print_output(output, "</div>\n</details>\n</li>\n");
+ output_firstcol = FALSE;
+ return 0;
}
int
-process_incdir(u8* token, const u8* link_prefix, FILE* output,
- BOOL read_yaml_macros_and_links)
+process_incdir(u8* token, const u8* link_prefix, FILE* output,
+ BOOL 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);
- size_t arg_len = 0;
- long num = 5;
- u8* macro_body = NULL;
- int names_total = 0;
- struct dirent** namelist;
- struct dirent** pnamelist;
- long names_output;
- BOOL details_open = TRUE;
-
-
- arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
- if (!arg)
- exit(error(1, (u8*)"incdir: Arguments required"));
-
- arg_len = strlen((char*)arg);
-
- if (*arg != '"' || *(arg + arg_len - 1) != '"')
- exit(error(1, (u8*)"incdir: First argument not string"));
-
- incdir = strdup((char*)(arg+1));
- *(incdir + strlen(incdir) - 1) = 0;
-
- arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
- if (!arg)
- exit(error(1, (u8*)"incdir: Second argument required"));
-
- if (*arg == '=')
- macro_body = get_value(macros, macros_count, arg+1, NULL);
- else
- {
- u8* parg = arg;
- while (parg && *parg)
- {
- if (*parg < '0' || *parg > '9')
- exit(error(1, (u8*)"incdir: Non-numeric argument"));
- parg++;
- }
- errno = 0;
- num = strtol((char*)arg, NULL, 10);
- if (errno)
- exit(error(errno, (u8*)"incdir: Invalid parameter 'num'"));
- arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
- if (arg)
- {
- if (*arg != '=')
- {
- free(incdir);
- exit(error(1, (u8*)"incdir: Third argument not macro"));
- }
- macro_body = get_value(macros, macros_count, arg+1, NULL);
- }
- }
-
- print_output(output, "<ul class=\"incdir\">\n");
-
- if ((names_total = scandir(incdir, &namelist, &filter_subdirs,
- &reverse_alphacompare)) < 0)
- {
- perror("scandir");
- exit(error(errno, (u8*)"incdir: scandir '%s' error", incdir));
- }
-
- pnamelist = namelist;
- names_output = 0;
- while (names_output < num && pnamelist && *pnamelist)
- {
- process_incdir_subdir((*pnamelist)->d_name, link_prefix, output,
- details_open, macro_body);
- details_open = FALSE;
- pnamelist++;
- names_output++;
- }
- while (names_total--)
- free(namelist[names_total]);
- free(namelist);
- free(incdir);
-
- print_output(output, "</ul>\n");
- output_firstcol = TRUE;
-
- return 0;
+ 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);
+ size_t arg_len = 0;
+ long num = 5;
+ u8* macro_body = NULL;
+ int names_total = 0;
+ struct dirent** namelist;
+ struct dirent** pnamelist;
+ long names_output;
+ BOOL details_open = TRUE;
+
+ arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
+ if (!arg)
+ exit(error(1, (u8*)"incdir: Arguments required"));
+
+ arg_len = strlen((char*)arg);
+
+ if (*arg != '"' || *(arg + arg_len - 1) != '"')
+ exit(error(1, (u8*)"incdir: First argument not string"));
+
+ incdir = strdup((char*)(arg + 1));
+ *(incdir + strlen(incdir) - 1) = 0;
+
+ arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
+ if (!arg)
+ exit(error(1, (u8*)"incdir: Second argument required"));
+
+ if (*arg == '=')
+ macro_body = get_value(macros, macros_count, arg + 1, NULL);
+ else
+ {
+ u8* parg = arg;
+ while (parg && *parg)
+ {
+ if (*parg < '0' || *parg > '9')
+ exit(error(1,
+ (u8*)"incdir: Non-numeric argument"));
+ parg++;
+ }
+ errno = 0;
+ num = strtol((char*)arg, NULL, 10);
+ if (errno)
+ exit(error(
+ errno, (u8*)"incdir: Invalid parameter 'num'"));
+ arg = (u8*)strtok_r(NULL, " ", (char**)&saveptr);
+ if (arg)
+ {
+ if (*arg != '=')
+ {
+ free(incdir);
+ exit(error(1,
+ (u8*)"incdir: Third argument not "
+ "macro"));
+ }
+ macro_body = get_value(
+ macros, macros_count, arg + 1, NULL);
+ }
+ }
+
+ print_output(output, "<ul class=\"incdir\">\n");
+
+ if ((names_total = scandir(
+ incdir, &namelist, &filter_subdirs, &reverse_alphacompare))
+ < 0)
+ {
+ perror("scandir");
+ exit(error(errno, (u8*)"incdir: scandir '%s' error", incdir));
+ }
+
+ pnamelist = namelist;
+ names_output = 0;
+ while (names_output < num && pnamelist && *pnamelist)
+ {
+ process_incdir_subdir((*pnamelist)->d_name, link_prefix, output,
+ details_open, macro_body);
+ details_open = FALSE;
+ pnamelist++;
+ names_output++;
+ }
+ while (names_total--)
+ free(namelist[names_total]);
+ free(namelist);
+ free(incdir);
+
+ print_output(output, "</ul>\n");
+ output_firstcol = TRUE;
+
+ return 0;
}
BOOL
url_is_local(const char* url);
int
-process_timestamp(FILE* output, const u8* link_prefix, const char* link,
- u8* permalink_macro, u8* date)
+process_timestamp(FILE* output, const u8* link_prefix, const char* link,
+ u8* permalink_macro, u8* date)
{
- u8* day = NULL;
- u8* month = NULL;
- u8* year = NULL;
- u8* formatted_date = NULL;
- u8* ptr = NULL;
- const char* ptimestamp_format = NULL;
- char* in_filename = NULL;
- char* in_line = NULL;
-
- CALLOC(formatted_date, u8, DATEBUFSIZE);
- ptr = NULL;
- year = (u8*)strtok_r((char*)date, "-", (char**)&ptr);
- if (year)
- {
- month = (u8*)strtok_r(NULL, "-", (char**)&ptr);
- if (month)
- {
- day = (u8*)strtok_r(NULL, "T", (char**)&ptr);
- if (day)
- {
- ptimestamp_format = timestamp_format;
- while (*ptimestamp_format)
- {
- if (*ptimestamp_format == 'd'
- || *ptimestamp_format == 'D')
- strncat((char*)formatted_date, (char*)day,
- DATEBUFSIZE-strlen((char*)formatted_date)-1);
- else if (*ptimestamp_format == 'm'
- || *ptimestamp_format == 'M')
- strncat((char*)formatted_date, (char*)month,
- DATEBUFSIZE-strlen((char*)formatted_date)-1);
- else if (*ptimestamp_format == 'y'
- || *ptimestamp_format == 'Y')
- strncat((char*)formatted_date, (char*)year,
- DATEBUFSIZE-strlen((char*)formatted_date)-1);
- else
- *(formatted_date + strlen((char*)formatted_date))
- = *ptimestamp_format;
-
- ptimestamp_format++;
- }
- print_output(output, "<a href=\"%s%s%s\""
- " class=\"timestamp\">%s%s</a>\n",
- url_is_local(link) && global_link_prefix
- ? (const char*)global_link_prefix : "",
- url_is_local(link) && link_prefix
- ? (const char*)link_prefix : "",
- link,
- permalink_macro ? (char*)permalink_macro : "",
- formatted_date);
- output_firstcol = TRUE;
- }
- }
- }
-
- free(formatted_date);
- free(in_line);
- free(in_filename);
-
- return 0;
+ u8* day = NULL;
+ u8* month = NULL;
+ u8* year = NULL;
+ u8* formatted_date = NULL;
+ u8* ptr = NULL;
+ const char* ptimestamp_format = NULL;
+ char* in_filename = NULL;
+ char* in_line = NULL;
+
+ CALLOC(formatted_date, u8, DATEBUFSIZE);
+ ptr = NULL;
+ year = (u8*)strtok_r((char*)date, "-", (char**)&ptr);
+ if (!year)
+ goto process_timestamp_cleanup;
+ month = (u8*)strtok_r(NULL, "-", (char**)&ptr);
+ if (!month)
+ goto process_timestamp_cleanup;
+ day = (u8*)strtok_r(NULL, "T", (char**)&ptr);
+ if (!day)
+ goto process_timestamp_cleanup;
+ ptimestamp_format = timestamp_format;
+ while (*ptimestamp_format)
+ {
+ if (*ptimestamp_format == 'd' || *ptimestamp_format == 'D')
+ strncat((char*)formatted_date, (char*)day,
+ DATEBUFSIZE - strlen((char*)formatted_date) - 1);
+ else if (*ptimestamp_format == 'm' || *ptimestamp_format == 'M')
+ strncat((char*)formatted_date, (char*)month,
+ DATEBUFSIZE - strlen((char*)formatted_date) - 1);
+ else if (*ptimestamp_format == 'y' || *ptimestamp_format == 'Y')
+ strncat((char*)formatted_date, (char*)year,
+ DATEBUFSIZE - strlen((char*)formatted_date) - 1);
+ else
+ *(formatted_date + strlen((char*)formatted_date))
+ = *ptimestamp_format;
+
+ ptimestamp_format++;
+ }
+ print_output(output,
+ "<a href=\"%s%s%s\""
+ " class=\"timestamp\">%s%s</a>\n",
+ url_is_local(link) && global_link_prefix
+ ? (const char*)global_link_prefix
+ : "",
+ url_is_local(link) && link_prefix ? (const char*)link_prefix
+ : "",
+ link, permalink_macro ? (char*)permalink_macro : "",
+ formatted_date);
+ output_firstcol = TRUE;
+process_timestamp_cleanup:
+
+ free(formatted_date);
+ free(in_line);
+ free(in_filename);
+
+ return 0;
}
int
-process_macro(u8* token, FILE* output, BOOL read_yaml_macros_and_links,
- BOOL end_tag)
+process_macro(
+ u8* token, FILE* output, BOOL read_yaml_macros_and_links, BOOL end_tag)
{
- if (!end_tag)
- {
- if (state & ST_MACRO_BODY)
- exit(error(1, (u8*)"Macro undefined or nested"));
-
- BOOL seen = FALSE;
- u8* macro_body = get_value(macros, macros_count, token+1,
- read_yaml_macros_and_links ? NULL : &seen);
-
- if (macro_body)
- {
- if (!read_yaml_macros_and_links)
- {
- if (seen)
- {
- u8* eol = (u8*)strrchr((char*)macro_body, '\n');
- size_t macro_body_len = strlen((char*)macro_body);
- if (eol)
- output_firstcol = macro_body + macro_body_len -
- (u8*)strrchr((char*)macro_body, '\n') > 0;
- else
- output_firstcol = !*macro_body
- || *(macro_body+macro_body_len-1) == '\n';
- print_output(output, "%s", macro_body);
- }
- else
- state |= ST_MACRO_BODY;
- }
- }
- else
- {
- if (read_yaml_macros_and_links)
- {
- macros_count++;
-
- if (!macros)
- {
- CALLOC(macros, KeyValue, macros_count);
- pmacros = macros;
- }
- else
- {
- REALLOC(macros, KeyValue, macros_count * sizeof(KeyValue));
- pmacros = macros + macros_count - 1;
- }
- CALLOC(pmacros->key, u8, KEYSIZE);
- pmacros->seen = FALSE;
- strncpy((char*)pmacros->key, (char*)token+1, KEYSIZE-1);
- pmacros->value = NULL;
- pmacros->value_size = 0;
- }
- state |= ST_MACRO_BODY;
- }
- }
- else
- state &= ~ST_MACRO_BODY;
-
- return 0;
+ if (!end_tag)
+ {
+ if (state & ST_MACRO_BODY)
+ exit(error(1, (u8*)"Macro undefined or nested"));
+
+ BOOL seen = FALSE;
+ u8* macro_body = get_value(macros, macros_count, token + 1,
+ read_yaml_macros_and_links ? NULL : &seen);
+
+ if (macro_body && !read_yaml_macros_and_links)
+ {
+ if (seen)
+ {
+ u8* eol = (u8*)strrchr((char*)macro_body, '\n');
+ size_t macro_body_len
+ = strlen((char*)macro_body);
+ if (eol)
+ output_firstcol = macro_body
+ + macro_body_len
+ - (u8*)strrchr(
+ (char*)macro_body,
+ '\n')
+ > 0;
+ else
+ output_firstcol = !*macro_body
+ || *(macro_body + macro_body_len
+ - 1)
+ == '\n';
+ print_output(output, "%s", macro_body);
+ }
+ else
+ state |= ST_MACRO_BODY;
+ }
+ else if (!macro_body)
+ {
+ if (read_yaml_macros_and_links)
+ {
+ macros_count++;
+
+ if (!macros)
+ {
+ CALLOC(macros, KeyValue, macros_count);
+ pmacros = macros;
+ }
+ else
+ {
+ REALLOC(macros, KeyValue,
+ macros_count * sizeof(KeyValue));
+ pmacros = macros + macros_count - 1;
+ }
+ CALLOC(pmacros->key, u8, KEYSIZE);
+ pmacros->seen = FALSE;
+ strncpy((char*)pmacros->key, (char*)token + 1,
+ KEYSIZE - 1);
+ pmacros->value = NULL;
+ pmacros->value_size = 0;
+ }
+ state |= ST_MACRO_BODY;
+ }
+ }
+ else
+ state &= ~ST_MACRO_BODY;
+
+ return 0;
}
int
-process_tag(u8* token, const u8* link_prefix, FILE* output,
- BOOL read_yaml_macros_and_links, BOOL* skip_eol, BOOL end_tag)
+process_tag(u8* token, const u8* link_prefix, FILE* output,
+ BOOL read_yaml_macros_and_links, BOOL* skip_eol, BOOL end_tag)
{
- if (!token || strlen((char*)token) < 1)
- return warning(1, (u8*)"%s:%ld:%ld: Empty tag name",
- input_filename, lineno, colno);
-
- if (!strcmp((char*)token, "git-log")
- && !read_yaml_macros_and_links) /* {git-log} */
- {
- process_git_log(output);
- }
- else if (!strcmp((char*)token, "made-by")
- && !read_yaml_macros_and_links) /* {made-by} */
- {
- print_output(output, "<div id=\"made-by\">\n"
- "Generated by <a href=\"%s\">"
- "slweb</a>\n"
- "© %s Strahinya Radich.\n"
- "</div><!--made-by-->\n",
- MADEBY_URL,
- COPYRIGHTYEAR);
- output_firstcol = TRUE;
- }
- else if (startswith((char*)token, "csv")) /* {csv} */
- {
- process_csv(token, output, read_yaml_macros_and_links, end_tag);
- }
- else if (startswith((char*)token, "include")) /* {include} */
- {
- process_include(token, output, read_yaml_macros_and_links);
- *skip_eol = TRUE;
- }
- else if (startswith((char*)token, "incdir")) /* {incdir} */
- {
- process_incdir(token, link_prefix, output, read_yaml_macros_and_links);
- *skip_eol = TRUE;
- }
- else if (*token == '=') /* {=macro} */
- {
- process_macro(token, output, read_yaml_macros_and_links, end_tag);
- *skip_eol = TRUE;
- }
- else if (!read_yaml_macros_and_links) /* general tags */
- {
- print_output(output, "<");
- if (end_tag)
- print_output(output, "/");
-
- if (*token == '.' || *token == '#')
- {
- print_output(output, "div");
- }
-
- while (*token && *token != '#' && *token != '.')
- print_output(output, "%c", *token++);
-
- if (!end_tag)
- {
- if (*token == '#')
- {
- token++;
- print_output(output, " id=\"");
- while (*token && *token != '.')
- print_output(output, "%c", *token++);
- print_output(output, "\"");
- if (*token == '.')
- {
- token++;
- print_output(output, " class=\"");
- while (*token)
- print_output(output, "%c", *token++);
- print_output(output, "\"");
- }
- }
- else if (*token == '.')
- {
- token++;
- print_output(output, " class=\"");
- while (*token && *token != '#')
- print_output(output, "%c", *token++);
- print_output(output, "\"");
- if (*token == '#')
- {
- token++;
- print_output(output, " id=\"");
- while (*token)
- print_output(output, "%c", *token++);
- print_output(output, "\"");
- }
- }
- }
- print_output(output, ">");
- output_firstcol = FALSE;
- }
-
- return 0;
+ if (!token || strlen((char*)token) < 1)
+ return warning(1, (u8*)"%s:%ld:%ld: Empty tag name",
+ input_filename, lineno, colno);
+
+ if (!strcmp((char*)token, "git-log")
+ && !read_yaml_macros_and_links) /* {git-log} */
+ {
+ process_git_log(output);
+ }
+ else if (!strcmp((char*)token, "made-by")
+ && !read_yaml_macros_and_links) /* {made-by} */
+ {
+ print_output(output,
+ "<div id=\"made-by\">\n"
+ "Generated by <a href=\"%s\">"
+ "slweb</a>\n"
+ "© %s Strahinya Radich.\n"
+ "</div><!--made-by-->\n",
+ MADEBY_URL, COPYRIGHTYEAR);
+ output_firstcol = TRUE;
+ }
+ else if (startswith((char*)token, "csv")) /* {csv} */
+ {
+ process_csv(token, output, read_yaml_macros_and_links, end_tag);
+ }
+ else if (startswith((char*)token, "include")) /* {include} */
+ {
+ process_include(token, output, read_yaml_macros_and_links);
+ *skip_eol = TRUE;
+ }
+ else if (startswith((char*)token, "incdir")) /* {incdir} */
+ {
+ process_incdir(
+ token, link_prefix, output, read_yaml_macros_and_links);
+ *skip_eol = TRUE;
+ }
+ else if (*token == '=') /* {=macro} */
+ {
+ process_macro(
+ token, output, read_yaml_macros_and_links, end_tag);
+ *skip_eol = TRUE;
+ }
+ else if (!read_yaml_macros_and_links) /* general tags */
+ {
+ print_output(output, "<");
+ if (end_tag)
+ print_output(output, "/");
+
+ if (*token == '.' || *token == '#')
+ {
+ print_output(output, "div");
+ }
+
+ while (*token && *token != '#' && *token != '.')
+ print_output(output, "%c", *token++);
+
+ if (!end_tag)
+ {
+ if (*token == '#')
+ {
+ token++;
+ print_output(output, " id=\"");
+ while (*token && *token != '.')
+ print_output(output, "%c", *token++);
+ print_output(output, "\"");
+ if (*token == '.')
+ {
+ token++;
+ print_output(output, " class=\"");
+ while (*token)
+ print_output(
+ output, "%c", *token++);
+ print_output(output, "\"");
+ }
+ }
+ else if (*token == '.')
+ {
+ token++;
+ print_output(output, " class=\"");
+ while (*token && *token != '#')
+ print_output(output, "%c", *token++);
+ print_output(output, "\"");
+ if (*token == '#')
+ {
+ token++;
+ print_output(output, " id=\"");
+ while (*token)
+ print_output(
+ output, "%c", *token++);
+ print_output(output, "\"");
+ }
+ }
+ }
+ print_output(output, ">");
+ output_firstcol = FALSE;
+ }
+
+ return 0;
}
int
process_bold(FILE* output, BOOL end_tag)
{
- print_output(output, "<%sstrong>", end_tag ? "/" : "");
- return 0;
+ print_output(output, "<%sstrong>", end_tag ? "/" : "");
+ return 0;
}
int
process_italic(FILE* output, BOOL end_tag)
{
- print_output(output, "<%sem>", end_tag ? "/" : "");
- return 0;
+ print_output(output, "<%sem>", end_tag ? "/" : "");
+ return 0;
}
int
process_code(FILE* output, BOOL end_tag)
{
- print_output(output, "<%scode>", end_tag ? "/" : "");
- return 0;
+ print_output(output, "<%scode>", end_tag ? "/" : "");
+ return 0;
}
int
process_blockquote(FILE* output, BOOL end_tag)
{
- print_output(output, "<%sblockquote>", end_tag ? "/" : "");
- return 0;
+ print_output(output, "<%sblockquote>", end_tag ? "/" : "");
+ return 0;
}
int
process_kbd(FILE* output, BOOL end_tag)
{
- print_output(output, "<%skbd>", end_tag ? "/" : "");
- return 0;
+ print_output(output, "<%skbd>", end_tag ? "/" : "");
+ return 0;
}
int
process_strike(FILE* output, BOOL end_tag)
{
- print_output(output, "<%ss>", end_tag ? "/" : "");
- return 0;
+ print_output(output, "<%ss>", end_tag ? "/" : "");
+ return 0;
}
int
process_table_start(FILE* output)
{
- print_output(output, "<table>\n"
- "<thead>\n<tr><th>");
- return 0;
+ print_output(output,
+ "<table>\n"
+ "<thead>\n<tr><th>");
+ return 0;
}
int
process_table_header_cell(FILE* output)
{
- print_output(output, "</th><th>");
- return 0;
+ print_output(output, "</th><th>");
+ return 0;
}
-int
+int
process_table_header_end(FILE* output)
{
- print_output(output, "</th></tr>\n</thead>\n");
- return 0;
+ print_output(output, "</th></tr>\n</thead>\n");
+ return 0;
}
int
process_table_body_start(FILE* output, BOOL start_row)
{
- print_output(output, "<tbody>\n");
- if (start_row)
- print_output(output, "<tr><td>");
- return 0;
+ print_output(output, "<tbody>\n");
+ if (start_row)
+ print_output(output, "<tr><td>");
+ return 0;
}
int
process_table_body_row_start(FILE* output)
{
- print_output(output, "<tr><td>");
- return 0;
+ print_output(output, "<tr><td>");
+ return 0;
}
int
process_table_body_cell(FILE* output)
{
- print_output(output, "</td><td>");
- return 0;
+ print_output(output, "</td><td>");
+ return 0;
}
int
process_table_body_row_end(FILE* output)
{
- print_output(output, "</td></tr>\n");
- return 0;
+ print_output(output, "</td></tr>\n");
+ return 0;
}
int
process_table_end(FILE* output)
{
- print_output(output, "</tbody>\n</table>\n");
- return 0;
+ print_output(output, "</tbody>\n</table>\n");
+ return 0;
}
BOOL
url_is_local(const char* url)
{
- return !(startswith(url, "http://")
- || startswith(url, "https://")
- || startswith(url, "gemini://")
- || startswith(url, "ftp://")
- || startswith(url, "ftps://")
- || startswith(url, "mailto://"));
+ return !(startswith(url, "http://") || startswith(url, "https://")
+ || startswith(url, "gemini://") || startswith(url, "ftp://")
+ || startswith(url, "ftps://") || startswith(url, "mailto://"));
}
int
get_realpath(char** realpath, char* relativeto, char* path)
{
- u8* command = NULL;
- FILE* cmd_output = NULL;
-
- CALLOC(command, u8, BUFSIZE);
- strncpy(*realpath, ".", BUFSIZE-1);
- snprintf((char*)command, BUFSIZE-1, "realpath --relative-to=%s %s",
- relativeto, path);
-
- cmd_output = popen((char*)command, "r");
- if (cmd_output)
- {
- u8* cmd_output_line = NULL;
- CALLOC(cmd_output_line, u8, BUFSIZE);
- while (!feof(cmd_output))
- {
- if (!fgets((char*)cmd_output_line, BUFSIZE, cmd_output))
- continue;
-
- char* eol = strchr((char*)cmd_output_line, '\n');
- if (eol)
- *eol = 0;
-
- strncpy(*realpath, (char*)cmd_output_line, BUFSIZE-1);
- }
- pclose(cmd_output);
- free(cmd_output_line);
- }
- else
- warning(1, (u8*)"get_realpath: Cannot popen");
-
- free(command);
-
- return 0;
+ u8* command = NULL;
+ FILE* cmd_output = NULL;
+
+ CALLOC(command, u8, BUFSIZE);
+ strncpy(*realpath, ".", BUFSIZE - 1);
+ snprintf((char*)command, BUFSIZE - 1, "realpath --relative-to=%s %s",
+ relativeto, path);
+
+ cmd_output = popen((char*)command, "r");
+ if (cmd_output)
+ {
+ u8* cmd_output_line = NULL;
+ CALLOC(cmd_output_line, u8, BUFSIZE);
+ while (!feof(cmd_output))
+ {
+ if (!fgets((char*)cmd_output_line, BUFSIZE, cmd_output))
+ continue;
+
+ char* eol = strchr((char*)cmd_output_line, '\n');
+ if (eol)
+ *eol = 0;
+
+ strncpy(*realpath, (char*)cmd_output_line, BUFSIZE - 1);
+ }
+ pclose(cmd_output);
+ free(cmd_output_line);
+ }
+ else
+ warning(1, (u8*)"get_realpath: Cannot popen");
+
+ free(command);
+
+ return 0;
}
int
-process_inline_link(u8* link_text, const u8* link_prefix,
- u8* link_macro_body, u8* link_url, FILE* output)
+process_inline_link(u8* link_text, const u8* link_prefix, u8* link_macro_body,
+ u8* link_url, FILE* output)
{
- print_output(output, "<a href=\"%s%s%s\">%s%s</a>",
- global_link_prefix ? (const char*)global_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;
-
- return 0;
+ print_output(output, "<a href=\"%s%s%s\">%s%s</a>",
+ global_link_prefix ? (const char*)global_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;
+
+ return 0;
}
int
-process_link(u8* link_text, const u8* link_prefix,
- u8* link_macro_body, u8* link_id, FILE* output)
+process_link(u8* link_text, const u8* link_prefix, u8* link_macro_body,
+ u8* link_id, FILE* output)
{
- u8* url = get_value(links, links_count, link_id, NULL);
- return process_inline_link(link_text, link_prefix, link_macro_body, url,
- output);
+ u8* url = get_value(links, links_count, link_id, NULL);
+ return process_inline_link(
+ link_text, link_prefix, link_macro_body, url, output);
}
int
-process_inline_image(u8* image_text, const u8* link_prefix,
- u8* image_url, FILE* output, BOOL add_link, BOOL add_figcaption)
+process_inline_image(u8* image_text, const u8* link_prefix, u8* image_url,
+ FILE* output, BOOL add_link, BOOL add_figcaption)
{
- if (add_figcaption)
- print_output(output, "<figure>\n");
-
- if (add_link)
- print_output(output, "<a href=\"%s%s%s\" title=\"%s\" class=\"image\""
- " target=\"_blank\">",
- global_link_prefix ? (const char*)global_link_prefix : "",
- link_prefix ? (const char*)link_prefix : "",
- image_url ? (char*)image_url : "",
- image_text);
-
- print_output(output, "<img src=\"%s\" alt=\"%s\" />",
- image_url ? (char*)image_url : "",
- image_text);
- output_firstcol = FALSE;
-
- if (add_link)
- print_output(output, "</a>");
-
- if (add_figcaption)
- {
- print_output(output, "<figcaption>%s</figcaption>\n</figure>\n",
- image_text);
- output_firstcol = TRUE;
- }
- return 0;
+ if (add_figcaption)
+ print_output(output, "<figure>\n");
+
+ if (add_link)
+ print_output(output,
+ "<a href=\"%s%s%s\" title=\"%s\" class=\"image\""
+ " target=\"_blank\">",
+ global_link_prefix ? (const char*)global_link_prefix
+ : "",
+ link_prefix ? (const char*)link_prefix : "",
+ image_url ? (char*)image_url : "", image_text);
+
+ print_output(output, "<img src=\"%s\" alt=\"%s\" />",
+ image_url ? (char*)image_url : "", image_text);
+ output_firstcol = FALSE;
+
+ if (add_link)
+ print_output(output, "</a>");
+
+ if (add_figcaption)
+ {
+ print_output(output, "<figcaption>%s</figcaption>\n</figure>\n",
+ image_text);
+ output_firstcol = TRUE;
+ }
+ return 0;
}
int
-process_image(u8* image_text, const u8* link_prefix,
- u8* image_id, FILE* output, BOOL add_link, BOOL add_figcaption)
+process_image(u8* image_text, const u8* link_prefix, u8* image_id, FILE* output,
+ BOOL add_link, BOOL add_figcaption)
{
- u8* url = get_value(links, links_count, image_id, NULL);
- return process_inline_image(image_text, link_prefix, url, output, add_link,
- add_figcaption);
+ u8* url = get_value(links, links_count, image_id, NULL);
+ return process_inline_image(
+ image_text, link_prefix, url, output, add_link, add_figcaption);
}
int
-process_line_start(u8* line, const u8* link_prefix,
- BOOL first_line_in_doc, BOOL previous_line_blank,
- BOOL read_yaml_macros_and_links, BOOL list_para, FILE* output,
- u8** token, u8** ptoken)
+process_line_start(u8* line, const u8* link_prefix, BOOL first_line_in_doc,
+ BOOL previous_line_blank, BOOL read_yaml_macros_and_links,
+ BOOL list_para, FILE* output, u8** token, u8** ptoken)
{
- if ((first_line_in_doc || previous_line_blank)
- && !(ANY(state, ST_BLOCKQUOTE | ST_PRE)))
- {
- if (!list_para)
- {
- if (state & ST_LIST)
- {
- state &= ~ST_LIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_list_end(output);
- }
- }
-
- if (state & ST_NUMLIST)
- {
- state &= ~ST_NUMLIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_numlist_end(output);
- }
- }
-
- if (state & ST_FOOTNOTE_TEXT)
- {
- if (!read_yaml_macros_and_links && (state & ST_PARA_OPEN))
- {
- print_output(output, "</p>\n");
- output_firstcol = TRUE;
- }
- state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN);
- }
- }
- if (!ANY(state, ST_TABLE | ST_TABLE_HEADER | ST_TABLE_LINE))
- {
- if (!read_yaml_macros_and_links)
- {
- print_output(output, "<p>");
- output_firstcol = FALSE;
- }
- state |= ST_PARA_OPEN;
- }
- }
- return 0;
+ if ((first_line_in_doc || previous_line_blank)
+ && !(ANY(state, ST_BLOCKQUOTE | ST_PRE)))
+ {
+ if (!list_para)
+ {
+ if (state & ST_LIST)
+ {
+ state &= ~ST_LIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_list_end(output);
+ }
+ }
+
+ if (state & ST_NUMLIST)
+ {
+ state &= ~ST_NUMLIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_numlist_end(output);
+ }
+ }
+
+ if (state & ST_FOOTNOTE_TEXT)
+ {
+ if (!read_yaml_macros_and_links
+ && (state & ST_PARA_OPEN))
+ {
+ print_output(output, "</p>\n");
+ output_firstcol = TRUE;
+ }
+ state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN);
+ }
+ }
+ if (!ANY(state, ST_TABLE | ST_TABLE_HEADER | ST_TABLE_LINE))
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ print_output(output, "<p>");
+ output_firstcol = FALSE;
+ }
+ state |= ST_PARA_OPEN;
+ }
+ }
+ return 0;
}
int
-process_text_token(u8* line, const u8* link_prefix,
- BOOL first_line_in_doc, BOOL previous_line_blank, BOOL
- processed_start_of_line, BOOL read_yaml_macros_and_links,
- BOOL list_para, FILE* output, u8** token, u8** ptoken,
- size_t* token_size, BOOL add_enclosing_paragraph)
+process_text_token(u8* line, const u8* link_prefix, BOOL first_line_in_doc,
+ BOOL previous_line_blank, BOOL processed_start_of_line,
+ BOOL read_yaml_macros_and_links, BOOL list_para, FILE* output,
+ u8** token, u8** ptoken, size_t* token_size,
+ BOOL add_enclosing_paragraph)
{
- if (!(state & ST_YAML))
- {
- if (add_enclosing_paragraph && !processed_start_of_line)
- process_line_start(line, link_prefix, first_line_in_doc,
- previous_line_blank, read_yaml_macros_and_links, list_para,
- output, token, ptoken);
- **ptoken = 0;
- if (**token && !read_yaml_macros_and_links
- && !(state & ST_MACRO_BODY))
- {
- print_output(output, "%s", *token);
- u8* eol = (u8*)strrchr((char*)*token, '\n');
- if (eol)
- output_firstcol = *token + strlen((char*)*token) - eol > 0;
- else
- output_firstcol = FALSE;
- }
- }
- RESET_TOKEN(*token, *ptoken, *token_size);
- return 0;
+ if (!(state & ST_YAML))
+ {
+ if (add_enclosing_paragraph && !processed_start_of_line)
+ process_line_start(line, link_prefix, first_line_in_doc,
+ previous_line_blank, read_yaml_macros_and_links,
+ list_para, output, token, ptoken);
+ **ptoken = 0;
+ if (**token && !read_yaml_macros_and_links
+ && !(state & ST_MACRO_BODY))
+ {
+ print_output(output, "%s", *token);
+ u8* eol = (u8*)strrchr((char*)*token, '\n');
+ if (eol)
+ output_firstcol
+ = *token + strlen((char*)*token) - eol
+ > 0;
+ else
+ output_firstcol = FALSE;
+ }
+ }
+ RESET_TOKEN(*token, *ptoken, *token_size);
+ return 0;
}
int
-process_inline_footnote(u8* token, BOOL read_yaml_macros_and_links,
- FILE* output)
+process_inline_footnote(u8* token, BOOL read_yaml_macros_and_links, FILE* output)
{
- current_inline_footnote++;
-
- if (read_yaml_macros_and_links)
- {
- size_t token_len = strlen((char*)token);
-
- inline_footnote_count++;
- if (inline_footnote_count == 1 && footnote_count > 0)
- warning(1, (u8*)"Both inline and regular footnotes present");
- else if (!inline_footnotes)
- {
- inline_footnote_count = 1;
- CALLOC(inline_footnotes, u8*, inline_footnote_count);
- }
- else
- REALLOC(inline_footnotes, u8*, sizeof(u8*) * inline_footnote_count);
- CALLOC(inline_footnotes[inline_footnote_count-1], u8, token_len+1);
-
- strncpy((char*)inline_footnotes[inline_footnote_count-1], (char*)token,
- token_len);
- *(inline_footnotes[inline_footnote_count-1] + token_len) = 0;
- }
- else
- {
- print_output(output, "<a href=\"#inline-footnote-%d\" "
- "id=\"inline-footnote-text-%d\"><sup>%d</sup></a>",
- current_inline_footnote, current_inline_footnote,
- current_inline_footnote);
- output_firstcol = FALSE;
- }
-
- return 0;
+ current_inline_footnote++;
+
+ if (read_yaml_macros_and_links)
+ {
+ size_t token_len = strlen((char*)token);
+
+ inline_footnote_count++;
+ if (inline_footnote_count == 1 && footnote_count > 0)
+ warning(1,
+ (u8*)"Both inline and regular footnotes "
+ "present");
+ else if (!inline_footnotes)
+ {
+ inline_footnote_count = 1;
+ CALLOC(inline_footnotes, u8*, inline_footnote_count);
+ }
+ else
+ REALLOC(inline_footnotes, u8*,
+ sizeof(u8*) * inline_footnote_count);
+ CALLOC(inline_footnotes[inline_footnote_count - 1], u8,
+ token_len + 1);
+
+ strncpy((char*)inline_footnotes[inline_footnote_count - 1],
+ (char*)token, token_len);
+ *(inline_footnotes[inline_footnote_count - 1] + token_len) = 0;
+ }
+ else
+ {
+ print_output(output,
+ "<a href=\"#inline-footnote-%d\" "
+ "id=\"inline-footnote-text-%d\"><sup>%d</sup></a>",
+ current_inline_footnote, current_inline_footnote,
+ current_inline_footnote);
+ output_firstcol = FALSE;
+ }
+
+ return 0;
}
int
-process_footnote(u8* token, BOOL footnote_definition, BOOL footnote_output,
- FILE* output)
+process_footnote(
+ u8* token, BOOL footnote_definition, BOOL footnote_output, FILE* output)
{
- current_footnote++;
-
- if (footnote_definition)
- {
- footnote_count++;
- if (footnote_count == 1 && inline_footnote_count > 0)
- warning(1, (u8*)"Both inline and regular footnotes present");
- else if (!footnotes)
- {
- CALLOC(footnotes, KeyValue, footnote_count);
- pfootnotes = footnotes;
- }
- else
- {
- REALLOCARRAY(footnotes, KeyValue, footnote_count);
- pfootnotes = footnotes + footnote_count - 1;
- }
- CALLOC(pfootnotes->key, u8, KEYSIZE);
- strncpy((char*)pfootnotes->key, (char*)token, KEYSIZE-1);
- pfootnotes->value = NULL;
- pfootnotes->value_size = 0;
- }
-
- if (footnote_output)
- {
- print_output(output, "<a href=\"#footnote-%d\" id=\"footnote-text-%d\">"
- "<sup>%d</sup></a>",
- current_footnote, current_footnote, current_footnote);
- output_firstcol = FALSE;
- }
-
- return 0;
+ current_footnote++;
+
+ if (footnote_definition)
+ {
+ footnote_count++;
+ if (footnote_count == 1 && inline_footnote_count > 0)
+ warning(1,
+ (u8*)"Both inline and regular footnotes "
+ "present");
+ else if (!footnotes)
+ {
+ CALLOC(footnotes, KeyValue, footnote_count);
+ pfootnotes = footnotes;
+ }
+ else
+ {
+ REALLOCARRAY(footnotes, KeyValue, footnote_count);
+ pfootnotes = footnotes + footnote_count - 1;
+ }
+ CALLOC(pfootnotes->key, u8, KEYSIZE);
+ strncpy((char*)pfootnotes->key, (char*)token, KEYSIZE - 1);
+ pfootnotes->value = NULL;
+ pfootnotes->value_size = 0;
+ }
+
+ if (footnote_output)
+ {
+ print_output(output,
+ "<a href=\"#footnote-%d\" id=\"footnote-text-%d\">"
+ "<sup>%d</sup></a>",
+ current_footnote, current_footnote, current_footnote);
+ output_firstcol = FALSE;
+ }
+
+ return 0;
}
int
process_horizontal_rule(FILE* output)
{
- /* Temporarily break paragraph as hr is para-level */
- if (state & ST_PARA_OPEN)
- print_output(output, "</p>\n");
- print_output(output, "<hr />\n");
- if (state & ST_PARA_OPEN)
- print_output(output, "<p>\n");
- output_firstcol = TRUE;
- return 0;
+ /* Temporarily break paragraph as hr is para-level */
+ if (state & ST_PARA_OPEN)
+ print_output(output, "</p>\n");
+ print_output(output, "<hr />\n");
+ if (state & ST_PARA_OPEN)
+ print_output(output, "<p>\n");
+ output_firstcol = TRUE;
+ return 0;
}
int
process_formula(FILE* output, const u8* token, BOOL display_formula)
{
- int result = 0;
- const u8* pipe_args[] = { token, NULL};
-
- result = print_command(CMD_KATEX,
- display_formula
- ? (const u8**)CMD_KATEX_DISPLAY_ARGS
- : (const u8**)CMD_KATEX_INLINE_ARGS,
- (const u8**)pipe_args, output, TRUE);
-
- if (result)
- {
- print_output(output, "%s$%s$%s",
- display_formula ? "$" : "",
- token,
- display_formula ? "$" : "");
- output_firstcol = FALSE;
- }
-
- return result;
+ int result = 0;
+ const u8* pipe_args[] = {token, NULL};
+
+ result = print_command(CMD_KATEX,
+ display_formula ? (const u8**)CMD_KATEX_DISPLAY_ARGS
+ : (const u8**)CMD_KATEX_INLINE_ARGS,
+ (const u8**)pipe_args, output, TRUE);
+
+ if (result)
+ {
+ print_output(output, "%s$%s$%s", display_formula ? "$" : "",
+ token, display_formula ? "$" : "");
+ output_firstcol = FALSE;
+ }
+
+ return result;
}
int
begin_html_and_head(FILE* output)
{
- u8* lang = get_value(vars, vars_count, (u8*)"lang", NULL);
- u8* site_name = get_value(vars, vars_count, (u8*)"site-name", NULL);
- u8* site_desc = get_value(vars, vars_count, (u8*)"site-desc", NULL);
- u8* canonical = get_value(vars, vars_count, (u8*)"canonical", NULL);
- u8* favicon_url = get_value(vars, vars_count, (u8*)"favicon-url", NULL);
- u8* meta = get_value(vars, vars_count, (u8*)"meta", NULL);
- u8* feed = get_value(vars, vars_count, (u8*)"feed", NULL);
- u8* feed_desc = get_value(vars, vars_count, (u8*)"feed-desc", NULL);
-
- print_output(output, "<!DOCTYPE html>\n"
- "<html lang=\"%s\">\n"
- "<head>\n"
- "<title>%s</title>\n"
- "<meta charset=\"utf-8\" />\n",
- lang ? (char*)lang : "en",
- site_name ? (char*)site_name : "");
-
- char* favicon = NULL;
- CALLOC(favicon, char, BUFSIZE);
- snprintf(favicon, BUFSIZE-1, "%s/favicon.ico", basedir);
- if (!access(favicon, R_OK))
- print_output(output, "<link rel=\"shortcut icon\" type=\"image/x-icon\""
- " href=\"%s\" />\n",
- favicon_url ? (char*)favicon_url : "/favicon.ico");
- free(favicon);
-
- if (meta)
- {
- char* filename = NULL;
- CALLOC(filename, char, BUFSIZE);
- snprintf(filename, BUFSIZE, "%s/%s", input_dirname, (char*)meta);
- read_csv(output, filename, &print_meta_var);
- free(filename);
- }
-
- if (canonical && *canonical)
- print_output(output, "<link rel=\"canonical\" href=\"%s\" />\n",
- (char*)canonical);
-
- if (feed && *feed && feed_desc && *feed_desc)
- print_output(output, "<link rel=\"alternate\""
- " type=\"application/rss+xml\" href=\"%s\" title=\"%s\" />\n",
- (char*)feed, (char*)feed_desc);
-
- if (site_desc && *site_desc)
- print_output(output, "<meta name=\"description\" content=\"%s\" />\n",
- (char*)site_desc);
-
- print_output(output, "<meta name=\"viewport\" content=\"width=device-width,"
- " initial-scale=1\" />\n<meta name=\"generator\" content=\"slweb\" />\n");
- output_firstcol = TRUE;
- return 0;
+ u8* lang = get_value(vars, vars_count, (u8*)"lang", NULL);
+ u8* site_name = get_value(vars, vars_count, (u8*)"site-name", NULL);
+ u8* site_desc = get_value(vars, vars_count, (u8*)"site-desc", NULL);
+ u8* canonical = get_value(vars, vars_count, (u8*)"canonical", NULL);
+ u8* favicon_url = get_value(vars, vars_count, (u8*)"favicon-url", NULL);
+ u8* meta = get_value(vars, vars_count, (u8*)"meta", NULL);
+ u8* feed = get_value(vars, vars_count, (u8*)"feed", NULL);
+ u8* feed_desc = get_value(vars, vars_count, (u8*)"feed-desc", NULL);
+
+ print_output(output,
+ "<!DOCTYPE html>\n"
+ "<html lang=\"%s\">\n"
+ "<head>\n"
+ "<title>%s</title>\n"
+ "<meta charset=\"utf-8\" />\n",
+ lang ? (char*)lang : "en", site_name ? (char*)site_name : "");
+
+ char* favicon = NULL;
+ CALLOC(favicon, char, BUFSIZE);
+ snprintf(favicon, BUFSIZE - 1, "%s/favicon.ico", basedir);
+ if (!access(favicon, R_OK))
+ print_output(output,
+ "<link rel=\"shortcut icon\" type=\"image/x-icon\""
+ " href=\"%s\" />\n",
+ favicon_url ? (char*)favicon_url : "/favicon.ico");
+ free(favicon);
+
+ if (meta)
+ {
+ char* filename = NULL;
+ CALLOC(filename, char, BUFSIZE);
+ snprintf(filename, BUFSIZE, "%s/%s", input_dirname, (char*)meta);
+ read_csv(output, filename, &print_meta_var);
+ free(filename);
+ }
+
+ if (canonical && *canonical)
+ print_output(output, "<link rel=\"canonical\" href=\"%s\" />\n",
+ (char*)canonical);
+
+ if (feed && *feed && feed_desc && *feed_desc)
+ print_output(output,
+ "<link rel=\"alternate\""
+ " type=\"application/rss+xml\" href=\"%s\" "
+ "title=\"%s\" />\n",
+ (char*)feed, (char*)feed_desc);
+
+ if (site_desc && *site_desc)
+ print_output(output,
+ "<meta name=\"description\" content=\"%s\" />\n",
+ (char*)site_desc);
+
+ print_output(output,
+ "<meta name=\"viewport\" content=\"width=device-width,"
+ " initial-scale=1\" />\n<meta name=\"generator\" "
+ "content=\"slweb\" />\n");
+ output_firstcol = TRUE;
+ return 0;
}
int
add_css(FILE* output)
{
- if (!vars)
- return -1;
- KeyValue* pvars = vars;
- while (pvars < vars + vars_count)
- {
- if (!strcmp((char*)pvars->key, "stylesheet"))
- {
- print_output(output, "<link rel=\"stylesheet\" href=\"%s\" />\n",
- pvars->value);
- output_firstcol = TRUE;
- }
- pvars++;
- }
- return 0;
+ if (!vars)
+ return -1;
+ KeyValue* pvars = vars;
+ while (pvars < vars + vars_count)
+ {
+ if (!strcmp((char*)pvars->key, "stylesheet"))
+ {
+ print_output(output,
+ "<link rel=\"stylesheet\" href=\"%s\" />\n",
+ pvars->value);
+ output_firstcol = TRUE;
+ }
+ pvars++;
+ }
+ return 0;
}
int
end_head_start_body(FILE* output)
{
- print_output(output, "</head>\n<body>\n");
- output_firstcol = TRUE;
+ print_output(output, "</head>\n<body>\n");
+ output_firstcol = TRUE;
- return 0;
+ return 0;
}
int
-begin_article(FILE* output, const u8* link_prefix,
- const BOOL 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)
+begin_article(FILE* output, const u8* link_prefix,
+ const BOOL 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)
{
- if (author || date || header_text || title)
- print_output(output, "<header>\n");
-
- if (title)
- print_output(output, "<h%s>%s</h%s>\n",
- title_heading_level ? title_heading_level : "2",
- (char*)title,
- title_heading_level ? title_heading_level : "2");
-
- if (header_text)
- print_output(output, "<p>%s</p>\n", (char*)header_text);
-
- if (author)
- print_output(output, "<address>%s</address>\n", author);
-
-
- if (date && input_filename)
- {
- char* link = strip_ext(input_filename);
- u8* samedir_permalink = get_value(vars, vars_count,
- (u8*)"samedir-permalink", NULL);
- char* real_link = NULL;
- u8* permalink_macro = get_value(macros, macros_count,
- (u8*)"permalink", NULL);
- CALLOC(real_link, char, BUFSIZE);
-
- if (ext_in_permalink)
- strncat(link, timestamp_output_ext, BUFSIZE-strlen(link)-1);
-
- if (permalink_url)
- process_timestamp(output, link_prefix, permalink_url,
- permalink_macro, date);
- else if (samedir_permalink && !strcmp((char*)samedir_permalink, "1"))
- {
- get_realpath(&real_link, input_dirname, link);
- process_timestamp(output, link_prefix, real_link, permalink_macro,
- date);
- }
- else
- process_timestamp(output, link_prefix, link, permalink_macro, date);
-
- free(real_link);
- free(link);
- }
-
- if (author || date || header_text || title)
- print_output(output, "</header>\n");
-
- output_firstcol = author || date || header_text || title;
-
- return 0;
+ if (author || date || header_text || title)
+ print_output(output, "<header>\n");
+
+ if (title)
+ print_output(output, "<h%s>%s</h%s>\n",
+ title_heading_level ? title_heading_level : "2",
+ (char*)title,
+ title_heading_level ? title_heading_level : "2");
+
+ if (header_text)
+ print_output(output, "<p>%s</p>\n", (char*)header_text);
+
+ if (author)
+ print_output(output, "<address>%s</address>\n", author);
+
+ if (date && input_filename)
+ {
+ char* link = strip_ext(input_filename);
+ u8* samedir_permalink = get_value(
+ vars, vars_count, (u8*)"samedir-permalink", NULL);
+ char* real_link = NULL;
+ u8* permalink_macro = get_value(
+ macros, macros_count, (u8*)"permalink", NULL);
+ CALLOC(real_link, char, BUFSIZE);
+
+ if (ext_in_permalink)
+ strncat(link, timestamp_output_ext,
+ BUFSIZE - strlen(link) - 1);
+
+ if (permalink_url)
+ process_timestamp(output, link_prefix, permalink_url,
+ permalink_macro, date);
+ else if (samedir_permalink
+ && !strcmp((char*)samedir_permalink, "1"))
+ {
+ get_realpath(&real_link, input_dirname, link);
+ process_timestamp(output, link_prefix, real_link,
+ permalink_macro, date);
+ }
+ else
+ process_timestamp(output, link_prefix, link,
+ permalink_macro, date);
+
+ free(real_link);
+ free(link);
+ }
+
+ if (author || date || header_text || title)
+ print_output(output, "</header>\n");
+
+ output_firstcol = author || date || header_text || title;
+
+ return 0;
}
int
end_footnotes(FILE* output, BOOL add_footnote_div)
{
- size_t footnote = 0;
-
- if (state & ST_PARA_OPEN)
- {
- print_output(output, "</p>\n");
- output_firstcol = TRUE;
- state &= ~ST_PARA_OPEN;
- }
-
- if (add_footnote_div)
- {
- print_output(output, "<div class=\"footnotes\">\n");
- output_firstcol = TRUE;
- }
-
- process_horizontal_rule(output);
-
- for (footnote = 0; footnote < inline_footnote_count; footnote++)
- {
- print_output(output, "<p id=\"inline-footnote-%d\">"
- "<a href=\"#inline-footnote-text-%d\">%d.</a> %s</p>\n",
- footnote+1, footnote+1, footnote+1,
- (char*)inline_footnotes[footnote]);
- output_firstcol = TRUE;
- }
-
- KeyValue* pfootnote = footnotes;
- footnote = 0;
- while (pfootnote && footnote < footnote_count)
- {
- print_output(output, "<p id=\"footnote-%d\">"
- "<a href=\"#footnote-text-%d\">%d.</a> %s</p>\n",
- footnote+1, footnote+1, footnote+1,
- (char*)pfootnote->value);
- output_firstcol = TRUE;
- pfootnote++;
- footnote++;
- }
-
- if (add_footnote_div)
- {
- print_output(output, "</div><!--footnotes-->\n");
- output_firstcol = TRUE;
- }
-
- return 0;
+ size_t footnote = 0;
+
+ if (state & ST_PARA_OPEN)
+ {
+ print_output(output, "</p>\n");
+ output_firstcol = TRUE;
+ state &= ~ST_PARA_OPEN;
+ }
+
+ if (add_footnote_div)
+ {
+ print_output(output, "<div class=\"footnotes\">\n");
+ output_firstcol = TRUE;
+ }
+
+ process_horizontal_rule(output);
+
+ for (footnote = 0; footnote < inline_footnote_count; footnote++)
+ {
+ print_output(output,
+ "<p id=\"inline-footnote-%d\">"
+ "<a href=\"#inline-footnote-text-%d\">%d.</a> %s</p>\n",
+ footnote + 1, footnote + 1, footnote + 1,
+ (char*)inline_footnotes[footnote]);
+ output_firstcol = TRUE;
+ }
+
+ KeyValue* pfootnote = footnotes;
+ footnote = 0;
+ while (pfootnote && footnote < footnote_count)
+ {
+ print_output(output,
+ "<p id=\"footnote-%d\">"
+ "<a href=\"#footnote-text-%d\">%d.</a> %s</p>\n",
+ footnote + 1, footnote + 1, footnote + 1,
+ (char*)pfootnote->value);
+ output_firstcol = TRUE;
+ pfootnote++;
+ footnote++;
+ }
+
+ if (add_footnote_div)
+ {
+ print_output(output, "</div><!--footnotes-->\n");
+ output_firstcol = TRUE;
+ }
+
+ return 0;
}
int
end_body_and_html(FILE* output)
{
- print_output(output, "</body>\n</html>\n");
- output_firstcol = TRUE;
- return 0;
+ print_output(output, "</body>\n</html>\n");
+ output_firstcol = TRUE;
+ return 0;
}
int
slweb_parse(u8* buffer, FILE* output, BOOL body_only,
- BOOL read_yaml_macros_and_links)
+ BOOL 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* link_prefix = NULL;
- 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;
-
- if (!buffer)
- exit(error(1, (u8*)"Empty buffer"));
-
- title = get_value(vars, vars_count, (u8*)"title", NULL);
- title_heading_level = get_value(vars, vars_count, (u8*)"title-heading-level", NULL);
- header_text = get_value(vars, vars_count, (u8*)"header-text", NULL);
- author = get_value(vars, vars_count, (u8*)"author", NULL);
- date = get_value(vars, vars_count, (u8*)"date", NULL);
- permalink_url = get_value(vars, vars_count, (u8*)"permalink-url", NULL);
- ext_in_permalink = get_value(vars, vars_count, (u8*)"ext-in-permalink", NULL);
- var_add_article_header = get_value(vars, vars_count, (u8*)"add-article-header", NULL);
- var_add_image_links = get_value(vars, vars_count, (u8*)"add-image-links", NULL);
- add_image_links = !(var_add_image_links && *var_add_image_links == '0');
- var_add_figcaption = get_value(vars, vars_count, (u8*)"add-figcaption", NULL);
- add_figcaption = !(var_add_figcaption && *var_add_figcaption == '0');
- var_add_footnote_div = get_value(vars, vars_count, (u8*)"add-footnote-div", NULL);
- add_footnote_div = var_add_footnote_div && *var_add_footnote_div == '1';
- link_prefix = get_value(vars, vars_count, (u8*)"link-prefix", NULL);
-
- CALLOC(line, u8, BUFSIZE);
- token_size = BUFSIZE;
- CALLOC(token, u8, BUFSIZE);
- CALLOC(link_macro, u8, BUFSIZE);
-
- pbuffer = buffer;
- pvars = vars;
- pmacros = macros;
- plinks = links;
- pfootnotes = footnotes;
- lineno = 0;
-
- if (!read_yaml_macros_and_links && !body_only)
- {
- begin_html_and_head(output);
- add_css(output);
- end_head_start_body(output);
- }
-
- if (!read_yaml_macros_and_links)
- begin_article(output, link_prefix,
- var_add_article_header && *var_add_article_header == '1',
- author, title, header_text, (char*)title_heading_level, date,
- ext_in_permalink && *ext_in_permalink != '0',
- (char*)permalink_url);
-
- RESET_TOKEN(token, ptoken, token_size);
-
- do
- {
- u8* eol = (u8*)strchr((char*)pbuffer, '\n');
- if (!eol)
- break;
-
- pline = line;
- while (pbuffer != eol)
- *pline++ = *pbuffer++;
- pbuffer++;
- *pline = 0;
- pline = line;
- line_len = strlen((char*)line);
-
- lineno++;
- colno = 1;
- output_firstcol = TRUE;
- processed_start_of_line = FALSE;
- skip_eol = FALSE;
- /*list_item = FALSE;*/
- list_para = FALSE;
-
- while (pline && *pline)
- {
- switch (*pline)
- {
- case '-':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_MACRO_BODY | ST_PRE | ST_YAML_VAL))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- else if (colno == 1
- && strlen((char*)pline) > 2
- && startswith((char*)pline, "---"))
- {
- skip_eol = TRUE;
-
- if (!(state & ST_YAML) && lineno > 1
- && !read_yaml_macros_and_links)
- process_horizontal_rule(output);
- else
- {
- if (lineno == 1)
- state |= ST_YAML;
- else
- state &= ~ST_YAML;
-
- skip_change_first_line_in_doc = TRUE;
- }
- pline = NULL;
- }
- else if (colno == 1
- && strlen((char*)pline) > 1
- && *(pline+1) == ' ')
- {
- if (state & ST_NUMLIST)
- {
- state &= ~ST_NUMLIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_numlist_end(output);
- }
- }
- if (!read_yaml_macros_and_links)
- {
- if (!(state & ST_LIST))
- process_list_start(output);
- else
- process_list_item_end(output);
- process_list_item_start(output);
- state |= ST_PARA_OPEN;
- }
-
- processed_start_of_line = TRUE;
- skip_eol = FALSE;
-
- state |= ST_LIST;
-
- pline += 2;
- colno += 2;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case ':':
- if (state & ST_YAML
- && !(ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HEADING | ST_IMAGE | ST_MACRO_BODY
- | ST_PRE | ST_TAG | ST_YAML_VAL))
- && read_yaml_macros_and_links)
- {
- *ptoken = 0;
-
- vars_count++;
-
- if (!vars)
- {
- CALLOC(vars, KeyValue, vars_count);
- pvars = vars;
- }
- else
- {
- REALLOCARRAY(vars, KeyValue, vars_count);
- pvars = vars + vars_count - 1;
- }
- CALLOC(pvars->key, u8, KEYSIZE);
- strncpy((char*)pvars->key, (char*)token, KEYSIZE-1);
- pvars->value = NULL;
- pvars->value_size = 0;
-
- state |= ST_YAML_VAL;
- RESET_TOKEN(token, ptoken, token_size);
- pline++;
- colno++;
-
- while (pline && (*pline == ' ' || *pline == '\t'))
- {
- pline++;
- colno++;
- }
- }
- else {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '~':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_IMAGE | ST_LINK_SECOND_ARG
- | ST_LINK_SECOND_ARG_END | ST_MACRO_BODY
- | ST_PRE | ST_TAG | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1 && *(pline+1) == '~')
- {
- /* Handle ~~ within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* entity = (u8*)" ";
- size_t entity_len = strlen((char*)entity);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + entity_len < BUFSIZE)
- {
- strncat((char*)token, (char*)entity,
- BUFSIZE-token_len-1);
- ptoken += entity_len;
- }
- }
- else
- {
- /* Output existing text up to ~~ */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- print_output(output, " ");
- }
-
- pline += 2;
- colno += 2;
- }
- else
- {
- /* Handle ~ within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* tag = state & ST_STRIKE
- ? (u8*)"</s>"
- : (u8*)"<s>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to ~ */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- process_strike(output, state & ST_STRIKE);
- }
-
- state ^= ST_STRIKE;
- pline++;
- colno++;
- }
- break;
-
-
- case '`':
- if (ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
- | ST_MACRO_BODY))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (colno == 1
- && strlen((char*)pline) > 2
- && startswith((char*)pline, "```"))
- {
- state ^= ST_PRE;
-
- if (!read_yaml_macros_and_links)
- {
- if (state & ST_PRE)
- print_output(output, "<pre>");
- else
- print_output(output, "</pre>");
- output_firstcol = FALSE;
- }
-
- /* Skip the rest of the line (language) */
- pline = NULL;
- }
- else if (!ANY(state, ST_PRE | ST_TAG | ST_YAML))
- {
- /* Handle ` within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* tag = state & ST_CODE
- ? (u8*)"</code>"
- : (u8*)"<code>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to ` */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_HEADING)))
- process_code(output, state & ST_CODE);
- }
-
- state ^= ST_CODE;
-
- pline++;
- colno++;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '#':
- if (colno == 1
- && !(ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_MACRO_BODY | ST_PRE | ST_YAML)))
- {
- if (state & ST_LIST)
- {
- state &= ~ST_LIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_list_end(output);
- }
- }
-
- if (state & ST_NUMLIST)
- {
- state &= ~ST_NUMLIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_numlist_end(output);
- }
- }
-
- state |= ST_HEADING;
- heading_level = 1;
- pline++;
- colno++;
- }
- else if (state & ST_HEADING && *(pline-1) == '#')
- {
- if (heading_level < MAX_HEADING_LEVEL)
- heading_level++;
- pline++;
- colno++;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '_':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_IMAGE | ST_LINK_SECOND_ARG
- | ST_LINK_SECOND_ARG_END | ST_MACRO_BODY | ST_PRE
- | ST_TAG | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1 && *(pline+1) == '_')
- {
- /* Handle __ within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* tag = state & ST_BOLD
- ? (u8*)"</strong>"
- : (u8*)"<strong>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to __ */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- process_bold(output, state & ST_BOLD);
- }
-
- state ^= ST_BOLD;
- pline += 2;
- colno += 2;
- }
- else
- {
- /* Handle _ within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* tag = state & ST_ITALIC
- ? (u8*)"</em>"
- : (u8*)"<em>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to _ */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- process_italic(output, state & ST_ITALIC);
- }
-
- state ^= ST_ITALIC;
- pline++;
- colno++;
- }
- break;
-
- case 'o':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_IMAGE | ST_MACRO_BODY | ST_PRE
- | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (colno == 1
- && strlen((char*)pline) > 1
- && *(pline+1) == ' ')
- {
- if (state & ST_NUMLIST)
- {
- state &= ~ST_NUMLIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_numlist_end(output);
- }
- }
- if (!read_yaml_macros_and_links)
- {
- if (!(state & ST_LIST))
- process_list_start(output);
- else
- process_list_item_end(output);
- process_list_item_start(output);
- state |= ST_PARA_OPEN;
- }
-
- processed_start_of_line = TRUE;
- skip_eol = FALSE;
-
- state |= ST_LIST;
-
- pline += 2;
- colno += 2;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '*':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_IMAGE | ST_MACRO_BODY | ST_PRE
- | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- pline_len = strlen((char*)pline);
- if (colno == 1
- && pline_len > 1 && *(pline+1) == '[')
- {
- process_line_start(line, link_prefix, first_line_in_doc,
- previous_line_blank, read_yaml_macros_and_links,
- list_para, output, &token, &ptoken);
-
- /* Ignore abbreviations (for now) */
- pline = NULL;
- }
- else if (colno == 1
- && pline_len > 2 && startswith((char*)pline, "***"))
- {
- skip_eol = TRUE;
- if (!read_yaml_macros_and_links)
- process_horizontal_rule(output);
- pline = NULL;
- }
- else if (colno == 1
- && strlen((char*)pline) > 1
- && *(pline+1) == ' ')
- {
- if (state & ST_NUMLIST)
- {
- state &= ~ST_NUMLIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_numlist_end(output);
- }
- }
- if (!read_yaml_macros_and_links)
- {
- if (!(state & ST_LIST))
- process_list_start(output);
- else
- process_list_item_end(output);
- process_list_item_start(output);
- state |= ST_PARA_OPEN;
- }
-
- processed_start_of_line = TRUE;
- skip_eol = FALSE;
-
- state |= ST_LIST;
-
- pline += 2;
- colno += 2;
- }
- else if (pline_len > 1 && *(pline+1) == '*')
- {
- /* Handle ** within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* tag = state & ST_BOLD
- ? (u8*)"</strong>"
- : (u8*)"<strong>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to * */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- process_bold(output, state & ST_BOLD);
- }
-
- state ^= ST_BOLD;
- pline += 2;
- colno += 2;
- }
- else
- {
- /* Handle * within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
-
- {
- u8* tag = state & ST_ITALIC
- ? (u8*)"</em>"
- : (u8*)"<em>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to * */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- process_italic(output, state & ST_ITALIC);
- }
-
- state ^= ST_ITALIC;
- pline++;
- colno++;
- }
- break;
-
- case ' ':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_IMAGE | ST_MACRO_BODY | ST_PRE | ST_YAML_VAL))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if ((state & ST_HEADING) && !(state & ST_HEADING_TEXT))
- {
- if (!read_yaml_macros_and_links)
- {
- heading_count++;
- process_heading_start(output, heading_level,
- heading_count);
- output_firstcol = FALSE;
- }
- state |= ST_HEADING_TEXT;
- pline++;
- colno++;
- break;
- }
-
- if (colno == 1
- && strlen((char*)pline) > 1
- && startswith((char*)pline, " "))
- {
- list_para = TRUE;
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
- while (*pline == ' ' || *pline == '\t')
- {
- pline++;
- colno++;
- }
- break;
- }
-
- if (strlen((char*)pline) == 2
- && *(pline+1) == ' ')
- {
- *ptoken = 0;
- strncat((char*)ptoken, "<br />",
- BUFSIZE-strlen((char*)token)-1);
- ptoken += strlen("<br />");
- output_firstcol = FALSE;
- pline++;
- colno++;
- }
- else if (state & ST_LINK_MACRO)
- {
- *ptoken = 0;
- strncpy((char*)link_macro, (char*)token, BUFSIZE-1);
- *(link_macro + strlen((char*)token)) = 0;
- RESET_TOKEN(token, ptoken, token_size);
- state &= ~ST_LINK_MACRO;
- }
- else if (!(state & ST_HEADING
- && *(pline-1) == '#'))
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
-
- case '{':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_PRE | ST_YAML | ST_YAML_VAL))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (state & ST_MACRO_BODY)
- {
- *ptoken = 0;
- size_t token_len = strlen((char*)token);
-
- skip_eol = TRUE;
- if (read_yaml_macros_and_links)
- {
- if (!macros)
- {
- macros_count = 1;
- CALLOC(macros, KeyValue, macros_count);
- pmacros = macros;
- }
- if (pmacros->value)
- {
- size_t value_len = strlen((char*)pmacros->value);
-
- if (pmacros->value_size < value_len + token_len + 1)
- {
- pmacros->value_size += token_len;
- REALLOC(pmacros->value, u8, pmacros->value_size);
- }
- strncat((char*)pmacros->value, (char*)token,
- pmacros->value_size-1);
- }
- else
- {
- pmacros->value_size = token_len+1;
- CALLOC(pmacros->value, u8, pmacros->value_size);
- strncpy((char*)pmacros->value, (char*)token,
- pmacros->value_size-1);
- }
- }
- }
- else
- {
- /* Output existing text up to { */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, FALSE);
- processed_start_of_line = TRUE;
- }
-
- state |= ST_TAG;
- RESET_TOKEN(token, ptoken, token_size);
-
- pline++;
- colno++;
- break;
-
- case '/':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_IMAGE | ST_PRE | ST_HEADING | ST_YAML_VAL))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if ((state & ST_TAG) && pline-1 && *(pline-1) == '{')
- {
- end_tag = TRUE;
- pline++;
- }
- else
- CHECKCOPY(token, ptoken, token_size, pline);
-
- colno++;
- break;
-
- case '}':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_IMAGE | ST_PRE | ST_YAML | ST_YAML_VAL))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (state & ST_TAG)
- {
- state &= ~ST_TAG;
- *ptoken = 0;
-
- process_tag(token, link_prefix, output,
- read_yaml_macros_and_links, &skip_eol, end_tag);
-
- RESET_TOKEN(token, ptoken, token_size);
- end_tag = FALSE;
- }
-
- pline++;
- colno++;
- break;
-
- case '|':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_IMAGE | ST_PRE | ST_TAG
- | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1 && *(pline+1) == '|')
- {
- /* Handle || within footnotes, headings and link text specially */
- if (ANY(state, ST_INLINE_FOOTNOTE | ST_HEADING
- | ST_FOOTNOTE_TEXT | ST_LINK))
- {
- u8* tag = state & ST_KBD
- ? (u8*)"</kbd>"
- : (u8*)"<kbd>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
-
- *ptoken = 0;
- token_len = strlen((char*)token);
-
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
- }
- else
- {
- /* Output existing text up to || */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- if (!read_yaml_macros_and_links
- && !(ANY(state, ST_PRE | ST_CODE | ST_HEADING)))
- {
- state ^= ST_KBD;
- process_kbd(output, !(state & ST_KBD));
- output_firstcol = FALSE;
- }
- }
-
- pline += 2;
- colno += 2;
- }
- /* Partial tables (for templating) */
- else if (!(state & ST_PRE) && colno == 1
- && strlen((char*)pline) > 1
- && *(pline+1) == '@')
- {
- skip_eol = TRUE;
-
- pline += 2;
- colno += 2;
-
- switch (*pline)
- {
- case '\\':
- if (!read_yaml_macros_and_links)
- {
- process_table_start(output);
- output_firstcol = FALSE;
- }
- pline = NULL;
- break;
-
- case '#':
- state |= ST_TABLE_HEADER;
- pline++;
- colno++;
- break;
-
- case '-':
- state &= ~ST_TABLE_HEADER;
- if (!read_yaml_macros_and_links)
- {
- process_table_body_start(output, FALSE);
- output_firstcol = TRUE;
- }
- pline = NULL;
- break;
-
- case ' ':
- state |= ST_TABLE;
- if (!read_yaml_macros_and_links)
- {
- process_table_body_row_start(output);
- output_firstcol = FALSE;
- }
- break;
-
- case '/':
- state &= ~ST_TABLE;
- process_table_end(output);
- output_firstcol = TRUE;
- pline = NULL;
- break;
-
- default:
- warning(1, (u8*)"Invalid partial table line");
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- }
- else if (!(state & ST_PRE) && colno == 1)
- {
- skip_eol = TRUE;
-
- if (state & ST_TABLE_HEADER)
- {
- state &= ~ST_TABLE_HEADER;
- state |= ST_TABLE_LINE;
- pline = NULL;
- break;
- }
-
- if (state & ST_TABLE_LINE)
- {
- state &= ~ST_TABLE_LINE;
- state |= ST_TABLE;
- if (!read_yaml_macros_and_links)
- {
- process_table_body_start(output, TRUE);
- output_firstcol = FALSE;
- }
- }
- else if (state & ST_TABLE)
- {
- if (!read_yaml_macros_and_links)
- {
- process_table_body_row_start(output);
- output_firstcol = FALSE;
- }
- }
- else
- {
- state |= ST_TABLE_HEADER;
- if (!read_yaml_macros_and_links)
- {
- process_table_start(output);
- output_firstcol = FALSE;
- }
- }
-
- pline++;
- colno++;
- }
- else if (state & ST_TABLE_HEADER)
- {
- *ptoken = 0;
- if (!read_yaml_macros_and_links)
- {
- print_output(output, "%s", token);
- if (*token)
- output_firstcol = FALSE;
- if (strlen((char*)pline) > 1)
- {
- process_table_header_cell(output);
- output_firstcol = FALSE;
- }
- else
- {
- process_table_header_end(output);
- output_firstcol = TRUE;
- }
- }
- RESET_TOKEN(token, ptoken, token_size);
- pline++;
- colno++;
- }
- else if (state & ST_TABLE)
- {
- *ptoken = 0;
- if (!read_yaml_macros_and_links)
- {
- print_output(output, "%s", token);
- if (*token)
- output_firstcol = FALSE;
- if (strlen((char*)pline) > 1)
- {
- process_table_body_cell(output);
- output_firstcol = FALSE;
- }
- else
- {
- process_table_body_row_end(output);
- output_firstcol = TRUE;
- }
- }
- RESET_TOKEN(token, ptoken, token_size);
- pline++;
- colno++;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '<':
- if (read_yaml_macros_and_links
- || ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_IMAGE))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (ANY(state, ST_CODE | ST_KBD | ST_PRE))
- {
- size_t lt_len = strlen("<");
- *ptoken = 0;
- strncat((char*)token, "<",
- BUFSIZE-(ptoken-token)-1);
- ptoken += lt_len;
- pline++;
- colno++;
- break;
- }
-
- state |= ST_HTML_TAG;
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
-
- case '>':
- if (state & ST_HTML_TAG)
- state &= ~ST_HTML_TAG;
-
- if (ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
- | ST_MACRO_BODY))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (!read_yaml_macros_and_links
- && !ANY(state, ST_CODE | ST_HEADING | ST_PRE)
- && colno == 1)
- {
- if (!read_yaml_macros_and_links
- && !(state & ST_BLOCKQUOTE))
- {
- process_blockquote(output, FALSE);
- output_firstcol = FALSE;
- }
-
- state |= ST_BLOCKQUOTE;
-
- pline++;
- colno++;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '!':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_FOOTNOTE_TEXT | ST_HEADING | ST_IMAGE
- | ST_INLINE_FOOTNOTE | ST_LINK | ST_MACRO_BODY
- | ST_PRE))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1 && *(pline+1) == '[')
- {
- /* Output existing text up to ! */
- *ptoken = 0;
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, FALSE);
- processed_start_of_line = TRUE;
-
- RESET_TOKEN(token, ptoken, token_size);
-
- state |= ST_IMAGE;
- keep_token = TRUE;
- pline += 2;
- colno += 2;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
-
- break;
-
- case '=':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_MACRO_BODY | ST_PRE | ST_TAG))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (colno != 1 && *(pline-1) == '[')
- {
- state |= ST_LINK_MACRO;
- pline++;
- colno++;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '[':
- pline_len = strlen((char*)pline);
-
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HEADING | ST_IMAGE | ST_MACRO_BODY | ST_PRE))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (state & ST_FOOTNOTE_TEXT)
- {
- if (!read_yaml_macros_and_links && (state & ST_PARA_OPEN))
- {
- print_output(output, "</p>\n");
- output_firstcol = TRUE;
- }
- state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN);
- }
-
- if (pline_len > 1 && *(pline+1) == '^')
- {
- footnote_at_line_start = colno == 1;
- if (*token)
- {
- /* Output existing text up to [^ */
- *ptoken = 0;
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- }
- processed_start_of_line = TRUE;
-
- RESET_TOKEN(token, ptoken, token_size);
- state |= ST_FOOTNOTE;
- pline += 2;
- colno += 2;
- break;
- }
- if (*token)
- {
- /* Output existing text up to [ */
- *ptoken = 0;
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- }
- processed_start_of_line = TRUE;
-
- RESET_TOKEN(token, ptoken, token_size);
- state |= ST_LINK;
- keep_token = TRUE;
- *link_macro = 0;
- pline++;
- colno++;
+ 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* link_prefix = NULL;
+ 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;
+
+ if (!buffer)
+ exit(error(1, (u8*)"Empty buffer"));
+
+ title = get_value(vars, vars_count, (u8*)"title", NULL);
+ title_heading_level
+ = get_value(vars, vars_count, (u8*)"title-heading-level", NULL);
+ header_text = get_value(vars, vars_count, (u8*)"header-text", NULL);
+ author = get_value(vars, vars_count, (u8*)"author", NULL);
+ date = get_value(vars, vars_count, (u8*)"date", NULL);
+ permalink_url = get_value(vars, vars_count, (u8*)"permalink-url", NULL);
+ ext_in_permalink
+ = get_value(vars, vars_count, (u8*)"ext-in-permalink", NULL);
+ var_add_article_header
+ = get_value(vars, vars_count, (u8*)"add-article-header", NULL);
+ var_add_image_links
+ = get_value(vars, vars_count, (u8*)"add-image-links", NULL);
+ add_image_links = !(var_add_image_links && *var_add_image_links == '0');
+ var_add_figcaption
+ = get_value(vars, vars_count, (u8*)"add-figcaption", NULL);
+ add_figcaption = !(var_add_figcaption && *var_add_figcaption == '0');
+ var_add_footnote_div
+ = get_value(vars, vars_count, (u8*)"add-footnote-div", NULL);
+ add_footnote_div = var_add_footnote_div && *var_add_footnote_div == '1';
+ link_prefix = get_value(vars, vars_count, (u8*)"link-prefix", NULL);
+
+ CALLOC(line, u8, BUFSIZE);
+ token_size = BUFSIZE;
+ CALLOC(token, u8, BUFSIZE);
+ CALLOC(link_macro, u8, BUFSIZE);
+
+ pbuffer = buffer;
+ pvars = vars;
+ pmacros = macros;
+ plinks = links;
+ pfootnotes = footnotes;
+ lineno = 0;
+
+ if (!read_yaml_macros_and_links && !body_only)
+ {
+ begin_html_and_head(output);
+ add_css(output);
+ end_head_start_body(output);
+ }
+
+ if (!read_yaml_macros_and_links)
+ begin_article(output, link_prefix,
+ var_add_article_header && *var_add_article_header == '1',
+ author, title, header_text, (char*)title_heading_level,
+ date, ext_in_permalink && *ext_in_permalink != '0',
+ (char*)permalink_url);
+
+ RESET_TOKEN(token, ptoken, token_size);
+
+do_buffer:;
+ u8* eol = (u8*)strchr((char*)pbuffer, '\n');
+ if (!eol)
+ goto done_buffer;
+
+ pline = line;
+ while (pbuffer != eol)
+ *pline++ = *pbuffer++;
+ pbuffer++;
+ *pline = 0;
+ pline = line;
+ line_len = strlen((char*)line);
+
+ lineno++;
+ colno = 1;
+ output_firstcol = TRUE;
+ processed_start_of_line = FALSE;
+ skip_eol = FALSE;
+ /*list_item = FALSE;*/
+ list_para = FALSE;
+
+do_line:
+ if (!pline || !*pline)
+ goto done_line;
+ switch (*pline)
+ {
+ case '-':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_MACRO_BODY | ST_PRE | ST_YAML_VAL))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ else if (colno == 1 && strlen((char*)pline) > 2
+ && startswith((char*)pline, "---"))
+ {
+ skip_eol = TRUE;
- if (*pline == '(')
+ if (!(state & ST_YAML) && lineno > 1
+ && !read_yaml_macros_and_links)
+ process_horizontal_rule(output);
+ else
+ {
+ if (lineno == 1)
+ state |= ST_YAML;
+ else
+ state &= ~ST_YAML;
+
+ skip_change_first_line_in_doc = TRUE;
+ }
+ pline = NULL;
+ }
+ else if (colno == 1 && strlen((char*)pline) > 1
+ && *(pline + 1) == ' ')
{
- u8* tag = (u8*)"<span>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
+ if (state & ST_NUMLIST)
+ {
+ state &= ~ST_NUMLIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_numlist_end(output);
+ }
+ }
+ if (!read_yaml_macros_and_links)
+ {
+ if (!(state & ST_LIST))
+ process_list_start(output);
+ else
+ process_list_item_end(output);
+ process_list_item_start(output);
+ state |= ST_PARA_OPEN;
+ }
- *ptoken = 0;
- token_len = strlen((char*)token);
+ processed_start_of_line = TRUE;
+ skip_eol = FALSE;
- if (token_len + tag_len < BUFSIZE)
- {
- strncat((char*)token, (char*)tag, BUFSIZE-token_len-1);
- ptoken += tag_len;
- }
+ state |= ST_LIST;
- state |= ST_LINK_SPAN;
- pline++;
- colno++;
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
}
+ break;
+
+ case ':':
+ if (state & ST_YAML
+ && !(ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HEADING | ST_IMAGE | ST_MACRO_BODY
+ | ST_PRE | ST_TAG | ST_YAML_VAL))
+ && read_yaml_macros_and_links)
+ {
+ *ptoken = 0;
- break;
+ vars_count++;
- case '(':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_FOOTNOTE_TEXT | ST_HEADING
- | ST_INLINE_FOOTNOTE | ST_LINK_SECOND_ARG_END
- | ST_MACRO_BODY | ST_PRE))
- CHECKCOPY(token, ptoken, token_size, pline);
- else if (*link_macro && (state & ST_LINK))
+ if (!vars)
+ {
+ CALLOC(vars, KeyValue, vars_count);
+ pvars = vars;
+ }
+ else
+ {
+ REALLOCARRAY(vars, KeyValue, vars_count);
+ pvars = vars + vars_count - 1;
+ }
+ CALLOC(pvars->key, u8, KEYSIZE);
+ strncpy((char*)pvars->key, (char*)token, KEYSIZE - 1);
+ pvars->value = NULL;
+ pvars->value_size = 0;
+
+ state |= ST_YAML_VAL;
+ RESET_TOKEN(token, ptoken, token_size);
+ pline++;
+ colno++;
+
+ while (pline && (*pline == ' ' || *pline == '\t'))
+ {
+ pline++;
+ colno++;
+ }
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '~':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HTML_TAG | ST_IMAGE | ST_LINK_SECOND_ARG
+ | ST_LINK_SECOND_ARG_END | ST_MACRO_BODY
+ | ST_PRE | ST_TAG | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1 && *(pline + 1) == '~')
+ {
+ /* Handle ~~ within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+ {
+ u8* entity = (u8*)" ";
+ size_t entity_len = strlen((char*)entity);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + entity_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)entity,
+ BUFSIZE - token_len - 1);
+ ptoken += entity_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to ~~ */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ print_output(output, " ");
+ }
+
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ /* Handle ~ within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
{
- u8* tag = (u8*)"<span>";
+ u8* tag = state & ST_STRIKE ? (u8*)"</s>"
+ : (u8*)"<s>";
size_t tag_len = strlen((char*)tag);
size_t token_len = 0;
- *ptoken = 0;
+ *ptoken = 0;
token_len = strlen((char*)token);
if (token_len + tag_len < BUFSIZE)
{
strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
+ BUFSIZE - token_len - 1);
ptoken += tag_len;
}
-
- state |= ST_LINK_SPAN;
- pline++;
}
else
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
-
- case ')':
- if (ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_LINK_SECOND_ARG_END))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
+ {
+ /* Output existing text up to ~ */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ process_strike(
+ output, state & ST_STRIKE);
+ }
- pline_len = strlen((char*)pline);
+ state ^= ST_STRIKE;
+ pline++;
+ colno++;
+ }
+ break;
- if (state & ST_LINK_SPAN && pline_len > 1
- && *(pline+1) == ']')
+ case '`':
+ if (ANY(state,
+ ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
+ | ST_MACRO_BODY))
{
- u8* tag = (u8*)"</span>";
- size_t tag_len = strlen((char*)tag);
- size_t token_len = 0;
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
- *ptoken = 0;
- token_len = strlen((char*)token);
+ if (colno == 1 && strlen((char*)pline) > 2
+ && startswith((char*)pline, "```"))
+ {
+ state ^= ST_PRE;
- if (token_len + tag_len + 1 < BUFSIZE)
+ if (!read_yaml_macros_and_links)
{
- strncat((char*)token, (char*)tag,
- BUFSIZE-token_len-1);
- ptoken += tag_len;
+ if (state & ST_PRE)
+ print_output(output, "<pre>");
+ else
+ print_output(output, "</pre>");
+ output_firstcol = FALSE;
}
- state &= ~ST_LINK_SPAN;
- /*pline += 2;*/
- pline++;
- colno++;
+
+ /* Skip the rest of the line (language) */
+ pline = NULL;
}
- else if (ANY(state, ST_LINK_SECOND_ARG | ST_IMAGE_SECOND_ARG))
- {
- *ptoken = 0;
- if (!read_yaml_macros_and_links)
- {
- if (state & ST_LINK_SECOND_ARG)
- process_inline_link(link_text, link_prefix,
- get_value(macros, macros_count,
- link_macro, NULL),
- token, output);
- else
- process_inline_image(link_text, link_prefix, token,
- output, add_image_links, add_figcaption);
- }
- RESET_TOKEN(token, ptoken, token_size);
- state &= ~(ST_LINK | ST_LINK_SECOND_ARG
- | ST_IMAGE | ST_IMAGE_SECOND_ARG);
- pline++;
- }
- else
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
-
- case ']':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HEADING | ST_MACRO_BODY | ST_PRE))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- *ptoken = 0;
- if (state & ST_INLINE_FOOTNOTE)
- {
- process_inline_footnote(token, read_yaml_macros_and_links,
- output);
-
- keep_token = FALSE;
- RESET_TOKEN(token, ptoken, token_size);
- state &= ~ST_INLINE_FOOTNOTE;
- pline++;
- colno++;
- }
- else if (state & ST_FOOTNOTE)
- {
- BOOL footnote_definition = (strlen((char*)pline) > 1)
- && (*(pline+1) == ':') && footnote_at_line_start;
-
- process_footnote(token,
- footnote_definition && read_yaml_macros_and_links,
- !footnote_definition && !read_yaml_macros_and_links,
- output);
-
- RESET_TOKEN(token, ptoken, token_size);
- state &= ~ST_FOOTNOTE;
- footnote_at_line_start = FALSE;
- pline++;
- colno++;
- if (footnote_definition)
- {
- pline++;
- colno++;
- while (*pline == ' ' || *pline == '\t')
- {
- pline++;
- colno++;
- }
- state |= ST_FOOTNOTE_TEXT;
- }
- }
- else if (state & ST_LINK_SECOND_ARG)
- {
- if (!read_yaml_macros_and_links)
- process_link(link_text, link_prefix,
- get_value(macros, macros_count,
- link_macro, NULL),
- token, output);
- RESET_TOKEN(token, ptoken, token_size);
- state &= ~(ST_LINK | ST_LINK_SECOND_ARG);
- pline++;
- colno++;
- }
- else if (state & ST_IMAGE_SECOND_ARG)
- {
- if (!read_yaml_macros_and_links)
- process_image(link_text, link_prefix, token, output,
- add_image_links, add_figcaption);
- RESET_TOKEN(token, ptoken, token_size);
- state &= ~(ST_IMAGE | ST_IMAGE_SECOND_ARG);
- pline++;
- colno++;
- }
- else if (strlen((char*)pline) > 1)
- {
- size_t token_len = 0;
- switch (*(pline+1))
- {
- case ':':
- links_count++;
-
- if (!links)
- {
- CALLOC(links, KeyValue, links_count);
- plinks = links;
- }
- else
- {
- REALLOCARRAY(links, KeyValue, links_count);
- plinks = links + links_count - 1;
- }
- CALLOC(plinks->key, u8, KEYSIZE);
- strncpy((char*)plinks->key, (char*)token,
- KEYSIZE-1);
- plinks->value = NULL;
- plinks->value_size = 0;
- pline += 2;
- colno += 2;
- while (pline && (*pline == ' ' || *pline == '\t'))
- {
- pline++;
- colno++;
- }
- RESET_TOKEN(token, ptoken, token_size);
- keep_token = FALSE;
- state |= ST_LINK_SECOND_ARG_END;
- break;
-
- case '[':
- case '(':
- token_len = strlen((char*)token);
- if (link_text)
- {
- if (token_len + 1 > link_size)
- {
- link_size = token_len+1;
- REALLOC(link_text, u8, link_size);
- }
- }
- else
- {
- link_size = token_len+1;
- CALLOC(link_text, u8, link_size);
- }
- strncpy((char*)link_text, (char*)token,
- link_size-1);
- *(link_text + token_len) = 0;
- pline += 2;
- colno += 2;
- RESET_TOKEN(token, ptoken, token_size);
- keep_token = FALSE;
- if (state & ST_LINK)
- state |= ST_LINK_SECOND_ARG;
- else
- state |= ST_IMAGE_SECOND_ARG;
- break;
- default:
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- state &= ~(ST_LINK | ST_IMAGE);
- break;
- }
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- case '^':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_FOOTNOTE_TEXT | ST_IMAGE | ST_INLINE_FOOTNOTE
- | ST_PRE | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1 && *(pline+1) == '[')
- {
- /* Output existing text up to ^[ */
- *ptoken = 0;
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- processed_start_of_line = TRUE;
-
- RESET_TOKEN(token, ptoken, token_size);
- state |= ST_INLINE_FOOTNOTE;
- keep_token = TRUE;
- pline += 2;
- colno += 2;
- break;
- }
-
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
-
- case '\\':
- *ptoken = 0;
- if (ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_HTML_TAG | ST_IMAGE | ST_LINK
- | ST_MACRO_BODY))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1)
- {
- pline++;
- colno++;
-
- CHECKCOPY(token, ptoken, token_size, pline);
- }
- else
- {
- pline = NULL;
- break;
- }
-
- colno++;
- break;
-
- case '$':
- if (ANY(state, ST_CODE | ST_CSV_BODY | ST_IMAGE | ST_PRE
- | ST_YAML))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- break;
- }
-
- if (strlen((char*)pline) > 1
- && *(pline+1) == '$')
- {
- if (state & ST_FORMULA)
- exit(error(1, (u8*)"Display formula within an"
- " open formula"));
-
- if (!(state & ST_DISPLAY_FORMULA))
- {
- /* Output existing text up to $$ */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- }
- processed_start_of_line = TRUE;
-
- state ^= ST_DISPLAY_FORMULA;
-
- if (state & ST_DISPLAY_FORMULA)
- keep_token = TRUE;
- else
- {
- *ptoken = 0;
-
- if (!read_yaml_macros_and_links)
- process_formula(output, token, TRUE);
-
- keep_token = FALSE;
- RESET_TOKEN(token, ptoken, token_size);
- }
-
- pline += 2;
- colno += 2;
- }
- else
- {
- if (state & ST_DISPLAY_FORMULA)
- exit(error(1, (u8*)"Formula within an open"
- " display formula"));
-
- if (!(state & ST_FORMULA))
- {
- /* Output existing text up to $ */
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- }
- processed_start_of_line = TRUE;
-
- state ^= ST_FORMULA;
-
- if (state & ST_FORMULA)
- keep_token = TRUE;
- else
- {
- *ptoken = 0;
-
- if (!read_yaml_macros_and_links)
- process_formula(output, token, FALSE);
-
- keep_token = FALSE;
- RESET_TOKEN(token, ptoken, token_size);
- }
-
- pline++;
- colno++;
- }
- break;
-
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9': case '0':
- if (ANY(state, ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_MACRO_BODY | ST_PRE | ST_YAML_VAL))
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- else if (colno == 1
- && strlen((char*)pline) > 1
- && (*(pline+1) == '.' || *(pline+1) == ')'))
- {
- if (state & ST_LIST)
- {
- state &= ~ST_LIST;
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_list_end(output);
- }
- }
- if (!read_yaml_macros_and_links)
- {
- if (!(state & ST_NUMLIST))
- process_numlist_start(output);
- else
- process_list_item_end(output);
- process_list_item_start(output);
- state |= ST_PARA_OPEN;
- }
-
- processed_start_of_line = TRUE;
- skip_eol = FALSE;
-
- state |= ST_NUMLIST;
-
- pline += 2;
- colno += 2;
- }
- else
- {
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- break;
-
- default:
- CHECKCOPY(token, ptoken, token_size, pline);
- colno++;
- }
- }
-
- *ptoken = 0;
-
- if (*token && read_yaml_macros_and_links
- && (state & ST_YAML_VAL))
- {
- *ptoken = 0;
- if (!vars)
- {
- vars_count = 1;
- CALLOC(vars, KeyValue, vars_count);
- pvars = vars;
- }
- pvars->value_size = strlen((char*)token)+1;
- CALLOC(pvars->value, u8, pvars->value_size);
- strncpy((char*)pvars->value, (char*)token, pvars->value_size-1);
- }
- else if (keep_token)
- {
- size_t token_len = strlen((char*)token);
-
- if (ptoken + 2 > token + token_size)
- {
- size_t old_size = token_size;
- token_size += BUFSIZE;
- REALLOC(token, u8, token_size);
- ptoken = token + old_size - 1;
- }
- strncat((char*)token, ANY(state, ST_IMAGE | ST_LINK)
- ? " " : "\n",
- token_size - token_len - 1);
- ptoken++;
- *ptoken = 0;
- }
- else
- {
- if (*token)
- {
- *ptoken = 0;
- size_t token_len = strlen((char*)token);
- if (state & ST_MACRO_BODY)
- {
- skip_eol = TRUE;
- if (read_yaml_macros_and_links)
- {
- if (!macros)
- {
- macros_count = 1;
- CALLOC(macros, KeyValue, macros_count);
- pmacros = macros;
- }
- if (pmacros->value)
- {
- size_t value_len = strlen((char*)pmacros->value);
-
- if (pmacros->value_size < value_len + token_len + 1)
- {
- pmacros->value_size += BUFSIZE;
- REALLOC(pmacros->value, u8, pmacros->value_size);
- }
- strncat((char*)pmacros->value, (char*)token,
- pmacros->value_size-value_len-1);
- strncat((char*)pmacros->value, "\n",
- pmacros->value_size
- -strlen((char*)pmacros->value)-1);
- }
- else
- {
- pmacros->value_size = BUFSIZE;
- CALLOC(pmacros->value, u8, pmacros->value_size);
- strncpy((char*)pmacros->value, (char*)token,
- pmacros->value_size-1);
- strncat((char*)pmacros->value, "\n",
- pmacros->value_size
- -strlen((char*)pmacros->value)-1);
- }
- }
- }
- else if (state & ST_FOOTNOTE_TEXT)
- {
- skip_eol = TRUE;
- if (read_yaml_macros_and_links)
- {
- if (!footnotes)
- {
- footnote_count = 1;
- CALLOC(footnotes, KeyValue, footnote_count);
- pfootnotes = footnotes;
- }
- if (pfootnotes->value)
- {
- size_t value_len = strlen((char*)pfootnotes->value);
-
- if (pfootnotes->value_size < value_len + token_len + 1)
- {
- pfootnotes->value_size += BUFSIZE;
- REALLOC(pfootnotes->value, u8, pfootnotes->value_size);
- }
- strncat((char*)pfootnotes->value, (char*)token,
- pfootnotes->value_size-value_len-1);
- strncat((char*)pfootnotes->value, "\n",
- pfootnotes->value_size
- -strlen((char*)pfootnotes->value)-1);
- }
- else
- {
- pfootnotes->value_size = BUFSIZE;
- CALLOC(pfootnotes->value, u8, pfootnotes->value_size);
- strncpy((char*)pfootnotes->value, (char*)token,
- pfootnotes->value_size-1);
- strncat((char*)pfootnotes->value, "\n",
- pfootnotes->value_size
- -strlen((char*)pfootnotes->value)-1);
- }
- }
- }
- else if (ANY(state, ST_LINK_SECOND_ARG | ST_LINK_SECOND_ARG_END))
- {
- if (read_yaml_macros_and_links)
- {
- if (!links)
- {
- links_count = 1;
- CALLOC(links, KeyValue, links_count);
- plinks = links;
- }
- plinks->value_size = strlen((char*)token)+1;
- CALLOC(plinks->value, u8, plinks->value_size);
- strncpy((char*)plinks->value, (char*)token,
- plinks->value_size-1);
- }
- }
- else if (state & ST_HEADING)
- {
- state &= ~(ST_HEADING | ST_HEADING_TEXT);
- if (!read_yaml_macros_and_links)
- {
- process_heading(token, output, heading_level);
- output_firstcol = FALSE;
- }
- first_line_in_doc = FALSE;
- RESET_TOKEN(token, ptoken, token_size);
- heading_level = 0;
- }
- else if (!ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA
- | ST_IMAGE | ST_LINK))
- process_text_token(line, link_prefix, first_line_in_doc,
- previous_line_blank, processed_start_of_line,
- read_yaml_macros_and_links, list_para, output,
- &token, &ptoken, &token_size, TRUE);
- }
-
- if (!ANY(state, ST_PRE | ST_IMAGE_SECOND_ARG | ST_LINK_SECOND_ARG
- | ST_LINK_SECOND_ARG_END)
- && (!*pbuffer || *pbuffer == '\n'))
- {
- if (state & ST_PARA_OPEN)
- {
- if (!read_yaml_macros_and_links)
- {
- print_output(output, "</p>");
- output_firstcol = FALSE;
- }
- if (state & ST_LIST)
- skip_eol = TRUE;
- state &= ~ST_PARA_OPEN;
- }
-
- if (!*pbuffer && (state & ST_LIST))
- {
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_list_end(output);
- }
- state &= ~ST_LIST;
- }
-
- if (!*pbuffer && (state & ST_NUMLIST))
- {
- if (!read_yaml_macros_and_links)
- {
- process_list_item_end(output);
- process_numlist_end(output);
- }
- state &= ~ST_NUMLIST;
- }
-
- if (!*pbuffer && (state & ST_FOOTNOTE_TEXT))
- {
- state &= ~ST_FOOTNOTE_TEXT;
-
- *ptoken = 0;
- size_t token_len = strlen((char*)token);
-
- skip_eol = TRUE;
- if (read_yaml_macros_and_links)
- {
- if (!footnotes)
- {
- footnote_count = 1;
- CALLOC(footnotes, KeyValue, footnote_count);
- pfootnotes = footnotes;
- }
- if (pfootnotes->value)
- {
- size_t value_len = strlen((char*)pfootnotes->value);
-
- if (pfootnotes->value_size < value_len + token_len + 1)
- {
- pfootnotes->value_size
- = value_len + token_len + 1;
- REALLOC(pfootnotes->value, u8, pfootnotes->value_size);
- }
- strncat((char*)pfootnotes->value, (char*)token,
- pfootnotes->value_size-1);
- }
- else
- {
- pfootnotes->value_size = token_len + 1;
- CALLOC(pfootnotes->value, u8, pfootnotes->value_size);
- strncpy((char*)pfootnotes->value, (char*)token,
- pfootnotes->value_size-1);
- }
- }
- }
- }
-
- if (state & ST_BLOCKQUOTE
- && (!*pbuffer || *pbuffer != '>'))
- {
- state &= ~ST_BLOCKQUOTE;
- process_blockquote(output, TRUE);
- output_firstcol = FALSE;
- }
-
- if (ANY(state, ST_TABLE_HEADER | ST_TABLE_LINE)
- && (!line_len || !*pbuffer))
- {
- if (!read_yaml_macros_and_links)
- {
- warning(1, (u8*)"Malformed table");
- process_table_end(output);
- output_firstcol = TRUE;
- }
- state &= ~(ST_TABLE_HEADER | ST_TABLE_LINE);
- }
-
- if ((state & ST_TABLE) && (!line_len || !*pbuffer))
- {
- if (!read_yaml_macros_and_links)
- {
- process_table_end(output);
- output_firstcol = TRUE;
- }
- state &= ~ST_TABLE;
- }
-
- previous_line_blank = FALSE;
- }
-
- if (!skip_eol && !keep_token && !read_yaml_macros_and_links
- && !ANY(state, ST_YAML | ST_YAML_VAL | ST_LINK_SECOND_ARG
- | ST_LINK_SECOND_ARG_END))
- {
- print_output(output, "\n");
- output_firstcol = TRUE;
- }
-
- if (!keep_token)
- RESET_TOKEN(token, ptoken, token_size);
-
- if (!skip_change_first_line_in_doc
- && !(state & ST_YAML))
- first_line_in_doc = FALSE;
-
- skip_change_first_line_in_doc = FALSE;
- if (line_len == 0)
- previous_line_blank = TRUE;
-
- /* Lasts until the end of line */
- state &= ~(ST_YAML_VAL | ST_IMAGE_SECOND_ARG | ST_LINK_SECOND_ARG
- | ST_LINK_SECOND_ARG_END);
- }
- while (pbuffer && *pbuffer);
-
- if (!read_yaml_macros_and_links
- && (footnote_count > 0 || inline_footnote_count > 0))
- end_footnotes(output, add_footnote_div);
-
- if (!read_yaml_macros_and_links && !body_only)
- end_body_and_html(output);
-
- if (link_text)
- free(link_text);
-
- free(link_macro);
- free(token);
- free(line);
-
- return 0;
-}
+ else if (!ANY(state, ST_PRE | ST_TAG | ST_YAML))
+ {
+ /* Handle ` within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+ {
+ u8* tag = state & ST_CODE ? (u8*)"</code>"
+ : (u8*)"<code>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to ` */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state, ST_PRE | ST_HEADING)))
+ process_code(output, state & ST_CODE);
+ }
+
+ state ^= ST_CODE;
+
+ pline++;
+ colno++;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '#':
+ if (colno == 1
+ && !(ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_MACRO_BODY | ST_PRE | ST_YAML)))
+ {
+ if (state & ST_LIST)
+ {
+ state &= ~ST_LIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_list_end(output);
+ }
+ }
+
+ if (state & ST_NUMLIST)
+ {
+ state &= ~ST_NUMLIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_numlist_end(output);
+ }
+ }
+
+ state |= ST_HEADING;
+ heading_level = 1;
+ pline++;
+ colno++;
+ }
+ else if (state & ST_HEADING && *(pline - 1) == '#')
+ {
+ if (heading_level < MAX_HEADING_LEVEL)
+ heading_level++;
+ pline++;
+ colno++;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '_':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HTML_TAG | ST_IMAGE | ST_LINK_SECOND_ARG
+ | ST_LINK_SECOND_ARG_END | ST_MACRO_BODY
+ | ST_PRE | ST_TAG | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1 && *(pline + 1) == '_')
+ {
+ /* Handle __ within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+ {
+ u8* tag = state & ST_BOLD ? (u8*)"</strong>"
+ : (u8*)"<strong>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to __ */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ process_bold(output, state & ST_BOLD);
+ }
+
+ state ^= ST_BOLD;
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ /* Handle _ within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+ {
+ u8* tag = state & ST_ITALIC ? (u8*)"</em>"
+ : (u8*)"<em>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to _ */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ process_italic(
+ output, state & ST_ITALIC);
+ }
+
+ state ^= ST_ITALIC;
+ pline++;
+ colno++;
+ }
+ break;
+
+ case 'o':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HTML_TAG | ST_IMAGE | ST_MACRO_BODY
+ | ST_PRE | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (colno == 1 && strlen((char*)pline) > 1
+ && *(pline + 1) == ' ')
+ {
+ if (state & ST_NUMLIST)
+ {
+ state &= ~ST_NUMLIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_numlist_end(output);
+ }
+ }
+ if (!read_yaml_macros_and_links)
+ {
+ if (!(state & ST_LIST))
+ process_list_start(output);
+ else
+ process_list_item_end(output);
+ process_list_item_start(output);
+ state |= ST_PARA_OPEN;
+ }
+
+ processed_start_of_line = TRUE;
+ skip_eol = FALSE;
+
+ state |= ST_LIST;
+
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '*':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HTML_TAG | ST_IMAGE | ST_MACRO_BODY
+ | ST_PRE | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ pline_len = strlen((char*)pline);
+ if (colno == 1 && pline_len > 1 && *(pline + 1) == '[')
+ {
+ process_line_start(line, link_prefix, first_line_in_doc,
+ previous_line_blank, read_yaml_macros_and_links,
+ list_para, output, &token, &ptoken);
+
+ /* Ignore abbreviations (for now) */
+ pline = NULL;
+ }
+ else if (colno == 1 && pline_len > 2
+ && startswith((char*)pline, "***"))
+ {
+ skip_eol = TRUE;
+ if (!read_yaml_macros_and_links)
+ process_horizontal_rule(output);
+ pline = NULL;
+ }
+ else if (colno == 1 && strlen((char*)pline) > 1
+ && *(pline + 1) == ' ')
+ {
+ if (state & ST_NUMLIST)
+ {
+ state &= ~ST_NUMLIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_numlist_end(output);
+ }
+ }
+ if (!read_yaml_macros_and_links)
+ {
+ if (!(state & ST_LIST))
+ process_list_start(output);
+ else
+ process_list_item_end(output);
+ process_list_item_start(output);
+ state |= ST_PARA_OPEN;
+ }
+
+ processed_start_of_line = TRUE;
+ skip_eol = FALSE;
+
+ state |= ST_LIST;
+
+ pline += 2;
+ colno += 2;
+ }
+ else if (pline_len > 1 && *(pline + 1) == '*')
+ {
+ /* Handle ** within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+ {
+ u8* tag = state & ST_BOLD ? (u8*)"</strong>"
+ : (u8*)"<strong>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to * */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ process_bold(output, state & ST_BOLD);
+ }
+
+ state ^= ST_BOLD;
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ /* Handle * within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+
+ {
+ u8* tag = state & ST_ITALIC ? (u8*)"</em>"
+ : (u8*)"<em>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to * */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ process_italic(
+ output, state & ST_ITALIC);
+ }
+
+ state ^= ST_ITALIC;
+ pline++;
+ colno++;
+ }
+ break;
+
+ case ' ':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
+ | ST_MACRO_BODY | ST_PRE | ST_YAML_VAL))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if ((state & ST_HEADING) && !(state & ST_HEADING_TEXT))
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ heading_count++;
+ process_heading_start(
+ output, heading_level, heading_count);
+ output_firstcol = FALSE;
+ }
+ state |= ST_HEADING_TEXT;
+ pline++;
+ colno++;
+ break;
+ }
+
+ if (colno == 1 && strlen((char*)pline) > 1
+ && startswith((char*)pline, " "))
+ {
+ list_para = TRUE;
+ process_text_token(line, link_prefix, first_line_in_doc,
+ previous_line_blank, processed_start_of_line,
+ read_yaml_macros_and_links, list_para, output,
+ &token, &ptoken, &token_size, TRUE);
+ processed_start_of_line = TRUE;
+ while (*pline == ' ' || *pline == '\t')
+ {
+ pline++;
+ colno++;
+ }
+ break;
+ }
+
+ if (strlen((char*)pline) == 2 && *(pline + 1) == ' ')
+ {
+ *ptoken = 0;
+ strncat((char*)ptoken, "<br />",
+ BUFSIZE - strlen((char*)token) - 1);
+ ptoken += strlen("<br />");
+ output_firstcol = FALSE;
+ pline++;
+ colno++;
+ }
+ else if (state & ST_LINK_MACRO)
+ {
+ *ptoken = 0;
+ strncpy((char*)link_macro, (char*)token, BUFSIZE - 1);
+ *(link_macro + strlen((char*)token)) = 0;
+ RESET_TOKEN(token, ptoken, token_size);
+ state &= ~ST_LINK_MACRO;
+ }
+ else if (!(state & ST_HEADING && *(pline - 1) == '#'))
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+
+ case '{':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HTML_TAG | ST_PRE | ST_YAML
+ | ST_YAML_VAL))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (state & ST_MACRO_BODY)
+ {
+ *ptoken = 0;
+ size_t token_len = strlen((char*)token);
+
+ skip_eol = TRUE;
+ if (read_yaml_macros_and_links)
+ {
+ if (!macros)
+ {
+ macros_count = 1;
+ CALLOC(macros, KeyValue, macros_count);
+ pmacros = macros;
+ }
+ if (pmacros->value)
+ {
+ size_t value_len
+ = strlen((char*)pmacros->value);
+
+ if (pmacros->value_size
+ < value_len + token_len + 1)
+ {
+ pmacros->value_size
+ += token_len;
+ REALLOC(pmacros->value, u8,
+ pmacros->value_size);
+ }
+ strncat((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size - 1);
+ }
+ else
+ {
+ pmacros->value_size = token_len + 1;
+ CALLOC(pmacros->value, u8,
+ pmacros->value_size);
+ strncpy((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size - 1);
+ }
+ }
+ }
+ else
+ {
+ /* Output existing text up to { */
+ process_text_token(line, link_prefix, first_line_in_doc,
+ previous_line_blank, processed_start_of_line,
+ read_yaml_macros_and_links, list_para, output,
+ &token, &ptoken, &token_size, FALSE);
+ processed_start_of_line = TRUE;
+ }
+
+ state |= ST_TAG;
+ RESET_TOKEN(token, ptoken, token_size);
+
+ pline++;
+ colno++;
+ break;
+
+ case '/':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
+ | ST_PRE | ST_HEADING | ST_YAML_VAL))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if ((state & ST_TAG) && pline - 1 && *(pline - 1) == '{')
+ {
+ end_tag = TRUE;
+ pline++;
+ }
+ else
+ CHECKCOPY(token, ptoken, token_size, pline);
+
+ colno++;
+ break;
+
+ case '}':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
+ | ST_PRE | ST_YAML | ST_YAML_VAL))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (state & ST_TAG)
+ {
+ state &= ~ST_TAG;
+ *ptoken = 0;
+
+ process_tag(token, link_prefix, output,
+ read_yaml_macros_and_links, &skip_eol, end_tag);
+
+ RESET_TOKEN(token, ptoken, token_size);
+ end_tag = FALSE;
+ }
+
+ pline++;
+ colno++;
+ break;
+
+ case '|':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HTML_TAG | ST_IMAGE | ST_PRE | ST_TAG
+ | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1 && *(pline + 1) == '|')
+ {
+ /* Handle || within footnotes, headings and link text
+ * specially */
+ if (ANY(state,
+ ST_INLINE_FOOTNOTE | ST_HEADING
+ | ST_FOOTNOTE_TEXT | ST_LINK))
+ {
+ u8* tag = state & ST_KBD ? (u8*)"</kbd>"
+ : (u8*)"<kbd>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ }
+ else
+ {
+ /* Output existing text up to || */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(ANY(state,
+ ST_PRE | ST_CODE | ST_HEADING)))
+ {
+ state ^= ST_KBD;
+ process_kbd(output, !(state & ST_KBD));
+ output_firstcol = FALSE;
+ }
+ }
+
+ pline += 2;
+ colno += 2;
+ }
+ /* Partial tables (for templating) */
+ else if (!(state & ST_PRE) && colno == 1
+ && strlen((char*)pline) > 1 && *(pline + 1) == '@')
+ {
+ skip_eol = TRUE;
+
+ pline += 2;
+ colno += 2;
+
+ switch (*pline)
+ {
+ case '\\':
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_start(output);
+ output_firstcol = FALSE;
+ }
+ pline = NULL;
+ break;
+
+ case '#':
+ state |= ST_TABLE_HEADER;
+ pline++;
+ colno++;
+ break;
+
+ case '-':
+ state &= ~ST_TABLE_HEADER;
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_body_start(output, FALSE);
+ output_firstcol = TRUE;
+ }
+ pline = NULL;
+ break;
+
+ case ' ':
+ state |= ST_TABLE;
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_body_row_start(output);
+ output_firstcol = FALSE;
+ }
+ break;
+
+ case '/':
+ state &= ~ST_TABLE;
+ process_table_end(output);
+ output_firstcol = TRUE;
+ pline = NULL;
+ break;
+
+ default:
+ warning(1, (u8*)"Invalid partial table line");
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ }
+ else if (!(state & ST_PRE) && colno == 1)
+ {
+ skip_eol = TRUE;
+
+ if (state & ST_TABLE_HEADER)
+ {
+ state &= ~ST_TABLE_HEADER;
+ state |= ST_TABLE_LINE;
+ pline = NULL;
+ break;
+ }
+
+ if (state & ST_TABLE_LINE)
+ {
+ state &= ~ST_TABLE_LINE;
+ state |= ST_TABLE;
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_body_start(output, TRUE);
+ output_firstcol = FALSE;
+ }
+ }
+ else if (state & ST_TABLE)
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_body_row_start(output);
+ output_firstcol = FALSE;
+ }
+ }
+ else
+ {
+ state |= ST_TABLE_HEADER;
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_start(output);
+ output_firstcol = FALSE;
+ }
+ }
+
+ pline++;
+ colno++;
+ }
+ else if (state & ST_TABLE_HEADER)
+ {
+ *ptoken = 0;
+ if (!read_yaml_macros_and_links)
+ {
+ print_output(output, "%s", token);
+ if (*token)
+ output_firstcol = FALSE;
+ if (strlen((char*)pline) > 1)
+ {
+ process_table_header_cell(output);
+ output_firstcol = FALSE;
+ }
+ else
+ {
+ process_table_header_end(output);
+ output_firstcol = TRUE;
+ }
+ }
+ RESET_TOKEN(token, ptoken, token_size);
+ pline++;
+ colno++;
+ }
+ else if (state & ST_TABLE)
+ {
+ *ptoken = 0;
+ if (!read_yaml_macros_and_links)
+ {
+ print_output(output, "%s", token);
+ if (*token)
+ output_firstcol = FALSE;
+ if (strlen((char*)pline) > 1)
+ {
+ process_table_body_cell(output);
+ output_firstcol = FALSE;
+ }
+ else
+ {
+ process_table_body_row_end(output);
+ output_firstcol = TRUE;
+ }
+ }
+ RESET_TOKEN(token, ptoken, token_size);
+ pline++;
+ colno++;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '<':
+ if (read_yaml_macros_and_links
+ || ANY(state,
+ ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (ANY(state, ST_CODE | ST_KBD | ST_PRE))
+ {
+ size_t lt_len = strlen("<");
+ *ptoken = 0;
+ strncat((char*)token, "<",
+ BUFSIZE - (ptoken - token) - 1);
+ ptoken += lt_len;
+ pline++;
+ colno++;
+ break;
+ }
+
+ state |= ST_HTML_TAG;
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+
+ case '>':
+ if (state & ST_HTML_TAG)
+ state &= ~ST_HTML_TAG;
+
+ if (ANY(state,
+ ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE
+ | ST_MACRO_BODY))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (!read_yaml_macros_and_links
+ && !ANY(state, ST_CODE | ST_HEADING | ST_PRE)
+ && colno == 1)
+ {
+ if (!read_yaml_macros_and_links
+ && !(state & ST_BLOCKQUOTE))
+ {
+ process_blockquote(output, FALSE);
+ output_firstcol = FALSE;
+ }
+
+ state |= ST_BLOCKQUOTE;
+
+ pline++;
+ colno++;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '!':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_FOOTNOTE_TEXT | ST_HEADING | ST_IMAGE
+ | ST_INLINE_FOOTNOTE | ST_LINK
+ | ST_MACRO_BODY | ST_PRE))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1 && *(pline + 1) == '[')
+ {
+ /* Output existing text up to ! */
+ *ptoken = 0;
+ process_text_token(line, link_prefix, first_line_in_doc,
+ previous_line_blank, processed_start_of_line,
+ read_yaml_macros_and_links, list_para, output,
+ &token, &ptoken, &token_size, FALSE);
+ processed_start_of_line = TRUE;
+
+ RESET_TOKEN(token, ptoken, token_size);
+
+ state |= ST_IMAGE;
+ keep_token = TRUE;
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+
+ break;
+
+ case '=':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_MACRO_BODY | ST_PRE | ST_TAG))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (colno != 1 && *(pline - 1) == '[')
+ {
+ state |= ST_LINK_MACRO;
+ pline++;
+ colno++;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '[':
+ pline_len = strlen((char*)pline);
+
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HEADING | ST_IMAGE | ST_MACRO_BODY
+ | ST_PRE))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (state & ST_FOOTNOTE_TEXT)
+ {
+ if (!read_yaml_macros_and_links
+ && (state & ST_PARA_OPEN))
+ {
+ print_output(output, "</p>\n");
+ output_firstcol = TRUE;
+ }
+ state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN);
+ }
+
+ if (pline_len > 1 && *(pline + 1) == '^')
+ {
+ footnote_at_line_start = colno == 1;
+ if (*token)
+ {
+ /* Output existing text up to [^ */
+ *ptoken = 0;
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ }
+ processed_start_of_line = TRUE;
+
+ RESET_TOKEN(token, ptoken, token_size);
+ state |= ST_FOOTNOTE;
+ pline += 2;
+ colno += 2;
+ break;
+ }
+ if (*token)
+ {
+ /* Output existing text up to [ */
+ *ptoken = 0;
+ process_text_token(line, link_prefix, first_line_in_doc,
+ previous_line_blank, processed_start_of_line,
+ read_yaml_macros_and_links, list_para, output,
+ &token, &ptoken, &token_size, TRUE);
+ }
+ processed_start_of_line = TRUE;
+
+ RESET_TOKEN(token, ptoken, token_size);
+ state |= ST_LINK;
+ keep_token = TRUE;
+ *link_macro = 0;
+ pline++;
+ colno++;
+
+ if (*pline == '(')
+ {
+ u8* tag = (u8*)"<span>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+
+ state |= ST_LINK_SPAN;
+ pline++;
+ colno++;
+ }
+
+ break;
+
+ case '(':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_FOOTNOTE_TEXT | ST_HEADING
+ | ST_INLINE_FOOTNOTE | ST_LINK_SECOND_ARG_END
+ | ST_MACRO_BODY | ST_PRE))
+ CHECKCOPY(token, ptoken, token_size, pline);
+ else if (*link_macro && (state & ST_LINK))
+ {
+ u8* tag = (u8*)"<span>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+
+ state |= ST_LINK_SPAN;
+ pline++;
+ }
+ else
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+
+ case ')':
+ if (ANY(state,
+ ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_LINK_SECOND_ARG_END))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ pline_len = strlen((char*)pline);
+
+ if (state & ST_LINK_SPAN && pline_len > 1 && *(pline + 1) == ']')
+ {
+ u8* tag = (u8*)"</span>";
+ size_t tag_len = strlen((char*)tag);
+ size_t token_len = 0;
+
+ *ptoken = 0;
+ token_len = strlen((char*)token);
+
+ if (token_len + tag_len + 1 < BUFSIZE)
+ {
+ strncat((char*)token, (char*)tag,
+ BUFSIZE - token_len - 1);
+ ptoken += tag_len;
+ }
+ state &= ~ST_LINK_SPAN;
+ /*pline += 2;*/
+ pline++;
+ colno++;
+ }
+ else if (ANY(state, ST_LINK_SECOND_ARG | ST_IMAGE_SECOND_ARG))
+ {
+ *ptoken = 0;
+ if (!read_yaml_macros_and_links)
+ {
+ if (state & ST_LINK_SECOND_ARG)
+ process_inline_link(link_text,
+ link_prefix,
+ get_value(macros, macros_count,
+ link_macro, NULL),
+ token, output);
+ else
+ process_inline_image(link_text,
+ link_prefix, token, output,
+ add_image_links,
+ add_figcaption);
+ }
+ RESET_TOKEN(token, ptoken, token_size);
+ state &= ~(ST_LINK | ST_LINK_SECOND_ARG | ST_IMAGE
+ | ST_IMAGE_SECOND_ARG);
+ pline++;
+ }
+ else
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+
+ case ']':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_HEADING | ST_MACRO_BODY | ST_PRE))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ *ptoken = 0;
+ if (state & ST_INLINE_FOOTNOTE)
+ {
+ process_inline_footnote(
+ token, read_yaml_macros_and_links, output);
+
+ keep_token = FALSE;
+ RESET_TOKEN(token, ptoken, token_size);
+ state &= ~ST_INLINE_FOOTNOTE;
+ pline++;
+ colno++;
+ }
+ else if (state & ST_FOOTNOTE)
+ {
+ BOOL footnote_definition = (strlen((char*)pline) > 1)
+ && (*(pline + 1) == ':')
+ && footnote_at_line_start;
+
+ process_footnote(token,
+ footnote_definition
+ && read_yaml_macros_and_links,
+ !footnote_definition
+ && !read_yaml_macros_and_links,
+ output);
+
+ RESET_TOKEN(token, ptoken, token_size);
+ state &= ~ST_FOOTNOTE;
+ footnote_at_line_start = FALSE;
+ pline++;
+ colno++;
+ if (footnote_definition)
+ {
+ pline++;
+ colno++;
+ while (*pline == ' ' || *pline == '\t')
+ {
+ pline++;
+ colno++;
+ }
+ state |= ST_FOOTNOTE_TEXT;
+ }
+ }
+ else if (state & ST_LINK_SECOND_ARG)
+ {
+ if (!read_yaml_macros_and_links)
+ process_link(link_text, link_prefix,
+ get_value(macros, macros_count,
+ link_macro, NULL),
+ token, output);
+ RESET_TOKEN(token, ptoken, token_size);
+ state &= ~(ST_LINK | ST_LINK_SECOND_ARG);
+ pline++;
+ colno++;
+ }
+ else if (state & ST_IMAGE_SECOND_ARG)
+ {
+ if (!read_yaml_macros_and_links)
+ process_image(link_text, link_prefix, token,
+ output, add_image_links,
+ add_figcaption);
+ RESET_TOKEN(token, ptoken, token_size);
+ state &= ~(ST_IMAGE | ST_IMAGE_SECOND_ARG);
+ pline++;
+ colno++;
+ }
+ else if (strlen((char*)pline) > 1)
+ {
+ size_t token_len = 0;
+ switch (*(pline + 1))
+ {
+ case ':':
+ links_count++;
+
+ if (!links)
+ {
+ CALLOC(links, KeyValue, links_count);
+ plinks = links;
+ }
+ else
+ {
+ REALLOCARRAY(
+ links, KeyValue, links_count);
+ plinks = links + links_count - 1;
+ }
+ CALLOC(plinks->key, u8, KEYSIZE);
+ strncpy((char*)plinks->key, (char*)token,
+ KEYSIZE - 1);
+ plinks->value = NULL;
+ plinks->value_size = 0;
+ pline += 2;
+ colno += 2;
+ while (pline
+ && (*pline == ' ' || *pline == '\t'))
+ {
+ pline++;
+ colno++;
+ }
+ RESET_TOKEN(token, ptoken, token_size);
+ keep_token = FALSE;
+ state |= ST_LINK_SECOND_ARG_END;
+ break;
+
+ case '[':
+ case '(':
+ token_len = strlen((char*)token);
+ if (link_text && token_len + 1 > link_size)
+ {
+ link_size = token_len + 1;
+ REALLOC(link_text, u8, link_size);
+ }
+ else if (!link_text)
+ {
+ link_size = token_len + 1;
+ CALLOC(link_text, u8, link_size);
+ }
+ strncpy((char*)link_text, (char*)token,
+ link_size - 1);
+ *(link_text + token_len) = 0;
+ pline += 2;
+ colno += 2;
+ RESET_TOKEN(token, ptoken, token_size);
+ keep_token = FALSE;
+ if (state & ST_LINK)
+ state |= ST_LINK_SECOND_ARG;
+ else
+ state |= ST_IMAGE_SECOND_ARG;
+ break;
+ default:
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ state &= ~(ST_LINK | ST_IMAGE);
+ break;
+ }
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ case '^':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_FOOTNOTE_TEXT | ST_IMAGE
+ | ST_INLINE_FOOTNOTE | ST_PRE | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1 && *(pline + 1) == '[')
+ {
+ /* Output existing text up to ^[ */
+ *ptoken = 0;
+ process_text_token(line, link_prefix, first_line_in_doc,
+ previous_line_blank, processed_start_of_line,
+ read_yaml_macros_and_links, list_para, output,
+ &token, &ptoken, &token_size, TRUE);
+ processed_start_of_line = TRUE;
+
+ RESET_TOKEN(token, ptoken, token_size);
+ state |= ST_INLINE_FOOTNOTE;
+ keep_token = TRUE;
+ pline += 2;
+ colno += 2;
+ break;
+ }
+
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+
+ case '\\':
+ *ptoken = 0;
+ if (ANY(state,
+ ST_DISPLAY_FORMULA | ST_FORMULA | ST_HTML_TAG
+ | ST_IMAGE | ST_LINK | ST_MACRO_BODY))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1)
+ {
+ pline++;
+ colno++;
+
+ CHECKCOPY(token, ptoken, token_size, pline);
+ }
+ else
+ {
+ pline = NULL;
+ break;
+ }
+
+ colno++;
+ break;
+
+ case '$':
+ if (ANY(state,
+ ST_CODE | ST_CSV_BODY | ST_IMAGE | ST_PRE | ST_YAML))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ break;
+ }
+
+ if (strlen((char*)pline) > 1 && *(pline + 1) == '$')
+ {
+ if (state & ST_FORMULA)
+ exit(error(1,
+ (u8*)"Display formula within an"
+ " open formula"));
+
+ if (!(state & ST_DISPLAY_FORMULA))
+ {
+ /* Output existing text up to $$ */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ }
+ processed_start_of_line = TRUE;
+
+ state ^= ST_DISPLAY_FORMULA;
+
+ if (state & ST_DISPLAY_FORMULA)
+ keep_token = TRUE;
+ else
+ {
+ *ptoken = 0;
+
+ if (!read_yaml_macros_and_links)
+ process_formula(output, token, TRUE);
+
+ keep_token = FALSE;
+ RESET_TOKEN(token, ptoken, token_size);
+ }
+
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ if (state & ST_DISPLAY_FORMULA)
+ exit(error(1,
+ (u8*)"Formula within an open"
+ " display formula"));
+
+ if (!(state & ST_FORMULA))
+ {
+ /* Output existing text up to $ */
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ }
+ processed_start_of_line = TRUE;
+
+ state ^= ST_FORMULA;
+
+ if (state & ST_FORMULA)
+ keep_token = TRUE;
+ else
+ {
+ *ptoken = 0;
+
+ if (!read_yaml_macros_and_links)
+ process_formula(output, token, FALSE);
+
+ keep_token = FALSE;
+ RESET_TOKEN(token, ptoken, token_size);
+ }
+
+ pline++;
+ colno++;
+ }
+ break;
+
+ case '1': /* FALLTHROUGH */
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ if (ANY(state,
+ ST_CODE | ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_MACRO_BODY | ST_PRE | ST_YAML_VAL))
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ else if (colno == 1 && strlen((char*)pline) > 1
+ && (*(pline + 1) == '.' || *(pline + 1) == ')'))
+ {
+ if (state & ST_LIST)
+ {
+ state &= ~ST_LIST;
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_list_end(output);
+ }
+ }
+ if (!read_yaml_macros_and_links)
+ {
+ if (!(state & ST_NUMLIST))
+ process_numlist_start(output);
+ else
+ process_list_item_end(output);
+ process_list_item_start(output);
+ state |= ST_PARA_OPEN;
+ }
+
+ processed_start_of_line = TRUE;
+ skip_eol = FALSE;
+
+ state |= ST_NUMLIST;
+
+ pline += 2;
+ colno += 2;
+ }
+ else
+ {
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ break;
+
+ default:
+ CHECKCOPY(token, ptoken, token_size, pline);
+ colno++;
+ }
+ goto do_line;
+
+done_line:
+ *ptoken = 0;
+
+ if (*token && read_yaml_macros_and_links && (state & ST_YAML_VAL))
+ {
+ *ptoken = 0;
+ if (!vars)
+ {
+ vars_count = 1;
+ CALLOC(vars, KeyValue, vars_count);
+ pvars = vars;
+ }
+ pvars->value_size = strlen((char*)token) + 1;
+ CALLOC(pvars->value, u8, pvars->value_size);
+ strncpy((char*)pvars->value, (char*)token,
+ pvars->value_size - 1);
+ }
+ else if (keep_token)
+ {
+ size_t token_len = strlen((char*)token);
+
+ if (ptoken + 2 > token + token_size)
+ {
+ size_t old_size = token_size;
+ token_size += BUFSIZE;
+ REALLOC(token, u8, token_size);
+ ptoken = token + old_size - 1;
+ }
+ strncat((char*)token,
+ ANY(state, ST_IMAGE | ST_LINK) ? " " : "\n",
+ token_size - token_len - 1);
+ ptoken++;
+ *ptoken = 0;
+ }
+ else
+ {
+ if (*token)
+ {
+ *ptoken = 0;
+ size_t token_len = strlen((char*)token);
+ if (state & ST_MACRO_BODY)
+ {
+ skip_eol = TRUE;
+ if (!read_yaml_macros_and_links)
+ goto skip_macro_read;
+ if (!macros)
+ {
+ macros_count = 1;
+ CALLOC(macros, KeyValue, macros_count);
+ pmacros = macros;
+ }
+ if (pmacros->value)
+ {
+ size_t value_len
+ = strlen((char*)pmacros->value);
+
+ if (pmacros->value_size
+ < value_len + token_len + 1)
+ {
+ pmacros->value_size += BUFSIZE;
+ REALLOC(pmacros->value, u8,
+ pmacros->value_size);
+ }
+ strncat((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size - value_len
+ - 1);
+ strncat((char*)pmacros->value, "\n",
+ pmacros->value_size
+ - strlen((char*)pmacros
+ ->value)
+ - 1);
+ }
+ else
+ {
+ pmacros->value_size = BUFSIZE;
+ CALLOC(pmacros->value, u8,
+ pmacros->value_size);
+ strncpy((char*)pmacros->value,
+ (char*)token,
+ pmacros->value_size - 1);
+ strncat((char*)pmacros->value, "\n",
+ pmacros->value_size
+ - strlen((char*)pmacros
+ ->value)
+ - 1);
+ }
+ skip_macro_read:;
+ }
+ else if (state & ST_FOOTNOTE_TEXT)
+ {
+ skip_eol = TRUE;
+ if (!read_yaml_macros_and_links)
+ goto skip_footnote_read;
+ if (!footnotes)
+ {
+ footnote_count = 1;
+ CALLOC(footnotes, KeyValue,
+ footnote_count);
+ pfootnotes = footnotes;
+ }
+ if (pfootnotes->value)
+ {
+ size_t value_len = strlen(
+ (char*)pfootnotes->value);
+
+ if (pfootnotes->value_size
+ < value_len + token_len + 1)
+ {
+ pfootnotes->value_size
+ += BUFSIZE;
+ REALLOC(pfootnotes->value, u8,
+ pfootnotes->value_size);
+ }
+ strncat((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size
+ - value_len - 1);
+ strncat((char*)pfootnotes->value, "\n",
+ pfootnotes->value_size
+ - strlen(
+ (char*)pfootnotes
+ ->value)
+ - 1);
+ }
+ else
+ {
+ pfootnotes->value_size = BUFSIZE;
+ CALLOC(pfootnotes->value, u8,
+ pfootnotes->value_size);
+ strncpy((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size - 1);
+ strncat((char*)pfootnotes->value, "\n",
+ pfootnotes->value_size
+ - strlen(
+ (char*)pfootnotes
+ ->value)
+ - 1);
+ }
+ skip_footnote_read:;
+ }
+ else if (ANY(state,
+ ST_LINK_SECOND_ARG
+ | ST_LINK_SECOND_ARG_END))
+ {
+ if (read_yaml_macros_and_links)
+ {
+ if (!links)
+ {
+ links_count = 1;
+ CALLOC(links, KeyValue,
+ links_count);
+ plinks = links;
+ }
+ plinks->value_size
+ = strlen((char*)token) + 1;
+ CALLOC(plinks->value, u8,
+ plinks->value_size);
+ strncpy((char*)plinks->value,
+ (char*)token,
+ plinks->value_size - 1);
+ }
+ }
+ else if (state & ST_HEADING)
+ {
+ state &= ~(ST_HEADING | ST_HEADING_TEXT);
+ if (!read_yaml_macros_and_links)
+ {
+ process_heading(
+ token, output, heading_level);
+ output_firstcol = FALSE;
+ }
+ first_line_in_doc = FALSE;
+ RESET_TOKEN(token, ptoken, token_size);
+ heading_level = 0;
+ }
+ else if (!ANY(state,
+ ST_DISPLAY_FORMULA | ST_FORMULA
+ | ST_IMAGE | ST_LINK))
+ process_text_token(line, link_prefix,
+ first_line_in_doc, previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links, list_para,
+ output, &token, &ptoken, &token_size,
+ TRUE);
+ }
+
+ if (!ANY(state,
+ ST_PRE | ST_IMAGE_SECOND_ARG | ST_LINK_SECOND_ARG
+ | ST_LINK_SECOND_ARG_END)
+ && (!*pbuffer || *pbuffer == '\n'))
+ {
+ if (state & ST_PARA_OPEN)
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ print_output(output, "</p>");
+ output_firstcol = FALSE;
+ }
+ if (state & ST_LIST)
+ skip_eol = TRUE;
+ state &= ~ST_PARA_OPEN;
+ }
+
+ if (!*pbuffer && (state & ST_LIST))
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_list_end(output);
+ }
+ state &= ~ST_LIST;
+ }
+
+ if (!*pbuffer && (state & ST_NUMLIST))
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ process_list_item_end(output);
+ process_numlist_end(output);
+ }
+ state &= ~ST_NUMLIST;
+ }
+
+ if (!*pbuffer && (state & ST_FOOTNOTE_TEXT))
+ {
+ state &= ~ST_FOOTNOTE_TEXT;
+
+ *ptoken = 0;
+ size_t token_len = strlen((char*)token);
+
+ skip_eol = TRUE;
+ if (!read_yaml_macros_and_links)
+ goto skip_footnote_text_read;
+ if (!footnotes)
+ {
+ footnote_count = 1;
+ CALLOC(footnotes, KeyValue,
+ footnote_count);
+ pfootnotes = footnotes;
+ }
+ if (pfootnotes->value)
+ {
+ size_t value_len = strlen(
+ (char*)pfootnotes->value);
+
+ if (pfootnotes->value_size
+ < value_len + token_len + 1)
+ {
+ pfootnotes->value_size
+ = value_len + token_len
+ + 1;
+ REALLOC(pfootnotes->value, u8,
+ pfootnotes->value_size);
+ }
+ strncat((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size - 1);
+ }
+ else
+ {
+ pfootnotes->value_size = token_len + 1;
+ CALLOC(pfootnotes->value, u8,
+ pfootnotes->value_size);
+ strncpy((char*)pfootnotes->value,
+ (char*)token,
+ pfootnotes->value_size - 1);
+ }
+ skip_footnote_text_read:;
+ }
+ }
+
+ if (state & ST_BLOCKQUOTE && (!*pbuffer || *pbuffer != '>'))
+ {
+ state &= ~ST_BLOCKQUOTE;
+ process_blockquote(output, TRUE);
+ output_firstcol = FALSE;
+ }
+
+ if (ANY(state, ST_TABLE_HEADER | ST_TABLE_LINE)
+ && (!line_len || !*pbuffer))
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ warning(1, (u8*)"Malformed table");
+ process_table_end(output);
+ output_firstcol = TRUE;
+ }
+ state &= ~(ST_TABLE_HEADER | ST_TABLE_LINE);
+ }
+
+ if ((state & ST_TABLE) && (!line_len || !*pbuffer))
+ {
+ if (!read_yaml_macros_and_links)
+ {
+ process_table_end(output);
+ output_firstcol = TRUE;
+ }
+ state &= ~ST_TABLE;
+ }
+
+ previous_line_blank = FALSE;
+ }
+
+ if (!skip_eol && !keep_token && !read_yaml_macros_and_links
+ && !ANY(state,
+ ST_YAML | ST_YAML_VAL | ST_LINK_SECOND_ARG
+ | ST_LINK_SECOND_ARG_END))
+ {
+ print_output(output, "\n");
+ output_firstcol = TRUE;
+ }
+
+ if (!keep_token)
+ RESET_TOKEN(token, ptoken, token_size);
+
+ if (!skip_change_first_line_in_doc && !(state & ST_YAML))
+ first_line_in_doc = FALSE;
+
+ skip_change_first_line_in_doc = FALSE;
+ if (line_len == 0)
+ previous_line_blank = TRUE;
+
+ /* Lasts until the end of line */
+ state &= ~(ST_YAML_VAL | ST_IMAGE_SECOND_ARG | ST_LINK_SECOND_ARG
+ | ST_LINK_SECOND_ARG_END);
+
+ if (pbuffer && *pbuffer)
+ goto do_buffer;
+done_buffer:
+ if (!read_yaml_macros_and_links
+ && (footnote_count > 0 || inline_footnote_count > 0))
+ end_footnotes(output, add_footnote_div);
+
+ if (!read_yaml_macros_and_links && !body_only)
+ end_body_and_html(output);
+
+ if (link_text)
+ free(link_text);
+
+ free(link_macro);
+ free(token);
+ free(line);
+
+ return 0;
+}
int
main(int argc, char** argv)
{
- char* arg;
- Command cmd = CMD_NONE;
- BOOL body_only = FALSE;
- int result = 0;
-
- basedir_size = 2;
- CALLOC(basedir, char, basedir_size);
- *basedir = '.';
-
- while ((arg = *++argv))
- {
- if (*arg == '-')
- {
- arg++;
- char c = *arg++;
- int result;
-
- if (c == '-')
- {
- if (!strcmp(arg, "version"))
- cmd = CMD_VERSION;
- else if (!strcmp(arg, "body-only"))
- {
- arg += strlen("body-only");
- body_only = TRUE;
- }
- else if (startswith(arg, "basedir"))
- {
- arg += strlen("basedir");
- result = set_basedir(arg, &basedir, &basedir_size);
- if (result)
- return result;
- }
- else if (startswith(arg, "global-link-prefix"))
- {
- arg += strlen("global-link-prefix");
- result = set_global_link_prefix(arg, &global_link_prefix,
- &global_link_prefix_size);
- if (result)
- return result;
- }
- else if (!strcmp(arg, "help"))
- return usage();
- else
- {
- error(EINVAL, (u8*)"Invalid argument: --%s", arg);
- return usage();
- }
- }
- else
- {
- switch (c)
- {
- case 'b':
- body_only = TRUE;
- break;
- case 'd':
- cmd = CMD_BASEDIR;
- break;
- case 'h':
- return usage();
- break;
- case 'p':
- cmd = CMD_LINK_PREFIX;
- break;
- case 'v':
- cmd = CMD_VERSION;
- break;
- default:
- error(EINVAL, (u8*)"Invalid argument: -%c", c);
- return usage();
- }
- }
- }
- else
- {
- int result;
-
- if (cmd == CMD_BASEDIR)
- {
- result = set_basedir(arg, &basedir, &basedir_size);
- if (result)
- return result;
- }
- else
- input_filename = arg;
- cmd = CMD_NONE;
- }
- }
-
- if (cmd == CMD_BASEDIR)
- return error(1, (u8*)"-d: Argument required");
-
- if (cmd == CMD_VERSION)
- return version();
-
- FILE* input = NULL;
- FILE* output = stdout;
- u8* buffer = NULL;
- size_t buffer_size = 0;
-
- if (input_filename)
- read_file_into_buffer(&buffer, &buffer_size, input_filename, &input_dirname, &input);
- else
- {
- u8* bufline = NULL;
- size_t buffer_len = 0;
- size_t buffer_size = 0;
- size_t bufline_len = 0;
-
- input = stdin;
-
- CALLOC(bufline, u8, BUFSIZE);
- buffer_size = BUFSIZE;
- CALLOC(buffer, u8, buffer_size);
-
- while (!feof(input))
- {
- u8* eol = NULL;
- if (!fgets((char*)bufline, BUFSIZE-1, input))
- break;
- eol = (u8*)strchr((char*)bufline, '\n');
- if (eol)
- *(eol+1) = 0;
- bufline_len = strlen((char*)bufline);
- if (buffer_len + bufline_len + 1 > buffer_size)
- {
- buffer_size += BUFSIZE;
- REALLOC(buffer, u8, buffer_size);
- }
- strncat((char*)buffer, (char*)bufline, buffer_size-buffer_len-1);
- buffer_len += bufline_len;
- }
- free(bufline);
- }
-
- vars = NULL;
- vars_count = 0;
- macros = NULL;
- macros_count = 0;
- links = NULL;
- links_count = 0;
- footnotes = NULL;
- footnote_count = 0;
- inline_footnotes = NULL;
- inline_footnote_count = 0;
-
- /* First pass: read YAML, macros and links */
- result = slweb_parse(buffer, output, body_only, TRUE);
-
- if (result)
- {
- slweb_cleanup();
- free(buffer);
- return result;
- }
-
- state = ST_NONE;
- current_footnote = 0;
- current_inline_footnote = 0;
-
- /* Second pass: parse and output */
- result = slweb_parse(buffer, output, body_only, FALSE);
-
- slweb_cleanup();
- free(buffer);
-
- return result;
-}
+ char* arg;
+ Command cmd = CMD_NONE;
+ BOOL body_only = FALSE;
+ int result = 0;
+
+ basedir_size = 2;
+ CALLOC(basedir, char, basedir_size);
+ *basedir = '.';
+
+ while ((arg = *++argv))
+ {
+ if (*arg == '-')
+ {
+ arg++;
+ char c = *arg++;
+ int result;
+
+ if (c == '-')
+ {
+ if (!strcmp(arg, "version"))
+ cmd = CMD_VERSION;
+ else if (!strcmp(arg, "body-only"))
+ {
+ arg += strlen("body-only");
+ body_only = TRUE;
+ }
+ else if (startswith(arg, "basedir"))
+ {
+ arg += strlen("basedir");
+ result = set_basedir(
+ arg, &basedir, &basedir_size);
+ if (result)
+ return result;
+ }
+ else if (startswith(arg, "global-link-prefix"))
+ {
+ arg += strlen("global-link-prefix");
+ result = set_global_link_prefix(arg,
+ &global_link_prefix,
+ &global_link_prefix_size);
+ if (result)
+ return result;
+ }
+ else if (!strcmp(arg, "help"))
+ return usage();
+ else
+ {
+ error(EINVAL,
+ (u8*)"Invalid argument: --%s",
+ arg);
+ return usage();
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case 'b':
+ body_only = TRUE;
+ break;
+ case 'd':
+ cmd = CMD_BASEDIR;
+ break;
+ case 'h':
+ return usage();
+ break;
+ case 'p':
+ cmd = CMD_LINK_PREFIX;
+ break;
+ case 'v':
+ cmd = CMD_VERSION;
+ break;
+ default:
+ error(EINVAL,
+ (u8*)"Invalid argument: -%c",
+ c);
+ return usage();
+ }
+ }
+ }
+ else
+ {
+ int result;
+ if (cmd == CMD_BASEDIR)
+ {
+ result = set_basedir(
+ arg, &basedir, &basedir_size);
+ if (result)
+ return result;
+ }
+ else
+ input_filename = arg;
+ cmd = CMD_NONE;
+ }
+ }
+
+ if (cmd == CMD_BASEDIR)
+ return error(1, (u8*)"-d: Argument required");
+
+ if (cmd == CMD_VERSION)
+ return version();
+
+ FILE* input = NULL;
+ FILE* output = stdout;
+ u8* buffer = NULL;
+ size_t buffer_size = 0;
+
+ if (input_filename)
+ read_file_into_buffer(&buffer, &buffer_size, input_filename,
+ &input_dirname, &input);
+ else
+ {
+ u8* bufline = NULL;
+ size_t buffer_len = 0;
+ size_t buffer_size = 0;
+ size_t bufline_len = 0;
+
+ input = stdin;
+
+ CALLOC(bufline, u8, BUFSIZE);
+ buffer_size = BUFSIZE;
+ CALLOC(buffer, u8, buffer_size);
+
+ while (!feof(input))
+ {
+ u8* eol = NULL;
+ if (!fgets((char*)bufline, BUFSIZE - 1, input))
+ break;
+ eol = (u8*)strchr((char*)bufline, '\n');
+ if (eol)
+ *(eol + 1) = 0;
+ bufline_len = strlen((char*)bufline);
+ if (buffer_len + bufline_len + 1 > buffer_size)
+ {
+ buffer_size += BUFSIZE;
+ REALLOC(buffer, u8, buffer_size);
+ }
+ strncat((char*)buffer, (char*)bufline,
+ buffer_size - buffer_len - 1);
+ buffer_len += bufline_len;
+ }
+ free(bufline);
+ }
+
+ vars = NULL;
+ vars_count = 0;
+ macros = NULL;
+ macros_count = 0;
+ links = NULL;
+ links_count = 0;
+ footnotes = NULL;
+ footnote_count = 0;
+ inline_footnotes = NULL;
+ inline_footnote_count = 0;
+
+ /* First pass: read YAML, macros and links */
+ result = slweb_parse(buffer, output, body_only, TRUE);
+
+ if (result)
+ {
+ slweb_cleanup();
+ free(buffer);
+ return result;
+ }
+
+ state = ST_NONE;
+ current_footnote = 0;
+ current_inline_footnote = 0;
+
+ /* Second pass: parse and output */
+ result = slweb_parse(buffer, output, body_only, FALSE);
+
+ slweb_cleanup();
+ free(buffer);
+
+ return result;
+}