mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.0981: Vim9: cannot compile "[var, var] = list"
Problem: Vim9: cannot compile "[var, var] = list". Solution: Implement list assignment.
This commit is contained in:
@@ -1431,7 +1431,7 @@ eval_for_line(
|
|||||||
if (fi == NULL)
|
if (fi == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
expr = skip_var_list(arg, TRUE, &fi->fi_varcount, &fi->fi_semicolon);
|
expr = skip_var_list(arg, TRUE, &fi->fi_varcount, &fi->fi_semicolon, FALSE);
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return fi;
|
return fi;
|
||||||
|
|
||||||
|
@@ -164,7 +164,6 @@ static dict_T vimvardict; // Dictionary with v: variables
|
|||||||
// for VIM_VERSION_ defines
|
// for VIM_VERSION_ defines
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
static char_u *skip_var_one(char_u *arg, int include_type);
|
|
||||||
static void list_glob_vars(int *first);
|
static void list_glob_vars(int *first);
|
||||||
static void list_buf_vars(int *first);
|
static void list_buf_vars(int *first);
|
||||||
static void list_win_vars(int *first);
|
static void list_win_vars(int *first);
|
||||||
@@ -709,7 +708,7 @@ ex_let(exarg_T *eap)
|
|||||||
if (eap->arg == eap->cmd)
|
if (eap->arg == eap->cmd)
|
||||||
flags |= LET_NO_COMMAND;
|
flags |= LET_NO_COMMAND;
|
||||||
|
|
||||||
argend = skip_var_list(arg, TRUE, &var_count, &semicolon);
|
argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
|
||||||
if (argend == NULL)
|
if (argend == NULL)
|
||||||
return;
|
return;
|
||||||
if (argend > arg && argend[-1] == '.') // for var.='str'
|
if (argend > arg && argend[-1] == '.') // for var.='str'
|
||||||
@@ -916,7 +915,8 @@ ex_let_vars(
|
|||||||
* Skip over assignable variable "var" or list of variables "[var, var]".
|
* Skip over assignable variable "var" or list of variables "[var, var]".
|
||||||
* Used for ":let varvar = expr" and ":for varvar in expr".
|
* Used for ":let varvar = expr" and ":for varvar in expr".
|
||||||
* For "[var, var]" increment "*var_count" for each variable.
|
* For "[var, var]" increment "*var_count" for each variable.
|
||||||
* for "[var, var; var]" set "semicolon".
|
* for "[var, var; var]" set "semicolon" to 1.
|
||||||
|
* If "silent" is TRUE do not give an "invalid argument" error message.
|
||||||
* Return NULL for an error.
|
* Return NULL for an error.
|
||||||
*/
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
@@ -924,7 +924,8 @@ skip_var_list(
|
|||||||
char_u *arg,
|
char_u *arg,
|
||||||
int include_type,
|
int include_type,
|
||||||
int *var_count,
|
int *var_count,
|
||||||
int *semicolon)
|
int *semicolon,
|
||||||
|
int silent)
|
||||||
{
|
{
|
||||||
char_u *p, *s;
|
char_u *p, *s;
|
||||||
|
|
||||||
@@ -935,9 +936,10 @@ skip_var_list(
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
p = skipwhite(p + 1); // skip whites after '[', ';' or ','
|
p = skipwhite(p + 1); // skip whites after '[', ';' or ','
|
||||||
s = skip_var_one(p, TRUE);
|
s = skip_var_one(p, FALSE);
|
||||||
if (s == p)
|
if (s == p)
|
||||||
{
|
{
|
||||||
|
if (!silent)
|
||||||
semsg(_(e_invarg2), p);
|
semsg(_(e_invarg2), p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -957,6 +959,7 @@ skip_var_list(
|
|||||||
}
|
}
|
||||||
else if (*p != ',')
|
else if (*p != ',')
|
||||||
{
|
{
|
||||||
|
if (!silent)
|
||||||
semsg(_(e_invarg2), p);
|
semsg(_(e_invarg2), p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -972,7 +975,7 @@ skip_var_list(
|
|||||||
* l[idx].
|
* l[idx].
|
||||||
* In Vim9 script also skip over ": type" if "include_type" is TRUE.
|
* In Vim9 script also skip over ": type" if "include_type" is TRUE.
|
||||||
*/
|
*/
|
||||||
static char_u *
|
char_u *
|
||||||
skip_var_one(char_u *arg, int include_type)
|
skip_var_one(char_u *arg, int include_type)
|
||||||
{
|
{
|
||||||
char_u *end;
|
char_u *end;
|
||||||
@@ -981,9 +984,12 @@ skip_var_one(char_u *arg, int include_type)
|
|||||||
return arg + 2;
|
return arg + 2;
|
||||||
end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
|
end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
|
||||||
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
|
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
|
||||||
if (include_type && current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
if (include_type && current_sctx.sc_version == SCRIPT_VERSION_VIM9)
|
||||||
&& *end == ':')
|
|
||||||
{
|
{
|
||||||
|
// "a: type" is declaring variable "a" with a type, not "a:".
|
||||||
|
if (end == arg + 2 && end[-1] == ':')
|
||||||
|
--end;
|
||||||
|
if (*end == ':')
|
||||||
end = skip_type(skipwhite(end + 1));
|
end = skip_type(skipwhite(end + 1));
|
||||||
}
|
}
|
||||||
return end;
|
return end;
|
||||||
|
@@ -16,7 +16,8 @@ void restore_vimvar(int idx, typval_T *save_tv);
|
|||||||
list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
|
list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
|
||||||
void ex_let(exarg_T *eap);
|
void ex_let(exarg_T *eap);
|
||||||
int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, int var_count, int flags, char_u *op);
|
int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, int var_count, int flags, char_u *op);
|
||||||
char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int *semicolon);
|
char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int *semicolon, int silent);
|
||||||
|
char_u *skip_var_one(char_u *arg, int include_type);
|
||||||
void list_hashtable_vars(hashtab_T *ht, char *prefix, int empty, int *first);
|
void list_hashtable_vars(hashtab_T *ht, char *prefix, int empty, int *first);
|
||||||
void ex_unlet(exarg_T *eap);
|
void ex_unlet(exarg_T *eap);
|
||||||
void ex_lockvar(exarg_T *eap);
|
void ex_lockvar(exarg_T *eap);
|
||||||
|
@@ -223,6 +223,14 @@ def Test_assignment_default()
|
|||||||
assert_equal(5678, nr)
|
assert_equal(5678, nr)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_assignment_var_list()
|
||||||
|
let v1: string
|
||||||
|
let v2: string
|
||||||
|
[v1, v2] = ['one', 'two']
|
||||||
|
assert_equal('one', v1)
|
||||||
|
assert_equal('two', v2)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Mess(): string
|
def Mess(): string
|
||||||
v:foldstart = 123
|
v:foldstart = 123
|
||||||
return 'xxx'
|
return 'xxx'
|
||||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
981,
|
||||||
/**/
|
/**/
|
||||||
980,
|
980,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -112,6 +112,7 @@ typedef enum {
|
|||||||
// expression operations
|
// expression operations
|
||||||
ISN_CONCAT,
|
ISN_CONCAT,
|
||||||
ISN_INDEX, // [expr] list index
|
ISN_INDEX, // [expr] list index
|
||||||
|
ISN_GETITEM, // push list item, isn_arg.number is the index
|
||||||
ISN_MEMBER, // dict[member]
|
ISN_MEMBER, // dict[member]
|
||||||
ISN_STRINGMEMBER, // dict.member using isn_arg.string
|
ISN_STRINGMEMBER, // dict.member using isn_arg.string
|
||||||
ISN_2BOOL, // convert value to bool, invert if isn_arg.number != 0
|
ISN_2BOOL, // convert value to bool, invert if isn_arg.number != 0
|
||||||
|
@@ -136,6 +136,7 @@ struct cctx_S {
|
|||||||
static char e_var_notfound[] = N_("E1001: variable not found: %s");
|
static char e_var_notfound[] = N_("E1001: variable not found: %s");
|
||||||
static char e_syntax_at[] = N_("E1002: Syntax error at %s");
|
static char e_syntax_at[] = N_("E1002: Syntax error at %s");
|
||||||
static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
|
static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
|
||||||
|
static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
|
||||||
|
|
||||||
static void delete_def_function_contents(dfunc_T *dfunc);
|
static void delete_def_function_contents(dfunc_T *dfunc);
|
||||||
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
|
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
|
||||||
@@ -1052,6 +1053,38 @@ generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate an ISN_GETITEM instruction with "index".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
generate_GETITEM(cctx_T *cctx, int index)
|
||||||
|
{
|
||||||
|
isn_T *isn;
|
||||||
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
|
type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
|
type_T *item_type = &t_any;
|
||||||
|
|
||||||
|
RETURN_OK_IF_SKIP(cctx);
|
||||||
|
|
||||||
|
if (type->tt_type == VAR_LIST)
|
||||||
|
item_type = type->tt_member;
|
||||||
|
else if (type->tt_type != VAR_ANY)
|
||||||
|
{
|
||||||
|
emsg(_(e_listreq));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
|
||||||
|
return FAIL;
|
||||||
|
isn->isn_arg.number = index;
|
||||||
|
|
||||||
|
// add the item type to the type stack
|
||||||
|
if (ga_grow(stack, 1) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
((type_T **)stack->ga_data)[stack->ga_len] = item_type;
|
||||||
|
++stack->ga_len;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate an ISN_STORE instruction.
|
* Generate an ISN_STORE instruction.
|
||||||
*/
|
*/
|
||||||
@@ -4573,67 +4606,157 @@ generate_loadvar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* compile "let var [= expr]", "const var = expr" and "var = expr"
|
* Compile declaration and assignment:
|
||||||
|
* "let var", "let var = expr", "const var = expr" and "var = expr"
|
||||||
* "arg" points to "var".
|
* "arg" points to "var".
|
||||||
|
* Return NULL for an error.
|
||||||
|
* Return "arg" if it does not look like a variable list.
|
||||||
*/
|
*/
|
||||||
static char_u *
|
static char_u *
|
||||||
compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
char_u *var_end;
|
char_u *var_start;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
char_u *end = arg;
|
char_u *end = arg;
|
||||||
char_u *ret = NULL;
|
char_u *ret = NULL;
|
||||||
int var_count = 0;
|
int var_count = 0;
|
||||||
|
int var_idx;
|
||||||
int semicolon = 0;
|
int semicolon = 0;
|
||||||
size_t varlen;
|
|
||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
garray_T *stack = &cctx->ctx_type_stack;
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
int new_local = FALSE;
|
|
||||||
char_u *op;
|
char_u *op;
|
||||||
int opt_type;
|
|
||||||
assign_dest_T dest = dest_local;
|
|
||||||
int opt_flags = 0;
|
|
||||||
int vimvaridx = -1;
|
|
||||||
int oplen = 0;
|
int oplen = 0;
|
||||||
int heredoc = FALSE;
|
int heredoc = FALSE;
|
||||||
type_T *type = &t_any;
|
type_T *type = &t_any;
|
||||||
type_T *member_type = &t_any;
|
type_T *member_type = &t_any;
|
||||||
lvar_T *lvar = NULL;
|
char_u *name = NULL;
|
||||||
lvar_T arg_lvar;
|
|
||||||
char_u *name;
|
|
||||||
char_u *sp;
|
char_u *sp;
|
||||||
int has_type = FALSE;
|
|
||||||
int has_index = FALSE;
|
|
||||||
int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
|
int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
|
||||||
int instr_count = -1;
|
|
||||||
|
|
||||||
var_end = skip_var_list(arg, FALSE, &var_count, &semicolon);
|
// Skip over the "var" or "[var, var]" to get to any "=".
|
||||||
if (var_end == NULL)
|
p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
|
||||||
return NULL;
|
if (p == NULL)
|
||||||
if (var_count > 0)
|
return *arg == '[' ? arg : NULL;
|
||||||
|
|
||||||
|
if (var_count > 0 && is_decl)
|
||||||
{
|
{
|
||||||
// TODO: let [var, var] = list
|
emsg(_("E1092: Cannot use a list for a declaration"));
|
||||||
emsg("Cannot handle a list yet");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = (*arg == '&' || *arg == '$' || *arg == '@') ? arg + 1 : arg;
|
sp = p;
|
||||||
p = to_name_end(p, TRUE);
|
p = skipwhite(p);
|
||||||
|
op = p;
|
||||||
|
oplen = assignment_len(p, &heredoc);
|
||||||
|
|
||||||
// "a: type" is declaring variable "a" with a type, not "a:".
|
if (var_count > 0 && oplen == 0)
|
||||||
if (is_decl && var_end == arg + 2 && var_end[-1] == ':')
|
// can be something like "[1, 2]->func()"
|
||||||
--var_end;
|
return arg;
|
||||||
if (is_decl && p == arg + 2 && p[-1] == ':')
|
|
||||||
--p;
|
|
||||||
|
|
||||||
varlen = p - arg;
|
if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
|
||||||
name = vim_strnsave(arg, varlen);
|
{
|
||||||
if (name == NULL)
|
char_u buf[4];
|
||||||
|
|
||||||
|
vim_strncpy(buf, op, oplen);
|
||||||
|
semsg(_(e_white_both), buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heredoc)
|
||||||
|
{
|
||||||
|
list_T *l;
|
||||||
|
listitem_T *li;
|
||||||
|
|
||||||
|
// [let] varname =<< [trim] {end}
|
||||||
|
eap->getline = exarg_getline;
|
||||||
|
eap->cookie = cctx;
|
||||||
|
l = heredoc_get(eap, op + 3, FALSE);
|
||||||
|
|
||||||
|
// Push each line and the create the list.
|
||||||
|
FOR_ALL_LIST_ITEMS(l, li)
|
||||||
|
{
|
||||||
|
generate_PUSHS(cctx, li->li_tv.vval.v_string);
|
||||||
|
li->li_tv.vval.v_string = NULL;
|
||||||
|
}
|
||||||
|
generate_NEWLIST(cctx, l->lv_len);
|
||||||
|
type = &t_list_string;
|
||||||
|
member_type = &t_list_string;
|
||||||
|
list_free(l);
|
||||||
|
p += STRLEN(p);
|
||||||
|
end = p;
|
||||||
|
}
|
||||||
|
else if (var_count > 0)
|
||||||
|
{
|
||||||
|
// for "[var, var] = expr" evaluate the expression here, loop over the
|
||||||
|
// list of variables below.
|
||||||
|
|
||||||
|
p = skipwhite(op + oplen);
|
||||||
|
if (compile_expr0(&p, cctx) == FAIL)
|
||||||
|
return NULL;
|
||||||
|
end = p;
|
||||||
|
|
||||||
if (cctx->ctx_skip != TRUE)
|
if (cctx->ctx_skip != TRUE)
|
||||||
{
|
{
|
||||||
if (*arg == '&')
|
type_T *stacktype;
|
||||||
|
|
||||||
|
stacktype = stack->ga_len == 0 ? &t_void
|
||||||
|
: ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
|
if (stacktype->tt_type == VAR_VOID)
|
||||||
|
{
|
||||||
|
emsg(_(e_cannot_use_void));
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
if (need_type(stacktype, &t_list_any, -1, cctx) == FAIL)
|
||||||
|
goto theend;
|
||||||
|
// TODO: check length of list to be var_count (or more if
|
||||||
|
// "semicolon" set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop over variables in "[var, var] = expr".
|
||||||
|
* For "var = expr" and "let var: type" this is done only once.
|
||||||
|
*/
|
||||||
|
if (var_count > 0)
|
||||||
|
var_start = skipwhite(arg + 1); // skip over the "["
|
||||||
|
else
|
||||||
|
var_start = arg;
|
||||||
|
for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
|
||||||
|
{
|
||||||
|
char_u *var_end = skip_var_one(var_start, FALSE);
|
||||||
|
size_t varlen;
|
||||||
|
int new_local = FALSE;
|
||||||
|
int opt_type;
|
||||||
|
int opt_flags = 0;
|
||||||
|
assign_dest_T dest = dest_local;
|
||||||
|
int vimvaridx = -1;
|
||||||
|
lvar_T *lvar = NULL;
|
||||||
|
lvar_T arg_lvar;
|
||||||
|
int has_type = FALSE;
|
||||||
|
int has_index = FALSE;
|
||||||
|
int instr_count = -1;
|
||||||
|
|
||||||
|
p = (*var_start == '&' || *var_start == '$'
|
||||||
|
|| *var_start == '@') ? var_start + 1 : var_start;
|
||||||
|
p = to_name_end(p, TRUE);
|
||||||
|
|
||||||
|
// "a: type" is declaring variable "a" with a type, not "a:".
|
||||||
|
if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
|
||||||
|
--var_end;
|
||||||
|
if (is_decl && p == var_start + 2 && p[-1] == ':')
|
||||||
|
--p;
|
||||||
|
|
||||||
|
varlen = p - var_start;
|
||||||
|
vim_free(name);
|
||||||
|
name = vim_strnsave(var_start, varlen);
|
||||||
|
if (name == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (!heredoc)
|
||||||
|
type = &t_any;
|
||||||
|
|
||||||
|
if (cctx->ctx_skip != TRUE)
|
||||||
|
{
|
||||||
|
if (*var_start == '&')
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
long numval;
|
long numval;
|
||||||
@@ -4646,10 +4769,10 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
{
|
{
|
||||||
semsg(_("E1052: Cannot declare an option: %s"), arg);
|
semsg(_("E1052: Cannot declare an option: %s"), var_start);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
p = arg;
|
p = var_start;
|
||||||
p = find_option_end(&p, &opt_flags);
|
p = find_option_end(&p, &opt_flags);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
@@ -4659,11 +4782,12 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
cc = *p;
|
cc = *p;
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
|
opt_type = get_option_value(var_start + 1, &numval,
|
||||||
|
NULL, opt_flags);
|
||||||
*p = cc;
|
*p = cc;
|
||||||
if (opt_type == -3)
|
if (opt_type == -3)
|
||||||
{
|
{
|
||||||
semsg(_(e_unknown_option), arg);
|
semsg(_(e_unknown_option), var_start);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
if (opt_type == -2 || opt_type == 0)
|
if (opt_type == -2 || opt_type == 0)
|
||||||
@@ -4671,7 +4795,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
else
|
else
|
||||||
type = &t_number; // both number and boolean option
|
type = &t_number; // both number and boolean option
|
||||||
}
|
}
|
||||||
else if (*arg == '$')
|
else if (*var_start == '$')
|
||||||
{
|
{
|
||||||
dest = dest_env;
|
dest = dest_env;
|
||||||
type = &t_string;
|
type = &t_string;
|
||||||
@@ -4682,11 +4806,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*arg == '@')
|
else if (*var_start == '@')
|
||||||
{
|
{
|
||||||
if (!valid_yank_reg(arg[1], TRUE))
|
if (!valid_yank_reg(var_start[1], TRUE))
|
||||||
{
|
{
|
||||||
emsg_invreg(arg[1]);
|
emsg_invreg(var_start[1]);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
dest = dest_reg;
|
dest = dest_reg;
|
||||||
@@ -4697,34 +4821,37 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(arg, "g:", 2) == 0)
|
else if (STRNCMP(var_start, "g:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_global;
|
dest = dest_global;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
{
|
{
|
||||||
semsg(_("E1016: Cannot declare a global variable: %s"), name);
|
semsg(_("E1016: Cannot declare a global variable: %s"),
|
||||||
|
name);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(arg, "b:", 2) == 0)
|
else if (STRNCMP(var_start, "b:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_buffer;
|
dest = dest_buffer;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
{
|
{
|
||||||
semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
|
semsg(_("E1078: Cannot declare a buffer variable: %s"),
|
||||||
|
name);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(arg, "w:", 2) == 0)
|
else if (STRNCMP(var_start, "w:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_window;
|
dest = dest_window;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
{
|
{
|
||||||
semsg(_("E1079: Cannot declare a window variable: %s"), name);
|
semsg(_("E1079: Cannot declare a window variable: %s"),
|
||||||
|
name);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(arg, "t:", 2) == 0)
|
else if (STRNCMP(var_start, "t:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_tab;
|
dest = dest_tab;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@@ -4733,7 +4860,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(arg, "v:", 2) == 0)
|
else if (STRNCMP(var_start, "v:", 2) == 0)
|
||||||
{
|
{
|
||||||
typval_T *vtv;
|
typval_T *vtv;
|
||||||
int di_flags;
|
int di_flags;
|
||||||
@@ -4741,7 +4868,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
vimvaridx = find_vim_var(name + 2, &di_flags);
|
vimvaridx = find_vim_var(name + 2, &di_flags);
|
||||||
if (vimvaridx < 0)
|
if (vimvaridx < 0)
|
||||||
{
|
{
|
||||||
semsg(_(e_var_notfound), arg);
|
semsg(_(e_var_notfound), var_start);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
// We use the current value of "sandbox" here, is that OK?
|
// We use the current value of "sandbox" here, is that OK?
|
||||||
@@ -4767,11 +4894,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
lvar = lookup_local(arg, varlen, cctx);
|
lvar = lookup_local(var_start, varlen, cctx);
|
||||||
if (lvar == NULL)
|
if (lvar == NULL)
|
||||||
{
|
{
|
||||||
CLEAR_FIELD(arg_lvar);
|
CLEAR_FIELD(arg_lvar);
|
||||||
if (lookup_arg(arg, varlen,
|
if (lookup_arg(var_start, varlen,
|
||||||
&arg_lvar.lv_idx, &arg_lvar.lv_type,
|
&arg_lvar.lv_idx, &arg_lvar.lv_type,
|
||||||
&arg_lvar.lv_from_outer, cctx) == OK)
|
&arg_lvar.lv_from_outer, cctx) == OK)
|
||||||
{
|
{
|
||||||
@@ -4792,13 +4919,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
else if (lvar->lv_const)
|
else if (lvar->lv_const)
|
||||||
{
|
{
|
||||||
semsg(_("E1018: Cannot assign to a constant: %s"), name);
|
semsg(_("E1018: Cannot assign to a constant: %s"),
|
||||||
|
name);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(arg, "s:", 2) == 0
|
else if (STRNCMP(var_start, "s:", 2) == 0
|
||||||
|| lookup_script(arg, varlen) == OK
|
|| lookup_script(var_start, varlen) == OK
|
||||||
|| find_imported(arg, varlen, cctx) != NULL)
|
|| find_imported(var_start, varlen, cctx) != NULL)
|
||||||
{
|
{
|
||||||
dest = dest_script;
|
dest = dest_script;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@@ -4810,7 +4938,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
else if (name[1] == ':' && name[2] != NUL)
|
else if (name[1] == ':' && name[2] != NUL)
|
||||||
{
|
{
|
||||||
semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
|
semsg(_("E1082: Cannot use a namespaced variable: %s"),
|
||||||
|
name);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
else if (!is_decl)
|
else if (!is_decl)
|
||||||
@@ -4822,7 +4951,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle "a:name" as a name, not index "name" on "a"
|
// handle "a:name" as a name, not index "name" on "a"
|
||||||
if (varlen > 1 || arg[varlen] != ':')
|
if (varlen > 1 || var_start[varlen] != ':')
|
||||||
p = var_end;
|
p = var_end;
|
||||||
|
|
||||||
if (dest != dest_option)
|
if (dest != dest_option)
|
||||||
@@ -4843,20 +4972,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
type = lvar->lv_type;
|
type = lvar->lv_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp = p;
|
|
||||||
p = skipwhite(p);
|
|
||||||
op = p;
|
|
||||||
oplen = assignment_len(p, &heredoc);
|
|
||||||
if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
|
|
||||||
{
|
|
||||||
char_u buf[4];
|
|
||||||
|
|
||||||
vim_strncpy(buf, op, oplen);
|
|
||||||
semsg(_(e_white_both), buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oplen == 3 && !heredoc && dest != dest_global
|
if (oplen == 3 && !heredoc && dest != dest_global
|
||||||
&& type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
|
&& type->tt_type != VAR_STRING
|
||||||
|
&& type->tt_type != VAR_ANY)
|
||||||
{
|
{
|
||||||
emsg(_("E1019: Can only concatenate to string"));
|
emsg(_("E1019: Can only concatenate to string"));
|
||||||
goto theend;
|
goto theend;
|
||||||
@@ -4875,14 +4993,15 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
// new local variable
|
// new local variable
|
||||||
if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
|
if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
|
||||||
goto theend;
|
goto theend;
|
||||||
lvar = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
|
lvar = reserve_local(cctx, var_start, varlen,
|
||||||
|
cmdidx == CMD_const, type);
|
||||||
if (lvar == NULL)
|
if (lvar == NULL)
|
||||||
goto theend;
|
goto theend;
|
||||||
new_local = TRUE;
|
new_local = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
member_type = type;
|
member_type = type;
|
||||||
if (var_end > arg + varlen)
|
if (var_end > var_start + varlen)
|
||||||
{
|
{
|
||||||
// Something follows after the variable: "var[idx]".
|
// Something follows after the variable: "var[idx]".
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@@ -4891,7 +5010,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg[varlen] == '[')
|
if (var_start[varlen] == '[')
|
||||||
{
|
{
|
||||||
has_index = TRUE;
|
has_index = TRUE;
|
||||||
if (type->tt_member == NULL)
|
if (type->tt_member == NULL)
|
||||||
@@ -4903,7 +5022,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
semsg("Not supported yet: %s", arg);
|
semsg("Not supported yet: %s", var_start);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4913,29 +5032,12 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (heredoc)
|
if (!heredoc)
|
||||||
{
|
{
|
||||||
list_T *l;
|
if (oplen > 0)
|
||||||
listitem_T *li;
|
|
||||||
|
|
||||||
// [let] varname =<< [trim] {end}
|
|
||||||
eap->getline = exarg_getline;
|
|
||||||
eap->cookie = cctx;
|
|
||||||
l = heredoc_get(eap, op + 3, FALSE);
|
|
||||||
|
|
||||||
// Push each line and the create the list.
|
|
||||||
FOR_ALL_LIST_ITEMS(l, li)
|
|
||||||
{
|
{
|
||||||
generate_PUSHS(cctx, li->li_tv.vval.v_string);
|
// For "var = expr" evaluate the expression.
|
||||||
li->li_tv.vval.v_string = NULL;
|
if (var_count == 0)
|
||||||
}
|
|
||||||
generate_NEWLIST(cctx, l->lv_len);
|
|
||||||
type = &t_list_string;
|
|
||||||
member_type = &t_list_string;
|
|
||||||
list_free(l);
|
|
||||||
p += STRLEN(p);
|
|
||||||
}
|
|
||||||
else if (oplen > 0)
|
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@@ -4952,17 +5054,25 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile the expression. Temporarily hide the new local variable
|
// Compile the expression. Temporarily hide the new local
|
||||||
// here, it is not available to this expression.
|
// variable here, it is not available to this expression.
|
||||||
if (new_local)
|
if (new_local)
|
||||||
--cctx->ctx_locals.ga_len;
|
--cctx->ctx_locals.ga_len;
|
||||||
instr_count = instr->ga_len;
|
instr_count = instr->ga_len;
|
||||||
p = skipwhite(p + oplen);
|
p = skipwhite(op + oplen);
|
||||||
r = compile_expr0(&p, cctx);
|
r = compile_expr0(&p, cctx);
|
||||||
if (new_local)
|
if (new_local)
|
||||||
++cctx->ctx_locals.ga_len;
|
++cctx->ctx_locals.ga_len;
|
||||||
if (r == FAIL)
|
if (r == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For "[var, var] = expr" get the "var_idx" item from the
|
||||||
|
// list.
|
||||||
|
if (generate_GETITEM(cctx, var_idx) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (cctx->ctx_skip != TRUE)
|
if (cctx->ctx_skip != TRUE)
|
||||||
{
|
{
|
||||||
@@ -4976,13 +5086,13 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
{
|
{
|
||||||
if (stacktype->tt_type == VAR_VOID)
|
if (stacktype->tt_type == VAR_VOID)
|
||||||
{
|
{
|
||||||
emsg(_("E1031: Cannot use void value"));
|
emsg(_(e_cannot_use_void));
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// An empty list or dict has a &t_void member, for a
|
// An empty list or dict has a &t_void member,
|
||||||
// variable that implies &t_any.
|
// for a variable that implies &t_any.
|
||||||
if (stacktype == &t_list_empty)
|
if (stacktype == &t_list_empty)
|
||||||
lvar->lv_type = &t_list_any;
|
lvar->lv_type = &t_list_any;
|
||||||
else if (stacktype == &t_dict_empty)
|
else if (stacktype == &t_dict_empty)
|
||||||
@@ -5001,7 +5111,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
if (use_type == NULL)
|
if (use_type == NULL)
|
||||||
use_type = &t_void;
|
use_type = &t_void;
|
||||||
}
|
}
|
||||||
if (need_type(stacktype, use_type, -1, cctx) == FAIL)
|
if (need_type(stacktype, use_type, -1, cctx)
|
||||||
|
== FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5066,7 +5177,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (var_count == 0)
|
||||||
end = p;
|
end = p;
|
||||||
|
}
|
||||||
|
|
||||||
if (oplen > 0 && *op != '=')
|
if (oplen > 0 && *op != '=')
|
||||||
{
|
{
|
||||||
@@ -5107,7 +5220,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
// Compile the "idx" in "var[idx]".
|
// Compile the "idx" in "var[idx]".
|
||||||
if (new_local)
|
if (new_local)
|
||||||
--cctx->ctx_locals.ga_len;
|
--cctx->ctx_locals.ga_len;
|
||||||
p = skipwhite(arg + varlen + 1);
|
p = skipwhite(var_start + varlen + 1);
|
||||||
r = compile_expr0(&p, cctx);
|
r = compile_expr0(&p, cctx);
|
||||||
if (new_local)
|
if (new_local)
|
||||||
++cctx->ctx_locals.ga_len;
|
++cctx->ctx_locals.ga_len;
|
||||||
@@ -5212,7 +5325,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
if (name_s == NULL)
|
if (name_s == NULL)
|
||||||
name_s = name;
|
name_s = name;
|
||||||
else
|
else
|
||||||
vim_snprintf((char *)name_s, len, "s:%s", name);
|
vim_snprintf((char *)name_s, len,
|
||||||
|
"s:%s", name);
|
||||||
}
|
}
|
||||||
generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid,
|
generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid,
|
||||||
&t_any);
|
&t_any);
|
||||||
@@ -5227,11 +5341,13 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
case dest_local:
|
case dest_local:
|
||||||
if (lvar != NULL)
|
if (lvar != NULL)
|
||||||
{
|
{
|
||||||
isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
|
isn_T *isn = ((isn_T *)instr->ga_data)
|
||||||
|
+ instr->ga_len - 1;
|
||||||
|
|
||||||
// optimization: turn "var = 123" from ISN_PUSHNR +
|
// optimization: turn "var = 123" from ISN_PUSHNR +
|
||||||
// ISN_STORE into ISN_STORENR
|
// ISN_STORE into ISN_STORENR
|
||||||
if (!lvar->lv_from_outer && instr->ga_len == instr_count + 1
|
if (!lvar->lv_from_outer
|
||||||
|
&& instr->ga_len == instr_count + 1
|
||||||
&& isn->isn_type == ISN_PUSHNR)
|
&& isn->isn_type == ISN_PUSHNR)
|
||||||
{
|
{
|
||||||
varnumber_T val = isn->isn_arg.number;
|
varnumber_T val = isn->isn_arg.number;
|
||||||
@@ -5251,6 +5367,15 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (var_idx + 1 < var_count)
|
||||||
|
var_start = skipwhite(var_end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for "[var, var] = expr" drop the "expr" value
|
||||||
|
if (var_count > 0 && generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
|
||||||
|
goto theend;
|
||||||
|
|
||||||
ret = end;
|
ret = end;
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
@@ -6575,12 +6700,22 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
|||||||
|| find_imported(ea.cmd, len, &cctx) != NULL)
|
|| find_imported(ea.cmd, len, &cctx) != NULL)
|
||||||
{
|
{
|
||||||
line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
|
line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
|
||||||
if (line == NULL)
|
if (line == NULL || line == ea.cmd)
|
||||||
goto erret;
|
goto erret;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*ea.cmd == '[')
|
||||||
|
{
|
||||||
|
// [var, var] = expr
|
||||||
|
line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
|
||||||
|
if (line == NULL)
|
||||||
|
goto erret;
|
||||||
|
if (line != ea.cmd)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -6646,6 +6781,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
|||||||
case CMD_let:
|
case CMD_let:
|
||||||
case CMD_const:
|
case CMD_const:
|
||||||
line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
|
line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
|
||||||
|
if (line == p)
|
||||||
|
line = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_unlet:
|
case CMD_unlet:
|
||||||
@@ -6957,6 +7094,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_EXECUTE:
|
case ISN_EXECUTE:
|
||||||
case ISN_FOR:
|
case ISN_FOR:
|
||||||
case ISN_INDEX:
|
case ISN_INDEX:
|
||||||
|
case ISN_GETITEM:
|
||||||
case ISN_MEMBER:
|
case ISN_MEMBER:
|
||||||
case ISN_JUMP:
|
case ISN_JUMP:
|
||||||
case ISN_LOAD:
|
case ISN_LOAD:
|
||||||
|
@@ -2114,6 +2114,31 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_GETITEM:
|
||||||
|
{
|
||||||
|
listitem_T *li;
|
||||||
|
int index = iptr->isn_arg.number;
|
||||||
|
|
||||||
|
// get list item: list is at stack-1, push item
|
||||||
|
tv = STACK_TV_BOT(-1);
|
||||||
|
if (tv->v_type != VAR_LIST)
|
||||||
|
{
|
||||||
|
emsg(_(e_listreq));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if ((li = list_find(tv->vval.v_list, index)) == NULL)
|
||||||
|
{
|
||||||
|
semsg(_(e_listidx), index);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
|
||||||
|
goto failed;
|
||||||
|
++ectx.ec_stack.ga_len;
|
||||||
|
copy_tv(&li->li_tv, STACK_TV_BOT(-1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_MEMBER:
|
case ISN_MEMBER:
|
||||||
{
|
{
|
||||||
dict_T *dict;
|
dict_T *dict;
|
||||||
@@ -2789,6 +2814,8 @@ ex_disassemble(exarg_T *eap)
|
|||||||
// expression operations
|
// expression operations
|
||||||
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
||||||
case ISN_INDEX: smsg("%4d INDEX", current); break;
|
case ISN_INDEX: smsg("%4d INDEX", current); break;
|
||||||
|
case ISN_GETITEM: smsg("%4d ITEM %lld",
|
||||||
|
current, iptr->isn_arg.number); break;
|
||||||
case ISN_MEMBER: smsg("%4d MEMBER", current); break;
|
case ISN_MEMBER: smsg("%4d MEMBER", current); break;
|
||||||
case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current,
|
case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current,
|
||||||
iptr->isn_arg.string); break;
|
iptr->isn_arg.string); break;
|
||||||
|
Reference in New Issue
Block a user