diff options
author | John MacFarlane <jgm@berkeley.edu> | 2014-11-30 09:33:47 -0800 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2014-11-30 09:33:47 -0800 |
commit | 2f1e4e0edb581927b25aeba9972ed71b4605a2ba (patch) | |
tree | 3035e34a1d7685b5a8da11d28cf720868fb79227 | |
parent | a17f54ca246ed607f02c165b916b17aa0be03492 (diff) | |
parent | a9e865831b5ad530cfc57421e57c2c106c21d135 (diff) |
Merge pull request #228 from nwellnhof/delimiters
Rename delimiter identifiers
-rw-r--r-- | src/inlines.c | 215 |
1 files changed, 103 insertions, 112 deletions
diff --git a/src/inlines.c b/src/inlines.c index 0dcfd72..643837b 100644 --- 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("!")); } |