heredoc_get(exarg_T *eap, char_u *cmd, int script_get)
{
    char_u	*theline;
    char_u	*marker;
    list_T	*l;
    char_u	*p;
    int		marker_indent_len = 0;
    int		text_indent_len = 0;
    char_u	*text_indent = NULL;
    char_u	dot[] = ".";
    int		comment_char = in_vim9script() ? '#' : '"';

    if (eap->getline == NULL)
    {
	emsg(_(e_cannot_use_heredoc_here));
	return NULL;
    }

    // Check for the optional 'trim' word before the marker
    cmd = skipwhite(cmd);
    if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
    {
	cmd = skipwhite(cmd + 4);

	// Trim the indentation from all the lines in the here document.
	// The amount of indentation trimmed is the same as the indentation of
	// the first line after the :let command line.  To find the end marker
	// the indent of the :let command line is trimmed.
	p = *eap->cmdlinep;
	while (VIM_ISWHITE(*p))
	{
	    p++;
	    marker_indent_len++;
	}
	text_indent_len = -1;
    }

    // The marker is the next word.
    if (*cmd != NUL && *cmd != comment_char)
    {
	marker = skipwhite(cmd);
	p = skiptowhite(marker);
	if (*skipwhite(p) != NUL && *skipwhite(p) != comment_char)
	{
	    semsg(_(e_trailing_characters_str), p);
	    return NULL;
	}
	*p = NUL;
	if (!script_get && vim_islower(*marker))
	{
	    emsg(_(e_marker_cannot_start_with_lower_case_letter));
	    return NULL;
	}
    }
    else
    {
	// When getting lines for an embedded script, if the marker is missing,
	// accept '.' as the marker.
	if (script_get)
	    marker = dot;
	else
	{
	    emsg(_(e_missing_marker));
	    return NULL;
	}
    }

    l = list_alloc();
    if (l == NULL)
	return NULL;

    for (;;)
    {
	int	mi = 0;
	int	ti = 0;

	theline = eap->getline(NUL, eap->cookie, 0, FALSE);
	if (theline == NULL)
	{
	    semsg(_(e_missing_end_marker_str), marker);
	    break;
	}

	// with "trim": skip the indent matching the :let line to find the
	// marker
	if (marker_indent_len > 0
		&& STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
	    mi = marker_indent_len;
	if (STRCMP(marker, theline + mi) == 0)
	{
	    vim_free(theline);
	    break;
	}

	if (text_indent_len == -1 && *theline != NUL)
	{
	    // set the text indent from the first line.
	    p = theline;
	    text_indent_len = 0;
	    while (VIM_ISWHITE(*p))
	    {
		p++;
		text_indent_len++;
	    }
	    text_indent = vim_strnsave(theline, text_indent_len);
	}
	// with "trim": skip the indent matching the first line
	if (text_indent != NULL)
	    for (ti = 0; ti < text_indent_len; ++ti)
		if (theline[ti] != text_indent[ti])
		    break;

	if (list_append_string(l, theline + ti, -1) == FAIL)
	    break;
	vim_free(theline);
    }
    vim_free(text_indent);

    return l;
}
heredoc_get(exarg_T *eap, char_u *cmd, int script_get)
{
    char_u	*theline;
    char_u	*marker;
    list_T	*l;
    char_u	*p;
    int		marker_indent_len = 0;
    int		text_indent_len = 0;
    char_u	*text_indent = NULL;
    char_u	dot[] = ".";
    int		comment_char = in_vim9script() ? '#' : '"';

    if (eap->getline == NULL)
    {
	emsg(_(e_cannot_use_heredoc_here));
	return NULL;
    }

     
    cmd = skipwhite(cmd);
    if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
    {
	cmd = skipwhite(cmd + 4);

	 
	 
	 
	 
	p = *eap->cmdlinep;
	while (VIM_ISWHITE(*p))
	{
	    p++;
	    marker_indent_len++;
	}
	text_indent_len = -1;
    }

     
    if (*cmd != NUL && *cmd != comment_char)
    {
	marker = skipwhite(cmd);
	p = skiptowhite(marker);
	if (*skipwhite(p) != NUL && *skipwhite(p) != comment_char)
	{
	    semsg(_(e_trailing_characters_str), p);
	    return NULL;
	}
	*p = NUL;
	if (!script_get && vim_islower(*marker))
	{
	    emsg(_(e_marker_cannot_start_with_lower_case_letter));
	    return NULL;
	}
    }
    else
    {
	 
	 
	if (script_get)
	    marker = dot;
	else
	{
	    emsg(_(e_missing_marker));
	    return NULL;
	}
    }

    l = list_alloc();
    if (l == NULL)
	return NULL;

    for (;;)
    {
	int	mi = 0;
	int	ti = 0;

	theline = eap->getline(NUL, eap->cookie, 0, FALSE);
	if (theline == NULL)
	{
	    semsg(_(e_missing_end_marker_str), marker);
	    break;
	}

	 
	 
	if (marker_indent_len > 0
		&& STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
	    mi = marker_indent_len;
	if (STRCMP(marker, theline + mi) == 0)
	{
	    vim_free(theline);
	    break;
	}

	if (text_indent_len == -1 && *theline != NUL)
	{
	     
	    p = theline;
	    text_indent_len = 0;
	    while (VIM_ISWHITE(*p))
	    {
		p++;
		text_indent_len++;
	    }
	    text_indent = vim_strnsave(theline, text_indent_len);
	}
	 
	if (text_indent != NULL)
	    for (ti = 0; ti < text_indent_len; ++ti)
		if (theline[ti] != text_indent[ti])
		    break;

	if (list_append_string(l, theline + ti, -1) == FAIL)
	    break;
	vim_free(theline);
    }
    vim_free(text_indent);

    return l;
}