* Skip over an expression at "*pp".
* If in Vim9 script and line breaks are encountered, the lines are
* concatenated. "evalarg->eval_tofree" will be set accordingly.
+ * "arg" is advanced to just after the expression.
+ * "start" is set to the start of the expression, "end" to just after the end.
+ * Also when the expression is copied to allocated memory.
* Return FAIL for an error, OK otherwise.
*/
int
-skip_expr_concatenate(char_u **start, char_u **end, evalarg_T *evalarg)
+skip_expr_concatenate(
+ char_u **arg,
+ char_u **start,
+ char_u **end,
+ evalarg_T *evalarg)
{
typval_T rettv;
int res;
if (ga_grow(gap, 1) == OK)
++gap->ga_len;
}
+ *start = *arg;
// Don't evaluate the expression.
if (evalarg != NULL)
evalarg->eval_flags &= ~EVAL_EVALUATE;
- *end = skipwhite(*end);
- res = eval1(end, &rettv, evalarg);
+ *arg = skipwhite(*arg);
+ res = eval1(arg, &rettv, evalarg);
+ *end = *arg;
if (evalarg != NULL)
evalarg->eval_flags = save_flags;
else
{
char_u *p;
- size_t endoff = STRLEN(*end);
+ size_t endoff = STRLEN(*arg);
// Line breaks encountered, concatenate all the lines.
*((char_u **)gap->ga_data) = *start;
// free the lines only when using getsourceline()
if (evalarg->eval_cookie != NULL)
{
+ // Do not free the first line, the caller can still use it.
*((char_u **)gap->ga_data) = NULL;
+ // Do not free the last line, "arg" points into it, free it
+ // later.
+ vim_free(evalarg->eval_tofree);
+ evalarg->eval_tofree =
+ ((char_u **)gap->ga_data)[gap->ga_len - 1];
+ ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL;
ga_clear_strings(gap);
}
else
if (p == NULL)
return FAIL;
*start = p;
- vim_free(evalarg->eval_tofree);
- evalarg->eval_tofree = p;
+ vim_free(evalarg->eval_tofree_lambda);
+ evalarg->eval_tofree_lambda = p;
// Compute "end" relative to the end.
*end = *start + STRLEN(*start) - endoff;
}
((char_u **)gap->ga_data)[gap->ga_len] = line;
++gap->ga_len;
}
- else
+ else if (evalarg->eval_cookie != NULL)
{
vim_free(evalarg->eval_tofree);
evalarg->eval_tofree = line;
}
/*
- * After using "evalarg" filled from "eap" free the memory.
+ * After using "evalarg" filled from "eap": free the memory.
*/
void
clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
{
- if (evalarg != NULL && evalarg->eval_tofree != NULL)
+ if (evalarg != NULL)
{
- if (eap != NULL)
+ if (evalarg->eval_tofree != NULL)
{
- // We may need to keep the original command line, e.g. for
- // ":let" it has the variable names. But we may also need the
- // new one, "nextcmd" points into it. Keep both.
- vim_free(eap->cmdline_tofree);
- eap->cmdline_tofree = *eap->cmdlinep;
- *eap->cmdlinep = evalarg->eval_tofree;
+ if (eap != NULL)
+ {
+ // We may need to keep the original command line, e.g. for
+ // ":let" it has the variable names. But we may also need the
+ // new one, "nextcmd" points into it. Keep both.
+ vim_free(eap->cmdline_tofree);
+ eap->cmdline_tofree = *eap->cmdlinep;
+ *eap->cmdlinep = evalarg->eval_tofree;
+ }
+ else
+ vim_free(evalarg->eval_tofree);
+ evalarg->eval_tofree = NULL;
}
- else
- vim_free(evalarg->eval_tofree);
- evalarg->eval_tofree = NULL;
+
+ vim_free(evalarg->eval_tofree_lambda);
+ evalarg->eval_tofree_lambda = NULL;
}
}
partial_T *pt = NULL;
int varargs;
int ret;
- char_u *start;
- char_u *s, *e;
+ char_u *s;
+ char_u *start, *end;
int *old_eval_lavars = eval_lavars_used;
int eval_lavars = FALSE;
char_u *tofree = NULL;
ga_init(&newlines);
// First, check if this is a lambda expression. "->" must exist.
- start = skipwhite(*arg + 1);
- ret = get_function_args(&start, '-', NULL, NULL, NULL, NULL, TRUE,
+ s = skipwhite(*arg + 1);
+ ret = get_function_args(&s, '-', NULL, NULL, NULL, NULL, TRUE,
NULL, NULL);
- if (ret == FAIL || *start != '>')
+ if (ret == FAIL || *s != '>')
return NOTDONE;
// Parse the arguments again.
// Get the start and the end of the expression.
*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
- s = *arg;
- ret = skip_expr_concatenate(&s, arg, evalarg);
+ start = *arg;
+ ret = skip_expr_concatenate(arg, &start, &end, evalarg);
if (ret == FAIL)
goto errret;
if (evalarg != NULL)
evalarg->eval_tofree = NULL;
}
- e = *arg;
*arg = skipwhite_and_linebreak(*arg, evalarg);
if (**arg != '}')
{
goto errret;
// Add "return " before the expression.
- len = 7 + (int)(e - s) + 1;
+ len = 7 + (int)(end - start) + 1;
p = alloc(len);
if (p == NULL)
goto errret;
((char_u **)(newlines.ga_data))[newlines.ga_len++] = p;
STRCPY(p, "return ");
- vim_strncpy(p + 7, s, e - s);
+ vim_strncpy(p + 7, start, end - start);
if (strstr((char *)p + 7, "a:") == NULL)
// No a: variables are used for sure.
flags |= FC_NOARGS;
}
eval_lavars_used = old_eval_lavars;
- vim_free(tofree);
+ if (evalarg->eval_tofree == NULL)
+ evalarg->eval_tofree = tofree;
+ else
+ vim_free(tofree);
return OK;
errret:
ga_clear_strings(&newlines);
vim_free(fp);
vim_free(pt);
- vim_free(tofree);
+ if (evalarg->eval_tofree == NULL)
+ evalarg->eval_tofree = tofree;
+ else
+ vim_free(tofree);
eval_lavars_used = old_eval_lavars;
return FAIL;
}