Exemplo n.º 1
0
/* parse_blockquote • hanldes parsing of a regular paragraph */
static size_t
parse_paragraph(struct buf *ob, struct render *rndr,
			char *data, size_t size) {
	size_t i = 0, end = 0;
	int level = 0;
	struct buf work = { data, 0, 0, 0, 0 }; /* volatile working buffer */

	while (i < size) {
		for (end = i + 1; end < size && data[end - 1] != '\n';
								end += 1);
		if (is_empty(data + i, size - i)
		|| (level = is_headerline(data + i, size - i)) != 0)
			break;
		if ((i && data[i] == '#')
		|| is_hrule(data + i, size - i)) {
			end = i;
			break; }
		i = end; }

	work.size = i;
	while (work.size && data[work.size - 1] == '\n')
		work.size -= 1;
	if (!level) {
		struct buf *tmp = new_work_buffer(rndr);
		parse_inline(tmp, rndr, work.data, work.size);
		if (rndr->make.paragraph)
			rndr->make.paragraph(ob, tmp, rndr->make.opaque);
		release_work_buffer(rndr, tmp); }
	else {
		if (work.size) {
			size_t beg;
			i = work.size;
			work.size -= 1;
			while (work.size && data[work.size] != '\n')
				work.size -= 1;
			beg = work.size + 1;
			while (work.size && data[work.size - 1] == '\n')
				work.size -= 1;
			if (work.size) {
				struct buf *tmp = new_work_buffer(rndr);
				parse_inline(tmp, rndr, work.data, work.size);
				if (rndr->make.paragraph)
					rndr->make.paragraph(ob, tmp,
							rndr->make.opaque);
				release_work_buffer(rndr, tmp);
				work.data += beg;
				work.size = i - beg; }
			else work.size = i; }
		if (rndr->make.header) {
			struct buf *span = new_work_buffer(rndr);
			parse_inline(span, rndr, work.data, work.size);
			rndr->make.header(ob, span, level,rndr->make.opaque);
			release_work_buffer(rndr, span); } }
	return end; }
Exemplo n.º 2
0
/* parse_table_cell • parse a cell inside a table */
static void
parse_table_cell(struct buf *ob, struct render *rndr, char *data, size_t size,
				int flags) {
	struct buf *span = new_work_buffer(rndr);
	parse_inline(span, rndr, data, size);
	rndr->make.table_cell(ob, span, flags, rndr->make.opaque);
	release_work_buffer(rndr, span); }
Exemplo n.º 3
0
/* parse_emph2 • parsing single emphase */
static size_t
parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c)
{
	int (*render_method)(struct buf *ob, struct buf *text, void *opaque);
	size_t i = 0, len;
	struct buf *work = 0;
	int r;

	render_method = (c == '~') ? rndr->make.strikethrough : rndr->make.double_emphasis;

	if (!render_method)
		return 0;
	
	while (i < size) {
		len = find_emph_char(data + i, size - i, c);
		if (!len) return 0;
		i += len;

		if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !isspace(data[i - 1])) {
			work = rndr_newbuf(rndr);
			parse_inline(work, rndr, data, i);
			r = render_method(ob, work, rndr->make.opaque);
			rndr_popbuf(rndr);
			return r ? i + 2 : 0;
		}
		i++;
	}
	return 0;
}
Exemplo n.º 4
0
Arquivo: if.c Projeto: choppsv1/ircii
void
ifcmd(u_char *command, u_char *args, u_char *subargs)
{
	u_char	*expr;
	u_char	*sub;
	int	flag = 0;
	int	result;

	if (!(expr = next_expr(&args, '(')))
	{
		yell("Missing CONDITION in IF");
		return;
	}
	sub = parse_inline(expr, subargs ? subargs : empty_string(), &flag);
	if (get_int_var(DEBUG_VAR) & DEBUG_EXPANSIONS)
		yell("If expression expands to: (%s)", sub);
	if (!*sub || *sub == '0')
		result = 0;
	else
		result = 1;
	new_free(&sub);
	if (!(expr = next_expr(&args, '{')))
	{
		yell("Missing THEN portion in IF");
		return;
	}
	if (!result && !(expr = next_expr(&args, '{')))
		return;
	parse_line(NULL, expr, subargs ? subargs : empty_string(), 0, 0, 0);
		return;
}
Exemplo n.º 5
0
/* parse_atxheader • parsing of atx-style headers */
static size_t
parse_atxheader(struct buf *ob, struct render *rndr,
			char *data, size_t size) {
	int level = 0;
	size_t i, end, skip, span_beg, span_size;

	if (!size || data[0] != '#') return 0;

	while (level < size && level < 6 && data[level] == '#') level += 1;
	for (i = level; i < size && (data[i] == ' ' || data[i] == '\t');
							i += 1);
	span_beg = i;

	for (end = i; end < size && data[end] != '\n'; end += 1);
	skip = end;
	if (end <= i)
		return parse_paragraph(ob, rndr, data, size);
	while (end && data[end - 1] == '#') end -= 1;
	while (end && (data[end - 1] == ' ' || data[end - 1] == '\t')) end -= 1;
	if (end <= i)
		return parse_paragraph(ob, rndr, data, size);

	span_size = end - span_beg;
	if (rndr->make.header) {
		struct buf *span = new_work_buffer(rndr);
		parse_inline(span, rndr, data + span_beg, span_size);
		rndr->make.header(ob, span, level, rndr->make.opaque);
		release_work_buffer(rndr, span); }
	return skip; }
Exemplo n.º 6
0
/* closed by a symbol not preceded by whitespace and not followed by symbol */
static size_t
parse_emph1(struct buf *ob, struct render *rndr,
			char *data, size_t size, char c) {
	size_t i = 0, len;
	struct buf *work = 0;
	int r;

	if (!rndr->make.emphasis) return 0;

	/* skipping one symbol if coming from emph3 */
	if (size > 1 && data[0] == c && data[1] == c) i = 1;

	while (i < size) {
		len = find_emph_char(data + i, size - i, c);
		if (!len) return 0;
		i += len;
		if (i >= size) return 0;

		if (i + 1 < size && data[i + 1] == c) {
			i += 1;
			continue; }
		if (data[i] == c && data[i - 1] != ' '
		&& data[i - 1] != '\t' && data[i - 1] != '\n') {
			work = new_work_buffer(rndr);
			parse_inline(work, rndr, data, i);
			r = rndr->make.emphasis(ob, work, c, rndr->make.opaque);
			release_work_buffer(rndr, work);
			return r ? i + 1 : 0; } }
	return 0; }
Exemplo n.º 7
0
static VALUE epic_expr (VALUE module, VALUE string)
{
	char *exprval;
	RUBY_STARTUP

	exprval = parse_inline(my_string, "");
	return rb_str_new(exprval, strlen(exprval));
}
Exemplo n.º 8
0
// Parse inlines from parent's string_content, adding as children of parent.
extern void cmark_parse_inlines(cmark_node* parent, cmark_reference_map *refmap, int options)
{
	subject subj;
	subject_from_buf(&subj, &parent->string_content, refmap);

	while (!is_eof(&subj) && parse_inline(&subj, parent, options)) ;

	process_emphasis(&subj, NULL);
}
Exemplo n.º 9
0
static XS (XS_expr) {
	int	foo = 0;
	char* retval=NULL;
	char* arg=NULL;
	dXSARGS;
	for (foo=0; foo<items; foo++) {
		arg = malloc_strdup((char*)SvPV_nolen(ST(foo)));
		retval = (char*)parse_inline(arg, "");
		XST_mPV(foo, retval);
		new_free(&arg);
		new_free(&retval);
	}
	XSRETURN(items);
}
Exemplo n.º 10
0
static void
parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, size_t columns, int *col_data)
{
	size_t i = 0, col;
	struct buf *row_work = 0;

	row_work = rndr_newbuf(rndr);

	if (i < size && data[i] == '|')
		i++;

	for (col = 0; col < columns && i < size; ++col) {
		size_t cell_start, cell_end;
		struct buf *cell_work;

		cell_work = rndr_newbuf(rndr);

		while (i < size && isspace(data[i]))
			i++;

		cell_start = i;

		while (i < size && data[i] != '|')
			i++;

		cell_end = i - 1;

		while (cell_end > cell_start && isspace(data[cell_end]))
			cell_end--;

		parse_inline(cell_work, rndr, data + cell_start, 1 + cell_end - cell_start);
		if (rndr->make.table_cell)
			rndr->make.table_cell(row_work, cell_work, col_data ? col_data[col] : 0, rndr->make.opaque);

		rndr_popbuf(rndr);
		i++;
	}

	for (; col < columns; ++col) {
		struct buf empty_cell = {0, 0, 0, 0, 0};
		if (rndr->make.table_cell)
			rndr->make.table_cell(row_work, &empty_cell, col_data ? col_data[col] : 0, rndr->make.opaque);
	}

	if (rndr->make.table_row)
		rndr->make.table_row(ob, row_work, rndr->make.opaque);

	rndr_popbuf(rndr);
}
Exemplo n.º 11
0
// Parse inlines from parent's string_content, adding as children of parent.
extern void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
                                cmark_reference_map *refmap, int options) {
  subject subj;
  subject_from_buf(mem, &subj, &parent->content, refmap);
  cmark_chunk_rtrim(&subj.input);

  while (!is_eof(&subj) && parse_inline(&subj, parent, options))
    ;

  process_emphasis(&subj, NULL);
  // free bracket and delim stack
  while (subj.last_delim) {
    remove_delimiter(&subj, subj.last_delim);
  }
  while (subj.last_bracket) {
    pop_bracket(&subj);
  }
}
Exemplo n.º 12
0
Arquivo: if.c Projeto: choppsv1/ircii
void
whilecmd(u_char *command, u_char *args, u_char *subargs)
{
	u_char	*expr = NULL,
		*ptr,
		*body = NULL,
		*newexp = NULL;
	int	args_used;	/* this isn't used here, but is passed
				 * to expand_alias() */

	if ((ptr = next_expr(&args, '(')) == NULL)
	{
		yell("WHILE: missing boolean expression");
		return;
	}
	malloc_strcpy(&expr, ptr);
	if ((ptr = next_expr(&args, '{')) == NULL)
	{
		say("WHILE: missing expression");
		new_free(&expr);
		return;
	}
	malloc_strcpy(&body, ptr);
	while (1)
	{
		malloc_strcpy(&newexp, expr);
		ptr = parse_inline(newexp, subargs ? subargs : empty_string(),
			&args_used);
		if (*ptr && *ptr !='0')
		{
			new_free(&ptr);
			parse_line(NULL, body, subargs ?
				subargs : empty_string(), 0, 0, 0);
		}
		else
			break;
	}
	new_free(&newexp);
	new_free(&ptr);
	new_free(&expr);
	new_free(&body);
}
Exemplo n.º 13
0
/* closed by a symbol not preceded by whitespace and not followed by symbol */
static size_t
parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c)
{
	size_t i = 0, len;
	struct buf *work = 0;
	int r;

	if (!rndr->make.emphasis) return 0;

	/* skipping one symbol if coming from emph3 */
	if (size > 1 && data[0] == c && data[1] == c) i = 1;

	while (i < size) {
		len = find_emph_char(data + i, size - i, c);
		if (!len) return 0;
		i += len;
		if (i >= size) return 0;

		if (i + 1 < size && data[i + 1] == c) {
			i += 1;
			continue;
		}

		if (data[i] == c && !isspace(data[i - 1])) {

			if ((rndr->ext_flags & MKDEXT_LAX_EMPHASIS) == 0) {
				if (!(i + 1 == size || isspace(data[i + 1]) || ispunct(data[i + 1])))
					continue;
			}

			work = rndr_newbuf(rndr);
			parse_inline(work, rndr, data, i);
			r = rndr->make.emphasis(ob, work, rndr->make.opaque);
			rndr_popbuf(rndr);
			return r ? i + 1 : 0;
		}
	}

	return 0;
}
Exemplo n.º 14
0
/* finds the first closing tag, and delegates to the other emph */
static size_t
parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c)
{
	size_t i = 0, len;
	int r;

	while (i < size) {
		len = find_emph_char(data + i, size - i, c);
		if (!len) return 0;
		i += len;

		/* skip whitespace preceded symbols */
		if (data[i] != c || isspace(data[i - 1]))
			continue;

		if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->make.triple_emphasis) {
			/* triple symbol found */
			struct buf *work = rndr_newbuf(rndr);

			parse_inline(work, rndr, data, i);
			r = rndr->make.triple_emphasis(ob, work, rndr->make.opaque);
			rndr_popbuf(rndr);
			return r ? i + 3 : 0;

		} else if (i + 1 < size && data[i + 1] == c) {
			/* double symbol found, handing over to emph1 */
			len = parse_emph1(ob, rndr, data - 2, size + 2, c);
			if (!len) return 0;
			else return len - 2;

		} else {
			/* single symbol found, handing over to emph2 */
			len = parse_emph2(ob, rndr, data - 1, size + 1, c);
			if (!len) return 0;
			else return len - 1;
		}
	}
	return 0; 
}
Exemplo n.º 15
0
/* parse_emph2 • parsing single emphase */
static size_t
parse_emph2(struct buf *ob, struct render *rndr,
			char *data, size_t size, char c) {
	size_t i = 0, len;
	struct buf *work = 0;
	int r;

	if (!rndr->make.double_emphasis) return 0;
	
	while (i < size) {
		len = find_emph_char(data + i, size - i, c);
		if (!len) return 0;
		i += len;
		if (i + 1 < size && data[i] == c && data[i + 1] == c
		&& i && data[i - 1] != ' '
		&& data[i - 1] != '\t' && data[i - 1] != '\n') {
			work = new_work_buffer(rndr);
			parse_inline(work, rndr, data, i);
			r = rndr->make.double_emphasis(ob, work, c,
				rndr->make.opaque);
			release_work_buffer(rndr, work);
			return r ? i + 2 : 0; }
		i += 1; }
	return 0; }
Exemplo n.º 16
0
/* parse_atxheader • parsing of atx-style headers */
static size_t
parse_atxheader(struct buf *ob, struct render *rndr, char *data, size_t size)
{
	size_t level = 0;
	size_t i, end, skip;

	if (!size || data[0] != '#')
		return 0;

	while (level < size && level < 6 && data[level] == '#')
		level++;

	for (i = level; i < size && (data[i] == ' ' || data[i] == '\t'); i++);

	for (end = i; end < size && data[end] != '\n'; end++);
	skip = end;

	while (end && data[end - 1] == '#')
		end--;

	while (end && (data[end - 1] == ' ' || data[end - 1] == '\t'))
		end--;

	if (end > i) {
		struct buf *work = rndr_newbuf(rndr);

		parse_inline(work, rndr, data + i, end - i);

		if (rndr->make.header)
			rndr->make.header(ob, work, (int)level, rndr->make.opaque);

		rndr_popbuf(rndr);
	}

	return skip;
}
Exemplo n.º 17
0
/* parse_blockquote • hanldes parsing of a regular paragraph */
static size_t
parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
{
	size_t i = 0, end = 0;
	int level = 0;
	struct buf work = { data, 0, 0, 0, 0 }; /* volatile working buffer */

	while (i < size) {
		for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;

		if (is_empty(data + i, size - i) || (level = is_headerline(data + i, size - i)) != 0)
			break;

		if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
			if (data[i] == '<' && rndr->make.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
				end = i;
				break;
			}
		}

		if (data[i] == '#' || is_hrule(data + i, size - i)) {
			end = i;
			break;
		}

		i = end;
	}

	work.size = i;
	while (work.size && data[work.size - 1] == '\n')
		work.size--;

	if (!level) {
		struct buf *tmp = rndr_newbuf(rndr);
		parse_inline(tmp, rndr, work.data, work.size);
		if (rndr->make.paragraph)
			rndr->make.paragraph(ob, tmp, rndr->make.opaque);
		rndr_popbuf(rndr);
	} else {
		struct buf *header_work;

		if (work.size) {
			size_t beg;
			i = work.size;
			work.size -= 1;

			while (work.size && data[work.size] != '\n')
				work.size -= 1;

			beg = work.size + 1;
			while (work.size && data[work.size - 1] == '\n')
				work.size -= 1;

			if (work.size > 0) {
				struct buf *tmp = rndr_newbuf(rndr);
				parse_inline(tmp, rndr, work.data, work.size);

				if (rndr->make.paragraph)
					rndr->make.paragraph(ob, tmp, rndr->make.opaque);

				rndr_popbuf(rndr);
				work.data += beg;
				work.size = i - beg;
			}
			else work.size = i;
		}

		header_work = rndr_newbuf(rndr);
		parse_inline(header_work, rndr, work.data, work.size);

		if (rndr->make.header)
			rndr->make.header(ob, header_work, (int)level, rndr->make.opaque);

		rndr_popbuf(rndr);
	}

	return end;
}
Exemplo n.º 18
0
Arquivo: if.c Projeto: choppsv1/ircii
/*  I suppose someone could make a case that since the
 *  foreach_handler() routine weeds out any for command that doesnt have
 *  two commands, that checking for those 2 commas is a waste.  I suppose.
 */
void
forcmd(u_char *command, u_char *args, u_char *subargs)
{
	u_char	*working = NULL;
	u_char	*commence = NULL;
	u_char	*evaluation = NULL;
	u_char	*lameeval = NULL;
	u_char	*iteration = NULL;
	u_char	*sa = NULL;
	int	argsused = 0;
	u_char	*line = NULL;
	u_char	*commands = NULL;

	/* Get the whole () thing */
	if ((working = next_expr(&args, '(')) == NULL)	/* ) */
	{
		yell("FOR: missing closing parenthesis");
		return;
	}
	malloc_strcpy(&commence, working);

	/* Find the beginning of the second expression */
	evaluation = my_index(commence, ',');
	if (!evaluation)
	{
		yell("FOR: no components!");
		new_free(&commence);
		return;
	}
	do 
		*evaluation++ = '\0';
	while (isspace(*evaluation));

	/* Find the beginning of the third expression */
	iteration = my_index(evaluation, ',');
	if (!iteration)
	{
		yell("FOR: Only two components!");
		new_free(&commence);
		return;
	}
	do 
	{
		*iteration++ = '\0';
	}
	while (isspace(*iteration));

	working = args;
	while (isspace(*working))
		*working++ = '\0';

	if ((working = next_expr(&working, '{')) == NULL)	/* } */
	{
		yell("FOR: badly formed commands");
		new_free(&commence);
		return;
	}

	malloc_strcpy(&commands, working);

	sa = subargs ? subargs : empty_string();
	parse_line(NULL, commence, sa, 0, 0, 0);

	while (1)
	{
		malloc_strcpy(&lameeval, evaluation);
		line = parse_inline(lameeval, sa, &argsused);
		if (*line && *line != '0')
		{
			new_free(&line);
			parse_line(NULL, commands, sa, 0, 0, 0);
			parse_line(NULL, iteration, sa, 0, 0, 0);
		}
		else break;
	}
	new_free(&line);
	new_free(&lameeval);
	new_free(&commence);
	new_free(&commands);
}
Exemplo n.º 19
0
/* char_link • '[': parsing a link or an image */
static size_t
char_link(struct buf *ob, struct render *rndr,
				char *data, size_t offset, size_t size) {
	int is_img = (offset && data[-1] == '!'), level;
	size_t i = 1, txt_e;
	struct buf *content = 0;
	struct buf *link = 0;
	struct buf *title = 0;
	int text_has_nl = 0, ret;

	/* checking whether the correct renderer exists */
	if ((is_img && !rndr->make.image) || (!is_img && !rndr->make.link))
		return 0;

	/* looking for the matching closing bracket */
	for (level = 1; i < size; i += 1)
		if (data[i] == '\n') text_has_nl = 1;
		else if (data[i - 1] == '\\') continue;
		else if (data[i] == '[') level += 1;
		else if (data[i] == ']') {
			level -= 1;
			if (level <= 0) break; }
	if (i >= size) return 0;
	txt_e = i;
	i += 1;

	/* skip any amount of whitespace or newline */
	/* (this is much more laxist than original markdown syntax) */
	while (i < size
	&& (data[i] == ' ' || data[i] == '\t' || data[i] == '\n'))
		i += 1;

	/* allocate temporary buffers to store content, link and title */
	content = new_work_buffer(rndr);
	link = new_work_buffer(rndr);
	title = new_work_buffer(rndr);
	ret = 0; /* error if we don't get to the callback */

	/* inline style link */
	if (i < size && data[i] == '(') {
		size_t span_end = i;
		while (span_end < size
		&& !(data[span_end] == ')'
		 && (span_end == i || data[span_end - 1] != '\\')))
			span_end += 1;

		if (span_end >= size
		|| get_link_inline(link, title,
					data + i+1, span_end - (i+1)) < 0)
			goto char_link_cleanup;

		i = span_end + 1; }

	/* reference style link */
	else if (i < size && data[i] == '[') {
		char *id_data;
		size_t id_size, id_end = i;
		while (id_end < size && data[id_end] != ']')
			id_end += 1;

		if (id_end >= size)
			goto char_link_cleanup;

		if (i + 1 == id_end) {
			/* implicit id - use the contents */
			id_data = data + 1;
			id_size = txt_e - 1; }
		else {
			/* explici id - between brackets */
			id_data = data + i + 1;
			id_size = id_end - (i + 1); }

		if (get_link_ref(rndr, link, title, id_data, id_size) < 0)
			goto char_link_cleanup;

		i = id_end + 1; }

	/* shortcut reference style link */
	else {
		if (get_link_ref(rndr, link, title, data + 1, txt_e - 1) < 0)
			goto char_link_cleanup;

		/* rewinding the whitespace */
		i = txt_e + 1; }

	/* building content: img alt is escaped, link content is parsed */
	if (txt_e > 1) {
		if (is_img) bufput(content, data + 1, txt_e - 1);
		else parse_inline(content, rndr, data + 1, txt_e - 1); }

	/* calling the relevant rendering function */
	if (is_img) {
		if (ob->size && ob->data[ob->size - 1] == '!') ob->size -= 1;
		ret = rndr->make.image(ob, link, title, content,
							rndr->make.opaque); }
	else ret = rndr->make.link(ob, link, title, content, rndr->make.opaque);

	/* cleanup */
char_link_cleanup:
	release_work_buffer(rndr, title);
	release_work_buffer(rndr, link);
	release_work_buffer(rndr, content);
	return ret ? i : 0; }
Exemplo n.º 20
0
/* char_link • '[': parsing a link or an image */
static size_t
char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
{
	int is_img = (offset && data[-1] == '!'), level;
	size_t i = 1, txt_e, link_b = 0, link_e = 0, title_b = 0, title_e = 0;
	struct buf *content = 0;
	struct buf *link = 0;
	struct buf *title = 0;
	struct buf *u_link = 0;
	size_t org_work_size = rndr->work.size;
	int text_has_nl = 0, ret = 0;

	/* checking whether the correct renderer exists */
	if ((is_img && !rndr->make.image) || (!is_img && !rndr->make.link))
		goto cleanup;

	/* looking for the matching closing bracket */
	for (level = 1; i < size; i += 1) {
		if (data[i] == '\n')
			text_has_nl = 1;

		else if (data[i - 1] == '\\')
			continue;

		else if (data[i] == '[')
			level++;

		else if (data[i] == ']') {
			level--;
			if (level <= 0)
				break;
		}
	}

	if (i >= size)
		goto cleanup;

	txt_e = i;
	i += 1;

	/* skip any amount of whitespace or newline */
	/* (this is much more laxist than original markdown syntax) */
	while (i < size && isspace(data[i]))
		i++;

	/* inline style link */
	if (i < size && data[i] == '(') {
		/* skipping initial whitespace */
		i += 1;

		while (i < size && isspace(data[i]))
			i++;

		link_b = i;

		/* looking for link end: ' " ) */
		while (i < size) {
			if (data[i] == '\\') i += 2;
			else if (data[i] == ')' || data[i] == '\'' || data[i] == '"') break;
			else i += 1;
		}

		if (i >= size) goto cleanup;
		link_e = i;

		/* looking for title end if present */
		if (data[i] == '\'' || data[i] == '"') {
			i++;
			title_b = i;

			while (i < size) {
				if (data[i] == '\\') i += 2;
				else if (data[i] == ')') break;
				else i += 1;
			}

			if (i >= size) goto cleanup;

			/* skipping whitespaces after title */
			title_e = i - 1;
			while (title_e > title_b && isspace(data[title_e]))
				title_e--;

			/* checking for closing quote presence */
			if (data[title_e] != '\'' &&  data[title_e] != '"') {
				title_b = title_e = 0;
				link_e = i;
			}
		}

		/* remove whitespace at the end of the link */
		while (link_e > link_b && isspace(data[link_e - 1]))
			link_e--;

		/* remove optional angle brackets around the link */
		if (data[link_b] == '<') link_b++;
		if (data[link_e - 1] == '>') link_e--;

		/* building escaped link and title */
		if (link_e > link_b) {
			link = rndr_newbuf(rndr);
			bufput(link, data + link_b, link_e - link_b);
		}

		if (title_e > title_b) {
			title = rndr_newbuf(rndr);
			bufput(title, data + title_b, title_e - title_b);
		}

		i++;
	}

	/* reference style link */
	else if (i < size && data[i] == '[') {
		struct buf id = { 0, 0, 0, 0, 0 };
		struct link_ref *lr;

		/* looking for the id */
		i += 1;
		link_b = i;
		while (i < size && data[i] != ']') i++;
		if (i >= size) goto cleanup;
		link_e = i;

		/* finding the link_ref */
		if (link_b == link_e) {
			if (text_has_nl) {
				struct buf *b = rndr_newbuf(rndr);
				size_t j;

				for (j = 1; j < txt_e; j++) {
					if (data[j] != '\n')
						bufputc(b, data[j]);
					else if (data[j - 1] != ' ')
						bufputc(b, ' ');
				}

				id.data = b->data;
				id.size = b->size;
			} else {
				id.data = data + 1;
				id.size = txt_e - 1;
			}
		} else {
			id.data = data + link_b;
			id.size = link_e - link_b;
		}

		lr = arr_sorted_find(&rndr->refs, &id, cmp_link_ref);
		if (!lr) goto cleanup;

		/* keeping link and title from link_ref */
		link = lr->link;
		title = lr->title;
		i += 1;
	}

	/* shortcut reference style link */
	else {
		struct buf id = { 0, 0, 0, 0, 0 };
		struct link_ref *lr;

		/* crafting the id */
		if (text_has_nl) {
			struct buf *b = rndr_newbuf(rndr);
			size_t j;

			for (j = 1; j < txt_e; j++) {
				if (data[j] != '\n')
					bufputc(b, data[j]);
				else if (data[j - 1] != ' ')
					bufputc(b, ' ');
			}

			id.data = b->data;
			id.size = b->size;
		} else {
			id.data = data + 1;
			id.size = txt_e - 1;
		}

		/* finding the link_ref */
		lr = arr_sorted_find(&rndr->refs, &id, cmp_link_ref);
		if (!lr) goto cleanup;

		/* keeping link and title from link_ref */
		link = lr->link;
		title = lr->title;

		/* rewinding the whitespace */
		i = txt_e + 1;
	}

	/* building content: img alt is escaped, link content is parsed */
	if (txt_e > 1) {
		content = rndr_newbuf(rndr);
		if (is_img) bufput(content, data + 1, txt_e - 1);
		else parse_inline(content, rndr, data + 1, txt_e - 1);
	}

	if (link) {
		u_link = rndr_newbuf(rndr);
		unscape_text(u_link, link);
	}

	/* calling the relevant rendering function */
	if (is_img) {
		if (ob->size && ob->data[ob->size - 1] == '!')
			ob->size -= 1;

		ret = rndr->make.image(ob, u_link, title, content, rndr->make.opaque);
	} else {
		ret = rndr->make.link(ob, u_link, title, content, rndr->make.opaque);
	}

	/* cleanup */
cleanup:
	rndr->work.size = (int)org_work_size;
	return ret ? i : 0;
}
Exemplo n.º 21
0
/*	assuming initial prefix is already removed */
static size_t
parse_listitem(struct buf *ob, struct render *rndr,
			char *data, size_t size, int *flags) {
	struct buf *work = 0, *inter = 0;
	size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
	int in_empty = 0, has_inside_empty = 0;

	/* keeping book of the first indentation prefix */
	if (size > 1 && data[0] == ' ') { orgpre = 1;
	if (size > 2 && data[1] == ' ') { orgpre = 2;
	if (size > 3 && data[2] == ' ') { orgpre = 3; } } }
	beg = prefix_uli(data, size);
	if (!beg) beg = prefix_oli(data, size);
	if (!beg) return 0;
	/* skipping to the beginning of the following line */
	end = beg;
	while (end < size && data[end - 1] != '\n') end += 1;

	/* getting working buffers */
	work = new_work_buffer(rndr);
	inter = new_work_buffer(rndr);

	/* putting the first line into the working buffer */
	bufput(work, data + beg, end - beg);
	beg = end;

	/* process the following lines */
	while (beg < size) {
		end += 1;
		while (end < size && data[end - 1] != '\n') end += 1;

		/* process an empty line */
		if (is_empty(data + beg, end - beg)) {
			in_empty = 1;
			beg = end;
			continue; }

		/* calculating the indentation */
		i = 0;
		if (end - beg > 1 && data[beg] == ' ') { i = 1;
		if (end - beg > 2 && data[beg + 1] == ' ') { i = 2;
		if (end - beg > 3 && data[beg + 2] == ' ') { i = 3;
		if (end - beg > 3 && data[beg + 3] == ' ') { i = 4; } } } }
		pre = i;
		if (data[beg] == '\t') { i = 1; pre = 8; }

		/* checking for a new item */
		if ((prefix_uli(data + beg + i, end - beg - i)
			&& !is_hrule(data + beg + i, end - beg - i))
		||  prefix_oli(data + beg + i, end - beg - i)) {
			if (in_empty) has_inside_empty = 1;
			if (pre == orgpre) /* the following item must have */
				break;             /* the same indentation */
			if (!sublist) sublist = work->size; }

		/* joining only indented stuff after empty lines */
		else if (in_empty && i < 4 && data[beg] != '\t') {
				*flags |= MKD_LI_END;
				break; }
		else if (in_empty) {
			bufputc(work, '\n');
			has_inside_empty = 1; }
		in_empty = 0;

		/* adding the line without prefix into the working buffer */
		bufput(work, data + beg + i, end - beg - i);
		beg = end; }

	/* render of li contents */
	if (has_inside_empty) *flags |= MKD_LI_BLOCK;
	if (*flags & MKD_LI_BLOCK) {
		/* intermediate render of block li */
		if (sublist && sublist < work->size) {
			parse_block(inter, rndr, work->data, sublist);
			parse_block(inter, rndr, work->data + sublist,
						work->size - sublist); }
		else
			parse_block(inter, rndr, work->data, work->size); }
	else {
		/* intermediate render of inline li */
		if (sublist && sublist < work->size) {
			parse_inline(inter, rndr, work->data, sublist);
			parse_block(inter, rndr, work->data + sublist,
						work->size - sublist); }
		else
			parse_inline(inter, rndr, work->data, work->size); }

	/* render of li itself */
	if (rndr->make.listitem)
		rndr->make.listitem(ob, inter, *flags, rndr->make.opaque);
	release_work_buffer(rndr, inter);
	release_work_buffer(rndr, work);
	return beg; }