Example #1
0
static delimiter *S_insert_emph(subject *subj, delimiter *opener,
                                delimiter *closer) {
  delimiter *delim, *tmp_delim;
  bufsize_t use_delims;
  cmark_node *opener_inl = opener->inl_text;
  cmark_node *closer_inl = closer->inl_text;
  bufsize_t opener_num_chars = opener_inl->as.literal.len;
  bufsize_t closer_num_chars = closer_inl->as.literal.len;
  cmark_node *tmp, *tmpnext, *emph;

  // calculate the actual number of characters used from this closer
  use_delims = (closer_num_chars >= 2 && opener_num_chars >=2) ? 2 : 1;

  // 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
  delim = closer->previous;
  while (delim != NULL && delim != opener) {
    tmp_delim = delim->previous;
    remove_delimiter(subj, delim);
    delim = tmp_delim;
  }

  // create new emph or strong, and splice it in to our inlines
  // between the opener and closer
  emph = use_delims == 1 ? make_emph(subj->mem) : make_strong(subj->mem);

  tmp = opener_inl->next;
  while (tmp && tmp != closer_inl) {
    tmpnext = tmp->next;
    cmark_node_append_child(emph, tmp);
    tmp = tmpnext;
  }
  cmark_node_insert_after(opener_inl, emph);

  // if opener has 0 characters, remove it and its associated inline
  if (opener_num_chars == 0) {
    cmark_node_free(opener_inl);
    remove_delimiter(subj, opener);
  }

  // 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 list
    tmp_delim = closer->next;
    remove_delimiter(subj, closer);
    closer = tmp_delim;
  }

  return closer;
}
Example #2
0
static void process_emphasis(subject *subj, delimiter *start_delim)
{
	delimiter *closer = subj->last_delim;
	delimiter *opener;

	// move back to first relevant delim.
	while (closer != NULL && closer->previous != start_delim) {
		closer = closer->previous;
	}

	// now move forward, looking for closers, and handling each
	while (closer != NULL) {
		if (closer->can_close &&
		    (closer->delim_char == '*' || closer->delim_char == '_' ||
		     closer->delim_char == '"' || closer->delim_char == '\'')) {
			// Now look backwards for first matching opener:
			opener = closer->previous;
			while (opener != NULL && opener != start_delim) {
				if (opener->delim_char == closer->delim_char &&
				    opener->can_open) {
					break;
				}
				opener = opener->previous;
			}
			if (closer->delim_char == '*' || closer->delim_char == '_') {
				if (opener != NULL && opener != start_delim) {
					closer = S_insert_emph(subj, opener, closer);
				} else {
					closer = closer->next;
				}
			} else if (closer->delim_char == '\'') {
				cmark_chunk_free(&closer->inl_text->as.literal);
				closer->inl_text->as.literal =
					cmark_chunk_literal(RIGHTSINGLEQUOTE);
				if (opener != NULL && opener != start_delim) {
					cmark_chunk_free(&opener->inl_text->as.literal);
					opener->inl_text->as.literal =
						cmark_chunk_literal(LEFTSINGLEQUOTE);
				}
				closer = closer->next;
			} else if (closer->delim_char == '"') {
				cmark_chunk_free(&closer->inl_text->as.literal);
				closer->inl_text->as.literal =
					cmark_chunk_literal(RIGHTDOUBLEQUOTE);
				if (opener != NULL && opener != start_delim) {
					cmark_chunk_free(&opener->inl_text->as.literal);
					opener->inl_text->as.literal =
						cmark_chunk_literal(LEFTDOUBLEQUOTE);
				}
				closer = closer->next;
			}
		} else {
			closer = closer->next;
		}
	}
	// free all delimiters in list until start_delim:
	while (subj->last_delim != start_delim) {
		remove_delimiter(subj, subj->last_delim);
	}
}
Example #3
0
/*
 * Parse a mapping table and create the appropriate targets or
 * check that a target type is registered with the device-mapper core.
 */
static int
handle_table(struct lib_context *lc, struct dm_task *dmt,
	     char *table, struct dm_versions *targets)
{
	int line = 0, n, ret = 0;
	uint64_t start, size;
	char *nl = table, *p, ttype[32];

	do {
		p = nl;
		line++;

		/*
		 * Not using sscanf string allocation
		 * because it's not available in dietlibc.
		 */
		*ttype = 0;
		if (sscanf(p, "%" PRIu64 " %" PRIu64 " %31s %n",
			   &start, &size, ttype, &n) < 3)
			LOG_ERR(lc, 0, "Invalid format in table line %d", line);

		if (!(ret = valid_ttype(lc, ttype, targets)))
			break;

		nl = remove_delimiter((p += n), '\n');
		if (dmt)
			ret = dm_task_add_target(dmt, start, size, ttype, p);

		add_delimiter(&nl, '\n');
	} while (nl && ret);

	return ret;
}
Example #4
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);
  }
}
Example #5
0
static void process_emphasis(subject *subj, delimiter *start_delim)
{
	delimiter *closer = subj->last_delim;
	delimiter *opener;

	// move back to first relevant delim.
	while (closer != NULL && closer->previous != start_delim) {
		closer = closer->previous;
	}

	// now move forward, looking for closers, and handling each
	while (closer != NULL) {
		if (closer->can_close &&
		    (closer->delim_char == '*' || closer->delim_char == '_')) {
			// Now look backwards for first matching opener:
			opener = closer->previous;
			while (opener != NULL && opener != start_delim) {
				if (opener->delim_char == closer->delim_char &&
				    opener->can_open) {
					break;
				}
				opener = opener->previous;
			}
			if (opener != NULL && opener != start_delim) {
				closer = S_insert_emph(subj, opener, closer);
			} else {
				closer = closer->next;
			}
		} else {
			closer = closer->next;
		}
	}
	// free all delimiters in list until start_delim:
	while (subj->last_delim != start_delim) {
		remove_delimiter(subj, subj->last_delim);
	}
}
Example #6
0
// Return a link, an image, or a literal close bracket.
static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
{
	int initial_pos;
	int starturl, endurl, starttitle, endtitle, endall;
	int n;
	int sps;
	cmark_reference *ref;
	bool is_image = false;
	cmark_chunk url_chunk, title_chunk;
	unsigned char *url, *title;
	delimiter *opener;
	cmark_node *link_text;
	cmark_node *inl;
	cmark_chunk raw_label;
	int found_label;

	advance(subj);  // advance past ]
	initial_pos = subj->pos;

	// look through list of delimiters for a [ or !
	opener = subj->last_delim;
	while (opener) {
		if (opener->delim_char == '[' || opener->delim_char == '!') {
			break;
		}
		opener = opener->previous;
	}

	if (opener == NULL) {
		return make_str(cmark_chunk_literal("]"));
	}

	if (!opener->active) {
		// take delimiter off stack
		remove_delimiter(subj, opener);
		return make_str(cmark_chunk_literal("]"));
	}

	// If we got here, we matched a potential link/image text.
	is_image = opener->delim_char == '!';
	link_text = opener->inl_text->next;

	// Now we check to see if it's a link/image.

	// First, look for an inline link.
	if (peek_char(subj) == '(' &&
	    ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
	    ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) {

		// try to parse an explicit link:
		starturl = subj->pos + 1 + sps; // after (
		endurl = starturl + n;
		starttitle = endurl + scan_spacechars(&subj->input, endurl);

		// ensure there are spaces btw url and title
		endtitle = (starttitle == endurl) ? starttitle :
		           starttitle + scan_link_title(&subj->input, starttitle);

		endall = endtitle + scan_spacechars(&subj->input, endtitle);

		if (peek_at(subj, endall) == ')') {
			subj->pos = endall + 1;

			url_chunk = cmark_chunk_dup(&subj->input, starturl, endurl - starturl);
			title_chunk = cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
			url = cmark_clean_url(&url_chunk);
			title = cmark_clean_title(&title_chunk);
			cmark_chunk_free(&url_chunk);
			cmark_chunk_free(&title_chunk);
			goto match;

		} else {
			goto noMatch;
		}
	}

	// Next, look for a following [link label] that matches in refmap.
	// skip spaces
	subj->pos = subj->pos + scan_spacechars(&subj->input, subj->pos);
	raw_label = cmark_chunk_literal("");
	found_label = link_label(subj, &raw_label);
	if (!found_label || raw_label.len == 0) {
		cmark_chunk_free(&raw_label);
		raw_label = cmark_chunk_dup(&subj->input, opener->position,
		                            initial_pos - opener->position - 1);
	}

	if (!found_label) {
		// If we have a shortcut reference link, back up
		// to before the spacse we skipped.
		subj->pos = initial_pos;
	}

	ref = cmark_reference_lookup(subj->refmap, &raw_label);
	cmark_chunk_free(&raw_label);

	if (ref != NULL) { // found
		url = bufdup(ref->url);
		title = bufdup(ref->title);
		goto match;
	} else {
		goto noMatch;
	}

noMatch:
	// If we fall through to here, it means we didn't match a link:
	remove_delimiter(subj, opener);  // remove this opener from delimiter list
	subj->pos = initial_pos;
	return make_str(cmark_chunk_literal("]"));

match:
	inl = opener->inl_text;
	inl->type = is_image ? NODE_IMAGE : NODE_LINK;
	cmark_chunk_free(&inl->as.literal);
	inl->first_child = link_text;
	process_emphasis(subj, opener->previous);
	inl->as.link.url   = url;
	inl->as.link.title = title;
	inl->next = NULL;
	if (link_text) {
		cmark_node *tmp;
		link_text->prev = NULL;
		for (tmp = link_text; tmp->next != NULL; tmp = tmp->next) {
			tmp->parent = inl;
		}
		tmp->parent = inl;
		inl->last_child = tmp;
	}
	parent->last_child = inl;

	// process_emphasis will remove this delimiter and all later ones.
	// Now, if we have a link, we also want to deactivate earlier link
	// delimiters. (This code can be removed if we decide to allow links
	// inside links.)
	if (!is_image) {
		opener = subj->last_delim;
		while (opener != NULL) {
			if (opener->delim_char == '[') {
				if (!opener->active) {
					break;
				} else {
					opener->active = false;
				}
			}
			opener = opener->previous;
		}
	}

	return NULL;
}
Example #7
0
static delimiter*
S_insert_emph(subject *subj, delimiter *opener, delimiter *closer)
{
	delimiter *delim, *tmp_delim;
	int use_delims;
	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 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 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
	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 characters, remove it and its associated inline
	if (opener_num_chars == 0) {
		// replace empty opener inline with emph
		cmark_chunk_free(&(opener_inl->as.literal));
		emph = opener_inl;
		emph->type = use_delims == 1 ? NODE_EMPH : NODE_STRONG;
		// remove opener from list
		remove_delimiter(subj, opener);
	} else {
		// create new emph or strong, and splice it in to our inlines
		// between the opener and closer
		emph = use_delims == 1 ? make_emph() : make_strong();
		emph->parent = opener_inl->parent;
		emph->prev = opener_inl;
		opener_inl->next = emph;
	}

	// push children below emph
	emph->next = closer_inl;
	closer_inl->prev = emph;
	emph->first_child = first_child;
	emph->last_child  = last_child;

	// fix children pointers
	first_child->prev = NULL;
	last_child->next  = NULL;
	for (tmp = first_child; tmp != NULL; tmp = tmp->next) {
		tmp->parent = emph;
	}

	// 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 list
		tmp_delim = closer->next;
		remove_delimiter(subj, closer);
		closer = tmp_delim;
	}

	return closer;
}
Example #8
0
static void process_emphasis(subject *subj, delimiter *stack_bottom) {
  delimiter *closer = subj->last_delim;
  delimiter *opener;
  delimiter *old_closer;
  bool opener_found;
  int openers_bottom_index;
  delimiter *openers_bottom[6] = {stack_bottom, stack_bottom, stack_bottom,
                                  stack_bottom, stack_bottom, stack_bottom};

  // move back to first relevant delim.
  while (closer != NULL && closer->previous != stack_bottom) {
    closer = closer->previous;
  }

  // now move forward, looking for closers, and handling each
  while (closer != NULL) {
    if (closer->can_close) {
      switch (closer->delim_char) {
      case '"':
        openers_bottom_index = 0;
        break;
      case '\'':
        openers_bottom_index = 1;
        break;
      case '_':
        openers_bottom_index = 2;
        break;
      case '*':
        openers_bottom_index = 3 + (closer->length % 3);
        break;
      default:
        assert(false);
      }

      // Now look backwards for first matching opener:
      opener = closer->previous;
      opener_found = false;
      while (opener != NULL && opener != openers_bottom[openers_bottom_index]) {
        if (opener->can_open && opener->delim_char == closer->delim_char) {
          // interior closer of size 2 can't match opener of size 1
          // or of size 1 can't match 2
          if (!(closer->can_open || opener->can_close) ||
              ((opener->length + closer->length) % 3) != 0) {
            opener_found = true;
            break;
          }
        }
        opener = opener->previous;
      }
      old_closer = closer;
      if (closer->delim_char == '*' || closer->delim_char == '_') {
        if (opener_found) {
          closer = S_insert_emph(subj, opener, closer);
        } else {
          closer = closer->next;
        }
      } else if (closer->delim_char == '\'') {
        cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
        closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE);
        if (opener_found) {
          cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
          opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE);
        }
        closer = closer->next;
      } else if (closer->delim_char == '"') {
        cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
        closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE);
        if (opener_found) {
          cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
          opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE);
        }
        closer = closer->next;
      }
      if (!opener_found) {
        // set lower bound for future searches for openers
        openers_bottom[openers_bottom_index] = old_closer->previous;
        if (!old_closer->can_open) {
          // we can remove a closer that can't be an
          // opener, once we've seen there's no
          // matching opener:
          remove_delimiter(subj, old_closer);
        }
      }
    } else {
      closer = closer->next;
    }
  }
  // free all delimiters in list until stack_bottom:
  while (subj->last_delim != NULL && subj->last_delim != stack_bottom) {
    remove_delimiter(subj, subj->last_delim);
  }
}
Example #9
0
static void process_emphasis(subject *subj, delimiter *stack_bottom) {
  delimiter *closer = subj->last_delim;
  delimiter *opener;
  delimiter *old_closer;
  bool opener_found;
  bool odd_match;
  delimiter *openers_bottom[128];

  // initialize openers_bottom:
  openers_bottom['*'] = stack_bottom;
  openers_bottom['_'] = stack_bottom;
  openers_bottom['\''] = stack_bottom;
  openers_bottom['"'] = stack_bottom;

  // move back to first relevant delim.
  while (closer != NULL && closer->previous != stack_bottom) {
    closer = closer->previous;
  }

  // now move forward, looking for closers, and handling each
  while (closer != NULL) {
    if (closer->can_close) {
      // Now look backwards for first matching opener:
      opener = closer->previous;
      opener_found = false;
      odd_match = false;
      while (opener != NULL && opener != stack_bottom &&
             opener != openers_bottom[closer->delim_char]) {
        // interior closer of size 2 can't match opener of size 1
        // or of size 1 can't match 2
        odd_match = (closer->can_open || opener->can_close) &&
                    ((opener->inl_text->as.literal.len +
                      closer->inl_text->as.literal.len) %
                         3 ==
                     0);
        if (opener->delim_char == closer->delim_char && opener->can_open &&
            !odd_match) {
          opener_found = true;
          break;
        }
        opener = opener->previous;
      }
      old_closer = closer;
      if (closer->delim_char == '*' || closer->delim_char == '_') {
        if (opener_found) {
          closer = S_insert_emph(subj, opener, closer);
        } else {
          closer = closer->next;
        }
      } else if (closer->delim_char == '\'') {
        cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
        closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE);
        if (opener_found) {
          cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
          opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE);
        }
        closer = closer->next;
      } else if (closer->delim_char == '"') {
        cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
        closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE);
        if (opener_found) {
          cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
          opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE);
        }
        closer = closer->next;
      }
      if (!opener_found && !odd_match) {
        // set lower bound for future searches for openers
        // (we don't do this with 'odd_match' set because
        // a ** that didn't match an earlier * might turn into
        // an opener, and the * might be matched by something
        // else.
        openers_bottom[old_closer->delim_char] = old_closer->previous;
        if (!old_closer->can_open) {
          // we can remove a closer that can't be an
          // opener, once we've seen there's no
          // matching opener:
          remove_delimiter(subj, old_closer);
        }
      }
    } else {
      closer = closer->next;
    }
  }
  // free all delimiters in list until stack_bottom:
  while (subj->last_delim != stack_bottom) {
    remove_delimiter(subj, subj->last_delim);
  }
}
Example #10
0
static void process_emphasis(subject *subj, delimiter *stack_bottom)
{
	delimiter *closer = subj->last_delim;
	delimiter *opener;
	delimiter *old_closer;
	bool opener_found;
	delimiter *openers_bottom[128];

	// initialize openers_bottom:
	openers_bottom['*'] = stack_bottom;
	openers_bottom['_'] = stack_bottom;
	openers_bottom['\''] = stack_bottom;
	openers_bottom['"'] = stack_bottom;

	// move back to first relevant delim.
	while (closer != NULL && closer->previous != stack_bottom) {
		closer = closer->previous;
	}

	// now move forward, looking for closers, and handling each
	while (closer != NULL) {
		if (closer->can_close &&
		    (closer->delim_char == '*' || closer->delim_char == '_' ||
		     closer->delim_char == '"' || closer->delim_char == '\'')) {
			// Now look backwards for first matching opener:
			opener = closer->previous;
			opener_found = false;
			while (opener != NULL && opener != stack_bottom &&
			       opener != openers_bottom[closer->delim_char]) {
				if (opener->delim_char == closer->delim_char &&
				    opener->can_open) {
					opener_found = true;
					break;
				}
				opener = opener->previous;
			}
			old_closer = closer;
			if (closer->delim_char == '*' || closer->delim_char == '_') {
				if (opener_found) {
					closer = S_insert_emph(subj, opener, closer);
				} else {
					closer = closer->next;
				}
			} else if (closer->delim_char == '\'') {
				cmark_chunk_free(&closer->inl_text->as.literal);
				closer->inl_text->as.literal =
				    cmark_chunk_literal(RIGHTSINGLEQUOTE);
				if (opener_found) {
					cmark_chunk_free(&opener->inl_text->as.literal);
					opener->inl_text->as.literal =
					    cmark_chunk_literal(LEFTSINGLEQUOTE);
				}
				closer = closer->next;
			} else if (closer->delim_char == '"') {
				cmark_chunk_free(&closer->inl_text->as.literal);
				closer->inl_text->as.literal =
				    cmark_chunk_literal(RIGHTDOUBLEQUOTE);
				if (opener_found) {
					cmark_chunk_free(&opener->inl_text->as.literal);
					opener->inl_text->as.literal =
					    cmark_chunk_literal(LEFTDOUBLEQUOTE);
				}
				closer = closer->next;
			}
			if (!opener_found) {
				// set lower bound for future searches for openers:
				openers_bottom[old_closer->delim_char] = old_closer->previous;
				if (!old_closer->can_open) {
					// we can remove a closer that can't be an
					// opener, once we've seen there's no
					// matching opener:
					remove_delimiter(subj, old_closer);
				}
			}
		} else {
			closer = closer->next;
		}
	}
	// free all delimiters in list until stack_bottom:
	while (subj->last_delim != stack_bottom) {
		remove_delimiter(subj, subj->last_delim);
	}
}