ex_getln: Refactor script_get()

1. Use `char *` for strings.
2. Add `const` qualifiers.
3. Add attributes and documentation.
4. Handle skipping *inside*.
5. Handle non-heredoc argument also inside: deferring this to the caller is
   pointless because all callers need the same thing. Though new ex_lua caller
   may live without allocations in this case, allocating nevertheless produces
   cleaner code.
6. Note that all callers call script_get with `eap` and `eap->arg`. Thus second
   argument is useless in practice: it is one and the same always and can be
   reached through the first argument.
This commit is contained in:
ZyX
2017-01-29 03:36:47 +03:00
parent 3531d8c8ea
commit 3d48c35d6b
4 changed files with 58 additions and 38 deletions

View File

@@ -3695,19 +3695,18 @@ char_u *get_locales(expand_T *xp, int idx)
static void script_host_execute(char *name, exarg_T *eap) static void script_host_execute(char *name, exarg_T *eap)
{ {
uint8_t *script = script_get(eap, eap->arg); size_t len;
char *const script = script_get(eap, &len);
if (!eap->skip) { if (script != NULL) {
list_T *args = list_alloc(); list_T *const args = list_alloc();
// script // script
list_append_string(args, script ? script : eap->arg, -1); list_append_allocated_string(args, script);
// current range // current range
list_append_number(args, (int)eap->line1); list_append_number(args, (int)eap->line1);
list_append_number(args, (int)eap->line2); list_append_number(args, (int)eap->line2);
(void)eval_call_provider(name, "execute", args); (void)eval_call_provider(name, "execute", args);
} }
xfree(script);
} }
static void script_host_execute_file(char *name, exarg_T *eap) static void script_host_execute_file(char *name, exarg_T *eap)

View File

@@ -3734,10 +3734,12 @@ void ex_ni(exarg_T *eap)
/// Skips over ":perl <<EOF" constructs. /// Skips over ":perl <<EOF" constructs.
static void ex_script_ni(exarg_T *eap) static void ex_script_ni(exarg_T *eap)
{ {
if (!eap->skip) if (!eap->skip) {
ex_ni(eap); ex_ni(eap);
else } else {
xfree(script_get(eap, eap->arg)); size_t len;
xfree(script_get(eap, &len));
}
} }
/* /*

View File

@@ -5343,47 +5343,61 @@ static int ex_window(void)
return cmdwin_result; return cmdwin_result;
} }
/* /// Get script string
* Used for commands that either take a simple command string argument, or: ///
* cmd << endmarker /// Used for commands which accept either `:command script` or
* {script} ///
* endmarker /// :command << endmarker
* Returns a pointer to allocated memory with {script} or NULL. /// script
*/ /// endmarker
char_u *script_get(exarg_T *eap, char_u *cmd) ///
/// @param eap Command being run.
/// @param[out] lenp Location where length of resulting string is saved. Will
/// be set to zero when skipping.
///
/// @return [allocated] NULL or script. Does not show any error messages.
/// NULL is returned when skipping and on error.
char *script_get(exarg_T *const eap, size_t *const lenp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
{ {
char_u *theline; const char *const cmd = (const char *)eap->arg;
char *end_pattern = NULL;
char dot[] = ".";
garray_T ga;
if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) {
return NULL; *lenp = STRLEN(eap->arg);
return xmemdupz(eap->arg, *lenp);
}
garray_T ga = { .ga_data = NULL, .ga_len = 0 };
if (!eap->skip) {
ga_init(&ga, 1, 0x400); ga_init(&ga, 1, 0x400);
}
if (cmd[2] != NUL) const char *const end_pattern = (
end_pattern = (char *)skipwhite(cmd + 2); cmd[2] != NUL
else ? (const char *)skipwhite((const char_u *)cmd + 2)
end_pattern = dot; : ".");
for (;;) { for (;;) {
theline = eap->getline( char *const theline = (char *)eap->getline(
eap->cstack->cs_looplevel > 0 ? -1 : eap->cstack->cs_looplevel > 0 ? -1 :
NUL, eap->cookie, 0); NUL, eap->cookie, 0);
if (theline == NULL || STRCMP(end_pattern, theline) == 0) { if (theline == NULL || strcmp(end_pattern, theline) == 0) {
xfree(theline); xfree(theline);
break; break;
} }
ga_concat(&ga, theline); if (!eap->skip) {
ga_concat(&ga, (const char_u *)theline);
ga_append(&ga, '\n'); ga_append(&ga, '\n');
}
xfree(theline); xfree(theline);
} }
*lenp = (size_t)ga.ga_len; // Set length without trailing NUL.
if (!eap->skip) {
ga_append(&ga, NUL); ga_append(&ga, NUL);
}
return (char_u *)ga.ga_data; return (char *)ga.ga_data;
} }
/// Iterate over history items /// Iterate over history items

View File

@@ -277,9 +277,14 @@ void executor_eval_lua(const String str, typval_T *const arg,
void ex_lua(exarg_T *const eap) void ex_lua(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
char *const code = (char *)script_get(eap, eap->arg); size_t len;
char *const code = script_get(eap, &len);
if (eap->skip) {
xfree(code);
return;
}
typval_T tv = { .v_type = VAR_UNKNOWN }; typval_T tv = { .v_type = VAR_UNKNOWN };
executor_exec_lua(cstr_as_string(code), &tv); executor_exec_lua((String) { .data = code, .size = len }, &tv);
clear_tv(&tv); clear_tv(&tv);
xfree(code); xfree(code);
} }