commit
a88343c593
9 changed files with 642 additions and 530 deletions
5
Makefile
5
Makefile
|
@ -1,4 +1,4 @@
|
|||
CFLAGS = -g -O3 -Wall -Wextra -Wno-unused-parameter -Isrc
|
||||
CFLAGS = -g -O3 -ansi -pedantic -Wall -Wextra -Wno-unused-parameter -Isrc
|
||||
|
||||
ifneq ($(OS),Windows_NT)
|
||||
CFLAGS += -fPIC
|
||||
|
@ -63,3 +63,6 @@ clean:
|
|||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
src/html_blocks.o: src/html_blocks.c
|
||||
$(CC) $(CFLAGS) -Wno-static-in-inline -c -o $@ $<
|
||||
|
|
77
bin/common.h
77
bin/common.h
|
@ -11,7 +11,8 @@
|
|||
#define count_of(arr) (sizeof(arr)/sizeof(0[arr]))
|
||||
|
||||
int
|
||||
parseint(const char *string, long *result) {
|
||||
parseint(const char *string, long *result)
|
||||
{
|
||||
char *end;
|
||||
errno = 0;
|
||||
*result = strtol(string, &end, 10);
|
||||
|
@ -19,7 +20,8 @@ parseint(const char *string, long *result) {
|
|||
}
|
||||
|
||||
const char *
|
||||
strprefix(const char *str, const char *prefix) {
|
||||
strprefix(const char *str, const char *prefix)
|
||||
{
|
||||
while (*prefix) {
|
||||
if (!(*str && *str == *prefix)) return 0;
|
||||
prefix++; str++;
|
||||
|
@ -28,7 +30,8 @@ strprefix(const char *str, const char *prefix) {
|
|||
}
|
||||
|
||||
void
|
||||
print_option(char short_opt, const char *long_opt, const char *description) {
|
||||
print_option(char short_opt, const char *long_opt, const char *description)
|
||||
{
|
||||
if (short_opt)
|
||||
printf(" -%c, ", short_opt);
|
||||
else
|
||||
|
@ -38,8 +41,68 @@ print_option(char short_opt, const char *long_opt, const char *description) {
|
|||
}
|
||||
|
||||
void
|
||||
print_version() {
|
||||
int major, minor, revision;
|
||||
hoedown_version(&major, &minor, &revision);
|
||||
printf("Built with Hoedown v%d.%d.%d.\n", major, minor, revision);
|
||||
print_version()
|
||||
{
|
||||
printf("Built with Hoedown " HOEDOWN_VERSION ".\n");
|
||||
}
|
||||
|
||||
int
|
||||
parse_options(
|
||||
int argc, char **argv,
|
||||
int(*parse_short_option)(char opt, char *next, void *opaque),
|
||||
int(*parse_long_option)(char *opt, char *next, void *opaque),
|
||||
int(*parse_argument)(int argn, char *arg, int is_forced, void *opaque),
|
||||
void *opaque)
|
||||
{
|
||||
int result;
|
||||
int i = 1, regular_args = 0;
|
||||
|
||||
/* Parse options mixed with arguments */
|
||||
while (i < argc) {
|
||||
char *arg = argv[i];
|
||||
|
||||
if (arg[0] == '-' && arg[1]) {
|
||||
char *next_arg = (i+1 < argc) ? argv[i+1] : NULL;
|
||||
|
||||
if (arg[1] == '-' && !arg[2]) {
|
||||
/* '--' signals end of options */
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (arg[1] == '-') {
|
||||
/* Long option */
|
||||
result = parse_long_option(arg + 2, next_arg, opaque);
|
||||
if (!result) return 0;
|
||||
i += result;
|
||||
} else {
|
||||
/* Sequence of short options */
|
||||
size_t pos;
|
||||
for (pos = 1; arg[pos]; pos++) {
|
||||
char *next = (arg[pos+1]) ? arg + pos+1 : next_arg;
|
||||
result = parse_short_option(arg[pos], next, opaque);
|
||||
if (!result) return 0;
|
||||
if (result == 2) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
/* Argument */
|
||||
result = parse_argument(regular_args++, arg, 0, opaque);
|
||||
if (!result) return 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse rest as forced arguments */
|
||||
while (i < argc) {
|
||||
result = parse_argument(regular_args++, argv[i], 1, opaque);
|
||||
if (!result) return 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
595
bin/hoedown.c
595
bin/hoedown.c
|
@ -2,32 +2,16 @@
|
|||
#include "html.h"
|
||||
|
||||
#include "common.h"
|
||||
//#include <time.h>
|
||||
|
||||
/* NULL RENDERER */
|
||||
|
||||
enum renderer_type {
|
||||
RENDERER_HTML,
|
||||
RENDERER_HTML_TOC,
|
||||
RENDERER_NULL,
|
||||
};
|
||||
|
||||
hoedown_renderer *
|
||||
null_renderer_new() {
|
||||
hoedown_renderer *rend = malloc(sizeof(hoedown_renderer));
|
||||
if (rend)
|
||||
memset(rend, 0x00, sizeof(hoedown_renderer));
|
||||
return rend;
|
||||
}
|
||||
|
||||
void
|
||||
null_renderer_free(hoedown_renderer *rend) {
|
||||
free(rend);
|
||||
}
|
||||
/*#include <time.h>*/
|
||||
|
||||
|
||||
/* FEATURES INFO / DEFAULTS */
|
||||
|
||||
enum renderer_type {
|
||||
RENDERER_HTML,
|
||||
RENDERER_HTML_TOC
|
||||
};
|
||||
|
||||
struct extension_category_info {
|
||||
unsigned int flags;
|
||||
const char *option_name;
|
||||
|
@ -91,7 +75,11 @@ static const char *negative_prefix = "no-";
|
|||
/* PRINT HELP */
|
||||
|
||||
void
|
||||
print_help(const char *basename) {
|
||||
print_help(const char *basename)
|
||||
{
|
||||
size_t i;
|
||||
size_t e;
|
||||
|
||||
/* usage */
|
||||
printf("Usage: %s [OPTION]... [FILE]\n\n", basename);
|
||||
|
||||
|
@ -105,7 +93,6 @@ print_help(const char *basename) {
|
|||
print_option('t', "toc-level=N", "Maximum level for headers included in the TOC. Zero disables TOC (the default).");
|
||||
print_option( 0, "html", "Render (X)HTML. The default.");
|
||||
print_option( 0, "html-toc", "Render the Table of Contents in (X)HTML.");
|
||||
print_option( 0, "null", "Use a special \"null\" renderer that has no callbacks.");
|
||||
print_option('T', "time", "Show time spent in rendering.");
|
||||
print_option('i', "input-unit=N", "Reading block size. Default is " str(DEF_IUNIT) ".");
|
||||
print_option('o', "output-unit=N", "Writing block size. Default is " str(DEF_OUNIT) ".");
|
||||
|
@ -114,8 +101,6 @@ print_help(const char *basename) {
|
|||
printf("\n");
|
||||
|
||||
/* extensions */
|
||||
size_t i;
|
||||
size_t e;
|
||||
for (i = 0; i < count_of(categories_info); i++) {
|
||||
struct extension_category_info *category = categories_info+i;
|
||||
printf("%s (--%s%s):\n", category->label, category_prefix, category->option_name);
|
||||
|
@ -145,320 +130,320 @@ print_help(const char *basename) {
|
|||
}
|
||||
|
||||
|
||||
/* OPTION PARSING */
|
||||
|
||||
struct option_data {
|
||||
char *basename;
|
||||
int done;
|
||||
|
||||
/* time reporting */
|
||||
int show_time;
|
||||
|
||||
/* I/O */
|
||||
size_t iunit;
|
||||
size_t ounit;
|
||||
const char *filename;
|
||||
|
||||
/* renderer */
|
||||
enum renderer_type renderer;
|
||||
int toc_level;
|
||||
hoedown_html_flags html_flags;
|
||||
|
||||
/* parsing */
|
||||
hoedown_extensions extensions;
|
||||
size_t max_nesting;
|
||||
};
|
||||
|
||||
int
|
||||
parse_short_option(char opt, char *next, void *opaque)
|
||||
{
|
||||
struct option_data *data = opaque;
|
||||
long int num;
|
||||
int isNum = next ? parseint(next, &num) : 0;
|
||||
|
||||
if (opt == 'h') {
|
||||
print_help(data->basename);
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt == 'v') {
|
||||
print_version();
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt == 'T') {
|
||||
data->show_time = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* options requiring value */
|
||||
/* FIXME: add validation */
|
||||
|
||||
if (opt == 'n' && isNum) {
|
||||
data->max_nesting = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (opt == 't' && isNum) {
|
||||
data->toc_level = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (opt == 'i' && isNum) {
|
||||
data->iunit = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (opt == 'o' && isNum) {
|
||||
data->ounit = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Wrong option '-%c' found.\n", opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_category_option(char *opt, struct option_data *data)
|
||||
{
|
||||
size_t i;
|
||||
const char *name = strprefix(opt, category_prefix);
|
||||
if (!name) return 0;
|
||||
|
||||
for (i = 0; i < count_of(categories_info); i++) {
|
||||
struct extension_category_info *category = &categories_info[i];
|
||||
if (strcmp(name, category->option_name)==0) {
|
||||
data->extensions |= category->flags;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_flag_option(char *opt, struct option_data *data)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < count_of(extensions_info); i++) {
|
||||
struct extension_info *extension = &extensions_info[i];
|
||||
if (strcmp(opt, extension->option_name)==0) {
|
||||
data->extensions |= extension->flag;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count_of(html_flags_info); i++) {
|
||||
struct html_flag_info *html_flag = &html_flags_info[i];
|
||||
if (strcmp(opt, html_flag->option_name)==0) {
|
||||
data->html_flags |= html_flag->flag;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_negative_option(char *opt, struct option_data *data)
|
||||
{
|
||||
size_t i;
|
||||
const char *name = strprefix(opt, negative_prefix);
|
||||
if (!name) return 0;
|
||||
|
||||
for (i = 0; i < count_of(categories_info); i++) {
|
||||
struct extension_category_info *category = &categories_info[i];
|
||||
if (strcmp(name, category->option_name)==0) {
|
||||
data->extensions &= ~(category->flags);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count_of(extensions_info); i++) {
|
||||
struct extension_info *extension = &extensions_info[i];
|
||||
if (strcmp(name, extension->option_name)==0) {
|
||||
data->extensions &= ~(extension->flag);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count_of(html_flags_info); i++) {
|
||||
struct html_flag_info *html_flag = &html_flags_info[i];
|
||||
if (strcmp(name, html_flag->option_name)==0) {
|
||||
data->html_flags &= ~(html_flag->flag);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_long_option(char *opt, char *next, void *opaque)
|
||||
{
|
||||
struct option_data *data = opaque;
|
||||
long int num;
|
||||
int isNum = next ? parseint(next, &num) : 0;
|
||||
|
||||
if (strcmp(opt, "help")==0) {
|
||||
print_help(data->basename);
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "version")==0) {
|
||||
print_version();
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "time")==0) {
|
||||
data->show_time = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME: validation */
|
||||
|
||||
if (strcmp(opt, "max-nesting")==0 && isNum) {
|
||||
data->max_nesting = num;
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(opt, "toc-level")==0 && isNum) {
|
||||
data->toc_level = num;
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(opt, "input-unit")==0 && isNum) {
|
||||
data->iunit = num;
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(opt, "output-unit")==0 && isNum) {
|
||||
data->ounit = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "html")==0) {
|
||||
data->renderer = RENDERER_HTML;
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(opt, "html-toc")==0) {
|
||||
data->renderer = RENDERER_HTML_TOC;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parse_category_option(opt, data) || parse_flag_option(opt, data) || parse_negative_option(opt, data))
|
||||
return 1;
|
||||
|
||||
fprintf(stderr, "Wrong option '--%s' found.\n", opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_argument(int argn, char *arg, int is_forced, void *opaque)
|
||||
{
|
||||
struct option_data *data = opaque;
|
||||
|
||||
if (argn == 0) {
|
||||
/* Input file */
|
||||
if (strcmp(arg, "-")!=0 || is_forced) data->filename = arg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Too many arguments.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* MAIN LOGIC */
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int show_time = 0;
|
||||
//struct timespec start, end;
|
||||
|
||||
/* buffers */
|
||||
struct option_data data;
|
||||
/*struct timespec start, end;*/
|
||||
FILE *file = stdin;
|
||||
hoedown_buffer *ib, *ob;
|
||||
size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT;
|
||||
|
||||
/* files */
|
||||
FILE *in = NULL;
|
||||
|
||||
/* renderer */
|
||||
int toc_level = 0;
|
||||
int renderer_type = RENDERER_HTML;
|
||||
|
||||
/* document */
|
||||
hoedown_renderer *renderer = NULL;
|
||||
void (*renderer_free)(hoedown_renderer *) = NULL;
|
||||
hoedown_document *document;
|
||||
unsigned int extensions = 0;
|
||||
size_t max_nesting = DEF_MAX_NESTING;
|
||||
|
||||
/* HTML renderer-specific */
|
||||
unsigned int html_flags = 0;
|
||||
/* Parse options */
|
||||
data.basename = argv[0];
|
||||
data.done = 0;
|
||||
data.show_time = 0;
|
||||
data.iunit = DEF_IUNIT;
|
||||
data.ounit = DEF_OUNIT;
|
||||
data.filename = NULL;
|
||||
data.renderer = RENDERER_HTML;
|
||||
data.toc_level = 0;
|
||||
data.html_flags = 0;
|
||||
data.extensions = 0;
|
||||
data.max_nesting = DEF_MAX_NESTING;
|
||||
|
||||
argc = parse_options(argc, argv, parse_short_option, parse_long_option, parse_argument, &data);
|
||||
if (data.done) return 0;
|
||||
if (!argc) return 1;
|
||||
|
||||
/* option parsing */
|
||||
int just_args = 0;
|
||||
int i, j;
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *arg = argv[i];
|
||||
if (!arg[0]) continue;
|
||||
|
||||
if (just_args || arg[0] != '-') {
|
||||
/* regular argument */
|
||||
in = fopen(arg, "r");
|
||||
if (!in) {
|
||||
fprintf(stderr, "Unable to open input file \"%s\": %s\n", arg, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!arg[1]) {
|
||||
/* arg is "-" */
|
||||
in = stdin;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg[1] != '-') {
|
||||
/* parse short options */
|
||||
char opt;
|
||||
const char *val;
|
||||
for (j = 1; (opt = arg[j]); j++) {
|
||||
if (opt == 'h') {
|
||||
print_help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opt == 'v') {
|
||||
print_version();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opt == 'T') {
|
||||
show_time = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* options requiring value */
|
||||
if (arg[++j]) val = arg+j;
|
||||
else if (argv[++i]) val = argv[i];
|
||||
else {
|
||||
fprintf(stderr, "Wrong option '-%c' found.\n", opt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
long int num;
|
||||
int isNum = parseint(val, &num);
|
||||
|
||||
if (opt == 'n' && isNum) {
|
||||
max_nesting = num;
|
||||
break;
|
||||
}
|
||||
|
||||
if (opt == 't' && isNum) {
|
||||
toc_level = num;
|
||||
break;
|
||||
}
|
||||
|
||||
if (opt == 'i' && isNum) {
|
||||
iunit = num;
|
||||
break;
|
||||
}
|
||||
|
||||
if (opt == 'o' && isNum) {
|
||||
ounit = num;
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Wrong option '-%c' found.\n", opt);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!arg[2]) {
|
||||
/* arg is "--" */
|
||||
just_args = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse long option */
|
||||
char opt [100];
|
||||
strncpy(opt, arg+2, 100);
|
||||
opt[99] = 0;
|
||||
|
||||
char *val = strchr(opt, '=');
|
||||
|
||||
long int num = 0;
|
||||
int isNum = 0;
|
||||
|
||||
if (val) {
|
||||
*val = 0;
|
||||
val++;
|
||||
|
||||
if (*val)
|
||||
isNum = parseint(val, &num);
|
||||
}
|
||||
|
||||
int opt_parsed = 0;
|
||||
|
||||
if (strcmp(opt, "help")==0) {
|
||||
print_help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "version")==0) {
|
||||
print_version();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "max-nesting")==0 && isNum) {
|
||||
opt_parsed = 1;
|
||||
max_nesting = num;
|
||||
}
|
||||
if (strcmp(opt, "toc-level")==0 && isNum) {
|
||||
opt_parsed = 1;
|
||||
toc_level = num;
|
||||
}
|
||||
if (strcmp(opt, "input-unit")==0 && isNum) {
|
||||
opt_parsed = 1;
|
||||
iunit = num;
|
||||
}
|
||||
if (strcmp(opt, "output-unit")==0 && isNum) {
|
||||
opt_parsed = 1;
|
||||
ounit = num;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "html")==0) {
|
||||
opt_parsed = 1;
|
||||
renderer_type = RENDERER_HTML;
|
||||
}
|
||||
if (strcmp(opt, "html-toc")==0) {
|
||||
opt_parsed = 1;
|
||||
renderer_type = RENDERER_HTML_TOC;
|
||||
}
|
||||
if (strcmp(opt, "null")==0) {
|
||||
opt_parsed = 1;
|
||||
renderer_type = RENDERER_NULL;
|
||||
}
|
||||
|
||||
const char *name;
|
||||
size_t i;
|
||||
|
||||
/* extension categories */
|
||||
if ((name = strprefix(opt, category_prefix))) {
|
||||
for (i = 0; i < count_of(categories_info); i++) {
|
||||
struct extension_category_info *category = categories_info+i;
|
||||
if (strcmp(name, category->option_name)==0) {
|
||||
opt_parsed = 1;
|
||||
extensions |= category->flags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* extensions */
|
||||
for (i = 0; i < count_of(extensions_info); i++) {
|
||||
struct extension_info *extension = extensions_info+i;
|
||||
if (strcmp(opt, extension->option_name)==0) {
|
||||
opt_parsed = 1;
|
||||
extensions |= extension->flag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* html flags */
|
||||
for (i = 0; i < count_of(html_flags_info); i++) {
|
||||
struct html_flag_info *html_flag = html_flags_info+i;
|
||||
if (strcmp(opt, html_flag->option_name)==0) {
|
||||
opt_parsed = 1;
|
||||
html_flags |= html_flag->flag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* negations */
|
||||
if ((name = strprefix(opt, negative_prefix))) {
|
||||
for (i = 0; i < count_of(categories_info); i++) {
|
||||
struct extension_category_info *category = categories_info+i;
|
||||
if (strcmp(name, category->option_name)==0) {
|
||||
opt_parsed = 1;
|
||||
extensions &= ~(category->flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count_of(extensions_info); i++) {
|
||||
struct extension_info *extension = extensions_info+i;
|
||||
if (strcmp(name, extension->option_name)==0) {
|
||||
opt_parsed = 1;
|
||||
extensions &= ~(extension->flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count_of(html_flags_info); i++) {
|
||||
struct html_flag_info *html_flag = html_flags_info+i;
|
||||
if (strcmp(name, html_flag->option_name)==0) {
|
||||
opt_parsed = 1;
|
||||
html_flags &= ~(html_flag->flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(opt, "time")==0) {
|
||||
opt_parsed = 1;
|
||||
show_time = 1;
|
||||
}
|
||||
|
||||
if (!opt_parsed) {
|
||||
fprintf(stderr, "Wrong option '%s' found.\n", arg);
|
||||
return 1;
|
||||
/* Open input file, if needed */
|
||||
if (data.filename) {
|
||||
file = fopen(data.filename, "r");
|
||||
if (!file) {
|
||||
fprintf(stderr, "Unable to open input file \"%s\": %s\n", data.filename, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in)
|
||||
in = stdin;
|
||||
/* Read everything */
|
||||
ib = hoedown_buffer_new(data.iunit);
|
||||
|
||||
|
||||
/* reading everything */
|
||||
ib = hoedown_buffer_new(iunit);
|
||||
|
||||
while (!feof(in)) {
|
||||
if (ferror(in)) {
|
||||
while (!feof(file)) {
|
||||
if (ferror(file)) {
|
||||
fprintf(stderr, "I/O errors found while reading input.\n");
|
||||
return 5;
|
||||
}
|
||||
hoedown_buffer_grow(ib, ib->size + iunit);
|
||||
ib->size += fread(ib->data + ib->size, 1, iunit, in);
|
||||
hoedown_buffer_grow(ib, ib->size + data.iunit);
|
||||
ib->size += fread(ib->data + ib->size, 1, data.iunit, file);
|
||||
}
|
||||
|
||||
if (in != stdin)
|
||||
fclose(in);
|
||||
if (file != stdin) fclose(file);
|
||||
|
||||
|
||||
/* creating the renderer */
|
||||
hoedown_renderer *renderer = NULL;
|
||||
void (*renderer_free)(hoedown_renderer*) = NULL;
|
||||
|
||||
switch (renderer_type) {
|
||||
/* Create the renderer */
|
||||
switch (data.renderer) {
|
||||
case RENDERER_HTML:
|
||||
renderer = hoedown_html_renderer_new(html_flags, toc_level);
|
||||
renderer = hoedown_html_renderer_new(data.html_flags, data.toc_level);
|
||||
renderer_free = hoedown_html_renderer_free;
|
||||
break;
|
||||
case RENDERER_HTML_TOC:
|
||||
renderer = hoedown_html_toc_renderer_new(toc_level);
|
||||
renderer = hoedown_html_toc_renderer_new(data.toc_level);
|
||||
renderer_free = hoedown_html_renderer_free;
|
||||
break;
|
||||
case RENDERER_NULL:
|
||||
renderer = null_renderer_new();
|
||||
renderer_free = null_renderer_free;
|
||||
break;
|
||||
};
|
||||
|
||||
/* Perform Markdown rendering */
|
||||
ob = hoedown_buffer_new(data.ounit);
|
||||
document = hoedown_document_new(renderer, data.extensions, data.max_nesting);
|
||||
|
||||
/* performing markdown rendering */
|
||||
ob = hoedown_buffer_new(ounit);
|
||||
document = hoedown_document_new(renderer, extensions, max_nesting);
|
||||
|
||||
//clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
/*clock_gettime(CLOCK_MONOTONIC, &start);*/
|
||||
hoedown_document_render(document, ob, ib->data, ib->size);
|
||||
//clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
/*clock_gettime(CLOCK_MONOTONIC, &end);*/
|
||||
|
||||
|
||||
/* writing the result to stdout */
|
||||
/* Write the result to stdout */
|
||||
(void)fwrite(ob->data, 1, ob->size, stdout);
|
||||
|
||||
|
||||
/* showing rendering time */
|
||||
if (show_time) {
|
||||
//TODO: enable this
|
||||
//long long elapsed = ( end.tv_sec*1000000000 + end.tv_nsec)
|
||||
// - (start.tv_sec*1000000000 + start.tv_nsec);
|
||||
//if (elapsed < 1000000000)
|
||||
// fprintf(stderr, "Time spent on rendering: %.2f ms.\n", ((double)elapsed)/1000000);
|
||||
//else
|
||||
// fprintf(stderr, "Time spent on rendering: %.3f s.\n", ((double)elapsed)/1000000000);
|
||||
/* Show rendering time */
|
||||
if (data.show_time) {
|
||||
/*TODO: enable this
|
||||
long long elapsed = (end.tv_sec - start.tv_sec)*1e9 + (end.tv_nsec - start.tv_nsec);
|
||||
if (elapsed < 1e9)
|
||||
fprintf(stderr, "Time spent on rendering: %.2f ms.\n", ((double)elapsed)/1e6);
|
||||
else
|
||||
fprintf(stderr, "Time spent on rendering: %.3f s.\n", ((double)elapsed)/1e9);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* cleanup */
|
||||
/* Cleanup */
|
||||
hoedown_buffer_free(ib);
|
||||
hoedown_buffer_free(ob);
|
||||
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
#include "html.h"
|
||||
|
||||
#include "common.h"
|
||||
//#include <time.h>
|
||||
/*#include <time.h>*/
|
||||
|
||||
|
||||
/* FEATURES INFO / DEFAULTS */
|
||||
|
||||
#define DEF_IUNIT 1024
|
||||
#define DEF_OUNIT 64
|
||||
#define DEF_MAX_NESTING 16
|
||||
|
||||
|
||||
/* PRINT HELP */
|
||||
|
||||
void
|
||||
print_help(const char *basename) {
|
||||
print_help(const char *basename)
|
||||
{
|
||||
/* usage */
|
||||
printf("Usage: %s [OPTION]... [FILE]\n\n", basename);
|
||||
|
||||
|
@ -35,193 +38,184 @@ print_help(const char *basename) {
|
|||
}
|
||||
|
||||
|
||||
/* OPTION PARSING */
|
||||
|
||||
struct option_data {
|
||||
char *basename;
|
||||
int done;
|
||||
|
||||
/* time reporting */
|
||||
int show_time;
|
||||
|
||||
/* I/O */
|
||||
size_t iunit;
|
||||
size_t ounit;
|
||||
const char *filename;
|
||||
};
|
||||
|
||||
int
|
||||
parse_short_option(char opt, char *next, void *opaque)
|
||||
{
|
||||
struct option_data *data = opaque;
|
||||
long int num;
|
||||
int isNum = next ? parseint(next, &num) : 0;
|
||||
|
||||
if (opt == 'h') {
|
||||
print_help(data->basename);
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt == 'v') {
|
||||
print_version();
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt == 'T') {
|
||||
data->show_time = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* options requiring value */
|
||||
/* FIXME: add validation */
|
||||
|
||||
if (opt == 'i' && isNum) {
|
||||
data->iunit = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (opt == 'o' && isNum) {
|
||||
data->ounit = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Wrong option '-%c' found.\n", opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_long_option(char *opt, char *next, void *opaque)
|
||||
{
|
||||
struct option_data *data = opaque;
|
||||
long int num;
|
||||
int isNum = next ? parseint(next, &num) : 0;
|
||||
|
||||
if (strcmp(opt, "help")==0) {
|
||||
print_help(data->basename);
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "version")==0) {
|
||||
print_version();
|
||||
data->done = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "time")==0) {
|
||||
data->show_time = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME: validation */
|
||||
|
||||
if (strcmp(opt, "input-unit")==0 && isNum) {
|
||||
data->iunit = num;
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(opt, "output-unit")==0 && isNum) {
|
||||
data->ounit = num;
|
||||
return 2;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Wrong option '--%s' found.\n", opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_argument(int argn, char *arg, int is_forced, void *opaque)
|
||||
{
|
||||
struct option_data *data = opaque;
|
||||
|
||||
if (argn == 0) {
|
||||
/* Input file */
|
||||
if (strcmp(arg, "-")!=0 || is_forced) data->filename = arg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Too many arguments.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* MAIN LOGIC */
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int show_time = 0;
|
||||
//struct timespec start, end;
|
||||
|
||||
/* buffers */
|
||||
struct option_data data;
|
||||
/*struct timespec start, end;*/
|
||||
FILE *file = stdin;
|
||||
hoedown_buffer *ib, *ob;
|
||||
size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT;
|
||||
|
||||
/* files */
|
||||
FILE *in = NULL;
|
||||
/* Parse options */
|
||||
data.basename = argv[0];
|
||||
data.done = 0;
|
||||
data.show_time = 0;
|
||||
data.iunit = DEF_IUNIT;
|
||||
data.ounit = DEF_OUNIT;
|
||||
data.filename = NULL;
|
||||
|
||||
argc = parse_options(argc, argv, parse_short_option, parse_long_option, parse_argument, &data);
|
||||
if (data.done) return 0;
|
||||
if (!argc) return 1;
|
||||
|
||||
/* option parsing */
|
||||
int just_args = 0;
|
||||
int i, j;
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *arg = argv[i];
|
||||
if (!arg[0]) continue;
|
||||
|
||||
if (just_args || arg[0] != '-') {
|
||||
/* regular argument */
|
||||
in = fopen(arg, "r");
|
||||
if (!in) {
|
||||
fprintf(stderr, "Unable to open input file \"%s\": %s\n", arg, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!arg[1]) {
|
||||
/* arg is "-" */
|
||||
in = stdin;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg[1] != '-') {
|
||||
/* parse short options */
|
||||
char opt;
|
||||
const char *val;
|
||||
for (j = 1; (opt = arg[j]); j++) {
|
||||
if (opt == 'h') {
|
||||
print_help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opt == 'v') {
|
||||
print_version();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opt == 'T') {
|
||||
show_time = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* options requiring value */
|
||||
if (arg[++j]) val = arg+j;
|
||||
else if (argv[++i]) val = argv[i];
|
||||
else {
|
||||
fprintf(stderr, "Wrong option '-%c' found.\n", opt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
long int num;
|
||||
int isNum = parseint(val, &num);
|
||||
|
||||
if (opt == 'i' && isNum) {
|
||||
iunit = num;
|
||||
break;
|
||||
}
|
||||
|
||||
if (opt == 'o' && isNum) {
|
||||
ounit = num;
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Wrong option '-%c' found.\n", opt);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!arg[2]) {
|
||||
/* arg is "--" */
|
||||
just_args = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse long option */
|
||||
char opt [100];
|
||||
strncpy(opt, arg+2, 100);
|
||||
opt[99] = 0;
|
||||
|
||||
char *val = strchr(opt, '=');
|
||||
|
||||
long int num = 0;
|
||||
int isNum = 0;
|
||||
|
||||
if (val) {
|
||||
*val = 0;
|
||||
val++;
|
||||
|
||||
if (*val)
|
||||
isNum = parseint(val, &num);
|
||||
}
|
||||
|
||||
int opt_parsed = 0;
|
||||
|
||||
if (strcmp(opt, "help")==0) {
|
||||
print_help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "version")==0) {
|
||||
print_version();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "input-unit")==0 && isNum) {
|
||||
opt_parsed = 1;
|
||||
iunit = num;
|
||||
}
|
||||
if (strcmp(opt, "output-unit")==0 && isNum) {
|
||||
opt_parsed = 1;
|
||||
ounit = num;
|
||||
}
|
||||
|
||||
if (strcmp(opt, "time")==0) {
|
||||
opt_parsed = 1;
|
||||
show_time = 1;
|
||||
}
|
||||
|
||||
if (!opt_parsed) {
|
||||
fprintf(stderr, "Wrong option '%s' found.\n", arg);
|
||||
return 1;
|
||||
/* Open input file, if needed */
|
||||
if (data.filename) {
|
||||
file = fopen(data.filename, "r");
|
||||
if (!file) {
|
||||
fprintf(stderr, "Unable to open input file \"%s\": %s\n", data.filename, strerror(errno));
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in)
|
||||
in = stdin;
|
||||
/* Read everything */
|
||||
ib = hoedown_buffer_new(data.iunit);
|
||||
|
||||
|
||||
/* reading everything */
|
||||
ib = hoedown_buffer_new(iunit);
|
||||
|
||||
while (!feof(in)) {
|
||||
if (ferror(in)) {
|
||||
while (!feof(file)) {
|
||||
if (ferror(file)) {
|
||||
fprintf(stderr, "I/O errors found while reading input.\n");
|
||||
return 5;
|
||||
}
|
||||
hoedown_buffer_grow(ib, ib->size + iunit);
|
||||
ib->size += fread(ib->data + ib->size, 1, iunit, in);
|
||||
hoedown_buffer_grow(ib, ib->size + data.iunit);
|
||||
ib->size += fread(ib->data + ib->size, 1, data.iunit, file);
|
||||
}
|
||||
|
||||
if (in != stdin)
|
||||
fclose(in);
|
||||
if (file != stdin) fclose(file);
|
||||
|
||||
/* Perform SmartyPants processing */
|
||||
ob = hoedown_buffer_new(data.ounit);
|
||||
|
||||
/* performing SmartyPants processing */
|
||||
ob = hoedown_buffer_new(ounit);
|
||||
|
||||
//clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
/*clock_gettime(CLOCK_MONOTONIC, &start);*/
|
||||
hoedown_html_smartypants(ob, ib->data, ib->size);
|
||||
//clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
/*clock_gettime(CLOCK_MONOTONIC, &end);*/
|
||||
|
||||
|
||||
/* writing the result to stdout */
|
||||
/* Write the result to stdout */
|
||||
(void)fwrite(ob->data, 1, ob->size, stdout);
|
||||
|
||||
|
||||
/* showing rendering time */
|
||||
if (show_time) {
|
||||
//TODO: enable this
|
||||
//long long elapsed = ( end.tv_sec*1000000000 + end.tv_nsec)
|
||||
// - (start.tv_sec*1000000000 + start.tv_nsec);
|
||||
//if (elapsed < 1000000000)
|
||||
// fprintf(stderr, "Time spent on rendering: %.2f ms.\n", ((double)elapsed)/1000000);
|
||||
//else
|
||||
// fprintf(stderr, "Time spent on rendering: %.3f s.\n", ((double)elapsed)/1000000000);
|
||||
/* Show rendering time */
|
||||
if (data.show_time) {
|
||||
/*TODO: enable this
|
||||
long long elapsed = (end.tv_sec - start.tv_sec)*1e9 + (end.tv_nsec - start.tv_nsec);
|
||||
if (elapsed < 1e9)
|
||||
fprintf(stderr, "Time spent on rendering: %.2f ms.\n", ((double)elapsed)/1e6);
|
||||
else
|
||||
fprintf(stderr, "Time spent on rendering: %.3f s.\n", ((double)elapsed)/1e9);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* cleanup */
|
||||
/* Cleanup */
|
||||
hoedown_buffer_free(ib);
|
||||
hoedown_buffer_free(ob);
|
||||
|
||||
|
|
42
src/buffer.c
42
src/buffer.c
|
@ -5,6 +5,45 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
void *
|
||||
hoedown_malloc(size_t size)
|
||||
{
|
||||
void *ret = malloc(size);
|
||||
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Allocation failed.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
hoedown_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ret = calloc(nmemb, size);
|
||||
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Allocation failed.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
hoedown_realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Allocation failed.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
hoedown_buffer_init(
|
||||
hoedown_buffer *buf,
|
||||
|
@ -133,9 +172,10 @@ hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str)
|
|||
int
|
||||
hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix)
|
||||
{
|
||||
assert(buf && buf->unit);
|
||||
size_t i;
|
||||
|
||||
assert(buf && buf->unit);
|
||||
|
||||
for (i = 0; i < buf->size; ++i) {
|
||||
if (prefix[i] == 0)
|
||||
return 0;
|
||||
|
|
19
src/buffer.h
19
src/buffer.h
|
@ -37,19 +37,8 @@ struct hoedown_buffer {
|
|||
hoedown_free_callback data_free;
|
||||
hoedown_free_callback buffer_free;
|
||||
};
|
||||
typedef struct hoedown_buffer hoedown_buffer;
|
||||
|
||||
/* malloc / realloc / calloc wrappers */
|
||||
#define HOEDOWN_ALLOC_WRAPPER(sig, call) \
|
||||
static inline void *hoedown_##sig __attribute__ ((malloc)); \
|
||||
static inline void *hoedown_##sig { \
|
||||
void *ret = call; \
|
||||
if (!ret) { \
|
||||
fprintf(stderr, "Allocation failed.\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
typedef struct hoedown_buffer hoedown_buffer;
|
||||
|
||||
|
||||
/*************
|
||||
|
@ -57,9 +46,9 @@ typedef struct hoedown_buffer hoedown_buffer;
|
|||
*************/
|
||||
|
||||
/* allocation wrappers */
|
||||
HOEDOWN_ALLOC_WRAPPER(malloc(size_t size), malloc(size));
|
||||
HOEDOWN_ALLOC_WRAPPER(calloc(size_t nmemb, size_t size), calloc(nmemb, size));
|
||||
HOEDOWN_ALLOC_WRAPPER(realloc(void *ptr, size_t size), realloc(ptr, size));
|
||||
void *hoedown_malloc(size_t size) __attribute__ ((malloc));
|
||||
void *hoedown_calloc(size_t nmemb, size_t size) __attribute__ ((malloc));
|
||||
void *hoedown_realloc(void *ptr, size_t size) __attribute__ ((malloc));
|
||||
|
||||
/* hoedown_buffer_init: initialize a buffer with custom allocators */
|
||||
void hoedown_buffer_init(
|
||||
|
|
|
@ -132,7 +132,7 @@ struct hoedown_document {
|
|||
* HELPER FUNCTIONS *
|
||||
***************************/
|
||||
|
||||
static inline hoedown_buffer *
|
||||
static hoedown_buffer *
|
||||
newbuf(hoedown_document *doc, int type)
|
||||
{
|
||||
static const size_t buf_size[2] = {256, 64};
|
||||
|
@ -151,7 +151,7 @@ newbuf(hoedown_document *doc, int type)
|
|||
return work;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
popbuf(hoedown_document *doc, int type)
|
||||
{
|
||||
doc->work_bufs[type].size--;
|
||||
|
@ -320,14 +320,14 @@ free_footnote_list(struct footnote_list *list, int free_refs)
|
|||
* should instead extract an Unicode codepoint from
|
||||
* this character and check for space properties.
|
||||
*/
|
||||
static inline int
|
||||
static int
|
||||
_isspace(int c)
|
||||
{
|
||||
return c == ' ' || c == '\n';
|
||||
}
|
||||
|
||||
/* is_empty_all: verify that all the data is spacing */
|
||||
static inline int
|
||||
static int
|
||||
is_empty_all(const uint8_t *data, size_t size)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
@ -339,7 +339,7 @@ is_empty_all(const uint8_t *data, size_t size)
|
|||
* Replace all spacing characters in data with spaces. As a special
|
||||
* case, this collapses a newline with the previous space, if possible.
|
||||
*/
|
||||
static inline void
|
||||
static void
|
||||
replace_spacing(hoedown_buffer *ob, const uint8_t *data, size_t size)
|
||||
{
|
||||
size_t i = 0, mark;
|
||||
|
@ -717,22 +717,30 @@ parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
|
|||
static size_t
|
||||
parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, const char *end, size_t delimsz, int displaymode)
|
||||
{
|
||||
hoedown_buffer text = { NULL, 0, 0, 0, NULL, NULL, NULL };
|
||||
size_t i = delimsz;
|
||||
if (!doc->md.math) return 0;
|
||||
|
||||
if (!doc->md.math)
|
||||
return 0;
|
||||
|
||||
/* find ending delimiter */
|
||||
while (1) {
|
||||
while (i < size && data[i] != (uint8_t)end[0]) i++;
|
||||
if (i >= size) return 0;
|
||||
while (i < size && data[i] != (uint8_t)end[0])
|
||||
i++;
|
||||
|
||||
if (i >= size)
|
||||
return 0;
|
||||
|
||||
if (!is_escaped(data, i) && !(i + delimsz > size)
|
||||
&& memcmp(data + i, end, delimsz) == 0)
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/* prepare buffers */
|
||||
hoedown_buffer text = { data + delimsz, i - delimsz, 0, 0, NULL, NULL, NULL };
|
||||
text.data = data + delimsz;
|
||||
text.size = i - delimsz;
|
||||
|
||||
/* if this is a $$ and MATH_EXPLICIT is not active,
|
||||
* guess whether displaymode should be enabled from the context */
|
||||
|
@ -743,6 +751,7 @@ parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs
|
|||
/* call callback */
|
||||
if (doc->md.math(ob, &text, displaymode, &doc->data))
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -804,6 +813,7 @@ char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
|
|||
static size_t
|
||||
char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
|
||||
{
|
||||
hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
|
||||
size_t end, nb = 0, i, f_begin, f_end;
|
||||
|
||||
/* counting the number of backticks in the delimiter */
|
||||
|
@ -831,7 +841,9 @@ char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o
|
|||
|
||||
/* real code span */
|
||||
if (f_begin < f_end) {
|
||||
hoedown_buffer work = { data + f_begin, f_end - f_begin, 0, 0, NULL, NULL, NULL };
|
||||
work.data = data + f_begin;
|
||||
work.size = f_end - f_begin;
|
||||
|
||||
if (!doc->md.codespan(ob, &work, &doc->data))
|
||||
end = 0;
|
||||
} else {
|
||||
|
@ -954,11 +966,14 @@ char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off
|
|||
static size_t
|
||||
char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
|
||||
{
|
||||
hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
|
||||
hoedown_autolink_type altype = HOEDOWN_AUTOLINK_NONE;
|
||||
size_t end = tag_length(data, size, &altype);
|
||||
hoedown_buffer work = { data, end, 0, 0, NULL, NULL, NULL };
|
||||
int ret = 0;
|
||||
|
||||
work.data = data;
|
||||
work.size = end;
|
||||
|
||||
if (end > 2) {
|
||||
if (doc->md.autolink && altype != HOEDOWN_AUTOLINK_NONE) {
|
||||
hoedown_buffer *u_link = newbuf(doc, BUFFER_SPAN);
|
||||
|
@ -1618,9 +1633,11 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
|
|||
static size_t
|
||||
parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
|
||||
{
|
||||
hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
|
||||
size_t i = 0, end = 0;
|
||||
int level = 0;
|
||||
hoedown_buffer work = { data, 0, 0, 0, NULL, NULL, NULL };
|
||||
|
||||
work.data = data;
|
||||
|
||||
while (i < size) {
|
||||
for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
|
||||
|
@ -1696,23 +1713,27 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
|
|||
static size_t
|
||||
parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
|
||||
{
|
||||
hoedown_buffer text = { 0, 0, 0, 0, NULL, NULL, NULL };
|
||||
hoedown_buffer lang = { 0, 0, 0, 0, NULL, NULL, NULL };
|
||||
size_t i = 0, text_start, line_start;
|
||||
size_t w, w2;
|
||||
size_t width, width2;
|
||||
uint8_t chr, chr2;
|
||||
hoedown_buffer text = { 0, 0, 0, 0, NULL, NULL, NULL };
|
||||
hoedown_buffer lang = { 0, 0, 0, 0, NULL, NULL, NULL };
|
||||
|
||||
// parse codefence line
|
||||
while (i < size && data[i] != '\n') i++;
|
||||
/* parse codefence line */
|
||||
while (i < size && data[i] != '\n')
|
||||
i++;
|
||||
|
||||
w = parse_codefence(data, i, &lang, &width, &chr);
|
||||
if (!w) return 0;
|
||||
if (!w)
|
||||
return 0;
|
||||
|
||||
// search for end
|
||||
/* search for end */
|
||||
i++;
|
||||
text_start = i;
|
||||
while ((line_start = i) < size) {
|
||||
while (i < size && data[i] != '\n') i++;
|
||||
while (i < size && data[i] != '\n')
|
||||
i++;
|
||||
|
||||
w2 = is_codefence(data + line_start, i - line_start, &width2, &chr2);
|
||||
if (w == w2 && width == width2 && chr == chr2 &&
|
||||
|
@ -1721,6 +1742,7 @@ parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_
|
|||
|
||||
i++;
|
||||
}
|
||||
|
||||
text.data = data + text_start;
|
||||
text.size = line_start - text_start;
|
||||
|
||||
|
@ -2009,7 +2031,7 @@ parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_l
|
|||
/* htmlblock_is_end • check for end of HTML block : </tag>( *)\n */
|
||||
/* returns tag length on match, 0 otherwise */
|
||||
/* assumes data starts with "<" */
|
||||
static inline size_t
|
||||
static size_t
|
||||
htmlblock_is_end(
|
||||
const char *tag,
|
||||
size_t tag_len,
|
||||
|
@ -2087,9 +2109,11 @@ htmlblock_find_end_strict(
|
|||
static size_t
|
||||
parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render)
|
||||
{
|
||||
size_t i, j = 0, tag_end;
|
||||
hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
|
||||
size_t i, j = 0, tag_len, tag_end;
|
||||
const char *curtag = NULL;
|
||||
hoedown_buffer work = { data, 0, 0, 0, NULL, NULL, NULL };
|
||||
|
||||
work.data = data;
|
||||
|
||||
/* identification of the opening tag */
|
||||
if (size < 2 || data[0] != '<')
|
||||
|
@ -2148,7 +2172,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
|
|||
}
|
||||
|
||||
/* looking for a matching closing tag in strict mode */
|
||||
size_t tag_len = strlen(curtag);
|
||||
tag_len = strlen(curtag);
|
||||
tag_end = htmlblock_find_end_strict(curtag, tag_len, doc, data, size);
|
||||
|
||||
/* if not found, trying a second pass looking for indented match */
|
||||
|
@ -2177,7 +2201,7 @@ parse_table_row(
|
|||
hoedown_table_flags *col_data,
|
||||
hoedown_table_flags header_flag)
|
||||
{
|
||||
size_t i = 0, col;
|
||||
size_t i = 0, col, len;
|
||||
hoedown_buffer *row_work = 0;
|
||||
|
||||
if (!doc->md.table_cell || !doc->md.table_row)
|
||||
|
@ -2199,7 +2223,7 @@ parse_table_row(
|
|||
|
||||
cell_start = i;
|
||||
|
||||
size_t len = find_emph_char(data + i, size - i, '|');
|
||||
len = find_emph_char(data + i, size - i, '|');
|
||||
i += len ? len : size - i;
|
||||
|
||||
cell_end = i - 1;
|
||||
|
|
36
src/html.c
36
src/html.c
|
@ -42,12 +42,12 @@ hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname)
|
|||
return HOEDOWN_HTML_TAG_NONE;
|
||||
}
|
||||
|
||||
static inline void escape_html(hoedown_buffer *ob, const uint8_t *source, size_t length)
|
||||
static void escape_html(hoedown_buffer *ob, const uint8_t *source, size_t length)
|
||||
{
|
||||
hoedown_escape_html(ob, source, length, 0);
|
||||
}
|
||||
|
||||
static inline void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t length)
|
||||
static void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t length)
|
||||
{
|
||||
hoedown_escape_href(ob, source, length);
|
||||
}
|
||||
|
@ -326,15 +326,25 @@ static void
|
|||
rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
|
||||
{
|
||||
size_t org, sz;
|
||||
if (!text) return;
|
||||
//FIXME: do we *really* need to trim the HTML?
|
||||
//how does that make a difference?
|
||||
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
/* FIXME: Do we *really* need to trim the HTML? How does that make a difference? */
|
||||
sz = text->size;
|
||||
while (sz > 0 && text->data[sz - 1] == '\n') sz--;
|
||||
while (sz > 0 && text->data[sz - 1] == '\n')
|
||||
sz--;
|
||||
|
||||
org = 0;
|
||||
while (org < sz && text->data[org] == '\n') org++;
|
||||
if (org >= sz) return;
|
||||
if (ob->size) hoedown_buffer_putc(ob, '\n');
|
||||
while (org < sz && text->data[org] == '\n')
|
||||
org++;
|
||||
|
||||
if (org >= sz)
|
||||
return;
|
||||
|
||||
if (ob->size)
|
||||
hoedown_buffer_putc(ob, '\n');
|
||||
|
||||
hoedown_buffer_put(ob, text->data + org, sz - org);
|
||||
hoedown_buffer_putc(ob, '\n');
|
||||
}
|
||||
|
@ -591,8 +601,12 @@ toc_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer
|
|||
static void
|
||||
toc_finalize(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)
|
||||
{
|
||||
if (inline_render) return;
|
||||
hoedown_html_renderer_state *state = data->opaque;
|
||||
hoedown_html_renderer_state *state;
|
||||
|
||||
if (inline_render)
|
||||
return;
|
||||
|
||||
state = data->opaque;
|
||||
|
||||
while (state->toc_data.current_level > 0) {
|
||||
HOEDOWN_BUFPUTSL(ob, "</li>\n</ul>\n");
|
||||
|
|
|
@ -60,7 +60,7 @@ static const uint8_t smartypants_cb_chars[UINT8_MAX+1] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static inline int
|
||||
static int
|
||||
word_boundary(uint8_t c)
|
||||
{
|
||||
return c == 0 || isspace(c) || ispunct(c);
|
||||
|
|
Loading…
Reference in a new issue