summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevin Torres <devin@devintorr.es>2014-10-21 03:15:03 -0500
committerDevin Torres <devin@devintorr.es>2014-10-21 03:15:03 -0500
commita88343c593a87d1d5c43ff2498e2a479e749cbee (patch)
treeefc63de694a94eae6a0d378ebe55251463bde812
parent4e1b16cfab1f99191f5dd9b9498df4162fd44ff9 (diff)
parent684357d279989d49945afe0154e742c0e0e4c35a (diff)
downloadrust-hoedown-a88343c593a87d1d5c43ff2498e2a479e749cbee.tar.gz
Merge pull request #137 from hoedown/ansi
Use a stricter subset of C
-rw-r--r--Makefile5
-rw-r--r--bin/common.h77
-rw-r--r--bin/hoedown.c541
-rw-r--r--bin/smartypants.c304
-rw-r--r--src/buffer.c42
-rw-r--r--src/buffer.h19
-rw-r--r--src/document.c74
-rw-r--r--src/html.c36
-rw-r--r--src/html_smartypants.c2
9 files changed, 606 insertions, 494 deletions
diff --git a/Makefile b/Makefile
index 56e1597..ae5f92c 100644
--- a/Makefile
+++ b/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 $@ $<
diff --git a/bin/common.h b/bin/common.h
index 9074bd6..5d55acc 100644
--- a/bin/common.h
+++ b/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;
}
diff --git a/bin/hoedown.c b/bin/hoedown.c
index 15f2e61..5aac21a 100644
--- a/bin/hoedown.c
+++ b/bin/hoedown.c
@@ -2,32 +2,16 @@
#include "html.h"
#include "common.h"
-//#include <time.h>
+/*#include <time.h>*/
-/* NULL RENDERER */
+
+/* FEATURES INFO / DEFAULTS */
enum renderer_type {
RENDERER_HTML,
- RENDERER_HTML_TOC,
- RENDERER_NULL,
+ RENDERER_HTML_TOC
};
-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);
-}
-
-
-/* FEATURES INFO / DEFAULTS */
-
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) {
}
-/* MAIN LOGIC */
+/* OPTION PARSING */
-int
-main(int argc, char **argv)
-{
- int show_time = 0;
- //struct timespec start, end;
+struct option_data {
+ char *basename;
+ int done;
- /* buffers */
- hoedown_buffer *ib, *ob;
- size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT;
+ /* time reporting */
+ int show_time;
- /* files */
- FILE *in = NULL;
+ /* I/O */
+ size_t iunit;
+ size_t ounit;
+ const char *filename;
/* renderer */
- int toc_level = 0;
- int renderer_type = RENDERER_HTML;
+ enum renderer_type renderer;
+ int toc_level;
+ hoedown_html_flags html_flags;
- /* document */
- hoedown_document *document;
- unsigned int extensions = 0;
- size_t max_nesting = DEF_MAX_NESTING;
-
- /* HTML renderer-specific */
- unsigned int html_flags = 0;
-
-
- /* 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;
- }
+ /* parsing */
+ hoedown_extensions extensions;
+ size_t max_nesting;
+};
- if (!arg[1]) {
- /* arg is "-" */
- in = stdin;
- continue;
- }
+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 (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 (opt == 'v') {
+ print_version();
+ data->done = 1;
+ return 0;
+ }
- if (!arg[2]) {
- /* arg is "--" */
- just_args = 1;
- continue;
- }
+ if (opt == 'T') {
+ data->show_time = 1;
+ return 1;
+ }
- /* parse long option */
- char opt [100];
- strncpy(opt, arg+2, 100);
- opt[99] = 0;
+ /* options requiring value */
+ /* FIXME: add validation */
- char *val = strchr(opt, '=');
+ if (opt == 'n' && isNum) {
+ data->max_nesting = num;
+ return 2;
+ }
- long int num = 0;
- int isNum = 0;
+ if (opt == 't' && isNum) {
+ data->toc_level = num;
+ return 2;
+ }
- if (val) {
- *val = 0;
- val++;
+ if (opt == 'i' && isNum) {
+ data->iunit = num;
+ return 2;
+ }
- if (*val)
- isNum = parseint(val, &num);
- }
+ if (opt == 'o' && isNum) {
+ data->ounit = num;
+ return 2;
+ }
- int opt_parsed = 0;
+ fprintf(stderr, "Wrong option '-%c' found.\n", opt);
+ return 0;
+}
- if (strcmp(opt, "help")==0) {
- print_help(argv[0]);
- return 1;
- }
+int
+parse_category_option(char *opt, struct option_data *data)
+{
+ size_t i;
+ const char *name = strprefix(opt, category_prefix);
+ if (!name) return 0;
- if (strcmp(opt, "version")==0) {
- print_version();
+ 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;
}
+ }
- 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;
- }
+ return 0;
+}
- 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;
- }
+int
+parse_flag_option(char *opt, struct option_data *data)
+{
+ size_t i;
- 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;
- }
- }
+ 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;
}
+ }
- /* 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;
- }
+ 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;
}
+ }
- /* 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;
- }
- }
+ return 0;
+}
- /* 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;
- }
- }
+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;
}
+ }
- if (strcmp(opt, "time")==0) {
- opt_parsed = 1;
- show_time = 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;
}
+ }
- if (!opt_parsed) {
- fprintf(stderr, "Wrong option '%s' found.\n", arg);
+ 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;
}
}
- if (!in)
- in = stdin;
+ 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;
+ }
- /* reading everything */
- ib = hoedown_buffer_new(iunit);
+ if (strcmp(opt, "version")==0) {
+ print_version();
+ data->done = 1;
+ return 0;
+ }
- while (!feof(in)) {
- if (ferror(in)) {
- fprintf(stderr, "I/O errors found while reading input.\n");
+ 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)
+{
+ struct option_data data;
+ /*struct timespec start, end;*/
+ FILE *file = stdin;
+ hoedown_buffer *ib, *ob;
+ hoedown_renderer *renderer = NULL;
+ void (*renderer_free)(hoedown_renderer *) = NULL;
+ hoedown_document *document;
+
+ /* 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;
+
+ /* 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;
}
- hoedown_buffer_grow(ib, ib->size + iunit);
- ib->size += fread(ib->data + ib->size, 1, iunit, in);
}
- if (in != stdin)
- fclose(in);
+ /* Read everything */
+ ib = hoedown_buffer_new(data.iunit);
+ while (!feof(file)) {
+ if (ferror(file)) {
+ fprintf(stderr, "I/O errors found while reading input.\n");
+ return 5;
+ }
+ hoedown_buffer_grow(ib, ib->size + data.iunit);
+ ib->size += fread(ib->data + ib->size, 1, data.iunit, file);
+ }
- /* creating the renderer */
- hoedown_renderer *renderer = NULL;
- void (*renderer_free)(hoedown_renderer*) = NULL;
+ if (file != stdin) fclose(file);
- 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);
diff --git a/bin/smartypants.c b/bin/smartypants.c
index d67165a..de0512e 100644
--- a/bin/smartypants.c
+++ b/bin/smartypants.c
@@ -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) {
}
-/* MAIN LOGIC */
+/* 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
-main(int argc, char **argv)
+parse_short_option(char opt, char *next, void *opaque)
{
- int show_time = 0;
- //struct timespec start, end;
-
- /* buffers */
- hoedown_buffer *ib, *ob;
- size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT;
-
- /* files */
- FILE *in = NULL;
-
-
- /* 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;
- }
+ 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 (!arg[1]) {
- /* arg is "-" */
- in = stdin;
- continue;
- }
+ if (opt == 'v') {
+ print_version();
+ data->done = 1;
+ return 0;
+ }
- 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 (opt == 'T') {
+ data->show_time = 1;
+ return 1;
+ }
- if (!arg[2]) {
- /* arg is "--" */
- just_args = 1;
- continue;
- }
+ /* options requiring value */
+ /* FIXME: add validation */
- /* parse long option */
- char opt [100];
- strncpy(opt, arg+2, 100);
- opt[99] = 0;
+ if (opt == 'i' && isNum) {
+ data->iunit = num;
+ return 2;
+ }
- char *val = strchr(opt, '=');
+ if (opt == 'o' && isNum) {
+ data->ounit = num;
+ return 2;
+ }
- long int num = 0;
- int isNum = 0;
+ fprintf(stderr, "Wrong option '-%c' found.\n", opt);
+ return 0;
+}
- if (val) {
- *val = 0;
- val++;
+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 (*val)
- isNum = parseint(val, &num);
- }
+ if (strcmp(opt, "version")==0) {
+ print_version();
+ data->done = 1;
+ return 0;
+ }
- int opt_parsed = 0;
+ if (strcmp(opt, "time")==0) {
+ data->show_time = 1;
+ return 1;
+ }
- if (strcmp(opt, "help")==0) {
- print_help(argv[0]);
- return 1;
- }
+ /* FIXME: validation */
- if (strcmp(opt, "version")==0) {
- print_version();
- return 1;
- }
+ 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, "input-unit")==0 && isNum) {
- opt_parsed = 1;
- iunit = num;
- }
- if (strcmp(opt, "output-unit")==0 && isNum) {
- opt_parsed = 1;
- ounit = num;
- }
+ fprintf(stderr, "Wrong option '--%s' found.\n", opt);
+ return 0;
+}
- if (strcmp(opt, "time")==0) {
- opt_parsed = 1;
- show_time = 1;
- }
+int
+parse_argument(int argn, char *arg, int is_forced, void *opaque)
+{
+ struct option_data *data = opaque;
- if (!opt_parsed) {
- fprintf(stderr, "Wrong option '%s' found.\n", arg);
- return 1;
- }
+ if (argn == 0) {
+ /* Input file */
+ if (strcmp(arg, "-")!=0 || is_forced) data->filename = arg;
+ return 1;
}
- if (!in)
- in = stdin;
+ fprintf(stderr, "Too many arguments.\n");
+ return 0;
+}
+
+/* MAIN LOGIC */
- /* reading everything */
- ib = hoedown_buffer_new(iunit);
+int
+main(int argc, char **argv)
+{
+ struct option_data data;
+ /*struct timespec start, end;*/
+ FILE *file = stdin;
+ hoedown_buffer *ib, *ob;
- while (!feof(in)) {
- if (ferror(in)) {
- fprintf(stderr, "I/O errors found while reading input.\n");
+ /* 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;
+
+ /* 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;
}
- hoedown_buffer_grow(ib, ib->size + iunit);
- ib->size += fread(ib->data + ib->size, 1, iunit, in);
}
- if (in != stdin)
- fclose(in);
+ /* Read everything */
+ ib = hoedown_buffer_new(data.iunit);
+
+ while (!feof(file)) {
+ if (ferror(file)) {
+ fprintf(stderr, "I/O errors found while reading input.\n");
+ return 5;
+ }
+ hoedown_buffer_grow(ib, ib->size + data.iunit);
+ ib->size += fread(ib->data + ib->size, 1, data.iunit, file);
+ }
+ if (file != stdin) fclose(file);
- /* performing SmartyPants processing */
- ob = hoedown_buffer_new(ounit);
+ /* Perform SmartyPants processing */
+ ob = hoedown_buffer_new(data.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);
diff --git a/src/buffer.c b/src/buffer.c
index daba5fd..2ca0fd1 100644
--- a/src/buffer.c
+++ b/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;
diff --git a/src/buffer.h b/src/buffer.h
index 6d42385..fcda83c 100644
--- a/src/buffer.h
+++ b/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(
diff --git a/src/document.c b/src/document.c
index f2ce139..3ce4416 100644
--- a/src/document.c
+++ b/src/document.c
@@ -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;
diff --git a/src/html.c b/src/html.c
index d24bf8e..ddebff7 100644
--- a/src/html.c
+++ b/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");
diff --git a/src/html_smartypants.c b/src/html_smartypants.c
index 9f9dcf0..bbe4fc5 100644
--- a/src/html_smartypants.c
+++ b/src/html_smartypants.c
@@ -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);