summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-02-02 23:11:38 +0000
committerBram Moolenaar <Bram@vim.org>2005-02-02 23:11:38 +0000
commit758711c5dc0cbbcc8499214a3743f0d6b17fbe27 (patch)
tree65b70ff12ddee792b9a915670517e44e8ff310d0 /src
parentf583668da17052a7b9ff4cc4fc248f295313d86f (diff)
updated for version 7.0047v7.0047
Diffstat (limited to 'src')
-rw-r--r--src/eval.c253
-rw-r--r--src/ex_cmds.c2
-rw-r--r--src/ex_cmds.h4
3 files changed, 157 insertions, 102 deletions
diff --git a/src/eval.c b/src/eval.c
index a5a076f50c..8a6904b473 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -330,7 +330,6 @@ static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
static int string_isa_number __ARGS((char_u *s));
static listitem_T *list_find __ARGS((list_T *l, long n));
static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
-static listitem_T *list_find_ext __ARGS((list_T *l, long *ip));
static void list_append __ARGS((list_T *l, listitem_T *item));
static int list_append_tv __ARGS((list_T *l, typval_T *tv));
static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
@@ -1058,8 +1057,7 @@ eval_foldexpr(arg, cp)
/* If the result is a number, just return the number. */
if (tv.v_type == VAR_NUMBER)
retval = tv.vval.v_number;
- else if (tv.v_type == VAR_UNKNOWN
- || tv.vval.v_string == NULL)
+ else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
retval = 0;
else
{
@@ -1257,8 +1255,7 @@ ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
/*
* ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
*/
- l = tv->vval.v_list;
- if (tv->v_type != VAR_LIST || l == NULL)
+ if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
{
EMSG(_(e_listreq));
return FAIL;
@@ -2211,6 +2208,7 @@ set_var_lval(lp, endp, rettv, copy, op)
else
{
*lp->ll_tv = *rettv;
+ lp->ll_tv->v_lock = 0;
init_tv(rettv);
}
}
@@ -2293,7 +2291,7 @@ list_add_watch(l, lw)
}
/*
- * Remove a watches from a list.
+ * Remove a watcher from a list.
* No warning when it isn't found...
*/
static void
@@ -4734,14 +4732,9 @@ listitem_remove(l, item)
list_len(l)
list_T *l;
{
- listitem_T *item;
- long len = 0;
-
if (l == NULL)
return 0L;
- for (item = l->lv_first; item != NULL; item = item->li_next)
- ++len;
- return len;
+ return l->lv_len;
}
/*
@@ -4881,20 +4874,70 @@ list_find(l, n)
if (l == NULL)
return NULL;
+
+ /* Negative index is relative to the end. */
if (n < 0)
+ n = l->lv_len + n;
+
+ /* Check for index out of range. */
+ if (n < 0 || n >= l->lv_len)
+ return NULL;
+
+ /* When there is a cached index may start search from there. */
+ if (l->lv_idx_item != NULL)
{
- idx = -1; /* search from the end */
- for (item = l->lv_last; item != NULL && idx > n; item = item->li_prev)
- --idx;
+ if (n < l->lv_idx / 2)
+ {
+ /* closest to the start of the list */
+ item = l->lv_first;
+ idx = 0;
+ }
+ else if (n > (l->lv_idx + l->lv_len) / 2)
+ {
+ /* closest to the end of the list */
+ item = l->lv_last;
+ idx = l->lv_len - 1;
+ }
+ else
+ {
+ /* closest to the cached index */
+ item = l->lv_idx_item;
+ idx = l->lv_idx;
+ }
}
else
{
- idx = 0; /* search from the start */
- for (item = l->lv_first; item != NULL && idx < n; item = item->li_next)
- ++idx;
+ if (n < l->lv_len / 2)
+ {
+ /* closest to the start of the list */
+ item = l->lv_first;
+ idx = 0;
+ }
+ else
+ {
+ /* closest to the end of the list */
+ item = l->lv_last;
+ idx = l->lv_len - 1;
+ }
}
- if (idx != n)
- return NULL;
+
+ while (n > idx)
+ {
+ /* search forward */
+ item = item->li_next;
+ ++idx;
+ }
+ while (n < idx)
+ {
+ /* search backward */
+ item = item->li_prev;
+ --idx;
+ }
+
+ /* cache the used index */
+ l->lv_idx = idx;
+ l->lv_idx_item = item;
+
return item;
}
@@ -4921,39 +4964,6 @@ list_idx_of_item(l, item)
}
/*
- * Like list_find(), but also find an item just past the end.
- * "*ip" is the item to find.
- * When found "*ip" is set to zero, when not found "*ip" is non-zero.
- * Returns NULL when item not found or item is just past the end.
- */
- static listitem_T *
-list_find_ext(l, ip)
- list_T *l;
- long *ip;
-{
- long n;
- listitem_T *item;
-
- if (*ip < 0)
- {
- /* Count from the end: -1 is before last item. */
- item = l->lv_last;
- for (n = *ip + 1; n < 0 && item != NULL; ++n)
- item = item->li_prev;
- if (item == NULL)
- n = 1; /* error! */
- }
- else
- {
- item = l->lv_first;
- for (n = *ip; n > 0 && item != NULL; --n)
- item = item->li_next;
- }
- *ip = n;
- return item;
-}
-
-/*
* Append item "item" to the end of list "l".
*/
static void
@@ -4974,6 +4984,7 @@ list_append(l, item)
item->li_prev = l->lv_last;
l->lv_last = item;
}
+ ++l->lv_len;
item->li_next = NULL;
}
@@ -5020,10 +5031,17 @@ list_insert_tv(l, tv, item)
ni->li_prev = item->li_prev;
ni->li_next = item;
if (item->li_prev == NULL)
+ {
l->lv_first = ni;
+ ++l->lv_idx;
+ }
else
+ {
item->li_prev->li_next = ni;
+ l->lv_idx_item = NULL;
+ }
item->li_prev = ni;
+ ++l->lv_len;
}
return OK;
}
@@ -5122,6 +5140,7 @@ list_remove(l, item, item2)
/* notify watchers */
for (ip = item; ip != NULL; ip = ip->li_next)
{
+ --l->lv_len;
list_fix_watch(l, ip);
if (ip == item2)
break;
@@ -5135,6 +5154,7 @@ list_remove(l, item, item2)
l->lv_first = item2->li_next;
else
item->li_prev->li_next = item2->li_next;
+ l->lv_idx_item = NULL;
}
/*
@@ -6547,7 +6567,7 @@ find_buffer(avar)
if (avar->v_type == VAR_NUMBER)
buf = buflist_findnr((int)avar->vval.v_number);
- else if (avar->vval.v_string != NULL)
+ else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
{
buf = buflist_findname_exp(avar->vval.v_string);
if (buf == NULL)
@@ -6623,6 +6643,8 @@ get_buf_tv(tv)
if (tv->v_type == VAR_NUMBER)
return buflist_findnr((int)tv->vval.v_number);
+ if (tv->v_type != VAR_STRING)
+ return NULL;
if (name == NULL || *name == NUL)
return curbuf;
if (name[0] == '$' && name[1] == NUL)
@@ -7289,9 +7311,8 @@ f_escape(argvars, rettv)
{
char_u buf[NUMBUFLEN];
- rettv->vval.v_string =
- vim_strsave_escaped(get_tv_string(&argvars[0]),
- get_tv_string_buf(&argvars[1], buf));
+ rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
+ get_tv_string_buf(&argvars[1], buf));
rettv->v_type = VAR_STRING;
}
@@ -7467,7 +7488,6 @@ f_extend(argvars, rettv)
list_T *l1, *l2;
listitem_T *item;
long before;
- long n;
l1 = argvars[0].vval.v_list;
l2 = argvars[1].vval.v_list;
@@ -7476,12 +7496,17 @@ f_extend(argvars, rettv)
{
if (argvars[2].v_type != VAR_UNKNOWN)
{
- n = before = get_tv_number(&argvars[2]);
- item = list_find_ext(l1, &n);
- if (n != 0)
+ before = get_tv_number(&argvars[2]);
+ if (before == l1->lv_len)
+ item = NULL;
+ else
{
- EMSGN(_(e_listidx), before);
- return;
+ item = list_find(l1, before);
+ if (item == NULL)
+ {
+ EMSGN(_(e_listidx), before);
+ return;
+ }
}
}
else
@@ -9487,7 +9512,6 @@ f_index(argvars, rettv)
list_T *l;
listitem_T *item;
long idx = 0;
- long min_idx = 0;
int ic = FALSE;
rettv->vval.v_number = -1;
@@ -9499,15 +9523,19 @@ f_index(argvars, rettv)
l = argvars[0].vval.v_list;
if (l != NULL)
{
+ item = l->lv_first;
if (argvars[2].v_type != VAR_UNKNOWN)
{
- min_idx = get_tv_number(&argvars[2]);
+ /* Start at specified item. Use the cached index that list_find()
+ * sets, so that a negative number also works. */
+ item = list_find(l, get_tv_number(&argvars[2]));
+ idx = l->lv_idx;
if (argvars[3].v_type != VAR_UNKNOWN)
ic = get_tv_number(&argvars[3]);
}
- for (item = l->lv_first; item != NULL; item = item->li_next, ++idx)
- if (idx >= min_idx && tv_equal(&item->li_tv, &argvars[1], ic))
+ for ( ; item != NULL; item = item->li_next, ++idx)
+ if (tv_equal(&item->li_tv, &argvars[1], ic))
{
rettv->vval.v_number = idx;
break;
@@ -9690,7 +9718,6 @@ f_insert(argvars, rettv)
typval_T *rettv;
{
long before = 0;
- long n;
listitem_T *item;
list_T *l;
@@ -9703,12 +9730,19 @@ f_insert(argvars, rettv)
if (argvars[2].v_type != VAR_UNKNOWN)
before = get_tv_number(&argvars[2]);
- n = before;
- item = list_find_ext(l, &n);
- if (n > 0)
- EMSGN(_(e_listidx), before);
+ if (before == l->lv_len)
+ item = NULL;
else
{
+ item = list_find(l, before);
+ if (item == NULL)
+ {
+ EMSGN(_(e_listidx), before);
+ l = NULL;
+ }
+ }
+ if (l != NULL)
+ {
list_insert_tv(l, &argvars[1], item);
++l->lv_refcount;
copy_tv(&argvars[0], rettv);
@@ -10021,9 +10055,8 @@ libcall_common(argvars, rettv, type)
/* The first two args must be strings, otherwise its meaningless */
if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
{
- if (argvars[2].v_type == VAR_NUMBER)
- string_in = NULL;
- else
+ string_in = NULL;
+ if (argvars[2].v_type == VAR_STRING)
string_in = argvars[2].vval.v_string;
if (type == VAR_NUMBER)
string_result = NULL;
@@ -10275,16 +10308,7 @@ find_some_match(argvars, rettv, type)
li = list_find(l, start);
if (li == NULL)
goto theend;
- if (start < 0)
- {
- listitem_T *ni;
-
- /* Need to compute the index. */
- for (ni = li; ni->li_prev != NULL; ni = ni->li_prev)
- ++idx;
- }
- else
- idx = start;
+ idx = l->lv_idx; /* use the cached index */
}
else
{
@@ -10468,7 +10492,7 @@ max_min(argvars, rettv, domax)
}
}
else
- EMSG(_(e_listreq));
+ EMSG(_(e_listdictarg));
rettv->vval.v_number = n;
}
@@ -10904,7 +10928,7 @@ f_remove(argvars, rettv)
if (argvars[2].v_type != VAR_UNKNOWN)
EMSG2(_(e_toomanyarg), "remove()");
else if ((d = argvars[0].vval.v_dict) != NULL
- && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
+ && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
{
key = get_tv_string(&argvars[1]);
di = dict_find(d, key, -1);
@@ -10945,8 +10969,14 @@ f_remove(argvars, rettv)
EMSGN(_(e_listidx), end);
else
{
- for (li = item; li != item2 && li != NULL; li = li->li_next)
- ;
+ int cnt = 0;
+
+ for (li = item; li != NULL; li = li->li_next)
+ {
+ ++cnt;
+ if (li == item2)
+ break;
+ }
if (li == NULL) /* didn't find "item2" after "item" */
EMSG(_(e_invrange));
else
@@ -10962,6 +10992,7 @@ f_remove(argvars, rettv)
l->lv_refcount = 1;
item->li_prev = NULL;
item2->li_next = NULL;
+ l->lv_len = cnt;
}
}
}
@@ -11260,6 +11291,7 @@ f_reverse(argvars, rettv)
{
li = l->lv_last;
l->lv_first = l->lv_last = li;
+ l->lv_len = 0;
while (li != NULL)
{
ni = li->li_prev;
@@ -11945,6 +11977,7 @@ f_sort(argvars, rettv)
/* Clear the List and append the items in the sorted order. */
l->lv_first = l->lv_last = NULL;
+ l->lv_len = 0;
for (i = 0; i < len; ++i)
list_append(l, ptrs[i]);
}
@@ -12773,6 +12806,7 @@ f_type(argvars, rettv)
case VAR_STRING: n = 1; break;
case VAR_FUNC: n = 2; break;
case VAR_LIST: n = 3; break;
+ case VAR_DICT: n = 4; break;
default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
}
rettv->vval.v_number = n;
@@ -13520,7 +13554,11 @@ free_tv(varp)
case VAR_DICT:
dict_unref(varp->vval.v_dict);
break;
+ case VAR_NUMBER:
+ case VAR_UNKNOWN:
+ break;
default:
+ EMSG2(_(e_intern2), "free_tv()");
break;
}
vim_free(varp);
@@ -13600,7 +13638,7 @@ get_tv_number(varp)
TRUE, TRUE, &n, NULL);
break;
case VAR_LIST:
- EMSG(_("E703: Using a List as a number"));
+ EMSG(_("E745: Using a List as a number"));
break;
case VAR_DICT:
EMSG(_("E728: Using a Dictionary as a number"));
@@ -14020,7 +14058,8 @@ set_var(name, tv, copy)
}
/*
- * Handle setting internal v: variables separately: we keep the type.
+ * Handle setting internal v: variables separately: we don't change
+ * the type.
*/
if (ht == &vimvarht)
{
@@ -14832,6 +14871,15 @@ ex_function(eap)
EMSG(_(e_funcdict));
goto erret;
}
+ if (fudi.fd_di == NULL)
+ {
+ /* Can't add a function to a locked dictionary */
+ if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
+ goto erret;
+ }
+ /* Can't change an existing function if it is locked */
+ else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
+ goto erret;
/* Give the function a sequential number. Can only be used with a
* Funcref! */
@@ -15510,6 +15558,8 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
if (p_verbose >= 14)
{
char_u buf[MSG_BUF_LEN];
+ char_u numbuf[NUMBUFLEN];
+ char_u *tofree;
msg_puts((char_u *)"(");
for (i = 0; i < argcount; ++i)
@@ -15520,11 +15570,10 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
msg_outnum((long)argvars[i].vval.v_number);
else
{
- trunc_string(get_tv_string(&argvars[i]),
+ trunc_string(tv2string(&argvars[i], &tofree, numbuf),
buf, MSG_BUF_LEN);
- msg_puts((char_u *)"\"");
msg_puts(buf);
- msg_puts((char_u *)"\"");
+ vim_free(tofree);
}
}
msg_puts((char_u *)")");
@@ -15556,7 +15605,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
/* when being verbose, mention the return value */
if (p_verbose >= 12)
{
- char_u *sn, *val;
+ char_u *sn;
++no_wait_return;
msg_scroll = TRUE; /* always scroll up, don't overwrite */
@@ -15571,12 +15620,16 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
else if (fc.rettv->v_type == VAR_NUMBER)
smsg((char_u *)_("%s returning #%ld"), sn,
(long)fc.rettv->vval.v_number);
- else if (fc.rettv->v_type == VAR_STRING)
+ else
{
- val = get_tv_string(fc.rettv);
- if (STRLEN(val) > IOSIZE / 2 - 50)
- val = val + STRLEN(val) - (IOSIZE / 2 - 50);
- smsg((char_u *)_("%s returning \"%s\""), sn, val);
+ char_u buf[MSG_BUF_LEN];
+ char_u numbuf[NUMBUFLEN];
+ char_u *tofree;
+
+ trunc_string(tv2string(fc.rettv, &tofree, numbuf),
+ buf, MSG_BUF_LEN);
+ smsg((char_u *)_("%s returning %s"), sn, buf);
+ vim_free(tofree);
}
msg_puts((char_u *)"\n"); /* don't overwrite this either */
cmdline_row = msg_row;
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 14f7580134..224a126682 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -1286,6 +1286,8 @@ viminfo_error(errnum, message, line)
{
sprintf((char *)IObuff, _("%sviminfo: %s in line: "), errnum, message);
STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
+ if (IObuff[STRLEN(IObuff) - 1] == '\n')
+ IObuff[STRLEN(IObuff) - 1] = NUL;
emsg(IObuff);
if (++viminfo_errcnt >= 10)
{
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 5e2592541a..80394b467c 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -849,9 +849,9 @@ EX(CMD_visual, "visual", ex_edit,
EX(CMD_view, "view", ex_edit,
BANG|FILE1|EDITCMD|ARGOPT|TRLBAR),
EX(CMD_vimgrep, "vimgrep", ex_vimgrep,
- EXTRA|TRLBAR|NEEDARG),
+ NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
EX(CMD_vimgrepadd, "vimgrepadd", ex_vimgrep,
- EXTRA|TRLBAR|NEEDARG),
+ NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE),
EX(CMD_viusage, "viusage", ex_viusage,
TRLBAR),
EX(CMD_vmap, "vmap", ex_map,