patch 9.0.0620: matchaddpos() can only add up to 8 matches

Problem:    matchaddpos() can only add up to 8 matches.
Solution:   Allocate the array of positions. (closes #11248)
diff --git a/src/match.c b/src/match.c
index ebdaeab..ecab28c 100644
--- a/src/match.c
+++ b/src/match.c
@@ -18,10 +18,12 @@
 # define SEARCH_HL_PRIORITY 0
 
 /*
- * Add match to the match list of window 'wp'.  The pattern 'pat' will be
- * highlighted with the group 'grp' with priority 'prio'.
- * Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
- * If no particular ID is desired, -1 must be specified for 'id'.
+ * Add match to the match list of window "wp".
+ * If "pat" is not NULL the pattern will be highlighted with the group "grp"
+ * with priority "prio".
+ * If "pos_list" is not NULL the list of posisions defines the highlights.
+ * Optionally, a desired ID "id" can be specified (greater than or equal to 1).
+ * If no particular ID is desired, -1 must be specified for "id".
  * Return ID of added match, -1 on failure.
  */
     static int
@@ -53,12 +55,12 @@
 	cur = wp->w_match_head;
 	while (cur != NULL)
 	{
-	    if (cur->id == id)
+	    if (cur->mit_id == id)
 	    {
 		semsg(_(e_id_already_taken_nr), id);
 		return -1;
 	    }
-	    cur = cur->next;
+	    cur = cur->mit_next;
 	}
     }
     if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0)
@@ -76,8 +78,8 @@
     while (id == -1)
     {
 	cur = wp->w_match_head;
-	while (cur != NULL && cur->id != wp->w_next_match_id)
-	    cur = cur->next;
+	while (cur != NULL && cur->mit_id != wp->w_next_match_id)
+	    cur = cur->mit_next;
 	if (cur == NULL)
 	    id = wp->w_next_match_id;
 	wp->w_next_match_id++;
@@ -85,17 +87,29 @@
 
     // Build new match.
     m = ALLOC_CLEAR_ONE(matchitem_T);
-    m->id = id;
-    m->priority = prio;
-    m->pattern = pat == NULL ? NULL : vim_strsave(pat);
-    m->hlg_id = hlg_id;
-    m->match.regprog = regprog;
-    m->match.rmm_ic = FALSE;
-    m->match.rmm_maxcol = 0;
+    if (m == NULL)
+	return -1;
+    if (pos_list != NULL)
+    {
+	m->mit_pos_array = ALLOC_CLEAR_MULT(llpos_T, pos_list->lv_len);
+	if (m->mit_pos_array == NULL)
+	{
+	    vim_free(m);
+	    return -1;
+	}
+	m->mit_pos_count = pos_list->lv_len;
+    }
+    m->mit_id = id;
+    m->mit_priority = prio;
+    m->mit_pattern = pat == NULL ? NULL : vim_strsave(pat);
+    m->mit_hlg_id = hlg_id;
+    m->mit_match.regprog = regprog;
+    m->mit_match.rmm_ic = FALSE;
+    m->mit_match.rmm_maxcol = 0;
 # if defined(FEAT_CONCEAL)
-    m->conceal_char = 0;
+    m->mit_conceal_char = 0;
     if (conceal_char != NULL)
-	m->conceal_char = (*mb_ptr2char)(conceal_char);
+	m->mit_conceal_char = (*mb_ptr2char)(conceal_char);
 # endif
 
     // Set up position matches
@@ -107,8 +121,7 @@
 	int		i;
 
 	CHECK_LIST_MATERIALIZE(pos_list);
-	for (i = 0, li = pos_list->lv_first; li != NULL && i < MAXPOSMATCH;
-							i++, li = li->li_next)
+	for (i = 0, li = pos_list->lv_first; li != NULL; i++, li = li->li_next)
 	{
 	    linenr_T	lnum = 0;
 	    colnr_T	col = 0;
@@ -133,7 +146,7 @@
 		    --i;
 		    continue;
 		}
-		m->pos.pos[i].lnum = lnum;
+		m->mit_pos_array[i].lnum = lnum;
 		subli = subli->li_next;
 		if (subli != NULL)
 		{
@@ -148,8 +161,8 @@
 			    goto fail;
 		    }
 		}
-		m->pos.pos[i].col = col;
-		m->pos.pos[i].len = len;
+		m->mit_pos_array[i].col = col;
+		m->mit_pos_array[i].len = len;
 	    }
 	    else if (li->li_tv.v_type == VAR_NUMBER)
 	    {
@@ -158,9 +171,9 @@
 		    --i;
 		    continue;
 		}
-		m->pos.pos[i].lnum = li->li_tv.vval.v_number;
-		m->pos.pos[i].col = 0;
-		m->pos.pos[i].len = 0;
+		m->mit_pos_array[i].lnum = li->li_tv.vval.v_number;
+		m->mit_pos_array[i].col = 0;
+		m->mit_pos_array[i].len = 0;
 	    }
 	    else
 	    {
@@ -190,8 +203,8 @@
 		wp->w_buffer->b_mod_bot = botlnum;
 		wp->w_buffer->b_mod_xlines = 0;
 	    }
-	    m->pos.toplnum = toplnum;
-	    m->pos.botlnum = botlnum;
+	    m->mit_toplnum = toplnum;
+	    m->mit_botlnum = botlnum;
 	    rtype = UPD_VALID;
 	}
     }
@@ -200,21 +213,23 @@
     // the match priorities.
     cur = wp->w_match_head;
     prev = cur;
-    while (cur != NULL && prio >= cur->priority)
+    while (cur != NULL && prio >= cur->mit_priority)
     {
 	prev = cur;
-	cur = cur->next;
+	cur = cur->mit_next;
     }
     if (cur == prev)
 	wp->w_match_head = m;
     else
-	prev->next = m;
-    m->next = cur;
+	prev->mit_next = m;
+    m->mit_next = cur;
 
     redraw_win_later(wp, rtype);
     return id;
 
 fail:
+    vim_free(m->mit_pattern);
+    vim_free(m->mit_pos_array);
     vim_free(m);
     return -1;
 }
@@ -233,13 +248,14 @@
     if (id < 1)
     {
 	if (perr == TRUE)
-	    semsg(_(e_invalid_id_nr_must_be_greater_than_or_equal_to_one_2), id);
+	    semsg(_(e_invalid_id_nr_must_be_greater_than_or_equal_to_one_2),
+									   id);
 	return -1;
     }
-    while (cur != NULL && cur->id != id)
+    while (cur != NULL && cur->mit_id != id)
     {
 	prev = cur;
-	cur = cur->next;
+	cur = cur->mit_next;
     }
     if (cur == NULL)
     {
@@ -248,29 +264,30 @@
 	return -1;
     }
     if (cur == prev)
-	wp->w_match_head = cur->next;
+	wp->w_match_head = cur->mit_next;
     else
-	prev->next = cur->next;
-    vim_regfree(cur->match.regprog);
-    vim_free(cur->pattern);
-    if (cur->pos.toplnum != 0)
+	prev->mit_next = cur->mit_next;
+    vim_regfree(cur->mit_match.regprog);
+    vim_free(cur->mit_pattern);
+    if (cur->mit_toplnum != 0)
     {
 	if (wp->w_buffer->b_mod_set)
 	{
-	    if (wp->w_buffer->b_mod_top > cur->pos.toplnum)
-		wp->w_buffer->b_mod_top = cur->pos.toplnum;
-	    if (wp->w_buffer->b_mod_bot < cur->pos.botlnum)
-		wp->w_buffer->b_mod_bot = cur->pos.botlnum;
+	    if (wp->w_buffer->b_mod_top > cur->mit_toplnum)
+		wp->w_buffer->b_mod_top = cur->mit_toplnum;
+	    if (wp->w_buffer->b_mod_bot < cur->mit_botlnum)
+		wp->w_buffer->b_mod_bot = cur->mit_botlnum;
 	}
 	else
 	{
 	    wp->w_buffer->b_mod_set = TRUE;
-	    wp->w_buffer->b_mod_top = cur->pos.toplnum;
-	    wp->w_buffer->b_mod_bot = cur->pos.botlnum;
+	    wp->w_buffer->b_mod_top = cur->mit_toplnum;
+	    wp->w_buffer->b_mod_bot = cur->mit_botlnum;
 	    wp->w_buffer->b_mod_xlines = 0;
 	}
 	rtype = UPD_VALID;
     }
+    vim_free(cur->mit_pos_array);
     vim_free(cur);
     redraw_win_later(wp, rtype);
     return 0;
@@ -286,9 +303,10 @@
 
     while (wp->w_match_head != NULL)
     {
-	m = wp->w_match_head->next;
-	vim_regfree(wp->w_match_head->match.regprog);
-	vim_free(wp->w_match_head->pattern);
+	m = wp->w_match_head->mit_next;
+	vim_regfree(wp->w_match_head->mit_match.regprog);
+	vim_free(wp->w_match_head->mit_pattern);
+	vim_free(wp->w_match_head->mit_pos_array);
 	vim_free(wp->w_match_head);
 	wp->w_match_head = m;
     }
@@ -304,8 +322,8 @@
 {
     matchitem_T *cur = wp->w_match_head;
 
-    while (cur != NULL && cur->id != id)
-	cur = cur->next;
+    while (cur != NULL && cur->mit_id != id)
+	cur = cur->mit_next;
     return cur;
 }
 
@@ -322,15 +340,15 @@
     cur = wp->w_match_head;
     while (cur != NULL)
     {
-	cur->hl.rm = cur->match;
-	if (cur->hlg_id == 0)
-	    cur->hl.attr = 0;
+	cur->mit_hl.rm = cur->mit_match;
+	if (cur->mit_hlg_id == 0)
+	    cur->mit_hl.attr = 0;
 	else
-	    cur->hl.attr = syn_id2attr(cur->hlg_id);
-	cur->hl.buf = wp->w_buffer;
-	cur->hl.lnum = 0;
-	cur->hl.first_lnum = 0;
-	cur = cur->next;
+	    cur->mit_hl.attr = syn_id2attr(cur->mit_hlg_id);
+	cur->mit_hl.buf = wp->w_buffer;
+	cur->mit_hl.lnum = 0;
+	cur->mit_hl.first_lnum = 0;
+	cur = cur->mit_next;
     }
     search_hl->buf = wp->w_buffer;
     search_hl->lnum = 0;
@@ -346,15 +364,15 @@
 next_search_hl_pos(
     match_T	    *shl,	// points to a match
     linenr_T	    lnum,
-    posmatch_T	    *posmatch,	// match positions
+    matchitem_T	    *match,	// match item with positions
     colnr_T	    mincol)	// minimal column for a match
 {
     int	    i;
     int	    found = -1;
 
-    for (i = posmatch->cur; i < MAXPOSMATCH; i++)
+    for (i = match->mit_pos_cur; i < match->mit_pos_count; i++)
     {
-	llpos_T	*pos = &posmatch->pos[i];
+	llpos_T	*pos = &match->mit_pos_array[i];
 
 	if (pos->lnum == 0)
 	    break;
@@ -364,27 +382,26 @@
 	{
 	    if (found >= 0)
 	    {
-		// if this match comes before the one at "found" then swap
-		// them
-		if (pos->col < posmatch->pos[found].col)
+		// if this match comes before the one at "found" then swap them
+		if (pos->col < match->mit_pos_array[found].col)
 		{
 		    llpos_T	tmp = *pos;
 
-		    *pos = posmatch->pos[found];
-		    posmatch->pos[found] = tmp;
+		    *pos = match->mit_pos_array[found];
+		    match->mit_pos_array[found] = tmp;
 		}
 	    }
 	    else
 		found = i;
 	}
     }
-    posmatch->cur = 0;
+    match->mit_pos_cur = 0;
     if (found >= 0)
     {
-	colnr_T	start = posmatch->pos[found].col == 0
-					    ? 0 : posmatch->pos[found].col - 1;
-	colnr_T	end = posmatch->pos[found].col == 0
-				   ? MAXCOL : start + posmatch->pos[found].len;
+	colnr_T	start = match->mit_pos_array[found].col == 0
+				     ? 0 : match->mit_pos_array[found].col - 1;
+	colnr_T	end = match->mit_pos_array[found].col == 0
+			    ? MAXCOL : start + match->mit_pos_array[found].len;
 
 	shl->lnum = lnum;
 	shl->rm.startpos[0].lnum = 0;
@@ -393,7 +410,7 @@
 	shl->rm.endpos[0].col = end;
 	shl->is_addpos = TRUE;
 	shl->has_cursor = FALSE;
-	posmatch->cur = found + 1;
+	match->mit_pos_cur = found + 1;
 	return 1;
     }
     return 0;
@@ -479,16 +496,16 @@
 	if (shl->rm.regprog != NULL)
 	{
 	    // Remember whether shl->rm is using a copy of the regprog in
-	    // cur->match.
+	    // cur->mit_match.
 	    int regprog_is_copy = (shl != search_hl && cur != NULL
-				&& shl == &cur->hl
-				&& cur->match.regprog == cur->hl.rm.regprog);
+			  && shl == &cur->mit_hl
+			  && cur->mit_match.regprog == cur->mit_hl.rm.regprog);
 
 	    nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum,
 							 matchcol, &timed_out);
 	    // Copy the regprog, in case it got freed and recompiled.
 	    if (regprog_is_copy)
-		cur->match.regprog = cur->hl.rm.regprog;
+		cur->mit_match.regprog = cur->mit_hl.rm.regprog;
 
 	    if (called_emsg > called_emsg_before || got_int || timed_out)
 	    {
@@ -506,7 +523,7 @@
 	    }
 	}
 	else if (cur != NULL)
-	    nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
+	    nmatched = next_search_hl_pos(shl, lnum, cur, matchcol);
 	else
 	    nmatched = 0;
 	if (nmatched == 0)
@@ -552,7 +569,7 @@
 	    shl_flag = TRUE;
 	}
 	else
-	    shl = &cur->hl;
+	    shl = &cur->mit_hl;
 	if (shl->rm.regprog != NULL
 		&& shl->lnum == 0
 		&& re_multiline(shl->rm.regprog))
@@ -570,7 +587,7 @@
 # endif
 	    }
 	    if (cur != NULL)
-		cur->pos.cur = 0;
+		cur->mit_pos_cur = 0;
 	    pos_inprogress = TRUE;
 	    n = 0;
 	    while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
@@ -578,7 +595,7 @@
 	    {
 		next_search_hl(wp, search_hl, shl, shl->first_lnum, (colnr_T)n,
 					       shl == search_hl ? NULL : cur);
-		pos_inprogress = cur == NULL || cur->pos.cur == 0
+		pos_inprogress = cur == NULL || cur->mit_pos_cur == 0
 							      ? FALSE : TRUE;
 		if (shl->lnum != 0)
 		{
@@ -595,7 +612,7 @@
 	    }
 	}
 	if (shl != search_hl && cur != NULL)
-	    cur = cur->next;
+	    cur = cur->mit_next;
     }
 }
 
@@ -652,14 +669,14 @@
 	    shl_flag = TRUE;
 	}
 	else
-	    shl = &cur->hl;
+	    shl = &cur->mit_hl;
 	shl->startcol = MAXCOL;
 	shl->endcol = MAXCOL;
 	shl->attr_cur = 0;
 	shl->is_addpos = FALSE;
 	shl->has_cursor = FALSE;
 	if (cur != NULL)
-	    cur->pos.cur = 0;
+	    cur->mit_pos_cur = 0;
 	next_search_hl(wp, search_hl, shl, lnum, mincol,
 						shl == search_hl ? NULL : cur);
 
@@ -699,7 +716,7 @@
 	    area_highlighting = TRUE;
 	}
 	if (shl != search_hl && cur != NULL)
-	    cur = cur->next;
+	    cur = cur->mit_next;
     }
     return area_highlighting;
 }
@@ -743,15 +760,15 @@
     {
 	if (shl_flag == FALSE
 		&& (cur == NULL
-			|| cur->priority > SEARCH_HL_PRIORITY))
+			|| cur->mit_priority > SEARCH_HL_PRIORITY))
 	{
 	    shl = search_hl;
 	    shl_flag = TRUE;
 	}
 	else
-	    shl = &cur->hl;
+	    shl = &cur->mit_hl;
 	if (cur != NULL)
-	    cur->pos.cur = 0;
+	    cur->mit_pos_cur = 0;
 	pos_inprogress = TRUE;
 	while (shl->rm.regprog != NULL || (cur != NULL && pos_inprogress))
 	{
@@ -769,10 +786,10 @@
 		// the match.
 		if (cur != NULL
 			&& shl != search_hl
-			&& syn_name2id((char_u *)"Conceal") == cur->hlg_id)
+			&& syn_name2id((char_u *)"Conceal") == cur->mit_hlg_id)
 		{
 		    *has_match_conc = col == shl->startcol ? 2 : 1;
-		    *match_conc = cur->conceal_char;
+		    *match_conc = cur->mit_conceal_char;
 		}
 		else
 		    *has_match_conc = 0;
@@ -792,7 +809,7 @@
 		shl->attr_cur = 0;
 		next_search_hl(wp, search_hl, shl, lnum, col,
 					       shl == search_hl ? NULL : cur);
-		pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
+		pos_inprogress = !(cur == NULL || cur->mit_pos_cur == 0);
 
 		// Need to get the line again, a multi-line regexp may have
 		// made it invalid.
@@ -836,7 +853,7 @@
 	    break;
 	}
 	if (shl != search_hl && cur != NULL)
-	    cur = cur->next;
+	    cur = cur->mit_next;
     }
 
     // Use attributes from match with highest priority among 'search_hl' and
@@ -847,20 +864,20 @@
     {
 	if (shl_flag == FALSE
 		&& (cur == NULL ||
-			cur->priority > SEARCH_HL_PRIORITY))
+			cur->mit_priority > SEARCH_HL_PRIORITY))
 	{
 	    shl = search_hl;
 	    shl_flag = TRUE;
 	}
 	else
-	    shl = &cur->hl;
+	    shl = &cur->mit_hl;
 	if (shl->attr_cur != 0)
 	{
 	    search_attr = shl->attr_cur;
 	    *on_last_col = col + 1 >= shl->endcol;
 	}
 	if (shl != search_hl && cur != NULL)
-	    cur = cur->next;
+	    cur = cur->mit_next;
     }
     // Only highlight one character after the last column.
     if (*(*line + col) == NUL && (did_line_attr >= 1
@@ -898,14 +915,14 @@
 	cur = wp->w_match_head;
 	while (cur != NULL)
 	{
-	    if (!cur->hl.is_addpos && (prevcol == (long)cur->hl.startcol
-			|| (prevcol > (long)cur->hl.startcol
-						 && cur->hl.endcol == MAXCOL)))
+	    if (!cur->mit_hl.is_addpos && (prevcol == (long)cur->mit_hl.startcol
+			|| (prevcol > (long)cur->mit_hl.startcol
+					     && cur->mit_hl.endcol == MAXCOL)))
 	    {
 		prevcol_hl_flag = TRUE;
 		break;
 	    }
-	    cur = cur->next;
+	    cur = cur->mit_next;
 	}
     }
     return prevcol_hl_flag;
@@ -929,19 +946,19 @@
     {
 	if (shl_flag == FALSE
 		&& ((cur != NULL
-			&& cur->priority > SEARCH_HL_PRIORITY)
+			&& cur->mit_priority > SEARCH_HL_PRIORITY)
 		    || cur == NULL))
 	{
 	    shl = search_hl;
 	    shl_flag = TRUE;
 	}
 	else
-	    shl = &cur->hl;
+	    shl = &cur->mit_hl;
 	if (col - 1 == (long)shl->startcol
 		&& (shl == search_hl || !shl->is_addpos))
 	    *char_attr = shl->attr;
 	if (shl != search_hl && cur != NULL)
-	    cur = cur->next;
+	    cur = cur->mit_next;
     }
 }
 
@@ -1020,16 +1037,16 @@
 	dict = dict_alloc();
 	if (dict == NULL)
 	    return;
-	if (cur->match.regprog == NULL)
+	if (cur->mit_match.regprog == NULL)
 	{
 	    // match added with matchaddpos()
-	    for (i = 0; i < MAXPOSMATCH; ++i)
+	    for (i = 0; i < cur->mit_pos_count; ++i)
 	    {
 		llpos_T	*llpos;
 		char	buf[30];  // use 30 to avoid compiler warning
 		list_T	*l;
 
-		llpos = &cur->pos.pos[i];
+		llpos = &cur->mit_pos_array[i];
 		if (llpos->lnum == 0)
 		    break;
 		l = list_alloc();
@@ -1047,22 +1064,22 @@
 	}
 	else
 	{
-	    dict_add_string(dict, "pattern", cur->pattern);
+	    dict_add_string(dict, "pattern", cur->mit_pattern);
 	}
-	dict_add_string(dict, "group", syn_id2name(cur->hlg_id));
-	dict_add_number(dict, "priority", (long)cur->priority);
-	dict_add_number(dict, "id", (long)cur->id);
+	dict_add_string(dict, "group", syn_id2name(cur->mit_hlg_id));
+	dict_add_number(dict, "priority", (long)cur->mit_priority);
+	dict_add_number(dict, "id", (long)cur->mit_id);
 #  if defined(FEAT_CONCEAL)
-	if (cur->conceal_char)
+	if (cur->mit_conceal_char)
 	{
 	    char_u buf[MB_MAXBYTES + 1];
 
-	    buf[(*mb_char2bytes)(cur->conceal_char, buf)] = NUL;
+	    buf[(*mb_char2bytes)(cur->mit_conceal_char, buf)] = NUL;
 	    dict_add_string(dict, "conceal", (char_u *)&buf);
 	}
 #  endif
 	list_append_dict(rettv->vval.v_list, dict);
-	cur = cur->next;
+	cur = cur->mit_next;
     }
 # endif
 }
@@ -1330,8 +1347,8 @@
 	    if ((m = get_match(curwin, id)) != NULL)
 	    {
 		list_append_string(rettv->vval.v_list,
-						syn_id2name(m->hlg_id), -1);
-		list_append_string(rettv->vval.v_list, m->pattern, -1);
+					       syn_id2name(m->mit_hlg_id), -1);
+		list_append_string(rettv->vval.v_list, m->mit_pattern, -1);
 	    }
 	    else
 	    {