xref: /vim-8.2.3635/src/usercmd.c (revision a6c27c47)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * usercmd.c: User defined command support
12  */
13 
14 #include "vim.h"
15 
16 typedef struct ucmd
17 {
18     char_u	*uc_name;	// The command name
19     long_u	uc_argt;	// The argument type
20     char_u	*uc_rep;	// The command's replacement string
21     long	uc_def;		// The default value for a range/count
22     int		uc_compl;	// completion type
23     cmd_addr_T	uc_addr_type;	// The command's address type
24 # ifdef FEAT_EVAL
25     sctx_T	uc_script_ctx;	// SCTX where the command was defined
26 #  ifdef FEAT_CMDL_COMPL
27     char_u	*uc_compl_arg;	// completion argument if any
28 #  endif
29 # endif
30 } ucmd_T;
31 
32 // List of all user commands.
33 static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
34 
35 #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
36 #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
37 
38 /*
39  * List of names for completion for ":command" with the EXPAND_ flag.
40  * Must be alphabetical for completion.
41  */
42 static struct
43 {
44     int	    expand;
45     char    *name;
46 } command_complete[] =
47 {
48     {EXPAND_ARGLIST, "arglist"},
49     {EXPAND_AUGROUP, "augroup"},
50     {EXPAND_BEHAVE, "behave"},
51     {EXPAND_BUFFERS, "buffer"},
52     {EXPAND_COLORS, "color"},
53     {EXPAND_COMMANDS, "command"},
54     {EXPAND_COMPILER, "compiler"},
55 #if defined(FEAT_CSCOPE)
56     {EXPAND_CSCOPE, "cscope"},
57 #endif
58 #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
59     {EXPAND_USER_DEFINED, "custom"},
60     {EXPAND_USER_LIST, "customlist"},
61 #endif
62     {EXPAND_DIRECTORIES, "dir"},
63     {EXPAND_ENV_VARS, "environment"},
64     {EXPAND_EVENTS, "event"},
65     {EXPAND_EXPRESSION, "expression"},
66     {EXPAND_FILES, "file"},
67     {EXPAND_FILES_IN_PATH, "file_in_path"},
68     {EXPAND_FILETYPE, "filetype"},
69     {EXPAND_FUNCTIONS, "function"},
70     {EXPAND_HELP, "help"},
71     {EXPAND_HIGHLIGHT, "highlight"},
72 #if defined(FEAT_CMDHIST)
73     {EXPAND_HISTORY, "history"},
74 #endif
75 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
76     {EXPAND_LOCALES, "locale"},
77 #endif
78     {EXPAND_MAPCLEAR, "mapclear"},
79     {EXPAND_MAPPINGS, "mapping"},
80     {EXPAND_MENUS, "menu"},
81     {EXPAND_MESSAGES, "messages"},
82     {EXPAND_OWNSYNTAX, "syntax"},
83 #if defined(FEAT_PROFILE)
84     {EXPAND_SYNTIME, "syntime"},
85 #endif
86     {EXPAND_SETTINGS, "option"},
87     {EXPAND_PACKADD, "packadd"},
88     {EXPAND_SHELLCMD, "shellcmd"},
89 #if defined(FEAT_SIGNS)
90     {EXPAND_SIGN, "sign"},
91 #endif
92     {EXPAND_TAGS, "tag"},
93     {EXPAND_TAGS_LISTFILES, "tag_listfiles"},
94     {EXPAND_USER, "user"},
95     {EXPAND_USER_VARS, "var"},
96     {0, NULL}
97 };
98 
99 /*
100  * List of names of address types.  Must be alphabetical for completion.
101  */
102 static struct
103 {
104     cmd_addr_T	expand;
105     char	*name;
106     char	*shortname;
107 } addr_type_complete[] =
108 {
109     {ADDR_ARGUMENTS, "arguments", "arg"},
110     {ADDR_LINES, "lines", "line"},
111     {ADDR_LOADED_BUFFERS, "loaded_buffers", "load"},
112     {ADDR_TABS, "tabs", "tab"},
113     {ADDR_BUFFERS, "buffers", "buf"},
114     {ADDR_WINDOWS, "windows", "win"},
115     {ADDR_QUICKFIX, "quickfix", "qf"},
116     {ADDR_OTHER, "other", "?"},
117     {ADDR_NONE, NULL, NULL}
118 };
119 
120 #define UC_BUFFER	1	// -buffer: local to current buffer
121 
122 /*
123  * Search for a user command that matches "eap->cmd".
124  * Return cmdidx in "eap->cmdidx", flags in "eap->argt", idx in "eap->useridx".
125  * Return a pointer to just after the command.
126  * Return NULL if there is no matching command.
127  */
128     char_u *
129 find_ucmd(
130     exarg_T	*eap,
131     char_u	*p,	// end of the command (possibly including count)
132     int		*full,	// set to TRUE for a full match
133     expand_T	*xp,	// used for completion, NULL otherwise
134     int		*complp UNUSED)	// completion flags or NULL
135 {
136     int		len = (int)(p - eap->cmd);
137     int		j, k, matchlen = 0;
138     ucmd_T	*uc;
139     int		found = FALSE;
140     int		possible = FALSE;
141     char_u	*cp, *np;	    // Point into typed cmd and test name
142     garray_T	*gap;
143     int		amb_local = FALSE;  // Found ambiguous buffer-local command,
144 				    // only full match global is accepted.
145 
146     /*
147      * Look for buffer-local user commands first, then global ones.
148      */
149     gap = &curbuf->b_ucmds;
150     for (;;)
151     {
152 	for (j = 0; j < gap->ga_len; ++j)
153 	{
154 	    uc = USER_CMD_GA(gap, j);
155 	    cp = eap->cmd;
156 	    np = uc->uc_name;
157 	    k = 0;
158 	    while (k < len && *np != NUL && *cp++ == *np++)
159 		k++;
160 	    if (k == len || (*np == NUL && vim_isdigit(eap->cmd[k])))
161 	    {
162 		// If finding a second match, the command is ambiguous.  But
163 		// not if a buffer-local command wasn't a full match and a
164 		// global command is a full match.
165 		if (k == len && found && *np != NUL)
166 		{
167 		    if (gap == &ucmds)
168 			return NULL;
169 		    amb_local = TRUE;
170 		}
171 
172 		if (!found || (k == len && *np == NUL))
173 		{
174 		    // If we matched up to a digit, then there could
175 		    // be another command including the digit that we
176 		    // should use instead.
177 		    if (k == len)
178 			found = TRUE;
179 		    else
180 			possible = TRUE;
181 
182 		    if (gap == &ucmds)
183 			eap->cmdidx = CMD_USER;
184 		    else
185 			eap->cmdidx = CMD_USER_BUF;
186 		    eap->argt = (long)uc->uc_argt;
187 		    eap->useridx = j;
188 		    eap->addr_type = uc->uc_addr_type;
189 
190 # ifdef FEAT_CMDL_COMPL
191 		    if (complp != NULL)
192 			*complp = uc->uc_compl;
193 #  ifdef FEAT_EVAL
194 		    if (xp != NULL)
195 		    {
196 			xp->xp_arg = uc->uc_compl_arg;
197 			xp->xp_script_ctx = uc->uc_script_ctx;
198 			xp->xp_script_ctx.sc_lnum += sourcing_lnum;
199 		    }
200 #  endif
201 # endif
202 		    // Do not search for further abbreviations
203 		    // if this is an exact match.
204 		    matchlen = k;
205 		    if (k == len && *np == NUL)
206 		    {
207 			if (full != NULL)
208 			    *full = TRUE;
209 			amb_local = FALSE;
210 			break;
211 		    }
212 		}
213 	    }
214 	}
215 
216 	// Stop if we found a full match or searched all.
217 	if (j < gap->ga_len || gap == &ucmds)
218 	    break;
219 	gap = &ucmds;
220     }
221 
222     // Only found ambiguous matches.
223     if (amb_local)
224     {
225 	if (xp != NULL)
226 	    xp->xp_context = EXPAND_UNSUCCESSFUL;
227 	return NULL;
228     }
229 
230     // The match we found may be followed immediately by a number.  Move "p"
231     // back to point to it.
232     if (found || possible)
233 	return p + (matchlen - len);
234     return p;
235 }
236 
237 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
238 
239     char_u *
240 set_context_in_user_cmd(expand_T *xp, char_u *arg_in)
241 {
242     char_u	*arg = arg_in;
243     char_u	*p;
244 
245     // Check for attributes
246     while (*arg == '-')
247     {
248 	arg++;	    // Skip "-"
249 	p = skiptowhite(arg);
250 	if (*p == NUL)
251 	{
252 	    // Cursor is still in the attribute
253 	    p = vim_strchr(arg, '=');
254 	    if (p == NULL)
255 	    {
256 		// No "=", so complete attribute names
257 		xp->xp_context = EXPAND_USER_CMD_FLAGS;
258 		xp->xp_pattern = arg;
259 		return NULL;
260 	    }
261 
262 	    // For the -complete, -nargs and -addr attributes, we complete
263 	    // their arguments as well.
264 	    if (STRNICMP(arg, "complete", p - arg) == 0)
265 	    {
266 		xp->xp_context = EXPAND_USER_COMPLETE;
267 		xp->xp_pattern = p + 1;
268 		return NULL;
269 	    }
270 	    else if (STRNICMP(arg, "nargs", p - arg) == 0)
271 	    {
272 		xp->xp_context = EXPAND_USER_NARGS;
273 		xp->xp_pattern = p + 1;
274 		return NULL;
275 	    }
276 	    else if (STRNICMP(arg, "addr", p - arg) == 0)
277 	    {
278 		xp->xp_context = EXPAND_USER_ADDR_TYPE;
279 		xp->xp_pattern = p + 1;
280 		return NULL;
281 	    }
282 	    return NULL;
283 	}
284 	arg = skipwhite(p);
285     }
286 
287     // After the attributes comes the new command name
288     p = skiptowhite(arg);
289     if (*p == NUL)
290     {
291 	xp->xp_context = EXPAND_USER_COMMANDS;
292 	xp->xp_pattern = arg;
293 	return NULL;
294     }
295 
296     // And finally comes a normal command
297     return skipwhite(p);
298 }
299 
300     char_u *
301 get_user_command_name(int idx)
302 {
303     return get_user_commands(NULL, idx - (int)CMD_SIZE);
304 }
305 
306 /*
307  * Function given to ExpandGeneric() to obtain the list of user command names.
308  */
309     char_u *
310 get_user_commands(expand_T *xp UNUSED, int idx)
311 {
312     if (idx < curbuf->b_ucmds.ga_len)
313 	return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name;
314     idx -= curbuf->b_ucmds.ga_len;
315     if (idx < ucmds.ga_len)
316 	return USER_CMD(idx)->uc_name;
317     return NULL;
318 }
319 
320 /*
321  * Function given to ExpandGeneric() to obtain the list of user address type
322  * names.
323  */
324     char_u *
325 get_user_cmd_addr_type(expand_T *xp UNUSED, int idx)
326 {
327     return (char_u *)addr_type_complete[idx].name;
328 }
329 
330 /*
331  * Function given to ExpandGeneric() to obtain the list of user command
332  * attributes.
333  */
334     char_u *
335 get_user_cmd_flags(expand_T *xp UNUSED, int idx)
336 {
337     static char *user_cmd_flags[] = {
338 	"addr", "bang", "bar", "buffer", "complete",
339 	"count", "nargs", "range", "register"
340     };
341 
342     if (idx >= (int)(sizeof(user_cmd_flags) / sizeof(user_cmd_flags[0])))
343 	return NULL;
344     return (char_u *)user_cmd_flags[idx];
345 }
346 
347 /*
348  * Function given to ExpandGeneric() to obtain the list of values for -nargs.
349  */
350     char_u *
351 get_user_cmd_nargs(expand_T *xp UNUSED, int idx)
352 {
353     static char *user_cmd_nargs[] = {"0", "1", "*", "?", "+"};
354 
355     if (idx >= (int)(sizeof(user_cmd_nargs) / sizeof(user_cmd_nargs[0])))
356 	return NULL;
357     return (char_u *)user_cmd_nargs[idx];
358 }
359 
360 /*
361  * Function given to ExpandGeneric() to obtain the list of values for
362  * -complete.
363  */
364     char_u *
365 get_user_cmd_complete(expand_T *xp UNUSED, int idx)
366 {
367     return (char_u *)command_complete[idx].name;
368 }
369 
370     int
371 cmdcomplete_str_to_type(char_u *complete_str)
372 {
373     int i;
374 
375     for (i = 0; command_complete[i].expand != 0; ++i)
376 	if (STRCMP(complete_str, command_complete[i].name) == 0)
377 	    return command_complete[i].expand;
378 
379     return EXPAND_NOTHING;
380 }
381 
382 #endif // FEAT_CMDL_COMPL
383 
384 /*
385  * List user commands starting with "name[name_len]".
386  */
387     static void
388 uc_list(char_u *name, size_t name_len)
389 {
390     int		i, j;
391     int		found = FALSE;
392     ucmd_T	*cmd;
393     int		len;
394     int		over;
395     long	a;
396     garray_T	*gap;
397 
398     gap = &curbuf->b_ucmds;
399     for (;;)
400     {
401 	for (i = 0; i < gap->ga_len; ++i)
402 	{
403 	    cmd = USER_CMD_GA(gap, i);
404 	    a = (long)cmd->uc_argt;
405 
406 	    // Skip commands which don't match the requested prefix and
407 	    // commands filtered out.
408 	    if (STRNCMP(name, cmd->uc_name, name_len) != 0
409 		    || message_filtered(cmd->uc_name))
410 		continue;
411 
412 	    // Put out the title first time
413 	    if (!found)
414 		msg_puts_title(_("\n    Name              Args Address Complete    Definition"));
415 	    found = TRUE;
416 	    msg_putchar('\n');
417 	    if (got_int)
418 		break;
419 
420 	    // Special cases
421 	    len = 4;
422 	    if (a & BANG)
423 	    {
424 		msg_putchar('!');
425 		--len;
426 	    }
427 	    if (a & REGSTR)
428 	    {
429 		msg_putchar('"');
430 		--len;
431 	    }
432 	    if (gap != &ucmds)
433 	    {
434 		msg_putchar('b');
435 		--len;
436 	    }
437 	    if (a & TRLBAR)
438 	    {
439 		msg_putchar('|');
440 		--len;
441 	    }
442 	    while (len-- > 0)
443 		msg_putchar(' ');
444 
445 	    msg_outtrans_attr(cmd->uc_name, HL_ATTR(HLF_D));
446 	    len = (int)STRLEN(cmd->uc_name) + 4;
447 
448 	    do {
449 		msg_putchar(' ');
450 		++len;
451 	    } while (len < 22);
452 
453 	    // "over" is how much longer the name is than the column width for
454 	    // the name, we'll try to align what comes after.
455 	    over = len - 22;
456 	    len = 0;
457 
458 	    // Arguments
459 	    switch ((int)(a & (EXTRA|NOSPC|NEEDARG)))
460 	    {
461 		case 0:			    IObuff[len++] = '0'; break;
462 		case (EXTRA):		    IObuff[len++] = '*'; break;
463 		case (EXTRA|NOSPC):	    IObuff[len++] = '?'; break;
464 		case (EXTRA|NEEDARG):	    IObuff[len++] = '+'; break;
465 		case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break;
466 	    }
467 
468 	    do {
469 		IObuff[len++] = ' ';
470 	    } while (len < 5 - over);
471 
472 	    // Address / Range
473 	    if (a & (RANGE|COUNT))
474 	    {
475 		if (a & COUNT)
476 		{
477 		    // -count=N
478 		    sprintf((char *)IObuff + len, "%ldc", cmd->uc_def);
479 		    len += (int)STRLEN(IObuff + len);
480 		}
481 		else if (a & DFLALL)
482 		    IObuff[len++] = '%';
483 		else if (cmd->uc_def >= 0)
484 		{
485 		    // -range=N
486 		    sprintf((char *)IObuff + len, "%ld", cmd->uc_def);
487 		    len += (int)STRLEN(IObuff + len);
488 		}
489 		else
490 		    IObuff[len++] = '.';
491 	    }
492 
493 	    do {
494 		IObuff[len++] = ' ';
495 	    } while (len < 8 - over);
496 
497 	    // Address Type
498 	    for (j = 0; addr_type_complete[j].expand != ADDR_NONE; ++j)
499 		if (addr_type_complete[j].expand != ADDR_LINES
500 			&& addr_type_complete[j].expand == cmd->uc_addr_type)
501 		{
502 		    STRCPY(IObuff + len, addr_type_complete[j].shortname);
503 		    len += (int)STRLEN(IObuff + len);
504 		    break;
505 		}
506 
507 	    do {
508 		IObuff[len++] = ' ';
509 	    } while (len < 13 - over);
510 
511 	    // Completion
512 	    for (j = 0; command_complete[j].expand != 0; ++j)
513 		if (command_complete[j].expand == cmd->uc_compl)
514 		{
515 		    STRCPY(IObuff + len, command_complete[j].name);
516 		    len += (int)STRLEN(IObuff + len);
517 		    break;
518 		}
519 
520 	    do {
521 		IObuff[len++] = ' ';
522 	    } while (len < 25 - over);
523 
524 	    IObuff[len] = '\0';
525 	    msg_outtrans(IObuff);
526 
527 	    msg_outtrans_special(cmd->uc_rep, FALSE,
528 					     name_len == 0 ? Columns - 47 : 0);
529 #ifdef FEAT_EVAL
530 	    if (p_verbose > 0)
531 		last_set_msg(cmd->uc_script_ctx);
532 #endif
533 	    out_flush();
534 	    ui_breakcheck();
535 	    if (got_int)
536 		break;
537 	}
538 	if (gap == &ucmds || i < gap->ga_len)
539 	    break;
540 	gap = &ucmds;
541     }
542 
543     if (!found)
544 	msg(_("No user-defined commands found"));
545 }
546 
547     char *
548 uc_fun_cmd(void)
549 {
550     static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4,
551 			    0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60,
552 			    0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2,
553 			    0xb9, 0x7f, 0};
554     int		i;
555 
556     for (i = 0; fcmd[i]; ++i)
557 	IObuff[i] = fcmd[i] - 0x40;
558     IObuff[i] = 0;
559     return (char *)IObuff;
560 }
561 
562 /*
563  * Parse address type argument
564  */
565     static int
566 parse_addr_type_arg(
567     char_u	*value,
568     int		vallen,
569     cmd_addr_T	*addr_type_arg)
570 {
571     int	    i, a, b;
572 
573     for (i = 0; addr_type_complete[i].expand != ADDR_NONE; ++i)
574     {
575 	a = (int)STRLEN(addr_type_complete[i].name) == vallen;
576 	b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0;
577 	if (a && b)
578 	{
579 	    *addr_type_arg = addr_type_complete[i].expand;
580 	    break;
581 	}
582     }
583 
584     if (addr_type_complete[i].expand == ADDR_NONE)
585     {
586 	char_u	*err = value;
587 
588 	for (i = 0; err[i] != NUL && !VIM_ISWHITE(err[i]); i++)
589 	    ;
590 	err[i] = NUL;
591 	semsg(_("E180: Invalid address type value: %s"), err);
592 	return FAIL;
593     }
594 
595     return OK;
596 }
597 
598 /*
599  * Parse a completion argument "value[vallen]".
600  * The detected completion goes in "*complp", argument type in "*argt".
601  * When there is an argument, for function and user defined completion, it's
602  * copied to allocated memory and stored in "*compl_arg".
603  * Returns FAIL if something is wrong.
604  */
605     int
606 parse_compl_arg(
607     char_u	*value,
608     int		vallen,
609     int		*complp,
610     long	*argt,
611     char_u	**compl_arg UNUSED)
612 {
613     char_u	*arg = NULL;
614 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
615     size_t	arglen = 0;
616 # endif
617     int		i;
618     int		valend = vallen;
619 
620     // Look for any argument part - which is the part after any ','
621     for (i = 0; i < vallen; ++i)
622     {
623 	if (value[i] == ',')
624 	{
625 	    arg = &value[i + 1];
626 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
627 	    arglen = vallen - i - 1;
628 # endif
629 	    valend = i;
630 	    break;
631 	}
632     }
633 
634     for (i = 0; command_complete[i].expand != 0; ++i)
635     {
636 	if ((int)STRLEN(command_complete[i].name) == valend
637 		&& STRNCMP(value, command_complete[i].name, valend) == 0)
638 	{
639 	    *complp = command_complete[i].expand;
640 	    if (command_complete[i].expand == EXPAND_BUFFERS)
641 		*argt |= BUFNAME;
642 	    else if (command_complete[i].expand == EXPAND_DIRECTORIES
643 		    || command_complete[i].expand == EXPAND_FILES)
644 		*argt |= XFILE;
645 	    break;
646 	}
647     }
648 
649     if (command_complete[i].expand == 0)
650     {
651 	semsg(_("E180: Invalid complete value: %s"), value);
652 	return FAIL;
653     }
654 
655 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
656     if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST
657 							       && arg != NULL)
658 # else
659     if (arg != NULL)
660 # endif
661     {
662 	emsg(_("E468: Completion argument only allowed for custom completion"));
663 	return FAIL;
664     }
665 
666 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
667     if ((*complp == EXPAND_USER_DEFINED || *complp == EXPAND_USER_LIST)
668 							       && arg == NULL)
669     {
670 	emsg(_("E467: Custom completion requires a function argument"));
671 	return FAIL;
672     }
673 
674     if (arg != NULL)
675 	*compl_arg = vim_strnsave(arg, (int)arglen);
676 # endif
677     return OK;
678 }
679 
680 /*
681  * Scan attributes in the ":command" command.
682  * Return FAIL when something is wrong.
683  */
684     static int
685 uc_scan_attr(
686     char_u	*attr,
687     size_t	len,
688     long	*argt,
689     long	*def,
690     int		*flags,
691     int		*complp,
692     char_u	**compl_arg,
693     cmd_addr_T	*addr_type_arg)
694 {
695     char_u	*p;
696 
697     if (len == 0)
698     {
699 	emsg(_("E175: No attribute specified"));
700 	return FAIL;
701     }
702 
703     // First, try the simple attributes (no arguments)
704     if (STRNICMP(attr, "bang", len) == 0)
705 	*argt |= BANG;
706     else if (STRNICMP(attr, "buffer", len) == 0)
707 	*flags |= UC_BUFFER;
708     else if (STRNICMP(attr, "register", len) == 0)
709 	*argt |= REGSTR;
710     else if (STRNICMP(attr, "bar", len) == 0)
711 	*argt |= TRLBAR;
712     else
713     {
714 	int	i;
715 	char_u	*val = NULL;
716 	size_t	vallen = 0;
717 	size_t	attrlen = len;
718 
719 	// Look for the attribute name - which is the part before any '='
720 	for (i = 0; i < (int)len; ++i)
721 	{
722 	    if (attr[i] == '=')
723 	    {
724 		val = &attr[i + 1];
725 		vallen = len - i - 1;
726 		attrlen = i;
727 		break;
728 	    }
729 	}
730 
731 	if (STRNICMP(attr, "nargs", attrlen) == 0)
732 	{
733 	    if (vallen == 1)
734 	    {
735 		if (*val == '0')
736 		    // Do nothing - this is the default
737 		    ;
738 		else if (*val == '1')
739 		    *argt |= (EXTRA | NOSPC | NEEDARG);
740 		else if (*val == '*')
741 		    *argt |= EXTRA;
742 		else if (*val == '?')
743 		    *argt |= (EXTRA | NOSPC);
744 		else if (*val == '+')
745 		    *argt |= (EXTRA | NEEDARG);
746 		else
747 		    goto wrong_nargs;
748 	    }
749 	    else
750 	    {
751 wrong_nargs:
752 		emsg(_("E176: Invalid number of arguments"));
753 		return FAIL;
754 	    }
755 	}
756 	else if (STRNICMP(attr, "range", attrlen) == 0)
757 	{
758 	    *argt |= RANGE;
759 	    if (vallen == 1 && *val == '%')
760 		*argt |= DFLALL;
761 	    else if (val != NULL)
762 	    {
763 		p = val;
764 		if (*def >= 0)
765 		{
766 two_count:
767 		    emsg(_("E177: Count cannot be specified twice"));
768 		    return FAIL;
769 		}
770 
771 		*def = getdigits(&p);
772 		*argt |= ZEROR;
773 
774 		if (p != val + vallen || vallen == 0)
775 		{
776 invalid_count:
777 		    emsg(_("E178: Invalid default value for count"));
778 		    return FAIL;
779 		}
780 	    }
781 	    // default for -range is using buffer lines
782 	    if (*addr_type_arg == ADDR_NONE)
783 		*addr_type_arg = ADDR_LINES;
784 	}
785 	else if (STRNICMP(attr, "count", attrlen) == 0)
786 	{
787 	    *argt |= (COUNT | ZEROR | RANGE);
788 	    // default for -count is using any number
789 	    if (*addr_type_arg == ADDR_NONE)
790 		*addr_type_arg = ADDR_OTHER;
791 
792 	    if (val != NULL)
793 	    {
794 		p = val;
795 		if (*def >= 0)
796 		    goto two_count;
797 
798 		*def = getdigits(&p);
799 
800 		if (p != val + vallen)
801 		    goto invalid_count;
802 	    }
803 
804 	    if (*def < 0)
805 		*def = 0;
806 	}
807 	else if (STRNICMP(attr, "complete", attrlen) == 0)
808 	{
809 	    if (val == NULL)
810 	    {
811 		emsg(_("E179: argument required for -complete"));
812 		return FAIL;
813 	    }
814 
815 	    if (parse_compl_arg(val, (int)vallen, complp, argt, compl_arg)
816 								      == FAIL)
817 		return FAIL;
818 	}
819 	else if (STRNICMP(attr, "addr", attrlen) == 0)
820 	{
821 	    *argt |= RANGE;
822 	    if (val == NULL)
823 	    {
824 		emsg(_("E179: argument required for -addr"));
825 		return FAIL;
826 	    }
827 	    if (parse_addr_type_arg(val, (int)vallen, addr_type_arg) == FAIL)
828 		return FAIL;
829 	    if (*addr_type_arg != ADDR_LINES)
830 		*argt |= ZEROR;
831 	}
832 	else
833 	{
834 	    char_u ch = attr[len];
835 	    attr[len] = '\0';
836 	    semsg(_("E181: Invalid attribute: %s"), attr);
837 	    attr[len] = ch;
838 	    return FAIL;
839 	}
840     }
841 
842     return OK;
843 }
844 
845 /*
846  * Add a user command to the list or replace an existing one.
847  */
848     static int
849 uc_add_command(
850     char_u	*name,
851     size_t	name_len,
852     char_u	*rep,
853     long	argt,
854     long	def,
855     int		flags,
856     int		compl,
857     char_u	*compl_arg UNUSED,
858     cmd_addr_T	addr_type,
859     int		force)
860 {
861     ucmd_T	*cmd = NULL;
862     char_u	*p;
863     int		i;
864     int		cmp = 1;
865     char_u	*rep_buf = NULL;
866     garray_T	*gap;
867 
868     replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE);
869     if (rep_buf == NULL)
870     {
871 	// Can't replace termcodes - try using the string as is
872 	rep_buf = vim_strsave(rep);
873 
874 	// Give up if out of memory
875 	if (rep_buf == NULL)
876 	    return FAIL;
877     }
878 
879     // get address of growarray: global or in curbuf
880     if (flags & UC_BUFFER)
881     {
882 	gap = &curbuf->b_ucmds;
883 	if (gap->ga_itemsize == 0)
884 	    ga_init2(gap, (int)sizeof(ucmd_T), 4);
885     }
886     else
887 	gap = &ucmds;
888 
889     // Search for the command in the already defined commands.
890     for (i = 0; i < gap->ga_len; ++i)
891     {
892 	size_t len;
893 
894 	cmd = USER_CMD_GA(gap, i);
895 	len = STRLEN(cmd->uc_name);
896 	cmp = STRNCMP(name, cmd->uc_name, name_len);
897 	if (cmp == 0)
898 	{
899 	    if (name_len < len)
900 		cmp = -1;
901 	    else if (name_len > len)
902 		cmp = 1;
903 	}
904 
905 	if (cmp == 0)
906 	{
907 	    // Command can be replaced with "command!" and when sourcing the
908 	    // same script again, but only once.
909 	    if (!force
910 #ifdef FEAT_EVAL
911 		    && (cmd->uc_script_ctx.sc_sid != current_sctx.sc_sid
912 			  || cmd->uc_script_ctx.sc_seq == current_sctx.sc_seq)
913 #endif
914 		    )
915 	    {
916 		semsg(_("E174: Command already exists: add ! to replace it: %s"),
917 									 name);
918 		goto fail;
919 	    }
920 
921 	    VIM_CLEAR(cmd->uc_rep);
922 #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
923 	    VIM_CLEAR(cmd->uc_compl_arg);
924 #endif
925 	    break;
926 	}
927 
928 	// Stop as soon as we pass the name to add
929 	if (cmp < 0)
930 	    break;
931     }
932 
933     // Extend the array unless we're replacing an existing command
934     if (cmp != 0)
935     {
936 	if (ga_grow(gap, 1) != OK)
937 	    goto fail;
938 	if ((p = vim_strnsave(name, (int)name_len)) == NULL)
939 	    goto fail;
940 
941 	cmd = USER_CMD_GA(gap, i);
942 	mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
943 
944 	++gap->ga_len;
945 
946 	cmd->uc_name = p;
947     }
948 
949     cmd->uc_rep = rep_buf;
950     cmd->uc_argt = argt;
951     cmd->uc_def = def;
952     cmd->uc_compl = compl;
953 #ifdef FEAT_EVAL
954     cmd->uc_script_ctx = current_sctx;
955     cmd->uc_script_ctx.sc_lnum += sourcing_lnum;
956 # ifdef FEAT_CMDL_COMPL
957     cmd->uc_compl_arg = compl_arg;
958 # endif
959 #endif
960     cmd->uc_addr_type = addr_type;
961 
962     return OK;
963 
964 fail:
965     vim_free(rep_buf);
966 #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
967     vim_free(compl_arg);
968 #endif
969     return FAIL;
970 }
971 
972 /*
973  * ":command ..." implementation
974  */
975     void
976 ex_command(exarg_T *eap)
977 {
978     char_u	*name;
979     char_u	*end;
980     char_u	*p;
981     long	argt = 0;
982     long	def = -1;
983     int		flags = 0;
984     int		compl = EXPAND_NOTHING;
985     char_u	*compl_arg = NULL;
986     cmd_addr_T	addr_type_arg = ADDR_NONE;
987     int		has_attr = (eap->arg[0] == '-');
988     int		name_len;
989 
990     p = eap->arg;
991 
992     // Check for attributes
993     while (*p == '-')
994     {
995 	++p;
996 	end = skiptowhite(p);
997 	if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl,
998 					   &compl_arg, &addr_type_arg) == FAIL)
999 	    return;
1000 	p = skipwhite(end);
1001     }
1002 
1003     // Get the name (if any) and skip to the following argument
1004     name = p;
1005     if (ASCII_ISALPHA(*p))
1006 	while (ASCII_ISALNUM(*p))
1007 	    ++p;
1008     if (!ends_excmd(*p) && !VIM_ISWHITE(*p))
1009     {
1010 	emsg(_("E182: Invalid command name"));
1011 	return;
1012     }
1013     end = p;
1014     name_len = (int)(end - name);
1015 
1016     // If there is nothing after the name, and no attributes were specified,
1017     // we are listing commands
1018     p = skipwhite(end);
1019     if (!has_attr && ends_excmd(*p))
1020     {
1021 	uc_list(name, end - name);
1022     }
1023     else if (!ASCII_ISUPPER(*name))
1024     {
1025 	emsg(_("E183: User defined commands must start with an uppercase letter"));
1026 	return;
1027     }
1028     else if ((name_len == 1 && *name == 'X')
1029 	  || (name_len <= 4
1030 		  && STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0))
1031     {
1032 	emsg(_("E841: Reserved name, cannot be used for user defined command"));
1033 	return;
1034     }
1035     else
1036 	uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
1037 						  addr_type_arg, eap->forceit);
1038 }
1039 
1040 /*
1041  * ":comclear" implementation
1042  * Clear all user commands, global and for current buffer.
1043  */
1044     void
1045 ex_comclear(exarg_T *eap UNUSED)
1046 {
1047     uc_clear(&ucmds);
1048     if (curbuf != NULL)
1049 	uc_clear(&curbuf->b_ucmds);
1050 }
1051 
1052 /*
1053  * Clear all user commands for "gap".
1054  */
1055     void
1056 uc_clear(garray_T *gap)
1057 {
1058     int		i;
1059     ucmd_T	*cmd;
1060 
1061     for (i = 0; i < gap->ga_len; ++i)
1062     {
1063 	cmd = USER_CMD_GA(gap, i);
1064 	vim_free(cmd->uc_name);
1065 	vim_free(cmd->uc_rep);
1066 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
1067 	vim_free(cmd->uc_compl_arg);
1068 # endif
1069     }
1070     ga_clear(gap);
1071 }
1072 
1073 /*
1074  * ":delcommand" implementation
1075  */
1076     void
1077 ex_delcommand(exarg_T *eap)
1078 {
1079     int		i = 0;
1080     ucmd_T	*cmd = NULL;
1081     int		cmp = -1;
1082     garray_T	*gap;
1083 
1084     gap = &curbuf->b_ucmds;
1085     for (;;)
1086     {
1087 	for (i = 0; i < gap->ga_len; ++i)
1088 	{
1089 	    cmd = USER_CMD_GA(gap, i);
1090 	    cmp = STRCMP(eap->arg, cmd->uc_name);
1091 	    if (cmp <= 0)
1092 		break;
1093 	}
1094 	if (gap == &ucmds || cmp == 0)
1095 	    break;
1096 	gap = &ucmds;
1097     }
1098 
1099     if (cmp != 0)
1100     {
1101 	semsg(_("E184: No such user-defined command: %s"), eap->arg);
1102 	return;
1103     }
1104 
1105     vim_free(cmd->uc_name);
1106     vim_free(cmd->uc_rep);
1107 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
1108     vim_free(cmd->uc_compl_arg);
1109 # endif
1110 
1111     --gap->ga_len;
1112 
1113     if (i < gap->ga_len)
1114 	mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
1115 }
1116 
1117 /*
1118  * Split and quote args for <f-args>.
1119  */
1120     static char_u *
1121 uc_split_args(char_u *arg, size_t *lenp)
1122 {
1123     char_u *buf;
1124     char_u *p;
1125     char_u *q;
1126     int len;
1127 
1128     // Precalculate length
1129     p = arg;
1130     len = 2; // Initial and final quotes
1131 
1132     while (*p)
1133     {
1134 	if (p[0] == '\\' && p[1] == '\\')
1135 	{
1136 	    len += 2;
1137 	    p += 2;
1138 	}
1139 	else if (p[0] == '\\' && VIM_ISWHITE(p[1]))
1140 	{
1141 	    len += 1;
1142 	    p += 2;
1143 	}
1144 	else if (*p == '\\' || *p == '"')
1145 	{
1146 	    len += 2;
1147 	    p += 1;
1148 	}
1149 	else if (VIM_ISWHITE(*p))
1150 	{
1151 	    p = skipwhite(p);
1152 	    if (*p == NUL)
1153 		break;
1154 	    len += 3; // ","
1155 	}
1156 	else
1157 	{
1158 	    int charlen = (*mb_ptr2len)(p);
1159 
1160 	    len += charlen;
1161 	    p += charlen;
1162 	}
1163     }
1164 
1165     buf = alloc(len + 1);
1166     if (buf == NULL)
1167     {
1168 	*lenp = 0;
1169 	return buf;
1170     }
1171 
1172     p = arg;
1173     q = buf;
1174     *q++ = '"';
1175     while (*p)
1176     {
1177 	if (p[0] == '\\' && p[1] == '\\')
1178 	{
1179 	    *q++ = '\\';
1180 	    *q++ = '\\';
1181 	    p += 2;
1182 	}
1183 	else if (p[0] == '\\' && VIM_ISWHITE(p[1]))
1184 	{
1185 	    *q++ = p[1];
1186 	    p += 2;
1187 	}
1188 	else if (*p == '\\' || *p == '"')
1189 	{
1190 	    *q++ = '\\';
1191 	    *q++ = *p++;
1192 	}
1193 	else if (VIM_ISWHITE(*p))
1194 	{
1195 	    p = skipwhite(p);
1196 	    if (*p == NUL)
1197 		break;
1198 	    *q++ = '"';
1199 	    *q++ = ',';
1200 	    *q++ = '"';
1201 	}
1202 	else
1203 	{
1204 	    MB_COPY_CHAR(p, q);
1205 	}
1206     }
1207     *q++ = '"';
1208     *q = 0;
1209 
1210     *lenp = len;
1211     return buf;
1212 }
1213 
1214     static size_t
1215 add_cmd_modifier(char_u *buf, char *mod_str, int *multi_mods)
1216 {
1217     size_t result;
1218 
1219     result = STRLEN(mod_str);
1220     if (*multi_mods)
1221 	result += 1;
1222     if (buf != NULL)
1223     {
1224 	if (*multi_mods)
1225 	    STRCAT(buf, " ");
1226 	STRCAT(buf, mod_str);
1227     }
1228 
1229     *multi_mods = 1;
1230 
1231     return result;
1232 }
1233 
1234 /*
1235  * Check for a <> code in a user command.
1236  * "code" points to the '<'.  "len" the length of the <> (inclusive).
1237  * "buf" is where the result is to be added.
1238  * "split_buf" points to a buffer used for splitting, caller should free it.
1239  * "split_len" is the length of what "split_buf" contains.
1240  * Returns the length of the replacement, which has been added to "buf".
1241  * Returns -1 if there was no match, and only the "<" has been copied.
1242  */
1243     static size_t
1244 uc_check_code(
1245     char_u	*code,
1246     size_t	len,
1247     char_u	*buf,
1248     ucmd_T	*cmd,		// the user command we're expanding
1249     exarg_T	*eap,		// ex arguments
1250     char_u	**split_buf,
1251     size_t	*split_len)
1252 {
1253     size_t	result = 0;
1254     char_u	*p = code + 1;
1255     size_t	l = len - 2;
1256     int		quote = 0;
1257     enum {
1258 	ct_ARGS,
1259 	ct_BANG,
1260 	ct_COUNT,
1261 	ct_LINE1,
1262 	ct_LINE2,
1263 	ct_RANGE,
1264 	ct_MODS,
1265 	ct_REGISTER,
1266 	ct_LT,
1267 	ct_NONE
1268     } type = ct_NONE;
1269 
1270     if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
1271     {
1272 	quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
1273 	p += 2;
1274 	l -= 2;
1275     }
1276 
1277     ++l;
1278     if (l <= 1)
1279 	type = ct_NONE;
1280     else if (STRNICMP(p, "args>", l) == 0)
1281 	type = ct_ARGS;
1282     else if (STRNICMP(p, "bang>", l) == 0)
1283 	type = ct_BANG;
1284     else if (STRNICMP(p, "count>", l) == 0)
1285 	type = ct_COUNT;
1286     else if (STRNICMP(p, "line1>", l) == 0)
1287 	type = ct_LINE1;
1288     else if (STRNICMP(p, "line2>", l) == 0)
1289 	type = ct_LINE2;
1290     else if (STRNICMP(p, "range>", l) == 0)
1291 	type = ct_RANGE;
1292     else if (STRNICMP(p, "lt>", l) == 0)
1293 	type = ct_LT;
1294     else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0)
1295 	type = ct_REGISTER;
1296     else if (STRNICMP(p, "mods>", l) == 0)
1297 	type = ct_MODS;
1298 
1299     switch (type)
1300     {
1301     case ct_ARGS:
1302 	// Simple case first
1303 	if (*eap->arg == NUL)
1304 	{
1305 	    if (quote == 1)
1306 	    {
1307 		result = 2;
1308 		if (buf != NULL)
1309 		    STRCPY(buf, "''");
1310 	    }
1311 	    else
1312 		result = 0;
1313 	    break;
1314 	}
1315 
1316 	// When specified there is a single argument don't split it.
1317 	// Works for ":Cmd %" when % is "a b c".
1318 	if ((eap->argt & NOSPC) && quote == 2)
1319 	    quote = 1;
1320 
1321 	switch (quote)
1322 	{
1323 	case 0: // No quoting, no splitting
1324 	    result = STRLEN(eap->arg);
1325 	    if (buf != NULL)
1326 		STRCPY(buf, eap->arg);
1327 	    break;
1328 	case 1: // Quote, but don't split
1329 	    result = STRLEN(eap->arg) + 2;
1330 	    for (p = eap->arg; *p; ++p)
1331 	    {
1332 		if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2)
1333 		    // DBCS can contain \ in a trail byte, skip the
1334 		    // double-byte character.
1335 		    ++p;
1336 		else
1337 		     if (*p == '\\' || *p == '"')
1338 		    ++result;
1339 	    }
1340 
1341 	    if (buf != NULL)
1342 	    {
1343 		*buf++ = '"';
1344 		for (p = eap->arg; *p; ++p)
1345 		{
1346 		    if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2)
1347 			// DBCS can contain \ in a trail byte, copy the
1348 			// double-byte character to avoid escaping.
1349 			*buf++ = *p++;
1350 		    else
1351 			 if (*p == '\\' || *p == '"')
1352 			*buf++ = '\\';
1353 		    *buf++ = *p;
1354 		}
1355 		*buf = '"';
1356 	    }
1357 
1358 	    break;
1359 	case 2: // Quote and split (<f-args>)
1360 	    // This is hard, so only do it once, and cache the result
1361 	    if (*split_buf == NULL)
1362 		*split_buf = uc_split_args(eap->arg, split_len);
1363 
1364 	    result = *split_len;
1365 	    if (buf != NULL && result != 0)
1366 		STRCPY(buf, *split_buf);
1367 
1368 	    break;
1369 	}
1370 	break;
1371 
1372     case ct_BANG:
1373 	result = eap->forceit ? 1 : 0;
1374 	if (quote)
1375 	    result += 2;
1376 	if (buf != NULL)
1377 	{
1378 	    if (quote)
1379 		*buf++ = '"';
1380 	    if (eap->forceit)
1381 		*buf++ = '!';
1382 	    if (quote)
1383 		*buf = '"';
1384 	}
1385 	break;
1386 
1387     case ct_LINE1:
1388     case ct_LINE2:
1389     case ct_RANGE:
1390     case ct_COUNT:
1391     {
1392 	char num_buf[20];
1393 	long num = (type == ct_LINE1) ? eap->line1 :
1394 		   (type == ct_LINE2) ? eap->line2 :
1395 		   (type == ct_RANGE) ? eap->addr_count :
1396 		   (eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
1397 	size_t num_len;
1398 
1399 	sprintf(num_buf, "%ld", num);
1400 	num_len = STRLEN(num_buf);
1401 	result = num_len;
1402 
1403 	if (quote)
1404 	    result += 2;
1405 
1406 	if (buf != NULL)
1407 	{
1408 	    if (quote)
1409 		*buf++ = '"';
1410 	    STRCPY(buf, num_buf);
1411 	    buf += num_len;
1412 	    if (quote)
1413 		*buf = '"';
1414 	}
1415 
1416 	break;
1417     }
1418 
1419     case ct_MODS:
1420     {
1421 	int multi_mods = 0;
1422 	typedef struct {
1423 	    int *varp;
1424 	    char *name;
1425 	} mod_entry_T;
1426 	static mod_entry_T mod_entries[] = {
1427 #ifdef FEAT_BROWSE_CMD
1428 	    {&cmdmod.browse, "browse"},
1429 #endif
1430 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1431 	    {&cmdmod.confirm, "confirm"},
1432 #endif
1433 	    {&cmdmod.hide, "hide"},
1434 	    {&cmdmod.keepalt, "keepalt"},
1435 	    {&cmdmod.keepjumps, "keepjumps"},
1436 	    {&cmdmod.keepmarks, "keepmarks"},
1437 	    {&cmdmod.keeppatterns, "keeppatterns"},
1438 	    {&cmdmod.lockmarks, "lockmarks"},
1439 	    {&cmdmod.noswapfile, "noswapfile"},
1440 	    {NULL, NULL}
1441 	};
1442 	int i;
1443 
1444 	result = quote ? 2 : 0;
1445 	if (buf != NULL)
1446 	{
1447 	    if (quote)
1448 		*buf++ = '"';
1449 	    *buf = '\0';
1450 	}
1451 
1452 	// :aboveleft and :leftabove
1453 	if (cmdmod.split & WSP_ABOVE)
1454 	    result += add_cmd_modifier(buf, "aboveleft", &multi_mods);
1455 	// :belowright and :rightbelow
1456 	if (cmdmod.split & WSP_BELOW)
1457 	    result += add_cmd_modifier(buf, "belowright", &multi_mods);
1458 	// :botright
1459 	if (cmdmod.split & WSP_BOT)
1460 	    result += add_cmd_modifier(buf, "botright", &multi_mods);
1461 
1462 	// the modifiers that are simple flags
1463 	for (i = 0; mod_entries[i].varp != NULL; ++i)
1464 	    if (*mod_entries[i].varp)
1465 		result += add_cmd_modifier(buf, mod_entries[i].name,
1466 								 &multi_mods);
1467 
1468 	// TODO: How to support :noautocmd?
1469 #ifdef HAVE_SANDBOX
1470 	// TODO: How to support :sandbox?
1471 #endif
1472 	// :silent
1473 	if (msg_silent > 0)
1474 	    result += add_cmd_modifier(buf,
1475 		    emsg_silent > 0 ? "silent!" : "silent", &multi_mods);
1476 	// :tab
1477 	if (cmdmod.tab > 0)
1478 	    result += add_cmd_modifier(buf, "tab", &multi_mods);
1479 	// :topleft
1480 	if (cmdmod.split & WSP_TOP)
1481 	    result += add_cmd_modifier(buf, "topleft", &multi_mods);
1482 	// TODO: How to support :unsilent?
1483 	// :verbose
1484 	if (p_verbose > 0)
1485 	    result += add_cmd_modifier(buf, "verbose", &multi_mods);
1486 	// :vertical
1487 	if (cmdmod.split & WSP_VERT)
1488 	    result += add_cmd_modifier(buf, "vertical", &multi_mods);
1489 	if (quote && buf != NULL)
1490 	{
1491 	    buf += result - 2;
1492 	    *buf = '"';
1493 	}
1494 	break;
1495     }
1496 
1497     case ct_REGISTER:
1498 	result = eap->regname ? 1 : 0;
1499 	if (quote)
1500 	    result += 2;
1501 	if (buf != NULL)
1502 	{
1503 	    if (quote)
1504 		*buf++ = '\'';
1505 	    if (eap->regname)
1506 		*buf++ = eap->regname;
1507 	    if (quote)
1508 		*buf = '\'';
1509 	}
1510 	break;
1511 
1512     case ct_LT:
1513 	result = 1;
1514 	if (buf != NULL)
1515 	    *buf = '<';
1516 	break;
1517 
1518     default:
1519 	// Not recognized: just copy the '<' and return -1.
1520 	result = (size_t)-1;
1521 	if (buf != NULL)
1522 	    *buf = '<';
1523 	break;
1524     }
1525 
1526     return result;
1527 }
1528 
1529 /*
1530  * Execute a user defined command.
1531  */
1532     void
1533 do_ucmd(exarg_T *eap)
1534 {
1535     char_u	*buf;
1536     char_u	*p;
1537     char_u	*q;
1538 
1539     char_u	*start;
1540     char_u	*end = NULL;
1541     char_u	*ksp;
1542     size_t	len, totlen;
1543 
1544     size_t	split_len = 0;
1545     char_u	*split_buf = NULL;
1546     ucmd_T	*cmd;
1547 #ifdef FEAT_EVAL
1548     sctx_T	save_current_sctx = current_sctx;
1549 #endif
1550 
1551     if (eap->cmdidx == CMD_USER)
1552 	cmd = USER_CMD(eap->useridx);
1553     else
1554 	cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx);
1555 
1556     /*
1557      * Replace <> in the command by the arguments.
1558      * First round: "buf" is NULL, compute length, allocate "buf".
1559      * Second round: copy result into "buf".
1560      */
1561     buf = NULL;
1562     for (;;)
1563     {
1564 	p = cmd->uc_rep;    // source
1565 	q = buf;	    // destination
1566 	totlen = 0;
1567 
1568 	for (;;)
1569 	{
1570 	    start = vim_strchr(p, '<');
1571 	    if (start != NULL)
1572 		end = vim_strchr(start + 1, '>');
1573 	    if (buf != NULL)
1574 	    {
1575 		for (ksp = p; *ksp != NUL && *ksp != K_SPECIAL; ++ksp)
1576 		    ;
1577 		if (*ksp == K_SPECIAL
1578 			&& (start == NULL || ksp < start || end == NULL)
1579 			&& ((ksp[1] == KS_SPECIAL && ksp[2] == KE_FILLER)
1580 # ifdef FEAT_GUI
1581 			    || (ksp[1] == KS_EXTRA && ksp[2] == (int)KE_CSI)
1582 # endif
1583 			    ))
1584 		{
1585 		    // K_SPECIAL has been put in the buffer as K_SPECIAL
1586 		    // KS_SPECIAL KE_FILLER, like for mappings, but
1587 		    // do_cmdline() doesn't handle that, so convert it back.
1588 		    // Also change K_SPECIAL KS_EXTRA KE_CSI into CSI.
1589 		    len = ksp - p;
1590 		    if (len > 0)
1591 		    {
1592 			mch_memmove(q, p, len);
1593 			q += len;
1594 		    }
1595 		    *q++ = ksp[1] == KS_SPECIAL ? K_SPECIAL : CSI;
1596 		    p = ksp + 3;
1597 		    continue;
1598 		}
1599 	    }
1600 
1601 	    // break if no <item> is found
1602 	    if (start == NULL || end == NULL)
1603 		break;
1604 
1605 	    // Include the '>'
1606 	    ++end;
1607 
1608 	    // Take everything up to the '<'
1609 	    len = start - p;
1610 	    if (buf == NULL)
1611 		totlen += len;
1612 	    else
1613 	    {
1614 		mch_memmove(q, p, len);
1615 		q += len;
1616 	    }
1617 
1618 	    len = uc_check_code(start, end - start, q, cmd, eap,
1619 			     &split_buf, &split_len);
1620 	    if (len == (size_t)-1)
1621 	    {
1622 		// no match, continue after '<'
1623 		p = start + 1;
1624 		len = 1;
1625 	    }
1626 	    else
1627 		p = end;
1628 	    if (buf == NULL)
1629 		totlen += len;
1630 	    else
1631 		q += len;
1632 	}
1633 	if (buf != NULL)	    // second time here, finished
1634 	{
1635 	    STRCPY(q, p);
1636 	    break;
1637 	}
1638 
1639 	totlen += STRLEN(p);	    // Add on the trailing characters
1640 	buf = alloc((unsigned)(totlen + 1));
1641 	if (buf == NULL)
1642 	{
1643 	    vim_free(split_buf);
1644 	    return;
1645 	}
1646     }
1647 
1648 #ifdef FEAT_EVAL
1649     current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
1650 #endif
1651     (void)do_cmdline(buf, eap->getline, eap->cookie,
1652 				   DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
1653 #ifdef FEAT_EVAL
1654     current_sctx = save_current_sctx;
1655 #endif
1656     vim_free(buf);
1657     vim_free(split_buf);
1658 }
1659