cmark

My personal build of CMark ✏️

Commit
2f1e4e0edb581927b25aeba9972ed71b4605a2ba
Parent
a17f54ca246ed607f02c165b916b17aa0be03492
Author
John MacFarlane <jgm@berkeley.edu>
Date

Merge pull request #228 from nwellnhof/delimiters

Rename delimiter identifiers

Diffstat

1 file changed, 103 insertions, 112 deletions

Status File Name N° Changes Insertions Deletions
Modified src/inlines.c 215 103 112
diff --git a/src/inlines.c b/src/inlines.c
@@ -23,26 +23,25 @@
 #define make_emph() make_simple(CMARK_NODE_EMPH)
 #define make_strong() make_simple(CMARK_NODE_STRONG)
 
-typedef struct DelimiterStack {
-	struct DelimiterStack *previous;
-	struct DelimiterStack *next;
-	cmark_node *first_inline;
-	int delim_count;
+typedef struct delimiter {
+	struct delimiter *previous;
+	struct delimiter *next;
+	cmark_node *inl_text;
 	unsigned char delim_char;
 	int position;
 	bool can_open;
 	bool can_close;
-} delimiter_stack;
+} delimiter;
 
-typedef struct Subject {
+typedef struct {
 	chunk input;
 	int pos;
 	cmark_reference_map *refmap;
-	delimiter_stack *delimiters;
+	delimiter *last_delim;
 } subject;
 
-static delimiter_stack*
-S_insert_emph(subject *subj, delimiter_stack *opener, delimiter_stack *closer);
+static delimiter*
+S_insert_emph(subject *subj, delimiter *opener, delimiter *closer);
 
 static int parse_inline(subject* subj, cmark_node * parent);
 
@@ -148,7 +147,7 @@ static void subject_from_buf(subject *e, strbuf *buffer,
 	e->input.alloc = 0;
 	e->pos = 0;
 	e->refmap = refmap;
-	e->delimiters = NULL;
+	e->last_delim = NULL;
 
 	chunk_rtrim(&e->input);
 }
@@ -265,62 +264,53 @@ static int scan_delims(subject* subj, unsigned char c, bool * can_open, bool * c
 /*
 static void print_delimiters(subject *subj)
 {
-	delimiter_stack *tempstack;
-	tempstack = subj->delimiters;
-	while (tempstack != NULL) {
-		printf("Item at %p: %d %d %d %d next(%p) prev(%p)\n",
-		       tempstack, tempstack->delim_count, tempstack->delim_char,
-		       tempstack->can_open, tempstack->can_close,
-		       tempstack->next, tempstack->previous);
-		tempstack = tempstack->previous;
+	delimiter *delim;
+	delim = subj->last_delim;
+	while (delim != NULL) {
+		printf("Item at %p: %d %d %d next(%p) prev(%p)\n",
+		       delim, delim->delim_char,
+		       delim->can_open, delim->can_close,
+		       delim->next, delim->previous);
+		delim = delim->previous;
 	}
 }
 */
 
-static void remove_delimiter(subject *subj, delimiter_stack *stack)
+static void remove_delimiter(subject *subj, delimiter *delim)
 {
-	if (stack == NULL) return;
-	if (stack->next == NULL) {
-		// top of stack:
-		assert(stack == subj->delimiters);
-		if (stack->previous != NULL) {
-			stack->previous->next = NULL;
-		}
-		subj->delimiters = stack->previous;
-	} else if (stack->previous == NULL) {
-		// bottom of stack, with something above it
-		stack->next->previous = NULL;
-	} else { // neither top nor bottom:
-		stack->previous->next = stack->next;
-		stack->next->previous = stack->previous;
-	}
-	free(stack);
-}
-
-static delimiter_stack * push_delimiter(subject *subj,
-					int numdelims,
-					unsigned char c,
-					bool can_open,
-					bool can_close,
-					cmark_node *inl_text)
-{
-	delimiter_stack *istack =
-		(delimiter_stack*)malloc(sizeof(delimiter_stack));
-	if (istack == NULL) {
-		return NULL;
+	if (delim == NULL) return;
+	if (delim->next == NULL) {
+		// end of list:
+		assert(delim == subj->last_delim);
+		subj->last_delim = delim->previous;
+	} else {
+		delim->next->previous = delim->previous;
+	}
+	if (delim->previous != NULL) {
+		delim->previous->next = delim->next;
+	}
+	free(delim);
+}
+
+static void push_delimiter(subject *subj, unsigned char c, bool can_open,
+			   bool can_close, cmark_node *inl_text)
+{
+	delimiter *delim =
+		(delimiter*)malloc(sizeof(delimiter));
+	if (delim == NULL) {
+		return;
 	}
-	istack->delim_count = numdelims;
-	istack->delim_char = c;
-	istack->can_open = can_open;
-	istack->can_close = can_close;
-	istack->first_inline = inl_text;
-	istack->previous = subj->delimiters;
-	istack->next = NULL;
-	if (istack->previous != NULL) {
-		istack->previous->next = istack;
+	delim->delim_char = c;
+	delim->can_open = can_open;
+	delim->can_close = can_close;
+	delim->inl_text = inl_text;
+	delim->previous = subj->last_delim;
+	delim->next = NULL;
+	if (delim->previous != NULL) {
+		delim->previous->next = delim;
 	}
-	istack->position = subj->pos;
-	return istack;
+	delim->position = subj->pos;
+	subj->last_delim = delim;
 }
 
 // Parse strong/emph or a fallback.
@@ -336,20 +326,19 @@ static cmark_node* handle_strong_emph(subject* subj, unsigned char c)
 	inl_text = make_str(chunk_dup(&subj->input, subj->pos - numdelims, numdelims));
 
 	if (can_open || can_close) {
-		subj->delimiters = push_delimiter(subj, numdelims, c, can_open, can_close,
-						  inl_text);
+		push_delimiter(subj, c, can_open, can_close, inl_text);
 	}
 
 	return inl_text;
 }
 
-static void process_emphasis(subject *subj, delimiter_stack *stack_bottom)
+static void process_emphasis(subject *subj, delimiter *start_delim)
 {
-	delimiter_stack *closer = subj->delimiters;
-	delimiter_stack *opener;
+	delimiter *closer = subj->last_delim;
+	delimiter *opener;
 
 	// move back to first relevant delim.
-	while (closer != NULL && closer->previous != stack_bottom) {
+	while (closer != NULL && closer->previous != start_delim) {
 		closer = closer->previous;
 	}
 
@@ -359,14 +348,14 @@ static void process_emphasis(subject *subj, delimiter_stack *stack_bottom)
 		    (closer->delim_char == '*' || closer->delim_char == '_')) {
 			// Now look backwards for first matching opener:
 			opener = closer->previous;
-			while (opener != NULL && opener != stack_bottom) {
+			while (opener != NULL && opener != start_delim) {
 				if (opener->delim_char == closer->delim_char &&
 				    opener->can_open) {
 					break;
 				}
 				opener = opener->previous;
 			}
-			if (opener != NULL && opener != stack_bottom) {
+			if (opener != NULL && opener != start_delim) {
 				closer = S_insert_emph(subj, opener, closer);
 			} else {
 				closer = closer->next;
@@ -375,53 +364,55 @@ static void process_emphasis(subject *subj, delimiter_stack *stack_bottom)
 			closer = closer->next;
 		}
 	}
-	// free all delimiters in stack down to stack_bottom:
-	while (subj->delimiters != stack_bottom) {
-		remove_delimiter(subj, subj->delimiters);
+	// free all delimiters in list until start_delim:
+	while (subj->last_delim != start_delim) {
+		remove_delimiter(subj, subj->last_delim);
 	}
 }
 
-static delimiter_stack*
-S_insert_emph(subject *subj, delimiter_stack *opener, delimiter_stack *closer)
+static delimiter*
+S_insert_emph(subject *subj, delimiter *opener, delimiter *closer)
 {
-	delimiter_stack *tempstack, *nextstack;
+	delimiter *delim, *tmp_delim;
 	int use_delims;
-	cmark_node *opener_inl = opener->first_inline;
-	cmark_node *closer_inl = closer->first_inline;
+	cmark_node *opener_inl = opener->inl_text;
+	cmark_node *closer_inl = closer->inl_text;
+	int opener_num_chars = opener_inl->as.literal.len;
+	int closer_num_chars = closer_inl->as.literal.len;
 	cmark_node *tmp, *emph, *first_child, *last_child;
 
-	// calculate the actual number of delimeters used from this closer
-	if (closer->delim_count < 3 || opener->delim_count < 3) {
-		use_delims = closer->delim_count <= opener->delim_count ?
-			closer->delim_count : opener->delim_count;
-	} else { // closer and opener both have >= 3 delims
-		use_delims = closer->delim_count % 2 == 0 ? 2 : 1;
+	// calculate the actual number of characters used from this closer
+	if (closer_num_chars < 3 || opener_num_chars < 3) {
+		use_delims = closer_num_chars <= opener_num_chars ?
+			closer_num_chars : opener_num_chars;
+	} else { // closer and opener both have >= 3 characters
+		use_delims = closer_num_chars % 2 == 0 ? 2 : 1;
 	}
 
-	// remove used delimiters from stack elements and associated inlines.
-	opener->delim_count -= use_delims;
-	closer->delim_count -= use_delims;
-	opener_inl->as.literal.len = opener->delim_count;
-	closer_inl->as.literal.len = closer->delim_count;
+	// remove used characters from associated inlines.
+	opener_num_chars -= use_delims;
+	closer_num_chars -= use_delims;
+	opener_inl->as.literal.len = opener_num_chars;
+	closer_inl->as.literal.len = closer_num_chars;
 
 	// free delimiters between opener and closer
-	tempstack = closer->previous;
-	while (tempstack != NULL && tempstack != opener) {
-		nextstack = tempstack->previous;
-		remove_delimiter(subj, tempstack);
-		tempstack = nextstack;
+	delim = closer->previous;
+	while (delim != NULL && delim != opener) {
+		tmp_delim = delim->previous;
+		remove_delimiter(subj, delim);
+		delim = tmp_delim;
 	}
 
 	first_child = opener_inl->next;
 	last_child  = closer_inl->prev;
 
-	// if opener has 0 delims, remove it and its associated inline
-	if (opener->delim_count == 0) {
+	// if opener has 0 characters, remove it and its associated inline
+	if (opener_num_chars == 0) {
 		// replace empty opener inline with emph
 		chunk_free(&(opener_inl->as.literal));
 		emph = opener_inl;
 		emph->type = use_delims == 1 ? NODE_EMPH : NODE_STRONG;
-		// remove opener from stack
+		// remove opener from list
 		remove_delimiter(subj, opener);
 	}
 	else {
@@ -446,14 +437,14 @@ S_insert_emph(subject *subj, delimiter_stack *opener, delimiter_stack *closer)
 		tmp->parent = emph;
 	}
 
-	// if closer has 0 delims, remove it and its associated inline
-	if (closer->delim_count == 0) {
+	// if closer has 0 characters, remove it and its associated inline
+	if (closer_num_chars == 0) {
 		// remove empty closer inline
 		cmark_node_free(closer_inl);
-		// remove closer from stack
-		tempstack = closer->next;
+		// remove closer from list
+		tmp_delim = closer->next;
 		remove_delimiter(subj, closer);
-		closer = tempstack;
+		closer = tmp_delim;
 	}
 
 	return closer;
@@ -656,8 +647,8 @@ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
 	bool is_image = false;
 	chunk urlchunk, titlechunk;
 	unsigned char *url, *title;
-	delimiter_stack *opener;
-	delimiter_stack *tempstack;
+	delimiter *opener;
+	delimiter *tmp_delim;
 	cmark_node *link_text;
 	cmark_node *inl;
 	chunk raw_label;
@@ -666,8 +657,8 @@ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
 	advance(subj);  // advance past ]
 	initial_pos = subj->pos;
 
-	// look through stack of delimiters for a [ or !
-	opener = subj->delimiters;
+	// look through list of delimiters for a [ or !
+	opener = subj->last_delim;
 	while (opener) {
 		if (opener->delim_char == '[' || opener->delim_char == '!') {
 			break;
@@ -681,7 +672,7 @@ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
 
 	// If we got here, we matched a potential link/image text.
 	is_image = opener->delim_char == '!';
-	link_text = opener->first_inline->next;
+	link_text = opener->inl_text->next;
 
 	// Now we check to see if it's a link/image.
 
@@ -747,12 +738,12 @@ static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
 
 noMatch:
 	// If we fall through to here, it means we didn't match a link:
-	remove_delimiter(subj, opener);  // remove this opener from delimiter stack
+	remove_delimiter(subj, opener);  // remove this opener from delimiter list
 	subj->pos = initial_pos;
 	return make_str(chunk_literal("]"));
 
 match:
-	inl = opener->first_inline;
+	inl = opener->inl_text;
 	inl->type = is_image ? NODE_IMAGE : NODE_LINK;
 	chunk_free(&inl->as.literal);
 	inl->first_child = link_text;
@@ -776,13 +767,13 @@ match:
         // delimiters. (This code can be removed if we decide to allow links
 	// inside links.)
 	if (!is_image) {
-		opener = subj->delimiters;
+		opener = subj->last_delim;
 		while (opener != NULL) {
-			tempstack = opener->previous;
+			tmp_delim = opener->previous;
 			if (opener->delim_char == '[') {
 				remove_delimiter(subj, opener);
 			}
-			opener = tempstack;
+			opener = tmp_delim;
 		}
 	}
 
@@ -876,7 +867,7 @@ static int parse_inline(subject* subj, cmark_node * parent)
 	case '[':
 		advance(subj);
 		new_inl = make_str(chunk_literal("["));
-		subj->delimiters = push_delimiter(subj, 1, '[', true, false, new_inl);
+		push_delimiter(subj, '[', true, false, new_inl);
 		break;
 	case ']':
 		new_inl = handle_close_bracket(subj, parent);
@@ -886,7 +877,7 @@ static int parse_inline(subject* subj, cmark_node * parent)
 		if (peek_char(subj) == '[') {
 			advance(subj);
 			new_inl = make_str(chunk_literal("!["));
-			subj->delimiters = push_delimiter(subj, 1, '!', false, true, new_inl);
+			push_delimiter(subj, '!', false, true, new_inl);
 		} else {
 			new_inl = make_str(chunk_literal("!"));
 		}