Пример #1
0
/* hoedown_buffer_putc: appends a single uint8_t to a buffer */
void
hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c)
{
	assert(buf && buf->unit);

	if (buf->size + 1 > buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0)
		return;

	buf->data[buf->size] = c;
	buf->size += 1;
}
Пример #2
0
void
hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size)
{
	assert(buf && buf->unit);

	if (buf->size + size > buf->asize)
		hoedown_buffer_grow(buf, buf->size + size);

	memcpy(buf->data + buf->size, data, size);
	buf->size += size;
}
Пример #3
0
/* hoedown_buffer_put: appends raw data to a buffer */
void
hoedown_buffer_put(hoedown_buffer *buf, const void *data, size_t len)
{
	assert(buf && buf->unit);

	if (buf->size + len > buf->asize && hoedown_buffer_grow(buf, buf->size + len) < 0)
		return;

	memcpy(buf->data + buf->size, data, len);
	buf->size += len;
}
Пример #4
0
void
hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c)
{
	assert(buf && buf->unit);

	if (buf->size >= buf->asize)
		hoedown_buffer_grow(buf, buf->size + 1);

	buf->data[buf->size] = c;
	buf->size += 1;
}
Пример #5
0
/* hoedown_buffer_printf: formatted printing to a buffer */
void
hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...)
{
	va_list ap;
	int n;

	assert(buf && buf->unit);

	if (buf->size >= buf->asize && hoedown_buffer_grow(buf, buf->size + 1) < 0)
		return;
	
	va_start(ap, fmt);
	n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
	va_end(ap);

	if (n < 0) {
#ifndef _MSC_VER
		return;
#else
		va_start(ap, fmt);
		n = _vscprintf(fmt, ap);
		va_end(ap);
#endif
	}

	if ((size_t)n >= buf->asize - buf->size) {
		if (hoedown_buffer_grow(buf, buf->size + n + 1) < 0)
			return;

		va_start(ap, fmt);
		n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
		va_end(ap);
	}

	if (n < 0)
		return;

	buf->size += n;
}
Пример #6
0
const char *
hoedown_buffer_cstr(hoedown_buffer *buf)
{
	assert(buf && buf->unit);

	if (buf->size < buf->asize && buf->data[buf->size] == 0)
		return (char *)buf->data;

	hoedown_buffer_grow(buf, buf->size + 1);
	buf->data[buf->size] = 0;

	return (char *)buf->data;
}
Пример #7
0
static void
rndr_footnote_ref_def(hoedown_buffer *orig, const hoedown_renderer_data *data)
{
	/* this is a little dirty, but it is simpler than maintaining this state in the renderer */
	hoedown_buffer *copy;
	copy = hoedown_buffer_new(64);
	hoedown_buffer_grow(copy, orig->size);
	memcpy(copy->data, orig->data, orig->size);
	copy->size = orig->size;

	printf("Footnote Reference Definition: %s\n", hoedown_buffer_cstr(copy));

	hoedown_buffer_free(copy);
}
Пример #8
0
int
main(int argc, char **argv)
{
	struct hoedown_buffer *ib, *ob;
	FILE *in = stdin;

	struct hoedown_callbacks callbacks;
	struct hoedown_html_renderopt options;
	struct hoedown_markdown *markdown;

	/* opening the file if given from the command line */
	if (argc > 1) {
		in = fopen(argv[1], "r");
		if (!in) {
			fprintf(stderr, "Unable to open input file \"%s\": %s\n", argv[1], strerror(errno));
			return 1;
		}
	}

	/* reading everything */
	ib = hoedown_buffer_new(READ_UNIT);
	while (!feof(in) && !ferror(in)) {
		hoedown_buffer_grow(ib, ib->size + READ_UNIT);
		ib->size += fread(ib->data + ib->size, 1, READ_UNIT, in);
	}

	if (in != stdin)
		fclose(in);

	/* performing markdown parsing */
	ob = hoedown_buffer_new(OUTPUT_UNIT);

	hoedown_html_renderer(&callbacks, &options, 0, 0);
	markdown = hoedown_markdown_new(0, 16, &callbacks, &options);

	hoedown_markdown_render(ob, ib->data, ib->size, markdown);
	hoedown_markdown_free(markdown);

	/* writing the result to stdout */
	(void)fwrite(ob->data, 1, ob->size, stdout);

	/* cleanup */
	hoedown_buffer_free(ib);
	hoedown_buffer_free(ob);

	return ferror(stdout);
}
Пример #9
0
void
hoedown_escape_html(struct hoedown_buffer *ob, const uint8_t *src, size_t size, int secure)
{
	size_t i = 0, org, esc = 0;

	while (i < size) {
		org = i;
		while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
			i++;

		if (i > org) {
			if (org == 0) {
				if (i >= size) {
					hoedown_buffer_put(ob, src, size);
					return;
				}

				hoedown_buffer_grow(ob, ESCAPE_GROW_FACTOR(size));
			}

			hoedown_buffer_put(ob, src + org, i - org);
		}

		/* escaping */
		if (i >= size)
			break;

		/* The forward slash is only escaped in secure mode */
		if (src[i] == '/' && !secure) {
			hoedown_buffer_putc(ob, '/');
		} else {
			hoedown_buffer_puts(ob, HTML_ESCAPES[esc]);
		}

		i++;
	}
}
Пример #10
0
int
main(int argc, char **argv)
{
	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;

	/* renderer */
	int toc_level = 0;
	int renderer_type = RENDERER_HTML;

	/* 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;
		}

		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;
		}
	}

	if (!in)
		in = stdin;


	/* reading everything */
	ib = hoedown_buffer_new(iunit);

	while (!feof(in)) {
		if (ferror(in)) {
			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);
	}

	if (in != stdin)
		fclose(in);


	/* creating the renderer */
	hoedown_renderer *renderer = NULL;
	void (*renderer_free)(hoedown_renderer*) = NULL;

	switch (renderer_type) {
		case RENDERER_HTML:
			renderer = hoedown_html_renderer_new(html_flags, toc_level);
			renderer_free = hoedown_html_renderer_free;
			break;
		case RENDERER_HTML_TOC:
			renderer = hoedown_html_toc_renderer_new(toc_level);
			renderer_free = hoedown_html_renderer_free;
			break;
		case RENDERER_NULL:
			renderer = null_renderer_new();
			renderer_free = null_renderer_free;
			break;
	};


	/* performing markdown rendering */
	ob = hoedown_buffer_new(ounit);
	document = hoedown_document_new(renderer, extensions, max_nesting);

	//clock_gettime(CLOCK_MONOTONIC, &start);
	hoedown_document_render(document, ob, ib->data, ib->size);
	//clock_gettime(CLOCK_MONOTONIC, &end);


	/* writing 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);
	}


	/* cleanup */
	hoedown_buffer_free(ib);
	hoedown_buffer_free(ob);

	hoedown_document_free(document);
	renderer_free(renderer);

	if (ferror(stdout)) {
		fprintf(stderr, "I/O errors found while writing output.\n");
		return 5;
	}

	return 0;
}
Пример #11
0
void
hoedown_escape_href(struct hoedown_buffer *ob, const uint8_t *src, size_t size)
{
	static const char hex_chars[] = "0123456789ABCDEF";
	size_t  i = 0, org;
	char hex_str[3];

	hex_str[0] = '%';

	while (i < size) {
		org = i;
		while (i < size && HREF_SAFE[src[i]] != 0)
			i++;

		if (i > org) {
			if (org == 0) {
				if (i >= size) {
					hoedown_buffer_put(ob, src, size);
					return;
				}

				hoedown_buffer_grow(ob, ESCAPE_GROW_FACTOR(size));
			}

			hoedown_buffer_put(ob, src + org, i - org);
		}

		/* escaping */
		if (i >= size)
			break;

		switch (src[i]) {
		/* amp appears all the time in URLs, but needs
		 * HTML-entity escaping to be inside an href */
		case '&': 
			BUFPUTSL(ob, "&amp;");
			break;

		/* the single quote is a valid URL character
		 * according to the standard; it needs HTML
		 * entity escaping too */
		case '\'':
			BUFPUTSL(ob, "&#x27;");
			break;
		
		/* the space can be escaped to %20 or a plus
		 * sign. we're going with the generic escape
		 * for now. the plus thing is more commonly seen
		 * when building GET strings */
#if 0
		case ' ':
			hoedown_buffer_putc(ob, '+');
			break;
#endif

		/* every other character goes with a %XX escaping */
		default:
			hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
			hex_str[2] = hex_chars[src[i] & 0xF];
			hoedown_buffer_put(ob, hex_str, 3);
		}

		i++;
	}
}