diff options
Diffstat (limited to 'src')
44 files changed, 1315 insertions, 1319 deletions
diff --git a/src/nvim/ascii.h b/src/nvim/ascii.h index 2b3e94d5a0..44ff540b40 100644 --- a/src/nvim/ascii.h +++ b/src/nvim/ascii.h @@ -85,10 +85,25 @@ # define PATHSEPSTR "/" #endif -static inline bool ascii_iswhite(int) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; -static inline bool ascii_isdigit(int) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; -static inline bool ascii_isxdigit(int) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; -static inline bool ascii_isspace(int) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; +static inline bool ascii_iswhite(int) + REAL_FATTR_CONST + REAL_FATTR_ALWAYS_INLINE; + +static inline bool ascii_isdigit(int) + REAL_FATTR_CONST + REAL_FATTR_ALWAYS_INLINE; + +static inline bool ascii_isxdigit(int) + REAL_FATTR_CONST + REAL_FATTR_ALWAYS_INLINE; + +static inline bool ascii_isbdigit(int) + REAL_FATTR_CONST + REAL_FATTR_ALWAYS_INLINE; + +static inline bool ascii_isspace(int) + REAL_FATTR_CONST + REAL_FATTR_ALWAYS_INLINE; /// Checks if `c` is a space or tab character. /// @@ -122,6 +137,14 @@ static inline bool ascii_isxdigit(int c) || (c >= 'A' && c <= 'F'); } +/// Checks if `c` is a binary digit, that is, 0-1. +/// +/// @see {ascii_isdigit} +static inline bool ascii_isbdigit(int c) +{ + return (c == '0' || c == '1'); +} + /// Checks if `c` is a white-space character, that is, /// one of \f, \n, \r, \t, \v. /// diff --git a/src/nvim/charset.c b/src/nvim/charset.c index b93eafbf60..e0c9443511 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1454,6 +1454,24 @@ char_u* skipdigits(char_u *q) return p; } +/// skip over binary digits +/// +/// @param q pointer to string +/// +/// @return Pointer to the character after the skipped digits. +const char* skipbin(const char *q) + FUNC_ATTR_PURE + FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_RET +{ + const char *p = q; + while (ascii_isbdigit(*p)) { + // skip to next non-digit + p++; + } + return p; +} + /// skip over digits and hex characters /// /// @param q @@ -1485,6 +1503,24 @@ char_u* skiptodigit(char_u *q) return p; } +/// skip to binary character (or NUL after the string) +/// +/// @param q pointer to string +/// +/// @return Pointer to the binary character or (NUL after the string). +const char* skiptobin(const char *q) + FUNC_ATTR_PURE + FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_RET +{ + const char *p = q; + while (*p != NUL && !ascii_isbdigit(*p)) { + // skip to next digit + p++; + } + return p; +} + /// skip to hex character (or NUL after the string) /// /// @param q @@ -1720,67 +1756,77 @@ int vim_isblankline(char_u *lbuf) } /// Convert a string into a long and/or unsigned long, taking care of -/// hexadecimal and octal numbers. Accepts a '-' sign. -/// If "hexp" is not NULL, returns a flag to indicate the type of the number: +/// hexadecimal, octal and binary numbers. Accepts a '-' sign. +/// If "prep" is not NULL, returns a flag to indicate the type of the number: /// 0 decimal /// '0' octal +/// 'B' bin +/// 'b' bin /// 'X' hex /// 'x' hex /// If "len" is not NULL, the length of the number in characters is returned. /// If "nptr" is not NULL, the signed result is returned in it. /// If "unptr" is not NULL, the unsigned result is returned in it. +/// If "dobin" is non-zero recognize binary numbers, when > 1 always assume +/// binary number. /// If "dooct" is non-zero recognize octal numbers, when > 1 always assume /// octal number. /// If "dohex" is non-zero recognize hex numbers, when > 1 always assume /// hex number. /// /// @param start -/// @param hexp Returns type of number 0 = decimal, 'x' or 'X' is hex, -// '0' = octal +/// @param prep Returns type of number 0 = decimal, 'x' or 'X' is hex, +// '0' = octal, 'b' or 'B' is bin /// @param len Returns the detected length of number. +/// @param dobin recognize binary number /// @param dooct recognize octal number /// @param dohex recognize hex number /// @param nptr Returns the signed result. /// @param unptr Returns the unsigned result. -void vim_str2nr(char_u *start, int *hexp, int *len, int dooct, int dohex, +void vim_str2nr(char_u *start, int *prep, int *len, + int dobin, int dooct, int dohex, long *nptr, unsigned long *unptr) { char_u *ptr = start; - int hex = 0; // default is decimal - int negative = FALSE; + int pre = 0; // default is decimal + int negative = false; unsigned long un = 0; int n; if (ptr[0] == '-') { - negative = TRUE; - ++ptr; + negative = true; + ptr++; } - // Recognize hex and octal. + // Recognize hex, octal, and bin. if ((ptr[0] == '0') && (ptr[1] != '8') && (ptr[1] != '9')) { - hex = ptr[1]; + pre = ptr[1]; if (dohex - && ((hex == 'X') || (hex == 'x')) + && ((pre == 'X') || (pre == 'x')) && ascii_isxdigit(ptr[2])) { // hexadecimal ptr += 2; + } else if (dobin + && ((pre == 'B') || (pre == 'b')) + && ascii_isbdigit(ptr[2])) { + // binary + ptr += 2; } else { // default is decimal - hex = 0; + pre = 0; if (dooct) { // Don't interpret "0", "08" or "0129" as octal. for (n = 1; ascii_isdigit(ptr[n]); ++n) { if (ptr[n] > '7') { // can't be octal - hex = 0; + pre = 0; break; } - if (ptr[n] >= '0') { // assume octal - hex = '0'; + pre = '0'; } } } @@ -1788,14 +1834,26 @@ void vim_str2nr(char_u *start, int *hexp, int *len, int dooct, int dohex, } // Do the string-to-numeric conversion "manually" to avoid sscanf quirks. - if ((hex == '0') || (dooct > 1)) { + if ((pre == 'B') || (pre == 'b') || (dobin > 1)) { + // bin + if (pre != 0) { + n += 2; // skip over "0b" + } + while ('0' <= *ptr && *ptr <= '1') { + un = 2 * un + (unsigned long)(*ptr - '0'); + ptr++; + } + } else if ((pre == '0') || (dooct > 1)) { // octal while ('0' <= *ptr && *ptr <= '7') { un = 8 * un + (unsigned long)(*ptr - '0'); ptr++; } - } else if ((hex != 0) || (dohex > 1)) { + } else if (pre != 0 || dohex > 1) { // hex + if (pre != 0) { + n += 2; // skip over "0x" + } while (ascii_isxdigit(*ptr)) { un = 16 * un + (unsigned long)hex2nr(*ptr); ptr++; @@ -1808,8 +1866,8 @@ void vim_str2nr(char_u *start, int *hexp, int *len, int dooct, int dohex, } } - if (hexp != NULL) { - *hexp = hex; + if (prep != NULL) { + *prep = pre; } if (len != NULL) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7ac51d7bd7..a5a8671697 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1113,19 +1113,17 @@ typval_T *eval_expr(char_u *arg, char_u **nextcmd) } -/* - * Call some vimL function and return the result in "*rettv". - * Uses argv[argc] for the function arguments. Only Number and String - * arguments are currently supported. - * Returns OK or FAIL. - */ -int -call_vim_function ( +// Call some vimL function and return the result in "*rettv". +// Uses argv[argc] for the function arguments. Only Number and String +// arguments are currently supported. +// +// Return OK or FAIL. +int call_vim_function( char_u *func, int argc, char_u **argv, - int safe, /* use the sandbox */ - int str_arg_only, /* all arguments are strings */ + int safe, // use the sandbox + int str_arg_only, // all arguments are strings typval_T *rettv ) { @@ -1138,18 +1136,19 @@ call_vim_function ( typval_T *argvars = xmalloc((argc + 1) * sizeof(typval_T)); for (int i = 0; i < argc; i++) { - /* Pass a NULL or empty argument as an empty string */ + // Pass a NULL or empty argument as an empty string if (argv[i] == NULL || *argv[i] == NUL) { argvars[i].v_type = VAR_STRING; argvars[i].vval.v_string = (char_u *)""; continue; } - if (str_arg_only) + if (str_arg_only) { len = 0; - else - /* Recognize a number argument, the others must be strings. */ - vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL); + } else { + // Recognize a number argument, the others must be strings. + vim_str2nr(argv[i], NULL, &len, true, true, true, &n, NULL); + } if (len != 0 && len == (int)STRLEN(argv[i])) { argvars[i].v_type = VAR_NUMBER; argvars[i].vval.v_number = n; @@ -1166,16 +1165,17 @@ call_vim_function ( rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */ ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &doesrange, TRUE, NULL); + curwin->w_cursor.lnum, curwin->w_cursor.lnum, + &doesrange, true, NULL); if (safe) { --sandbox; restore_funccal(save_funccalp); } xfree(argvars); - if (ret == FAIL) + if (ret == FAIL) { clear_tv(rettv); + } return ret; } @@ -4025,38 +4025,35 @@ eval6 ( return OK; } -/* - * Handle sixth level expression: - * number number constant - * "string" string constant - * 'string' literal string constant - * &option-name option value - * @r register contents - * identifier variable value - * function() function call - * $VAR environment variable - * (expression) nested expression - * [expr, expr] List - * {key: val, key: val} Dictionary - * - * Also handle: - * ! in front logical NOT - * - in front unary minus - * + in front unary plus (ignored) - * trailing [] subscript in String or List - * trailing .name entry in Dictionary - * - * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. - * - * Return OK or FAIL. - */ -static int -eval7 ( +// Handle sixth level expression: +// number number constant +// "string" string constant +// 'string' literal string constant +// &option-name option value +// @r register contents +// identifier variable value +// function() function call +// $VAR environment variable +// (expression) nested expression +// [expr, expr] List +// {key: val, key: val} Dictionary +// +// Also handle: +// ! in front logical NOT +// - in front unary minus +// + in front unary plus (ignored) +// trailing [] subscript in String or List +// trailing .name entry in Dictionary +// +// "arg" must point to the first non-white of the expression. +// "arg" is advanced to the next non-white after the recognized expression. +// +// Return OK or FAIL. +static int eval7( char_u **arg, typval_T *rettv, int evaluate, - int want_string /* after "." operator */ + int want_string // after "." operator ) { long n; @@ -4066,24 +4063,19 @@ eval7 ( int ret = OK; char_u *alias; - /* - * Initialise variable so that clear_tv() can't mistake this for a - * string and free a string that isn't there. - */ + // Initialise variable so that clear_tv() can't mistake this for a + // string and free a string that isn't there. rettv->v_type = VAR_UNKNOWN; - /* - * Skip '!' and '-' characters. They are handled later. - */ + // Skip '!' and '-' characters. They are handled later. start_leader = *arg; - while (**arg == '!' || **arg == '-' || **arg == '+') + while (**arg == '!' || **arg == '-' || **arg == '+') { *arg = skipwhite(*arg + 1); + } end_leader = *arg; switch (**arg) { - /* - * Number constant. - */ + // Number constant. case '0': case '1': case '2': @@ -4096,27 +4088,30 @@ eval7 ( case '9': { char_u *p = skipdigits(*arg + 1); - int get_float = FALSE; + int get_float = false; - /* We accept a float when the format matches - * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very - * strict to avoid backwards compatibility problems. - * Don't look for a float after the "." operator, so that - * ":let vers = 1.2.3" doesn't fail. */ + // We accept a float when the format matches + // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very + // strict to avoid backwards compatibility problems. + // Don't look for a float after the "." operator, so that + // ":let vers = 1.2.3" doesn't fail. if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) { - get_float = TRUE; + get_float = true; p = skipdigits(p + 2); if (*p == 'e' || *p == 'E') { ++p; - if (*p == '-' || *p == '+') + if (*p == '-' || *p == '+') { ++p; - if (!ascii_isdigit(*p)) - get_float = FALSE; - else + } + if (!ascii_isdigit(*p)) { + get_float = false; + } else { p = skipdigits(p + 1); + } + } + if (ASCII_ISALPHA(*p) || *p == '.') { + get_float = false; } - if (ASCII_ISALPHA(*p) || *p == '.') - get_float = FALSE; } if (get_float) { float_T f; @@ -4127,7 +4122,7 @@ eval7 ( rettv->vval.v_float = f; } } else { - vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL); + vim_str2nr(*arg, NULL, &len, true, true, true, &n, NULL); *arg += len; if (evaluate) { rettv->v_type = VAR_NUMBER; @@ -4137,62 +4132,47 @@ eval7 ( break; } - /* - * String constant: "string". - */ + // String constant: "string". case '"': ret = get_string_tv(arg, rettv, evaluate); break; - /* - * Literal string constant: 'str''ing'. - */ + // Literal string constant: 'str''ing'. case '\'': ret = get_lit_string_tv(arg, rettv, evaluate); break; - /* - * List: [expr, expr] - */ + // List: [expr, expr] case '[': ret = get_list_tv(arg, rettv, evaluate); break; - /* - * Dictionary: {key: val, key: val} - */ + // Dictionary: {key: val, key: val} case '{': ret = get_dict_tv(arg, rettv, evaluate); break; - /* - * Option value: &name - */ + // Option value: &name case '&': ret = get_option_tv(arg, rettv, evaluate); break; - /* - * Environment variable: $VAR. - */ + // Environment variable: $VAR. case '$': ret = get_env_tv(arg, rettv, evaluate); break; - /* - * Register contents: @r. - */ + // Register contents: @r. case '@': ++*arg; if (evaluate) { rettv->v_type = VAR_STRING; rettv->vval.v_string = get_reg_contents(**arg, kGRegExprSrc); } - if (**arg != NUL) + if (**arg != NUL) { ++*arg; + } break; - /* - * nested expression: (expression). - */ + // nested expression: (expression). case '(': *arg = skipwhite(*arg + 1); - ret = eval1(arg, rettv, evaluate); /* recursive! */ - if (**arg == ')') + ret = eval1(arg, rettv, evaluate); // recursive! + if (**arg == ')') { ++*arg; - else if (ret == OK) { + } else if (ret == OK) { EMSG(_("E110: Missing ')'")); clear_tv(rettv); ret = FAIL; @@ -4204,71 +4184,72 @@ eval7 ( } if (ret == NOTDONE) { - /* - * Must be a variable or function name. - * Can also be a curly-braces kind of name: {expr}. - */ + // Must be a variable or function name. + // Can also be a curly-braces kind of name: {expr}. s = *arg; - len = get_name_len(arg, &alias, evaluate, TRUE); - if (alias != NULL) + len = get_name_len(arg, &alias, evaluate, true); + if (alias != NULL) { s = alias; + } - if (len <= 0) + if (len <= 0) { ret = FAIL; - else { - if (**arg == '(') { /* recursive! */ - /* If "s" is the name of a variable of type VAR_FUNC - * use its contents. */ + } else { + if (**arg == '(') { // recursive! + // If "s" is the name of a variable of type VAR_FUNC + // use its contents. s = deref_func_name(s, &len, !evaluate); - /* Invoke the function. */ + // Invoke the function. ret = get_func_tv(s, len, rettv, arg, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &len, evaluate, NULL); - /* If evaluate is FALSE rettv->v_type was not set in - * get_func_tv, but it's needed in handle_subscript() to parse - * what follows. So set it here. */ + // If evaluate is false rettv->v_type was not set in + // get_func_tv, but it's needed in handle_subscript() to parse + // what follows. So set it here. if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') { rettv->vval.v_string = empty_string; rettv->v_type = VAR_FUNC; } - /* Stop the expression evaluation when immediately - * aborting on error, or when an interrupt occurred or - * an exception was thrown but not caught. */ + // Stop the expression evaluation when immediately + // aborting on error, or when an interrupt occurred or + // an exception was thrown but not caught. if (aborting()) { - if (ret == OK) + if (ret == OK) { clear_tv(rettv); + } ret = FAIL; } - } else if (evaluate) - ret = get_var_tv(s, len, rettv, TRUE, FALSE); - else + } else if (evaluate) { + ret = get_var_tv(s, len, rettv, true, false); + } else { ret = OK; + } } xfree(alias); } *arg = skipwhite(*arg); - /* Handle following '[', '(' and '.' for expr[expr], expr.name, - * expr(expr). */ - if (ret == OK) - ret = handle_subscript(arg, rettv, evaluate, TRUE); + // Handle following '[', '(' and '.' for expr[expr], expr.name, + // expr(expr). + if (ret == OK) { + ret = handle_subscript(arg, rettv, evaluate, true); + } - /* - * Apply logical NOT and unary '-', from right to left, ignore '+'. - */ + // Apply logical NOT and unary '-', from right to left, ignore '+'. if (ret == OK && evaluate && end_leader > start_leader) { - int error = FALSE; + int error = false; int val = 0; float_T f = 0.0; - if (rettv->v_type == VAR_FLOAT) + if (rettv->v_type == VAR_FLOAT) { f = rettv->vval.v_float; - else + } else { val = get_tv_number_chk(rettv, &error); + } if (error) { clear_tv(rettv); ret = FAIL; @@ -4276,15 +4257,17 @@ eval7 ( while (end_leader > start_leader) { --end_leader; if (*end_leader == '!') { - if (rettv->v_type == VAR_FLOAT) + if (rettv->v_type == VAR_FLOAT) { f = !f; - else + } else { val = !val; + } } else if (*end_leader == '-') { - if (rettv->v_type == VAR_FLOAT) + if (rettv->v_type == VAR_FLOAT) { f = -f; - else + } else { val = -val; + } } } if (rettv->v_type == VAR_FLOAT) { @@ -7236,6 +7219,7 @@ static struct fst { { "islocked", 1, 1, f_islocked }, { "items", 1, 1, f_items }, { "jobclose", 1, 2, f_jobclose }, + { "jobpid", 1, 1, f_jobpid }, { "jobresize", 3, 3, f_jobresize }, { "jobsend", 2, 2, f_jobsend }, { "jobstart", 1, 2, f_jobstart }, @@ -11611,6 +11595,31 @@ static void f_jobclose(typval_T *argvars, typval_T *rettv) } } +// "jobpid(id)" function +static void f_jobpid(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_NUMBER) { + EMSG(_(e_invarg)); + return; + } + + TerminalJobData *data = find_job(argvars[0].vval.v_number); + if (!data) { + EMSG(_(e_invjob)); + return; + } + + Process *proc = (Process *)&data->proc; + rettv->vval.v_number = proc->pid; +} + // "jobsend()" function static void f_jobsend(typval_T *argvars, typval_T *rettv) { @@ -11771,8 +11780,9 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv) } bool pty = job_opts && get_dict_number(job_opts, (uint8_t *)"pty") != 0; + bool detach = job_opts && get_dict_number(job_opts, (uint8_t *)"detach") != 0; TerminalJobData *data = common_job_init(argv, on_stdout, on_stderr, on_exit, - job_opts, pty); + job_opts, pty, detach); Process *proc = (Process *)&data->proc; if (pty) { @@ -15971,9 +15981,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv) rettv->v_type = VAR_FLOAT; } -/* - * "str2nr()" function - */ +// "str2nr()" function static void f_str2nr(typval_T *argvars, typval_T *rettv) { int base = 10; @@ -15982,16 +15990,21 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv) if (argvars[1].v_type != VAR_UNKNOWN) { base = get_tv_number(&argvars[1]); - if (base != 8 && base != 10 && base != 16) { + if (base != 2 && base != 8 && base != 10 && base != 16) { EMSG(_(e_invarg)); return; } } p = skipwhite(get_tv_string(&argvars[0])); - if (*p == '+') + if (*p == '+') { p = skipwhite(p + 1); - vim_str2nr(p, NULL, NULL, base == 8 ? 2 : 0, base == 16 ? 2 : 0, &n, NULL); + } + vim_str2nr(p, NULL, NULL, + base == 2 ? 2 : 0, + base == 8 ? 2 : 0, + base == 16 ? 2 : 0, + &n, NULL); rettv->vval.v_number = n; } @@ -16776,7 +16789,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv) } TerminalJobData *data = common_job_init(argv, on_stdout, on_stderr, on_exit, - job_opts, true); + job_opts, true, false); data->proc.pty.width = curwin->w_width; data->proc.pty.height = curwin->w_height; data->proc.pty.term_name = xstrdup("xterm-256color"); @@ -18271,9 +18284,10 @@ long get_tv_number_chk(typval_T *varp, int *denote) EMSG(_("E703: Using a Funcref as a Number")); break; case VAR_STRING: - if (varp->vval.v_string != NULL) + if (varp->vval.v_string != NULL) { vim_str2nr(varp->vval.v_string, NULL, NULL, - TRUE, TRUE, &n, NULL); + true, true, true, &n, NULL); + } return n; case VAR_LIST: EMSG(_("E745: Using a List as a Number")); @@ -18285,10 +18299,12 @@ long get_tv_number_chk(typval_T *varp, int *denote) EMSG2(_(e_intern2), "get_tv_number()"); break; } - if (denote == NULL) /* useful for values that must be unsigned */ + if (denote == NULL) { + // useful for values that must be unsigned n = -1; - else - *denote = TRUE; + } else { + *denote = true; + } return n; } @@ -21782,8 +21798,13 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) return ret; } -static inline TerminalJobData *common_job_init(char **argv, ufunc_T *on_stdout, - ufunc_T *on_stderr, ufunc_T *on_exit, dict_T *self, bool pty) +static inline TerminalJobData *common_job_init(char **argv, + ufunc_T *on_stdout, + ufunc_T *on_stderr, + ufunc_T *on_exit, + dict_T *self, + bool pty, + bool detach) { TerminalJobData *data = xcalloc(1, sizeof(TerminalJobData)); data->stopped = false; @@ -21806,6 +21827,7 @@ static inline TerminalJobData *common_job_init(char **argv, ufunc_T *on_stdout, } proc->cb = on_process_exit; proc->events = data->events; + proc->detach = detach; return data; } @@ -21833,8 +21855,13 @@ static inline bool common_job_callbacks(dict_T *vopts, ufunc_T **on_stdout, static inline bool common_job_start(TerminalJobData *data, typval_T *rettv) { - data->refcount++; Process *proc = (Process *)&data->proc; + if (proc->type == kProcessTypePty && proc->detach) { + EMSG2(_(e_invarg2), "terminal/pty job cannot be detached"); + return false; + } + + data->refcount++; char *cmd = xstrdup(proc->argv[0]); if (!process_spawn(proc)) { EMSG2(_(e_jobspawn), cmd); diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index 44305c69bc..9ef3468284 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -21,6 +21,9 @@ bool libuv_process_spawn(LibuvProcess *uvproc) uvproc->uvopts.args = proc->argv; uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + if (proc->detach) { + uvproc->uvopts.flags |= UV_PROCESS_DETACHED; + } uvproc->uvopts.exit_cb = exit_cb; uvproc->uvopts.cwd = NULL; uvproc->uvopts.env = NULL; diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 0336eb880a..e6012595fd 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -29,6 +29,7 @@ } \ } while (0) +static bool process_is_tearing_down = false; bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL { @@ -112,11 +113,22 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL { + process_is_tearing_down = true; kl_iter(WatcherPtr, loop->children, current) { Process *proc = (*current)->data; - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; - process_stop(proc); + if (proc->detach) { + // Close handles to process without killing it. + CREATE_EVENT(loop->events, process_close_handles, 1, proc); + } else { + if (proc->type == kProcessTypeUv) { + uv_kill(proc->pid, SIGTERM); + proc->term_sent = true; + process_stop(proc); + } else { // kProcessTypePty + process_close_streams(proc); + pty_process_close_master((PtyProcess *)proc); + } + } } // Wait until all children exit @@ -303,6 +315,10 @@ static void decref(Process *proc) static void process_close(Process *proc) FUNC_ATTR_NONNULL_ARG(1) { + if (process_is_tearing_down && proc->detach && proc->closed) { + // If a detached process dies while tearing down it might get closed twice. + return; + } assert(!proc->closed); proc->closed = true; switch (proc->type) { @@ -333,6 +349,7 @@ static void on_process_exit(Process *proc) DLOG("Stopping process kill timer"); uv_timer_stop(&loop->children_kill_timer); } + // Process handles are closed in the next event loop tick. This is done to // give libuv more time to read data from the OS after the process exits(If // process_close_streams is called with data still in the OS buffer, we lose diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 45edc46b95..e23c8ea60f 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -25,7 +25,7 @@ struct process { Stream *in, *out, *err; process_exit_cb cb; internal_process_cb internal_exit_cb, internal_close_cb; - bool closed, term_sent; + bool closed, term_sent, detach; Queue *events; }; @@ -48,7 +48,8 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data) .closed = false, .term_sent = false, .internal_close_cb = NULL, - .internal_exit_cb = NULL + .internal_exit_cb = NULL, + .detach = false }; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index b1ae6520b1..407dded6af 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -329,9 +329,7 @@ static int sort_compare(const void *s1, const void *s2) return result; } -/* - * ":sort". - */ +// ":sort". void ex_sort(exarg_T *eap) { regmatch_T regmatch; @@ -343,17 +341,19 @@ void ex_sort(exarg_T *eap) char_u *p; char_u *s; char_u *s2; - char_u c; /* temporary character storage */ - int unique = FALSE; + char_u c; // temporary character storage + int unique = false; long deleted; colnr_T start_col; colnr_T end_col; - int sort_oct; /* sort on octal number */ - int sort_hex; /* sort on hex number */ + int sort_bin; // sort on bin number + int sort_oct; // sort on octal number + int sort_hex; // sort on hex number - /* Sorting one line is really quick! */ - if (count <= 1) + // Sorting one line is really quick! + if (count <= 1) { return; + } if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL) return; @@ -362,47 +362,51 @@ void ex_sort(exarg_T *eap) regmatch.regprog = NULL; sorti_T *nrs = xmalloc(count * sizeof(sorti_T)); - sort_abort = sort_ic = sort_rx = sort_nr = sort_oct = sort_hex = 0; + sort_abort = sort_ic = sort_rx = sort_nr = sort_bin = sort_oct = sort_hex = 0; for (p = eap->arg; *p != NUL; ++p) { - if (ascii_iswhite(*p)) - ; - else if (*p == 'i') - sort_ic = TRUE; - else if (*p == 'r') - sort_rx = TRUE; - else if (*p == 'n') + if (ascii_iswhite(*p)) { + } else if (*p == 'i') { + sort_ic = true; + } else if (*p == 'r') { + sort_rx = true; + } else if (*p == 'n') { sort_nr = 2; - else if (*p == 'o') + } else if (*p == 'b') { + sort_bin = 2; + } else if (*p == 'o') { sort_oct = 2; - else if (*p == 'x') + } else if (*p == 'x') { sort_hex = 2; - else if (*p == 'u') - unique = TRUE; - else if (*p == '"') /* comment start */ + } else if (*p == 'u') { + unique = true; + } else if (*p == '"') { + // comment start break; - else if (check_nextcmd(p) != NULL) { + } else if (check_nextcmd(p) != NULL) { eap->nextcmd = check_nextcmd(p); break; } else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) { - s = skip_regexp(p + 1, *p, TRUE, NULL); + s = skip_regexp(p + 1, *p, true, NULL); if (*s != *p) { EMSG(_(e_invalpat)); goto sortend; } *s = NUL; - /* Use last search pattern if sort pattern is empty. */ + // Use last search pattern if sort pattern is empty. if (s == p + 1) { if (last_search_pat() == NULL) { EMSG(_(e_noprevre)); goto sortend; } regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC); - } else + } else { regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC); - if (regmatch.regprog == NULL) + } + if (regmatch.regprog == NULL) { goto sortend; - p = s; /* continue after the regexp */ + } + p = s; // continue after the regexp regmatch.rm_ic = p_ic; } else { EMSG2(_(e_invarg2), p); @@ -410,28 +414,27 @@ void ex_sort(exarg_T *eap) } } - /* Can only have one of 'n', 'o' and 'x'. */ - if (sort_nr + sort_oct + sort_hex > 2) { + // Can only have one of 'n', 'b', 'o' and 'x'. + if (sort_nr + sort_bin + sort_oct + sort_hex > 2) { EMSG(_(e_invarg)); goto sortend; } - /* From here on "sort_nr" is used as a flag for any number sorting. */ - sort_nr += sort_oct + sort_hex; + // From here on "sort_nr" is used as a flag for any number sorting. + sort_nr += sort_bin + sort_oct + sort_hex; - /* - * Make an array with all line numbers. This avoids having to copy all - * the lines into allocated memory. - * When sorting on strings "start_col_nr" is the offset in the line, for - * numbers sorting it's the number to sort on. This means the pattern - * matching and number conversion only has to be done once per line. - * Also get the longest line length for allocating "sortbuf". - */ + // Make an array with all line numbers. This avoids having to copy all + // the lines into allocated memory. + // When sorting on strings "start_col_nr" is the offset in the line, for + // numbers sorting it's the number to sort on. This means the pattern + // matching and number conversion only has to be done once per line. + // Also get the longest line length for allocating "sortbuf". for (lnum = eap->line1; lnum <= eap->line2; ++lnum) { s = ml_get(lnum); len = (int)STRLEN(s); - if (maxlen < len) + if (maxlen < len) { maxlen = len; + } start_col = 0; end_col = len; @@ -439,34 +442,41 @@ void ex_sort(exarg_T *eap) if (sort_rx) { start_col = (colnr_T)(regmatch.startp[0] - s); end_col = (colnr_T)(regmatch.endp[0] - s); - } else + } else { start_col = (colnr_T)(regmatch.endp[0] - s); - } else if (regmatch.regprog != NULL) + } + } else if (regmatch.regprog != NULL) { end_col = 0; + } if (sort_nr) { - /* Make sure vim_str2nr doesn't read any digits past the end - * of the match, by temporarily terminating the string there */ + // Make sure vim_str2nr doesn't read any digits past the end + // of the match, by temporarily terminating the string there s2 = s + end_col; c = *s2; *s2 = NUL; - /* Sorting on number: Store the number itself. */ + // Sorting on number: Store the number itself. p = s + start_col; - if (sort_hex) + if (sort_hex) { s = skiptohex(p); - else + } else if (sort_bin) { + s = (char_u*) skiptobin((char*) p); + } else { s = skiptodigit(p); - if (s > p && s[-1] == '-') - --s; /* include preceding negative sign */ - if (*s == NUL) - /* empty line should sort before any number */ + } + if (s > p && s[-1] == '-') { + --s; // include preceding negative sign + } + if (*s == NUL) { + // empty line should sort before any number nrs[lnum - eap->line1].start_col_nr = -MAXLNUM; - else - vim_str2nr(s, NULL, NULL, sort_oct, sort_hex, - &nrs[lnum - eap->line1].start_col_nr, NULL); + } else { + vim_str2nr(s, NULL, NULL, sort_bin, sort_oct, sort_hex, + &nrs[lnum - eap->line1].start_col_nr, NULL); + } *s2 = c; } else { - /* Store the column to sort at. */ + // Store the column to sort at. nrs[lnum - eap->line1].start_col_nr = start_col; nrs[lnum - eap->line1].end_col_nr = end_col; } @@ -479,17 +489,17 @@ void ex_sort(exarg_T *eap) goto sortend; } - /* Allocate a buffer that can hold the longest line. */ + // Allocate a buffer that can hold the longest line. sortbuf1 = xmalloc(maxlen + 1); sortbuf2 = xmalloc(maxlen + 1); - /* Sort the array of line numbers. Note: can't be interrupted! */ + // Sort the array of line numbers. Note: can't be interrupted! qsort((void *)nrs, count, sizeof(sorti_T), sort_compare); if (sort_abort) goto sortend; - /* Insert the lines in the sorted order below the last one. */ + // Insert the lines in the sorted order below the last one. lnum = eap->line2; for (i = 0; i < count; ++i) { s = ml_get(nrs[eap->forceit ? count - i - 1 : i].lnum); @@ -507,19 +517,22 @@ void ex_sort(exarg_T *eap) goto sortend; } - /* delete the original lines if appending worked */ - if (i == count) - for (i = 0; i < count; ++i) - ml_delete(eap->line1, FALSE); - else + // delete the original lines if appending worked + if (i == count) { + for (i = 0; i < count; ++i) { + ml_delete(eap->line1, false); + } + } else { count = 0; + } - /* Adjust marks for deleted (or added) lines and prepare for displaying. */ + // Adjust marks for deleted (or added) lines and prepare for displaying. deleted = (long)(count - (lnum - eap->line2)); - if (deleted > 0) + if (deleted > 0) { mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted); - else if (deleted < 0) + } else if (deleted < 0) { mark_adjust(eap->line2, MAXLNUM, -deleted, 0L); + } changed_lines(eap->line1, 0, eap->line2 + 1, -deleted); curwin->w_cursor.lnum = eap->line1; @@ -530,8 +543,9 @@ sortend: xfree(sortbuf1); xfree(sortbuf2); vim_regfree(regmatch.regprog); - if (got_int) + if (got_int) { EMSG(_(e_interr)); + } } /* @@ -951,30 +965,26 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out) xfree(newcmd); } -/* - * do_filter: filter lines through a command given by the user - * - * We mostly use temp files and the call_shell() routine here. This would - * normally be done using pipes on a UNIX machine, but this is more portable - * to non-unix machines. The call_shell() routine needs to be able - * to deal with redirection somehow, and should handle things like looking - * at the PATH env. variable, and adding reasonable extensions to the - * command name given by the user. All reasonable versions of call_shell() - * do this. - * Alternatively, if on Unix and redirecting input or output, but not both, - * and the 'shelltemp' option isn't set, use pipes. - * We use input redirection if do_in is TRUE. - * We use output redirection if do_out is TRUE. - */ -static void -do_filter ( +// do_filter: filter lines through a command given by the user +// +// We mostly use temp files and the call_shell() routine here. This would +// normally be done using pipes on a Unix system, but this is more portable +// to non-Unix systems. The call_shell() routine needs to be able +// to deal with redirection somehow, and should handle things like looking +// at the PATH env. variable, and adding reasonable extensions to the +// command name given by the user. All reasonable versions of call_shell() +// do this. +// Alternatively, if on Unix and redirecting input or output, but not both, +// and the 'shelltemp' option isn't set, use pipes. +// We use input redirection if do_in is TRUE. +// We use output redirection if do_out is TRUE. +static void do_filter( linenr_T line1, linenr_T line2, exarg_T *eap, /* for forced 'ff' and 'fenc' */ char_u *cmd, int do_in, - int do_out -) + int do_out) { char_u *itmp = NULL; char_u *otmp = NULL; @@ -1690,7 +1700,7 @@ check_overwrite ( && os_file_exists(ffname)) { if (!eap->forceit && !eap->append) { #ifdef UNIX - /* with UNIX it is possible to open a directory */ + // It is possible to open a directory on Unix. if (os_isdir(ffname)) { EMSG2(_(e_isadir2), ffname); return FAIL; @@ -2859,6 +2869,8 @@ void do_sub(exarg_T *eap) static int do_list = FALSE; /* list last line with subs. */ static int do_number = FALSE; /* list last line with line nr*/ static int do_ic = 0; /* ignore case flag */ + int save_do_all; // remember user specified 'g' flag + int save_do_ask; // remember user specified 'c' flag char_u *pat = NULL, *sub = NULL; /* init for GCC */ int delimiter; int sublen; @@ -3048,12 +3060,14 @@ void do_sub(exarg_T *eap) break; ++cmd; } - if (do_count) + if (do_count) { do_ask = FALSE; + } - /* - * check for a trailing count - */ + save_do_all = do_all; + save_do_ask = do_ask; + + // check for a trailing count cmd = skipwhite(cmd); if (ascii_isdigit(*cmd)) { i = getdigits_long(&cmd); @@ -3752,8 +3766,12 @@ skip: /* Cursor position may require updating */ changed_window_setting(); - vim_regfree(regmatch.regprog); -} + vim_regfree(regmatch.regprog); + + // Restore the flag values, they can be used for ":&&". + do_all = save_do_all; + do_ask = save_do_ask; + } /* * Give message for number of substitutions. diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 702abf3cf0..6c8835b5c5 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1025,12 +1025,6 @@ return { func='ex_helpclose', }, { - command='helpfind', - flags=bit.bor(EXTRA, NOTRLCOM), - addr_type=ADDR_LINES, - func='ex_ni', - }, - { command='helpgrep', flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG), addr_type=ADDR_LINES, diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 57153cf5a1..47774f5a99 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -6,6 +6,7 @@ #include <inttypes.h> #include <stdbool.h> #include <string.h> +#include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 84bd31d9ad..cbe7c1a231 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6843,9 +6843,9 @@ void ex_cd(exarg_T *eap) prev_dir = NULL; #if defined(UNIX) - /* for UNIX ":cd" means: go to home directory */ + // On Unix ":cd" means: go to home directory. if (*new_dir == NUL) { - /* use NameBuff for home directory name */ + // Use NameBuff for home directory name. expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); new_dir = NameBuff; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6d81f3680a..87a6bf8901 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -596,7 +596,7 @@ static int command_line_execute(VimState *state, int key) } if (s->j > 0) { - // TODO(tarruda): this is only for DOS/UNIX systems - need to put in + // TODO(tarruda): this is only for DOS/Unix systems - need to put in // machine-specific stuff here and in upseg init cmdline_del(s->j); put_on_cmdline(upseg + 1, 3, false); @@ -4767,35 +4767,40 @@ int del_history_idx(int histype, int idx) return TRUE; } -/* - * Get indices "num1,num2" that specify a range within a list (not a range of - * text lines in a buffer!) from a string. Used for ":history" and ":clist". - * Returns OK if parsed successfully, otherwise FAIL. - */ +/// Get indices that specify a range within a list (not a range of text lines +/// in a buffer!) from a string. Used for ":history" and ":clist". +/// +/// @param str string to parse range from +/// @param num1 from +/// @param num2 to +/// +/// @return OK if parsed successfully, otherwise FAIL. int get_list_range(char_u **str, int *num1, int *num2) { int len; - int first = FALSE; + int first = false; long num; *str = skipwhite(*str); - if (**str == '-' || ascii_isdigit(**str)) { /* parse "from" part of range */ - vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL); + if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range + vim_str2nr(*str, NULL, &len, false, false, false, &num, NULL); *str += len; *num1 = (int)num; - first = TRUE; + first = true; } *str = skipwhite(*str); - if (**str == ',') { /* parse "to" part of range */ + if (**str == ',') { // parse "to" part of range *str = skipwhite(*str + 1); - vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL); + vim_str2nr(*str, NULL, &len, false, false, false, &num, NULL); if (len > 0) { *num2 = (int)num; *str = skipwhite(*str + len); - } else if (!first) /* no number given at all */ + } else if (!first) { // no number given at all return FAIL; - } else if (first) /* only one number given */ + } + } else if (first) { // only one number given *num2 = *num1; + } return OK; } diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index bd0f0fc80a..26376afa27 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -7,6 +7,7 @@ #include <stdbool.h> #include <string.h> #include <inttypes.h> +#include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" @@ -366,14 +367,13 @@ readfile ( /* don't display the file info for another buffer now */ need_fileinfo = FALSE; - /* - * For Unix: Use the short file name whenever possible. - * Avoids problems with networks and when directory names are changed. - * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to - * another directory, which we don't detect. - */ - if (sfname == NULL) + // For Unix: Use the short file name whenever possible. + // Avoids problems with networks and when directory names are changed. + // Don't do this for Windows, a "cd" in a sub-shell may have moved us to + // another directory, which we don't detect. + if (sfname == NULL) { sfname = fname; + } #if defined(UNIX) fname = sfname; #endif @@ -1992,13 +1992,14 @@ failed: } #ifdef OPEN_CHR_FILES -/* - * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+", - * which is the name of files used for process substitution output by - * some shells on some operating systems, e.g., bash on SunOS. - * Do not accept "/dev/fd/[012]", opening these may hang Vim. - */ -static int is_dev_fd_file(char_u *fname) +/// Returns true if the file name argument is of the form "/dev/fd/\d\+", +/// which is the name of files used for process substitution output by +/// some shells on some operating systems, e.g., bash on SunOS. +/// Do not accept "/dev/fd/[012]", opening these may hang Vim. +/// +/// @param fname file name to check +static bool is_dev_fd_file(char_u *fname) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { return STRNCMP(fname, "/dev/fd/", 8) == 0 && ascii_isdigit(fname[8]) @@ -2353,13 +2354,12 @@ buf_write ( if (sfname == NULL) sfname = fname; - /* - * For Unix: Use the short file name whenever possible. - * Avoids problems with networks and when directory names are changed. - * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to - * another directory, which we don't detect - */ - ffname = fname; /* remember full fname */ + + // For Unix: Use the short file name whenever possible. + // Avoids problems with networks and when directory names are changed. + // Don't do this for Windows, a "cd" in a sub-shell may have moved us to + // another directory, which we don't detect. + ffname = fname; // remember full fname #ifdef UNIX fname = sfname; #endif @@ -3807,29 +3807,30 @@ void msg_add_fname(buf_T *buf, char_u *fname) STRCAT(IObuff, "\" "); } -/* - * Append message for text mode to IObuff. - * Return TRUE if something appended. - */ -static int msg_add_fileformat(int eol_type) +/// Append message for text mode to IObuff. +/// +/// @param eol_type line ending type +/// +/// @return true if something was appended. +static bool msg_add_fileformat(int eol_type) { #ifndef USE_CRNL if (eol_type == EOL_DOS) { STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]")); - return TRUE; + return true; } #endif if (eol_type == EOL_MAC) { STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]")); - return TRUE; + return true; } #ifdef USE_CRNL if (eol_type == EOL_UNIX) { STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]")); - return TRUE; + return true; } #endif - return FALSE; + return false; } /* @@ -3893,7 +3894,11 @@ static int check_mtime(buf_T *buf, FileInfo *file_info) return OK; } -static int time_differs(long t1, long t2) +/// Return true if the times differ +/// +/// @param t1 first time +/// @param t2 second time +static bool time_differs(long t1, long t2) FUNC_ATTR_CONST { #if defined(__linux__) || defined(MSWIN) /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store @@ -4082,19 +4087,17 @@ static int buf_write_bytes(struct bw_info *ip) return (wlen < len) ? FAIL : OK; } -/* - * Convert a Unicode character to bytes. - * Return TRUE for an error, FALSE when it's OK. - */ -static int -ucs2bytes ( - unsigned c, /* in: character */ - char_u **pp, /* in/out: pointer to result */ - int flags /* FIO_ flags */ -) +/// Convert a Unicode character to bytes. +/// +/// @param c character to convert +/// @param[in,out] pp pointer to store the result at +/// @param flags FIO_ flags that specify which encoding to use +/// +/// @return true for an error, false when it's OK. +static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL { char_u *p = *pp; - int error = FALSE; + bool error = false; int cc; @@ -4116,8 +4119,9 @@ ucs2bytes ( /* Make two words, ten bits of the character in each. First * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */ c -= 0x10000; - if (c >= 0x100000) - error = TRUE; + if (c >= 0x100000) { + error = true; + } cc = ((c >> 10) & 0x3ff) + 0xd800; if (flags & FIO_ENDIAN_L) { *p++ = cc; @@ -4127,8 +4131,9 @@ ucs2bytes ( *p++ = cc; } c = (c & 0x3ff) + 0xdc00; - } else - error = TRUE; + } else { + error = true; + } } if (flags & FIO_ENDIAN_L) { *p++ = c; @@ -4139,7 +4144,7 @@ ucs2bytes ( } } else { /* Latin1 */ if (c >= 0x100) { - error = TRUE; + error = true; *p++ = 0xBF; } else *p++ = c; @@ -4149,11 +4154,14 @@ ucs2bytes ( return error; } -/* - * Return TRUE if file encoding "fenc" requires conversion from or to - * 'encoding'. - */ -static int need_conversion(char_u *fenc) +/// Return true if file encoding "fenc" requires conversion from or to +/// 'encoding'. +/// +/// @param fenc file encoding to check +/// +/// @return true if conversion is required +static bool need_conversion(const char_u *fenc) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int same_encoding; int enc_flags; @@ -4180,19 +4188,19 @@ static int need_conversion(char_u *fenc) return !(enc_utf8 && fenc_flags == FIO_UTF8); } -/* - * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the - * internal conversion. - * if "ptr" is an empty string, use 'encoding'. - */ -static int get_fio_flags(char_u *ptr) +/// Return the FIO_ flags needed for the internal conversion if 'name' was +/// unicode or latin1, otherwise 0. If "name" is an empty string, +/// use 'encoding'. +/// +/// @param name string to check for encoding +static int get_fio_flags(const char_u *name) { int prop; - if (*ptr == NUL) - ptr = p_enc; - - prop = enc_canon_props(ptr); + if (*name == NUL) { + name = p_enc; + } + prop = enc_canon_props(name); if (prop & ENC_UNICODE) { if (prop & ENC_2BYTE) { if (prop & ENC_ENDIAN_L) @@ -4424,11 +4432,15 @@ char *modname(const char *fname, const char *ext, bool prepend_dot) return retval; } -/* - * Like fgets(), but if the file line is too long, it is truncated and the - * rest of the line is thrown away. Returns TRUE for end-of-file. - */ -int vim_fgets(char_u *buf, int size, FILE *fp) +/// Like fgets(), but if the file line is too long, it is truncated and the +/// rest of the line is thrown away. +/// +/// @param[out] buf buffer to fill +/// @param size size of the buffer +/// @param fp file to read from +/// +/// @return true for end-of-file. +bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL { char *eof; #define FGETS_SIZE 200 @@ -5327,11 +5339,13 @@ static void au_del_group(char_u *name) } } -/* - * Find the ID of an autocmd group name. - * Return it's ID. Returns AUGROUP_ERROR (< 0) for error. - */ -static int au_find_group(char_u *name) +/// Find the ID of an autocmd group name. +/// +/// @param name augroup name +/// +/// @return the ID or AUGROUP_ERROR (< 0) for error. +static int au_find_group(const char_u *name) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { for (int i = 0; i < augroups.ga_len; ++i) { if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0) { @@ -5341,10 +5355,11 @@ static int au_find_group(char_u *name) return AUGROUP_ERROR; } -/* - * Return TRUE if augroup "name" exists. - */ -int au_has_group(char_u *name) +/// Return true if augroup "name" exists. +/// +/// @param name augroup name +bool au_has_group(const char_u *name) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { return au_find_group(name) != AUGROUP_ERROR; } @@ -5461,21 +5476,24 @@ find_end_event ( return pat; } -/* - * Return TRUE if "event" is included in 'eventignore'. - */ -static int event_ignored(event_T event) +/// Return true if "event" is included in 'eventignore'. +/// +/// @param event event to check +static bool event_ignored(event_T event) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - char_u *p = p_ei; + char_u *p = p_ei; while (*p != NUL) { - if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) - return TRUE; - if (event_name2nr(p, &p) == event) - return TRUE; + if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) { + return true; + } + if (event_name2nr(p, &p) == event) { + return true; + } } - return FALSE; + return false; } /* @@ -5992,18 +6010,19 @@ void ex_doautoall(exarg_T *eap) check_cursor(); /* just in case lines got deleted */ } -/* - * Check *argp for <nomodeline>. When it is present return FALSE, otherwise - * return TRUE and advance *argp to after it. - * Thus return TRUE when do_modelines() should be called. - */ -int check_nomodeline(char_u **argp) +/// Check *argp for <nomodeline>. When it is present return false, otherwise +/// return true and advance *argp to after it. Thus do_modelines() should be +/// called when true is returned. +/// +/// @param[in,out] argp argument string +bool check_nomodeline(char_u **argp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { if (STRNCMP(*argp, "<nomodeline>", 12) == 0) { *argp = skipwhite(*argp + 12); - return FALSE; + return false; } - return TRUE; + return true; } /* @@ -6180,76 +6199,78 @@ win_found: static int autocmd_nested = FALSE; -/* - * Execute autocommands for "event" and file name "fname". - * Return TRUE if some commands were executed. - */ -int -apply_autocmds ( - event_T event, - char_u *fname, /* NULL or empty means use actual file name */ - char_u *fname_io, /* fname to use for <afile> on cmdline */ - int force, /* when TRUE, ignore autocmd_busy */ - buf_T *buf /* buffer for <abuf> */ -) +/// Execute autocommands for "event" and file name "fname". +/// +/// @param event event that occured +/// @param fname filename, NULL or empty means use actual file name +/// @param fname_io filename to use for <afile> on cmdline +/// @param force When true, ignore autocmd_busy +/// @param buf Buffer for <abuf> +/// +/// @return true if some commands were executed. +bool apply_autocmds(event_T event, char_u *fname, char_u *fname_io, bool force, + buf_T *buf) { return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL); } -/* - * Like apply_autocmds(), but with extra "eap" argument. This takes care of - * setting v:filearg. - */ -static int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap) +/// Like apply_autocmds(), but with extra "eap" argument. This takes care of +/// setting v:filearg. +/// +/// @param event event that occured +/// @param fname NULL or empty means use actual file name +/// @param fname_io fname to use for <afile> on cmdline +/// @param force When true, ignore autocmd_busy +/// @param buf Buffer for <abuf> +/// @param exarg Ex command arguments +/// +/// @return true if some commands were executed. +static bool apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, + bool force, buf_T *buf, exarg_T *eap) { return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap); } -/* - * Like apply_autocmds(), but handles the caller's retval. If the script - * processing is being aborted or if retval is FAIL when inside a try - * conditional, no autocommands are executed. If otherwise the autocommands - * cause the script to be aborted, retval is set to FAIL. - */ -int -apply_autocmds_retval ( - event_T event, - char_u *fname, /* NULL or empty means use actual file name */ - char_u *fname_io, /* fname to use for <afile> on cmdline */ - int force, /* when TRUE, ignore autocmd_busy */ - buf_T *buf, /* buffer for <abuf> */ - int *retval /* pointer to caller's retval */ -) +/// Like apply_autocmds(), but handles the caller's retval. If the script +/// processing is being aborted or if retval is FAIL when inside a try +/// conditional, no autocommands are executed. If otherwise the autocommands +/// cause the script to be aborted, retval is set to FAIL. +/// +/// @param event event that occured +/// @param fname NULL or empty means use actual file name +/// @param fname_io fname to use for <afile> on cmdline +/// @param force When true, ignore autocmd_busy +/// @param buf Buffer for <abuf> +/// @param[in,out] retval caller's retval +/// +/// @return true if some autocommands were executed +bool apply_autocmds_retval(event_T event, char_u *fname, char_u *fname_io, + bool force, buf_T *buf, int *retval) { - int did_cmd; - - if (should_abort(*retval)) - return FALSE; + if (should_abort(*retval)) { + return false; + } - did_cmd = apply_autocmds_group(event, fname, fname_io, force, - AUGROUP_ALL, buf, NULL); - if (did_cmd - && aborting() - ) + bool did_cmd = apply_autocmds_group(event, fname, fname_io, force, + AUGROUP_ALL, buf, NULL); + if (did_cmd && aborting()) { *retval = FAIL; + } return did_cmd; } -/* - * Return TRUE when there is a CursorHold autocommand defined. - */ -int has_cursorhold(void) +/// Return true when there is a CursorHold/CursorHoldI autocommand defined for +/// the current mode. +bool has_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { return first_autopat[(int)(get_real_state() == NORMAL_BUSY ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL; } -/* - * Return TRUE if the CursorHold event can be triggered. - */ -int trigger_cursorhold(void) +/// Return true if the CursorHold/CursorHoldI event can be triggered. +bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { int state; @@ -6260,10 +6281,11 @@ int trigger_cursorhold(void) && !ins_compl_active() ) { state = get_real_state(); - if (state == NORMAL_BUSY || (state & INSERT) != 0) - return TRUE; + if (state == NORMAL_BUSY || (state & INSERT) != 0) { + return true; + } } - return FALSE; + return false; } /// Return true if "event" autocommand is defined. @@ -6274,23 +6296,27 @@ bool has_event(int event) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return first_autopat[event] != NULL; } -static int -apply_autocmds_group ( - event_T event, - char_u *fname, /* NULL or empty means use actual file name */ - char_u *fname_io, /* fname to use for <afile> on cmdline, NULL means - use fname */ - int force, /* when TRUE, ignore autocmd_busy */ - int group, /* group ID, or AUGROUP_ALL */ - buf_T *buf, /* buffer for <abuf> */ - exarg_T *eap /* command arguments */ -) +/// Execute autocommands for "event" and file name "fname". +/// +/// @param event event that occured +/// @param fname filename, NULL or empty means use actual file name +/// @param fname_io filename to use for <afile> on cmdline, +/// NULL means use `fname`. +/// @param force When true, ignore autocmd_busy +/// @param group autocmd group ID or AUGROUP_ALL +/// @param buf Buffer for <abuf> +/// @param exarg Ex command arguments +/// +/// @return true if some commands were executed. +static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, + bool force, int group, buf_T *buf, + exarg_T *eap) { char_u *sfname = NULL; /* short file name */ char_u *tail; bool save_changed; buf_T *old_curbuf; - int retval = FALSE; + bool retval = false; char_u *save_sourcing_name; linenr_T save_sourcing_lnum; char_u *save_autocmd_fname; @@ -6444,17 +6470,16 @@ apply_autocmds_group ( } if (fname == NULL) { /* out of memory */ xfree(sfname); - retval = FALSE; + retval = false; goto BYPASS_AU; } #ifdef BACKSLASH_IN_FILENAME - /* - * Replace all backslashes with forward slashes. This makes the - * autocommand patterns portable between Unix and MS-DOS. - */ - if (sfname != NULL) + // Replace all backslashes with forward slashes. This makes the + // autocommand patterns portable between Unix and Windows. + if (sfname != NULL) { forward_slash(sfname); + } forward_slash(fname); #endif @@ -6528,17 +6553,19 @@ apply_autocmds_group ( if (eap != NULL) { save_cmdarg = set_cmdarg(eap, NULL); set_vim_var_nr(VV_CMDBANG, (long)eap->forceit); - } else - save_cmdarg = NULL; /* avoid gcc warning */ - retval = TRUE; - /* mark the last pattern, to avoid an endless loop when more patterns - * are added when executing autocommands */ - for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next) - ap->last = FALSE; - ap->last = TRUE; - check_lnums(TRUE); /* make sure cursor and topline are valid */ + } else { + save_cmdarg = NULL; // avoid gcc warning + } + retval = true; + // mark the last pattern, to avoid an endless loop when more patterns + // are added when executing autocommands + for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next) { + ap->last = false; + } + ap->last = true; + check_lnums(true); // make sure cursor and topline are valid do_cmdline(NULL, getnextac, (void *)&patcmd, - DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); + DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); if (eap != NULL) { (void)set_cmdarg(NULL, save_cmdarg); set_vim_var_nr(VV_CMDBANG, save_cmdbang); @@ -6754,42 +6781,44 @@ char_u *getnextac(int c, void *cookie, int indent) return retval; } -/* - * Return TRUE if there is a matching autocommand for "fname". - * To account for buffer-local autocommands, function needs to know - * in which buffer the file will be opened. - */ -int has_autocmd(event_T event, char_u *sfname, buf_T *buf) +/// Return true if there is a matching autocommand for "fname". +/// To account for buffer-local autocommands, function needs to know +/// in which buffer the file will be opened. +/// +/// @param event event that occured. +/// @param sfname filename the event occured in. +/// @param buf buffer the file is open in +bool has_autocmd(event_T event, char_u *sfname, buf_T *buf) + FUNC_ATTR_WARN_UNUSED_RESULT { AutoPat *ap; char_u *fname; char_u *tail = path_tail(sfname); - int retval = FALSE; + bool retval = false; - fname = (char_u *)FullName_save((char *)sfname, FALSE); - if (fname == NULL) - return FALSE; + fname = (char_u *)FullName_save((char *)sfname, false); + if (fname == NULL) { + return false; + } #ifdef BACKSLASH_IN_FILENAME - /* - * Replace all backslashes with forward slashes. This makes the - * autocommand patterns portable between Unix and MS-DOS. - */ + // Replace all backslashes with forward slashes. This makes the + // autocommand patterns portable between Unix and Windows. sfname = vim_strsave(sfname); forward_slash(sfname); forward_slash(fname); #endif - for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) + for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) { if (ap->pat != NULL && ap->cmds != NULL && (ap->buflocal_nr == 0 ? match_file_pat(NULL, &ap->reg_prog, fname, sfname, tail, ap->allow_dirs) - : buf != NULL && ap->buflocal_nr == buf->b_fnum - )) { - retval = TRUE; + : buf != NULL && ap->buflocal_nr == buf->b_fnum)) { + retval = true; break; } + } xfree(fname); #ifdef BACKSLASH_IN_FILENAME @@ -6877,29 +6906,27 @@ char_u *get_event_name(expand_T *xp, int idx) } -/* - * Return TRUE if autocmd is supported. - */ -int autocmd_supported(char_u *name) +/// Return true if autocmd "event" is supported. +bool autocmd_supported(char_u *event) { char_u *p; - return event_name2nr(name, &p) != NUM_EVENTS; + return event_name2nr(event, &p) != NUM_EVENTS; } -/* - * Return TRUE if an autocommand is defined for a group, event and - * pattern: The group can be omitted to accept any group. "event" and "pattern" - * can be NULL to accept any event and pattern. "pattern" can be NULL to accept - * any pattern. Buffer-local patterns <buffer> or <buffer=N> are accepted. - * Used for: - * exists("#Group") or - * exists("#Group#Event") or - * exists("#Group#Event#pat") or - * exists("#Event") or - * exists("#Event#pat") - */ -int au_exists(char_u *arg) +/// Return true if an autocommand is defined for a group, event and +/// pattern: The group can be omitted to accept any group. +/// `event` and `pattern` can be omitted to accept any event and pattern. +/// Buffer-local patterns <buffer> or <buffer=N> are accepted. +/// Used for: +/// exists("#Group") or +/// exists("#Group#Event") or +/// exists("#Group#Event#pat") or +/// exists("#Event") or +/// exists("#Event#pat") +/// +/// @param arg autocommand string +bool au_exists(const char_u *arg) FUNC_ATTR_WARN_UNUSED_RESULT { char_u *arg_save; char_u *pattern = NULL; @@ -6909,7 +6936,7 @@ int au_exists(char_u *arg) AutoPat *ap; buf_T *buflocal_buf = NULL; int group; - int retval = FALSE; + bool retval = false; /* Make a copy so that we can change the '#' chars to a NUL. */ arg_save = vim_strsave(arg); @@ -6925,8 +6952,8 @@ int au_exists(char_u *arg) event_name = arg_save; } else { if (p == NULL) { - /* "Group": group name is present and it's recognized */ - retval = TRUE; + // "Group": group name is present and it's recognized + retval = true; goto theend; } @@ -6968,7 +6995,7 @@ int au_exists(char_u *arg) || (buflocal_buf == NULL ? fnamecmp(ap->pat, pattern) == 0 : ap->buflocal_nr == buflocal_buf->b_fnum))) { - retval = TRUE; + retval = true; break; } @@ -6983,12 +7010,13 @@ theend: /// /// Used for autocommands and 'wildignore'. /// -/// @param pattern the pattern to match with -/// @param prog the pre-compiled regprog or NULL -/// @param fname the full path of the file name -/// @param sfname the short file name or NULL -/// @param tail the tail of the path -/// @param allow_dirs allow matching with dir +/// @param pattern pattern to match with +/// @param prog pre-compiled regprog or NULL +/// @param fname full path of the file name +/// @param sfname short file name or NULL +/// @param tail tail of the path +/// @param allow_dirs Allow matching with dir +/// /// @return true if there is a match, false otherwise static bool match_file_pat(char_u *pattern, regprog_T **prog, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs) @@ -7027,12 +7055,17 @@ static bool match_file_pat(char_u *pattern, regprog_T **prog, char_u *fname, return result; } -/* - * Return TRUE if a file matches with a pattern in "list". - * "list" is a comma-separated list of patterns, like 'wildignore'. - * "sfname" is the short file name or NULL, "ffname" the long file name. - */ -int match_file_list(char_u *list, char_u *sfname, char_u *ffname) +/// Check if a file matches with a pattern in "list". +/// "list" is a comma-separated list of patterns, like 'wildignore'. +/// "sfname" is the short file name or NULL, "ffname" the long file name. +/// +/// @param list list of patterns to match +/// @param sfname short file name +/// @param ffname full file name +/// +/// @return true if there was a match +bool match_file_list(char_u *list, char_u *sfname, char_u *ffname) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3) { char_u buf[100]; char_u *tail; @@ -7043,20 +7076,21 @@ int match_file_list(char_u *list, char_u *sfname, char_u *ffname) tail = path_tail(sfname); - /* try all patterns in 'wildignore' */ + // try all patterns in 'wildignore' p = list; while (*p) { - copy_option_part(&p, buf, 100, ","); - regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE); - if (regpat == NULL) + copy_option_part(&p, buf, ARRAY_SIZE(buf), ","); + regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false); + if (regpat == NULL) { break; - match = match_file_pat(regpat, NULL, ffname, sfname, - tail, (int)allow_dirs); + } + match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs); xfree(regpat); - if (match) - return TRUE; + if (match) { + return true; + } } - return FALSE; + return false; } /// Convert the given pattern "pat" which has shell style wildcards in it, into diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 50eda6cb17..b45f13de4c 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -8,11 +8,10 @@ // actually defined and initialized. #ifndef EXTERN # define EXTERN extern -# define INIT(x) +# define INIT(...) #else # ifndef INIT -# define INIT(x) x -# define DO_INIT +# define INIT(...) __VA_ARGS__ # endif #endif @@ -117,12 +116,9 @@ #define DFLT_COLS 80 /* default value for 'columns' */ #define DFLT_ROWS 24 /* default value for 'lines' */ -EXTERN long Rows /* nr of rows in the screen */ -#ifdef DO_INIT - = DFLT_ROWS -#endif -; -EXTERN long Columns INIT(= DFLT_COLS); /* nr of columns in the screen */ +EXTERN long Rows INIT(= DFLT_ROWS); // nr of rows in the screen + +EXTERN long Columns INIT(= DFLT_COLS); // nr of columns in the screen /* * The characters and attributes cached for the screen. @@ -751,11 +747,8 @@ EXTERN int can_si INIT(= FALSE); */ EXTERN int can_si_back INIT(= FALSE); -EXTERN pos_T saved_cursor /* w_cursor before formatting text. */ -#ifdef DO_INIT - = INIT_POS_T(0, 0, 0) -#endif -; +// w_cursor before formatting text. +EXTERN pos_T saved_cursor INIT(= INIT_POS_T(0, 0, 0)); /* * Stuff for insert mode. @@ -917,19 +910,16 @@ EXTERN int RedrawingDisabled INIT(= 0); EXTERN int readonlymode INIT(= FALSE); /* Set to TRUE for "view" */ EXTERN int recoverymode INIT(= FALSE); /* Set to TRUE for "-r" option */ -EXTERN typebuf_T typebuf /* typeahead buffer */ -#ifdef DO_INIT - = {NULL, NULL, 0, 0, 0, 0, 0, 0, 0} -#endif -; -EXTERN int ex_normal_busy INIT(= 0); /* recursiveness of ex_normal() */ -EXTERN int ex_normal_lock INIT(= 0); /* forbid use of ex_normal() */ -EXTERN int ignore_script INIT(= FALSE); /* ignore script input */ -EXTERN int stop_insert_mode; /* for ":stopinsert" and 'insertmode' */ +// typeahead buffer +EXTERN typebuf_T typebuf INIT(= { NULL, NULL, 0, 0, 0, 0, 0, 0, 0 }); -EXTERN int KeyTyped; /* TRUE if user typed current char */ -EXTERN int KeyStuffed; /* TRUE if current char from stuffbuf */ -EXTERN int maptick INIT(= 0); /* tick for each non-mapped char */ +EXTERN int ex_normal_busy INIT(= 0); // recursiveness of ex_normal() +EXTERN int ex_normal_lock INIT(= 0); // forbid use of ex_normal() +EXTERN int ignore_script INIT(= false); // ignore script input +EXTERN int stop_insert_mode; // for ":stopinsert" and 'insertmode' +EXTERN int KeyTyped; // TRUE if user typed current char +EXTERN int KeyStuffed; // TRUE if current char from stuffbuf +EXTERN int maptick INIT(= 0); // tick for each non-mapped char EXTERN char_u chartab[256]; /* table used in charset.c; See init_chartab() for explanation */ @@ -959,30 +949,28 @@ EXTERN reg_extmatch_T *re_extmatch_in INIT(= NULL); /* Used by vim_regexec(): EXTERN reg_extmatch_T *re_extmatch_out INIT(= NULL); /* Set by vim_regexec() * to store \z\(...\) matches */ -EXTERN int did_outofmem_msg INIT(= FALSE); -/* set after out of memory msg */ -EXTERN int did_swapwrite_msg INIT(= FALSE); -/* set after swap write error msg */ -EXTERN int undo_off INIT(= FALSE); /* undo switched off for now */ -EXTERN int global_busy INIT(= 0); /* set when :global is executing */ -EXTERN int listcmd_busy INIT(= FALSE); /* set when :argdo, :windo or - :bufdo is executing */ -EXTERN int need_start_insertmode INIT(= FALSE); -/* start insert mode soon */ -EXTERN char_u *last_cmdline INIT(= NULL); /* last command line (for ":) */ -EXTERN char_u *repeat_cmdline INIT(= NULL); /* command line for "." */ -EXTERN char_u *new_last_cmdline INIT(= NULL); /* new value for last_cmdline */ -EXTERN char_u *autocmd_fname INIT(= NULL); /* fname for <afile> on cmdline */ -EXTERN int autocmd_fname_full; /* autocmd_fname is full path */ -EXTERN int autocmd_bufnr INIT(= 0); /* fnum for <abuf> on cmdline */ -EXTERN char_u *autocmd_match INIT(= NULL); /* name for <amatch> on cmdline */ -EXTERN int did_cursorhold INIT(= FALSE); /* set when CursorHold t'gerd */ -EXTERN pos_T last_cursormoved /* for CursorMoved event */ -# ifdef DO_INIT - = INIT_POS_T(0, 0, 0) -# endif -; -EXTERN int last_changedtick INIT(= 0); /* for TextChanged event */ +EXTERN int did_outofmem_msg INIT(= false); +// set after out of memory msg +EXTERN int did_swapwrite_msg INIT(= false); +// set after swap write error msg +EXTERN int undo_off INIT(= false); // undo switched off for now +EXTERN int global_busy INIT(= 0); // set when :global is executing +EXTERN int listcmd_busy INIT(= false); // set when :argdo, :windo or + // :bufdo is executing +EXTERN int need_start_insertmode INIT(= false); +// start insert mode soon +EXTERN char_u *last_cmdline INIT(= NULL); // last command line (for ":) +EXTERN char_u *repeat_cmdline INIT(= NULL); // command line for "." +EXTERN char_u *new_last_cmdline INIT(= NULL); // new value for last_cmdline +EXTERN char_u *autocmd_fname INIT(= NULL); // fname for <afile> on cmdline +EXTERN int autocmd_fname_full; // autocmd_fname is full path +EXTERN int autocmd_bufnr INIT(= 0); // fnum for <abuf> on cmdline +EXTERN char_u *autocmd_match INIT(= NULL); // name for <amatch> on cmdline +EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd +// for CursorMoved event +EXTERN pos_T last_cursormoved INIT(= INIT_POS_T(0, 0, 0)); + +EXTERN int last_changedtick INIT(= 0); // for TextChanged event EXTERN buf_T *last_changedtick_buf INIT(= NULL); EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */ @@ -1092,13 +1080,9 @@ EXTERN int typebuf_was_filled INIT(= FALSE); /* received text from client #ifdef BACKSLASH_IN_FILENAME -EXTERN char psepc INIT(= '\\'); /* normal path separator character */ -EXTERN char psepcN INIT(= '/'); /* abnormal path separator character */ -EXTERN char pseps[2] /* normal path separator string */ -# ifdef DO_INIT - = {'\\', 0} -# endif -; +EXTERN char psepc INIT(= '\\'); // normal path separator character +EXTERN char psepcN INIT(= '/'); // abnormal path separator character +EXTERN char pseps[2] INIT(= { '\\', 0 }); // normal path separator string #endif /* Set to TRUE when an operator is being executed with virtual editing, MAYBE @@ -1117,12 +1101,8 @@ EXTERN int need_cursor_line_redraw INIT(= FALSE); #ifdef USE_MCH_ERRMSG -/* Grow array to collect error messages in until they can be displayed. */ -EXTERN garray_T error_ga -# ifdef DO_INIT - = GA_EMPTY_INIT_VALUE -# endif -; +// Grow array to collect error messages in until they can be displayed. +EXTERN garray_T error_ga INIT(= GA_EMPTY_INIT_VALUE); #endif diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index cd206e2e0d..d236501b3f 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -11,6 +11,7 @@ #include <assert.h> #include <errno.h> #include <inttypes.h> +#include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" @@ -1841,9 +1842,7 @@ static void sig_handler(int s) { */ static void cs_release_csp(size_t i, int freefnpp) { - /* - * Trying to exit normally (not sure whether it is fit to UNIX cscope - */ + // Trying to exit normally (not sure whether it is fit to Unix cscope) if (csinfo[i].to_fp != NULL) { (void)fputs("q\n", csinfo[i].to_fp); (void)fflush(csinfo[i].to_fp); diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index b2fd929714..7054bb822a 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -531,17 +531,14 @@ trans_special ( return dlen; } -/* - * Try translating a <> name at (*srcp)[], return the key and modifiers. - * srcp is advanced to after the <> name. - * returns 0 if there is no match. - */ -int -find_special_key ( +// Try translating a <> name at (*srcp)[], return the key and modifiers. +// srcp is advanced to after the <> name. +// returns 0 if there is no match. +int find_special_key( char_u **srcp, int *modp, - int keycode, /* prefer key code, e.g. K_DEL instead of DEL */ - int keep_x_key /* don't translate xHome to Home key */ + int keycode, // prefer key code, e.g. K_DEL instead of DEL + int keep_x_key // don't translate xHome to Home key ) { char_u *last_dash; @@ -558,24 +555,26 @@ find_special_key ( if (src[0] != '<') return 0; - /* Find end of modifier list */ + // Find end of modifier list last_dash = src; for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++) { if (*bp == '-') { last_dash = bp; if (bp[1] != NUL) { - if (has_mbyte) + if (has_mbyte) { l = mb_ptr2len(bp + 1); - else + } else { l = 1; - if (bp[l + 1] == '>') - bp += l; /* anything accepted, like <C-?> */ + } + if (bp[l + 1] == '>') { + bp += l; // anything accepted, like <C-?> + } } } - if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) - bp += 3; /* skip t_xx, xx may be '-' or '>' */ - else if (STRNICMP(bp, "char-", 5) == 0) { - vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL); + if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) { + bp += 3; // skip t_xx, xx may be '-' or '>' + } else if (STRNICMP(bp, "char-", 5) == 0) { + vim_str2nr(bp + 5, NULL, &l, true, true, true, NULL, NULL); bp += l + 5; break; } @@ -589,55 +588,53 @@ find_special_key ( for (bp = src + 1; bp < last_dash; bp++) { if (*bp != '-') { bit = name_to_mod_mask(*bp); - if (bit == 0x0) - break; /* Illegal modifier name */ + if (bit == 0x0) { + break; // Illegal modifier name + } modifiers |= bit; } } - /* - * Legal modifier name. - */ + // Legal modifier name. if (bp >= last_dash) { if (STRNICMP(last_dash + 1, "char-", 5) == 0 && ascii_isdigit(last_dash[6])) { - /* <Char-123> or <Char-033> or <Char-0x33> */ - vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n); + // <Char-123> or <Char-033> or <Char-0x33> + vim_str2nr(last_dash + 6, NULL, NULL, true, true, true, NULL, &n); key = (int)n; } else { /* * Modifier with single letter, or special key name. */ - if (has_mbyte) + if (has_mbyte) { l = mb_ptr2len(last_dash + 1); - else + } else { l = 1; - if (modifiers != 0 && last_dash[l + 1] == '>') + } + if (modifiers != 0 && last_dash[l + 1] == '>') { key = PTR2CHAR(last_dash + 1); - else { + } else { key = get_special_key_code(last_dash + 1); - if (!keep_x_key) + if (!keep_x_key) { key = handle_x_keys(key); + } } } - /* - * get_special_key_code() may return NUL for invalid - * special key name. - */ + // get_special_key_code() may return NUL for invalid + // special key name. if (key != NUL) { - /* - * Only use a modifier when there is no special key code that - * includes the modifier. - */ + // Only use a modifier when there is no special key code that + // includes the modifier. key = simplify_key(key, &modifiers); if (!keycode) { - /* don't want keycode, use single byte code */ - if (key == K_BS) + // don't want keycode, use single byte code + if (key == K_BS) { key = BS; - else if (key == K_DEL || key == K_KDEL) + } else if (key == K_DEL || key == K_KDEL) { key = DEL; + } } // Normal Key with modifier: diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 9f5e4247b5..8cf5642a80 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -40,6 +40,7 @@ #include <limits.h> #include <string.h> #include <stdbool.h> +#include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" @@ -459,11 +460,9 @@ int mf_sync(memfile_T *mfp, int flags) if (hp == NULL || status == FAIL) mfp->mf_dirty = false; - if ((flags & MFS_FLUSH) && *p_sws != NUL) { - if (STRCMP(p_sws, "fsync") == 0) { - if (os_fsync(mfp->mf_fd)) { - status = FAIL; - } + if (flags & MFS_FLUSH) { + if (os_fsync(mfp->mf_fd)) { + status = FAIL; } } diff --git a/src/nvim/memline.c b/src/nvim/memline.c index c91a25df6e..f58b2ac38f 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -38,6 +38,7 @@ #include <inttypes.h> #include <string.h> #include <stdbool.h> +#include <fcntl.h> #include "nvim/ascii.h" #include "nvim/vim.h" diff --git a/src/nvim/message.c b/src/nvim/message.c index 66b8b9b5d2..00f4c0a85c 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -3037,7 +3037,7 @@ static double tv_float(typval_T *tvs, int *idxp) * http://www.ijs.si/software/snprintf/ * * This snprintf() only supports the following conversion specifiers: - * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) + * s, c, b, B, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) * with flags: '-', '+', ' ', '0' and '#'. * An asterisk is supported for field width as well as precision. * @@ -3103,8 +3103,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) char *p = fmt; int arg_idx = 1; - if (!p) + if (!p) { p = ""; + } while (*p) { if (*p != '%') { // copy up to the next '%' or NUL without any changes @@ -3176,9 +3177,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (*p == '*') { p++; int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (j >= 0) + if (j >= 0) { min_field_width = j; - else { + } else { min_field_width = -j; justify_left = 1; } @@ -3187,8 +3188,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // argument like common implementations do unsigned int uj = *p++ - '0'; - while (ascii_isdigit((int)(*p))) + while (ascii_isdigit((int)(*p))) { uj = 10 * uj + (unsigned int)(*p++ - '0'); + } min_field_width = uj; } @@ -3199,9 +3201,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (*p == '*') { int j = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); p++; - if (j >= 0) + if (j >= 0) { precision = j; - else { + } else { precision_specified = 0; precision = 0; } @@ -3210,8 +3212,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // treat argument like common implementations do unsigned int uj = *p++ - '0'; - while (ascii_isdigit((int)(*p))) + while (ascii_isdigit((int)(*p))) { uj = 10 * uj + (unsigned int)(*p++ - '0'); + } precision = uj; } } @@ -3262,14 +3265,13 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (!str_arg) { str_arg = "[NULL]"; str_arg_l = 6; - } - // make sure not to address string beyond the specified precision - else if (!precision_specified) + } else if (!precision_specified) { + // make sure not to address string beyond the specified precision str_arg_l = strlen(str_arg); - // truncate string if necessary as requested by precision - else if (precision == 0) + } else if (precision == 0) { + // truncate string if necessary as requested by precision str_arg_l = 0; - else { + } else { // memchr on HP does not like n > 2^31 // TODO(elmart): check if this still holds / is relevant str_arg_l = (size_t)((char *)xmemscan(str_arg, @@ -3283,8 +3285,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) - mb_string2cells((char_u *) str_arg); if (precision) { char_u *p1 = (char_u *)str_arg; - for (size_t i = 0; i < precision && *p1; i++) + for (size_t i = 0; i < precision && *p1; i++) { p1 += mb_ptr2len(p1); + } str_arg_l = precision = p1 - (char_u *)str_arg; } } @@ -3295,9 +3298,14 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) } break; - case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { - // u, o, x, X and p conversion specifiers imply the value is unsigned; - // d implies a signed value + case 'd': + case 'u': + case 'b': case 'B': + case 'o': + case 'x': case 'X': + case 'p': { + // u, b, B, o, x, X and p conversion specifiers imply + // the value is unsigned; d implies a signed value // 0 if numeric argument is zero (or if pointer is NULL for 'p'), // +1 if greater than zero (or non NULL for 'p'), @@ -3325,8 +3333,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (fmt_spec == 'p') { length_modifier = '\0'; ptr_arg = tvs ? (void *)tv_str(tvs, &arg_idx) : va_arg(ap, void *); - if (ptr_arg) + if (ptr_arg) { arg_sign = 1; + } } else if (fmt_spec == 'd') { // signed switch (length_modifier) { @@ -3334,25 +3343,28 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case 'h': // char and short arguments are passed as int int_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, int); - if (int_arg > 0) + if (int_arg > 0) { arg_sign = 1; - else if (int_arg < 0) + } else if (int_arg < 0) { arg_sign = -1; + } break; case 'l': long_arg = tvs ? tv_nr(tvs, &arg_idx) : va_arg(ap, long int); - if (long_arg > 0) + if (long_arg > 0) { arg_sign = 1; - else if (long_arg < 0) + } else if (long_arg < 0) { arg_sign = -1; + } break; case '2': long_long_arg = tvs ? tv_nr(tvs, &arg_idx) - : va_arg(ap, long long int); - if (long_long_arg > 0) + : va_arg(ap, long long int); // NOLINT (runtime/int) + if (long_long_arg > 0) { arg_sign = 1; - else if (long_long_arg < 0) + } else if (long_long_arg < 0) { arg_sign = -1; + } break; } } else { @@ -3362,24 +3374,23 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case 'h': uint_arg = tvs ? (unsigned)tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned int); - if (uint_arg != 0) - arg_sign = 1; + if (uint_arg != 0) { arg_sign = 1; } break; case 'l': ulong_arg = tvs ? (unsigned long)tv_nr(tvs, &arg_idx) : va_arg(ap, unsigned long int); - if (ulong_arg != 0) - arg_sign = 1; + if (ulong_arg != 0) { arg_sign = 1; } break; case '2': - ulong_long_arg = tvs ? (unsigned long long)tv_nr(tvs, &arg_idx) - : va_arg(ap, unsigned long long int); - if (ulong_long_arg) arg_sign = 1; + ulong_long_arg = tvs + ? (unsigned long long)tv_nr(tvs, &arg_idx) // NOLINT (runtime/int) + : va_arg(ap, unsigned long long int); // NOLINT (runtime/int) + if (ulong_long_arg) { arg_sign = 1; } break; case 'z': size_t_arg = tvs ? (size_t)tv_nr(tvs, &arg_idx) : va_arg(ap, size_t); - if (size_t_arg) arg_sign = 1; + if (size_t_arg) { arg_sign = 1; } break; } } @@ -3390,16 +3401,19 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // For d, i, u, o, x, and X conversions, if precision is specified, // '0' flag should be ignored. This is so with Solaris 2.6, Digital UNIX // 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - if (precision_specified) + if (precision_specified) { zero_padding = 0; + } if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) + if (force_sign && arg_sign >= 0) { tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + } // leave negative numbers for sprintf to handle, to // avoid handling tricky cases like (short int)-32768 } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X' || + fmt_spec == 'b' || fmt_spec == 'B')) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } @@ -3407,20 +3421,20 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) } zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) + if (!precision_specified) { precision = 1; // default precision is 1 + } if (precision == 0 && arg_sign == 0) { // when zero value is formatted with an explicit precision 0, - // resulting formatted string is empty (d, i, u, o, x, X, p) + // resulting formatted string is empty (d, i, u, b, B, o, x, X, p) } else { char f[5]; int f_l = 0; // construct a simple format string for sprintf f[f_l++] = '%'; - if (!length_modifier) - ; - else if (length_modifier == '2') { + if (!length_modifier) { + } else if (length_modifier == '2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } else @@ -3441,6 +3455,41 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) case '2': str_arg_l += sprintf(tmp + str_arg_l, f, long_long_arg); break; } + } else if (fmt_spec == 'b' || fmt_spec == 'B') { + // binary + size_t bits = 0; + switch (length_modifier) { + case '\0': + case 'h': for (bits = sizeof(unsigned) * 8; bits > 0; bits--) { + if ((uint_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((uint_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + case 'l': for (bits = sizeof(unsigned long) * 8; bits > 0; bits--) { + if ((ulong_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((ulong_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + case '2': for (bits = sizeof(unsigned long long) * 8; // NOLINT (runtime/int) + bits > 0; bits--) { + if ((ulong_long_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((ulong_long_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + case 'z': for (bits = sizeof(size_t) * 8; bits > 0; bits--) { + if ((size_t_arg >> (bits - 1)) & 0x1) { break; } } + + while (bits > 0) { + tmp[str_arg_l++] = + ((size_t_arg >> --bits) & 0x1) ? '1' : '0'; } + break; + } } else { // unsigned switch (length_modifier) { @@ -3464,7 +3513,9 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) if (zero_padding_insertion_ind + 1 < str_arg_l && tmp[zero_padding_insertion_ind] == '0' && (tmp[zero_padding_insertion_ind + 1] == 'x' - || tmp[zero_padding_insertion_ind + 1] == 'X')) + || tmp[zero_padding_insertion_ind + 1] == 'X' + || tmp[zero_padding_insertion_ind + 1] == 'b' + || tmp[zero_padding_insertion_ind + 1] == 'B')) zero_padding_insertion_ind += 2; } @@ -3507,7 +3558,7 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) // floating point char format[40]; int l; - int remove_trailing_zeroes = FALSE; + int remove_trailing_zeroes = false; double f = tvs ? tv_float(tvs, &arg_idx) : va_arg(ap, double); double abs_f = f < 0 ? -f : f; @@ -3518,7 +3569,7 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs) fmt_spec = 'f'; else fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; - remove_trailing_zeroes = TRUE; + remove_trailing_zeroes = true; } if (fmt_spec == 'f' && abs_f > 1.0e307) { diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index b2cec82121..6c969a43fc 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -2729,13 +2729,6 @@ void fast_breakcheck(void) } } -#ifndef SEEK_SET -# define SEEK_SET 0 -#endif -#ifndef SEEK_END -# define SEEK_END 2 -#endif - /* * Get the stdout of an external command. * If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not diff --git a/src/nvim/ops.c b/src/nvim/ops.c index c3d968ca51..19dbd0f9f6 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1991,6 +1991,7 @@ void op_insert(oparg_T *oap, long count1) char_u *firstline, *ins_text; struct block_def bd; int i; + pos_T t1; /* edit() changes this - record it for OP_APPEND */ bd.is_MAX = (curwin->w_curswant == MAXCOL); @@ -2053,7 +2054,16 @@ void op_insert(oparg_T *oap, long count1) } } - edit(NUL, FALSE, (linenr_T)count1); + t1 = oap->start; + edit(NUL, false, (linenr_T)count1); + + // When a tab was inserted, and the characters in front of the tab + // have been converted to a tab as well, the column of the cursor + // might have actually been reduced, so need to adjust here. */ + if (t1.lnum == curbuf->b_op_start_orig.lnum && + lt(curbuf->b_op_start_orig, t1)) { + oap->start = curbuf->b_op_start_orig; + } /* If user has moved off this line, we don't know what to do, so do * nothing. @@ -2069,21 +2079,23 @@ void op_insert(oparg_T *oap, long count1) if (oap->start.lnum == curbuf->b_op_start_orig.lnum && !bd.is_MAX) { if (oap->op_type == OP_INSERT && oap->start.col + oap->start.coladd - != curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) { + != curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) { + size_t t = getviscol2(curbuf->b_op_start_orig.col, + curbuf->b_op_start_orig.coladd); oap->start.col = curbuf->b_op_start_orig.col; - pre_textlen -= getviscol2(oap->start.col, oap->start.coladd) - - oap->start_vcol; - oap->start_vcol = getviscol2(oap->start.col, oap->start.coladd); + pre_textlen -= t - oap->start_vcol; + oap->start_vcol = t; } else if (oap->op_type == OP_APPEND && oap->end.col + oap->end.coladd - >= curbuf->b_op_start_orig.col - + curbuf->b_op_start_orig.coladd) { + >= curbuf->b_op_start_orig.col + + curbuf->b_op_start_orig.coladd) { + size_t t = getviscol2(curbuf->b_op_start_orig.col, + curbuf->b_op_start_orig.coladd); oap->start.col = curbuf->b_op_start_orig.col; /* reset pre_textlen to the value of OP_INSERT */ pre_textlen += bd.textlen; - pre_textlen -= getviscol2(oap->start.col, oap->start.coladd) - - oap->start_vcol; - oap->start_vcol = getviscol2(oap->start.col, oap->start.coladd); + pre_textlen -= t - oap->start_vcol; + oap->start_vcol = t; oap->op_type = OP_INSERT; } } @@ -4186,75 +4198,102 @@ static void reverse_line(char_u *s) # define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr); -/* - * add or subtract 'Prenum1' from a number in a line - * 'command' is CTRL-A for add, CTRL-X for subtract - * - * return FAIL for failure, OK otherwise - */ +/// Add or subtract from a number in a line. +/// +/// @param command CTRL-A for add, CTRL-X for subtract +// @param Prenum1 number to add or subtract +/// +/// @return FAIL for failure, OK otherwise int do_addsub(int command, linenr_T Prenum1) { int col; char_u *buf1; char_u buf2[NUMBUFLEN]; - int hex; /* 'X' or 'x': hex; '0': octal */ - static int hexupper = FALSE; /* 0xABC */ + int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin + static int hexupper = false; // 0xABC unsigned long n, oldn; char_u *ptr; int c; - int length = 0; /* character length of the number */ + int length = 0; // character length of the number int todel; int dohex; int dooct; + int dobin; int doalp; int firstdigit; int negative; int subtract; - dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */ - dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */ - doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */ + dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); // "heX" + dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); // "Octal" + dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); // "Bin" + doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); // "alPha" ptr = get_cursor_line_ptr(); RLADDSUBFIX(ptr); - /* - * First check if we are on a hexadecimal number, after the "0x". - */ + // First check if we are on a hexadecimal number, after the "0x". col = curwin->w_cursor.col; - if (dohex) - while (col > 0 && ascii_isxdigit(ptr[col])) - --col; - if ( dohex - && col > 0 - && (ptr[col] == 'X' - || ptr[col] == 'x') - && ptr[col - 1] == '0' - && ascii_isxdigit(ptr[col + 1])) { - /* - * Found hexadecimal number, move to its start. - */ - --col; + + if (dobin) { + while (col > 0 && ascii_isbdigit(ptr[col])) { + col--; + } + } + + if (dohex) { + while (col > 0 && ascii_isxdigit(ptr[col])) { + col--; + } + } + if (dobin + && dohex + && !((col > 0 + && (ptr[col] == 'X' || + ptr[col] == 'x') + && ptr[col - 1] == '0' + && ascii_isxdigit(ptr[col + 1])))) { + // In case of binary/hexadecimal pattern overlap match, rescan + + col = curwin->w_cursor.col; + + while (col > 0 && ascii_isdigit(ptr[col])) { + col--; + } + } + + if ((dohex + && col > 0 + && (ptr[col] == 'X' + || ptr[col] == 'x') + && ptr[col - 1] == '0' + && ascii_isxdigit(ptr[col + 1])) || + (dobin + && col > 0 + && (ptr[col] == 'B' + || ptr[col] == 'b') + && ptr[col - 1] == '0' + && ascii_isbdigit(ptr[col + 1]))) { + // Found hexadecimal or binary number, move to its start. + col--; } else { - /* - * Search forward and then backward to find the start of number. - */ + // Search forward and then backward to find the start of number. col = curwin->w_cursor.col; while (ptr[col] != NUL && !ascii_isdigit(ptr[col]) - && !(doalp && ASCII_ISALPHA(ptr[col]))) - ++col; + && !(doalp && ASCII_ISALPHA(ptr[col]))) { + col++; + } while (col > 0 && ascii_isdigit(ptr[col - 1]) - && !(doalp && ASCII_ISALPHA(ptr[col]))) - --col; + && !(doalp && ASCII_ISALPHA(ptr[col]))) { + col--; + } } - /* - * If a number was found, and saving for undo works, replace the number. - */ + // If a number was found, and saving for undo works, replace the number. firstdigit = ptr[col]; RLADDSUBFIX(ptr); if ((!ascii_isdigit(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) @@ -4263,152 +4302,170 @@ int do_addsub(int command, linenr_T Prenum1) return FAIL; } - /* get ptr again, because u_save() may have changed it */ + // get ptr again, because u_save() may have changed it ptr = get_cursor_line_ptr(); RLADDSUBFIX(ptr); if (doalp && ASCII_ISALPHA(firstdigit)) { - /* decrement or increment alphabetic character */ + // decrement or increment alphabetic character if (command == Ctrl_X) { if (CharOrd(firstdigit) < Prenum1) { - if (isupper(firstdigit)) + if (isupper(firstdigit)) { firstdigit = 'A'; - else + } else { firstdigit = 'a'; - } else + } + } else { firstdigit -= Prenum1; + } } else { if (26 - CharOrd(firstdigit) - 1 < Prenum1) { - if (isupper(firstdigit)) + if (isupper(firstdigit)) { firstdigit = 'Z'; - else + } else { firstdigit = 'z'; - } else + } + } else { firstdigit += Prenum1; + } } curwin->w_cursor.col = col; - (void)del_char(FALSE); + (void)del_char(false); ins_char(firstdigit); } else { - negative = FALSE; - if (col > 0 && ptr[col - 1] == '-') { /* negative number */ + negative = false; + if (col > 0 && ptr[col - 1] == '-') { // negative number --col; - negative = TRUE; + negative = true; } - /* get the number value (unsigned) */ - vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n); + // get the number value (unsigned) + vim_str2nr(ptr + col, &pre, &length, dobin, dooct, dohex, NULL, &n); - /* ignore leading '-' for hex and octal numbers */ - if (hex && negative) { + // ignore leading '-' for hex, octal and bin numbers + if (pre && negative) { ++col; --length; - negative = FALSE; + negative = false; } - /* add or subtract */ - subtract = FALSE; - if (command == Ctrl_X) - subtract ^= TRUE; - if (negative) - subtract ^= TRUE; + // add or subtract + subtract = false; + if (command == Ctrl_X) { + subtract ^= true; + } + if (negative) { + subtract ^= true; + } oldn = n; - if (subtract) - n -= (unsigned long)Prenum1; - else - n += (unsigned long)Prenum1; - /* handle wraparound for decimal numbers */ - if (!hex) { + n = subtract ? n - (unsigned long) Prenum1 + : n + (unsigned long) Prenum1; + + // handle wraparound for decimal numbers + if (!pre) { if (subtract) { if (n > oldn) { n = 1 + (n ^ (unsigned long)-1); - negative ^= TRUE; + negative ^= true; } } else { /* add */ if (n < oldn) { n = (n ^ (unsigned long)-1); - negative ^= TRUE; + negative ^= true; } } - if (n == 0) - negative = FALSE; + if (n == 0) { + negative = false; + } } - /* - * Delete the old number. - */ + // Delete the old number. curwin->w_cursor.col = col; todel = length; c = gchar_cursor(); - /* - * Don't include the '-' in the length, only the length of the part - * after it is kept the same. - */ - if (c == '-') + + // Don't include the '-' in the length, only the length of the part + // after it is kept the same. + if (c == '-') { --length; + } while (todel-- > 0) { if (c < 0x100 && isalpha(c)) { - if (isupper(c)) - hexupper = TRUE; - else - hexupper = FALSE; + if (isupper(c)) { + hexupper = true; + } else { + hexupper = false; + } } - /* del_char() will mark line needing displaying */ - (void)del_char(FALSE); + // del_char() will mark line needing displaying + (void)del_char(false); c = gchar_cursor(); } - /* - * Prepare the leading characters in buf1[]. - * When there are many leading zeros it could be very long. Allocate - * a bit too much. - */ + // Prepare the leading characters in buf1[]. + // When there are many leading zeros it could be very long. Allocate + // a bit too much. buf1 = xmalloc(length + NUMBUFLEN); ptr = buf1; if (negative) { *ptr++ = '-'; } - if (hex) { + if (pre) { *ptr++ = '0'; --length; } - if (hex == 'x' || hex == 'X') { - *ptr++ = hex; + if (pre == 'b' || pre == 'B' || + pre == 'x' || pre == 'X') { + *ptr++ = pre; --length; } - /* - * Put the number characters in buf2[]. - */ - if (hex == 0) - sprintf((char *)buf2, "%" PRIu64, (uint64_t)n); - else if (hex == '0') - sprintf((char *)buf2, "%" PRIo64, (uint64_t)n); - else if (hex && hexupper) - sprintf((char *)buf2, "%" PRIX64, (uint64_t)n); - else - sprintf((char *)buf2, "%" PRIx64, (uint64_t)n); + // Put the number characters in buf2[]. + if (pre == 'b' || pre == 'B') { + size_t bits = 0; + size_t pos = 0; + + // leading zeros + for (bits = 8 * sizeof(unsigned long); bits > 0; bits--) { + if ((n >> (bits - 1)) & 0x1) { break; } + } + + while (bits > 0) { + buf2[pos++] = ((n >> --bits) & 0x1) ? '1' : '0'; + } + + buf2[pos] = '\0'; + + } else if (pre == 0) { + snprintf((char *)buf2, NUMBUFLEN, "%" PRIu64, (uint64_t)n); + } else if (pre == '0') { + snprintf((char *)buf2, NUMBUFLEN, "%" PRIo64, (uint64_t)n); + } else if (pre && hexupper) { + snprintf((char *)buf2, NUMBUFLEN, "%" PRIX64, (uint64_t)n); + } else { + snprintf((char *)buf2, NUMBUFLEN, "%" PRIx64, (uint64_t)n); + } length -= (int)STRLEN(buf2); - /* - * Adjust number of zeros to the new number of digits, so the - * total length of the number remains the same. - * Don't do this when - * the result may look like an octal number. - */ - if (firstdigit == '0' && !(dooct && hex == 0)) - while (length-- > 0) + // Adjust number of zeros to the new number of digits, so the + // total length of the number remains the same. + // Don't do this when + // the result may look like an octal number. + if (firstdigit == '0' && !(dooct && pre == 0)) { + while (length-- > 0) { *ptr++ = '0'; + } + } *ptr = NUL; STRCAT(buf1, buf2); ins_str(buf1); /* insert the new number */ xfree(buf1); } --curwin->w_cursor.col; - curwin->w_set_curswant = TRUE; - ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE); + curwin->w_set_curswant = true; + ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, true); RLADDSUBFIX(ptr); return OK; } diff --git a/src/nvim/option.c b/src/nvim/option.c index 2ac1abeeba..b4054dc28c 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -258,30 +258,31 @@ typedef struct vimoption { #define PARAM_COUNT ARRAY_SIZE(options) -static char *(p_ambw_values[]) = {"single", "double", NULL}; -static char *(p_bg_values[]) = {"light", "dark", NULL}; -static char *(p_nf_values[]) = {"octal", "hex", "alpha", NULL}; -static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL}; -static char *(p_wop_values[]) = {"tagfile", NULL}; -static char *(p_wak_values[]) = {"yes", "menu", "no", NULL}; -static char *(p_mousem_values[]) = -{"extend", "popup", "popup_setpos", "mac", NULL}; -static char *(p_sel_values[]) = {"inclusive", "exclusive", "old", NULL}; -static char *(p_slm_values[]) = {"mouse", "key", "cmd", NULL}; -static char *(p_km_values[]) = {"startsel", "stopsel", NULL}; -static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL}; -static char *(p_debug_values[]) = {"msg", "throw", "beep", NULL}; -static char *(p_ead_values[]) = {"both", "ver", "hor", NULL}; -static char *(p_buftype_values[]) = -{"nofile", "nowrite", "quickfix", "help", "acwrite", "terminal", NULL}; -static char *(p_bufhidden_values[]) = {"hide", "unload", "delete", "wipe", NULL}; -static char *(p_bs_values[]) = {"indent", "eol", "start", NULL}; -static char *(p_fdm_values[]) = {"manual", "expr", "marker", "indent", "syntax", - "diff", - NULL}; -static char *(p_fcl_values[]) = {"all", NULL}; -static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", - "noinsert", "noselect", NULL}; +static char *(p_ambw_values[]) = { "single", "double", NULL }; +static char *(p_bg_values[]) = { "light", "dark", NULL }; +static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", NULL }; +static char *(p_ff_values[]) = { FF_UNIX, FF_DOS, FF_MAC, NULL }; +static char *(p_wop_values[]) = { "tagfile", NULL }; +static char *(p_wak_values[]) = { "yes", "menu", "no", NULL }; +static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos", + "mac", NULL }; +static char *(p_sel_values[]) = { "inclusive", "exclusive", "old", NULL }; +static char *(p_slm_values[]) = { "mouse", "key", "cmd", NULL }; +static char *(p_km_values[]) = { "startsel", "stopsel", NULL }; +static char *(p_scbopt_values[]) = { "ver", "hor", "jump", NULL }; +static char *(p_debug_values[]) = { "msg", "throw", "beep", NULL }; +static char *(p_ead_values[]) = { "both", "ver", "hor", NULL }; +static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix", + "help", "acwrite", "terminal", NULL }; + +static char *(p_bufhidden_values[]) = { "hide", "unload", "delete", + "wipe", NULL }; +static char *(p_bs_values[]) = { "indent", "eol", "start", NULL }; +static char *(p_fdm_values[]) = { "manual", "expr", "marker", "indent", + "syntax", "diff", NULL }; +static char *(p_fcl_values[]) = { "all", NULL }; +static char *(p_cot_values[]) = { "menu", "menuone", "longest", "preview", + "noinsert", "noselect", NULL }; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "option.c.generated.h" @@ -1431,7 +1432,7 @@ do_set ( } else if (*arg == '-' || ascii_isdigit(*arg)) { // Allow negative (for 'undolevels'), octal and // hex numbers. - vim_str2nr(arg, NULL, &i, true, true, &value, NULL); + vim_str2nr(arg, NULL, &i, true, true, true, &value, NULL); if (arg[i] != NUL && !ascii_iswhite(arg[i])) { errmsg = e_invarg; goto skip; diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 938aa9bc83..7a837de45c 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -535,27 +535,26 @@ EXTERN int p_stmp; /* 'shelltemp' */ #ifdef BACKSLASH_IN_FILENAME EXTERN int p_ssl; /* 'shellslash' */ #endif -EXTERN char_u *p_stl; /* 'statusline' */ -EXTERN int p_sr; /* 'shiftround' */ -EXTERN char_u *p_shm; /* 'shortmess' */ -EXTERN char_u *p_sbr; /* 'showbreak' */ -EXTERN int p_sc; /* 'showcmd' */ -EXTERN int p_sft; /* 'showfulltag' */ -EXTERN int p_sm; /* 'showmatch' */ -EXTERN int p_smd; /* 'showmode' */ -EXTERN long p_ss; /* 'sidescroll' */ -EXTERN long p_siso; /* 'sidescrolloff' */ -EXTERN int p_scs; /* 'smartcase' */ -EXTERN int p_sta; /* 'smarttab' */ -EXTERN int p_sb; /* 'splitbelow' */ -EXTERN long p_tpm; /* 'tabpagemax' */ -EXTERN char_u *p_tal; /* 'tabline' */ -EXTERN char_u *p_sps; /* 'spellsuggest' */ -EXTERN int p_spr; /* 'splitright' */ -EXTERN int p_sol; /* 'startofline' */ -EXTERN char_u *p_su; /* 'suffixes' */ -EXTERN char_u *p_sws; /* 'swapsync' */ -EXTERN char_u *p_swb; /* 'switchbuf' */ +EXTERN char_u *p_stl; // 'statusline' +EXTERN int p_sr; // 'shiftround' +EXTERN char_u *p_shm; // 'shortmess' +EXTERN char_u *p_sbr; // 'showbreak' +EXTERN int p_sc; // 'showcmd' +EXTERN int p_sft; // 'showfulltag' +EXTERN int p_sm; // 'showmatch' +EXTERN int p_smd; // 'showmode' +EXTERN long p_ss; // 'sidescroll' +EXTERN long p_siso; // 'sidescrolloff' +EXTERN int p_scs; // 'smartcase' +EXTERN int p_sta; // 'smarttab' +EXTERN int p_sb; // 'splitbelow' +EXTERN long p_tpm; // 'tabpagemax' +EXTERN char_u *p_tal; // 'tabline' +EXTERN char_u *p_sps; // 'spellsuggest' +EXTERN int p_spr; // 'splitright' +EXTERN int p_sol; // 'startofline' +EXTERN char_u *p_su; // 'suffixes' +EXTERN char_u *p_swb; // 'switchbuf' EXTERN unsigned swb_flags; #ifdef IN_OPTION_C static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", NULL}; diff --git a/src/nvim/options.lua b/src/nvim/options.lua index cdac6ffd5c..3dd37cb5dc 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1144,20 +1144,6 @@ return { defaults={if_true={vi=false}} }, { - full_name='imactivatefunc', abbreviation='imaf', - type='string', scope={'global'}, - secure=true, - vi_def=true, - enable_if=false, - }, - { - full_name='imactivatekey', abbreviation='imak', - type='string', scope={'global'}, - vi_def=true, - enable_if=false, - defaults={if_true={vi=""}} - }, - { full_name='imcmdline', abbreviation='imc', type='bool', scope={'global'}, vi_def=true, @@ -1194,13 +1180,6 @@ return { } }, { - full_name='imstatusfunc', abbreviation='imsf', - type='string', scope={'global'}, - secure=true, - vi_def=true, - enable_if=false, - }, - { full_name='include', abbreviation='inc', type='string', scope={'global', 'buffer'}, vi_def=true, @@ -1620,7 +1599,7 @@ return { deny_duplicates=true, alloced=true, varname='p_nf', - defaults={if_true={vi="octal,hex", vim="hex"}} + defaults={if_true={vi="bin,octal,hex", vim="bin,hex"}} }, { full_name='number', abbreviation='nu', @@ -2297,13 +2276,6 @@ return { defaults={if_true={vi=true}} }, { - full_name='swapsync', abbreviation='sws', - type='string', scope={'global'}, - vi_def=true, - varname='p_sws', - defaults={if_true={vi="fsync"}} - }, - { full_name='switchbuf', abbreviation='swb', type='string', list='comma', scope={'global'}, deny_duplicates=true, diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c index b4a35e203e..fef02cc784 100644 --- a/src/nvim/os/dl.c +++ b/src/nvim/os/dl.c @@ -63,7 +63,7 @@ bool os_libcall(const char *libname, // call the library and save the result // TODO(aktau): catch signals and use jmp (if available) to handle - // exceptions. jmp's on UNIX seem to interact trickily with signals as + // exceptions. jmp's on Unix seem to interact trickily with signals as // well. So for now we only support those libraries that are well-behaved. if (str_out) { str_str_fn sfn = (str_str_fn) fn; diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index a791dca39c..c1804067e9 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -142,7 +142,7 @@ void os_get_hostname(char *hostname, size_t len) /// - go to that directory /// - do os_dirname() to get the real name of that directory. /// This also works with mounts and links. -/// Don't do this for MS-DOS, it will change the "current dir" for a drive. +/// Don't do this for Windows, it will change the "current dir" for a drive. static char_u *homedir = NULL; void init_homedir(void) @@ -290,7 +290,7 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one, } #if defined(UNIX) - // Verify that we have found the end of a UNIX ${VAR} style variable + // Verify that we have found the end of a Unix ${VAR} style variable if (src[1] == '{' && *tail != '}') { var = NULL; } else { diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index 8afbd29292..eee0cdd10b 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -34,28 +34,6 @@ # define DFLT_MAXMEMTOT (10*1024) #endif -#if !defined(S_ISDIR) && defined(S_IFDIR) -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif -#if !defined(S_ISREG) && defined(S_IFREG) -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif -#if !defined(S_ISLNK) && defined(S_IFLNK) -# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#endif -#if !defined(S_ISBLK) && defined(S_IFBLK) -# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -#endif -#if !defined(S_ISSOCK) && defined(S_IFSOCK) -# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -#endif -#if !defined(S_ISFIFO) && defined(S_IFIFO) -# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) -#endif -#if !defined(S_ISCHR) && defined(S_IFCHR) -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -#endif - // Note: Some systems need both string.h and strings.h (Savage). However, // some systems can't handle both, only use string.h in that case. #include <string.h> diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index ba1dcf631a..188f0802c9 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -93,7 +93,7 @@ struct tm *os_localtime_r(const time_t *restrict clock, #endif } -/// Obtains the current UNIX timestamp and adjusts it to local time +/// Obtains the current Unix timestamp and adjusts it to local time. /// /// @param result Pointer to a 'struct tm' where the result should be placed /// @return A pointer to a 'struct tm' in the current time zone (the 'result' @@ -104,7 +104,7 @@ struct tm *os_get_localtime(struct tm *result) FUNC_ATTR_NONNULL_ALL return os_localtime_r(&rawtime, result); } -/// Obtains the current UNIX timestamp +/// Obtains the current Unix timestamp. /// /// @return Seconds since epoch. Timestamp os_time(void) diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index e6a714601f..ba96347a12 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -5,6 +5,10 @@ #include <sys/stat.h> #include <stdio.h> +// Windows does not have S_IFLNK but libuv defines it +// and sets the flag for us when calling uv_fs_stat. +#include <uv.h> + #define NAME_MAX _MAX_PATH #define TEMP_DIR_NAMES {"$TMP", "$TEMP", "$USERPROFILE", ""} @@ -17,6 +21,9 @@ #define USE_CRNL +// We have our own RGB macro in macros.h. +#undef RGB + #ifdef _MSC_VER # ifndef inline # define inline __inline @@ -47,4 +54,30 @@ typedef SSIZE_T ssize_t; # endif #endif +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#if !defined(S_ISDIR) && defined(S_IFDIR) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) && defined(S_IFREG) +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) && defined(S_IFLNK) +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISBLK) && defined(S_IFBLK) +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#endif +#if !defined(S_ISSOCK) && defined(S_IFSOCK) +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISFIFO) && defined(S_IFIFO) +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISCHR) && defined(S_IFCHR) +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#endif + #endif // NVIM_OS_WIN_DEFS_H diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 6c7cb3bba7..cb9a58cc77 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -175,13 +175,6 @@ void mch_exit(int r) exit(r); } -#ifndef SEEK_SET -# define SEEK_SET 0 -#endif -#ifndef SEEK_END -# define SEEK_END 2 -#endif - #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|" /// Does wildcard pattern matching using the shell. diff --git a/src/nvim/path.c b/src/nvim/path.c index 23b22b67f1..5ac3d07f67 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -196,7 +196,7 @@ char_u *get_past_head(char_u *path) int vim_ispathsep(int c) { #ifdef UNIX - return c == '/'; /* UNIX has ':' inside file names */ + return c == '/'; // Unix has ':' inside file names #else # ifdef BACKSLASH_IN_FILENAME return c == ':' || c == '/' || c == '\\'; diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index e2c4b590d0..e01e812a70 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -4186,7 +4186,7 @@ regmatch ( /* When only a composing char is given match at any * position where that composing char appears. */ status = RA_NOMATCH; - for (i = 0; reginput[i] != NUL; i += utf_char2len(inpc)) { + for (i = 0; reginput[i] != NUL; i += utf_ptr2len(reginput + i)) { inpc = mb_ptr2char(reginput + i); if (!utf_iscomposing(inpc)) { if (i > 0) @@ -5333,10 +5333,12 @@ do_class: if ((len = (*mb_ptr2len)(opnd)) > 1) { if (ireg_ic && enc_utf8) cf = utf_fold(utf_ptr2char(opnd)); - while (count < maxcount) { - for (i = 0; i < len; ++i) - if (opnd[i] != scan[i]) + while (count < maxcount && (*mb_ptr2len)(scan) >= len) { + for (i = 0; i < len; ++i) { + if (opnd[i] != scan[i]) { break; + } + } if (i < len && (!ireg_ic || !enc_utf8 || utf_fold(utf_ptr2char(scan)) != cf)) break; diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index b96dcc66b3..1fd024a062 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -5875,7 +5875,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm // If ireg_icombine is not set only skip over the character // itself. When it is set skip over composing characters. if (result && enc_utf8 && !ireg_icombine) { - clen = utf_char2len(curc); + clen = utf_ptr2len(reginput); } ADD_STATE_IF_MATCH(t->state); diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 977dd5b2d4..9a64a7c3a9 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -752,10 +752,11 @@ static void win_update(win_T *wp) lnumt = wp->w_lines[i].wl_lastlnum + 1; if (lnumb == MAXLNUM && wp->w_lines[i].wl_lnum >= mod_bot) { lnumb = wp->w_lines[i].wl_lnum; - /* When there is a fold column it might need updating - * in the next line ("J" just above an open fold). */ - if (wp->w_p_fdc > 0) - ++lnumb; + // When there is a fold column it might need updating + // in the next line ("J" just above an open fold). + if (compute_foldcolumn(wp, 0) > 0) { + lnumb++; + } } } @@ -1567,10 +1568,11 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h { int n = 0; # define FDC_OFF n + int fdc = compute_foldcolumn(wp, 0); if (wp->w_p_rl) { - /* No check for cmdline window: should never be right-left. */ - n = wp->w_p_fdc; + // No check for cmdline window: should never be right-left. + n = fdc; if (n > 0) { /* draw the fold column at the right */ @@ -1610,8 +1612,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h wp->w_wincol, wp->w_wincol + n, cmdwin_type, ' ', hl_attr(HLF_AT)); } - if (wp->w_p_fdc > 0) { - int nn = n + wp->w_p_fdc; + if (fdc > 0) { + int nn = n + fdc; /* draw the fold column at the left */ if (nn > wp->w_width) @@ -1654,6 +1656,20 @@ static int advance_color_col(int vcol, int **color_cols) return **color_cols >= 0; } +// Compute the width of the foldcolumn. Based on 'foldcolumn' and how much +// space is available for window "wp", minus "col". +static int compute_foldcolumn(win_T *wp, int col) +{ + int fdc = wp->w_p_fdc; + int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw; + int wwidth = wp->w_width; + + if (fdc > wwidth - (col + wmw)) { + fdc = wwidth - (col + wmw); + } + return fdc; +} + /* * Display one folded line. */ @@ -1692,12 +1708,9 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T ++col; } - /* - * 2. Add the 'foldcolumn' - */ - fdc = wp->w_p_fdc; - if (fdc > wp->w_width - col) - fdc = wp->w_width - col; + // 2. Add the 'foldcolumn' + // Reduce the width when there is not enough space. + fdc = compute_foldcolumn(wp, col); if (fdc > 0) { fill_foldcolumn(buf, wp, TRUE, lnum); if (wp->w_p_rl) { @@ -2018,37 +2031,42 @@ fill_foldcolumn ( int level; int first_level; int empty; + int fdc = compute_foldcolumn(wp, 0); - /* Init to all spaces. */ - memset(p, ' ', (size_t)wp->w_p_fdc); + // Init to all spaces. + memset(p, ' ', (size_t)fdc); level = win_foldinfo.fi_level; if (level > 0) { - /* If there is only one column put more info in it. */ - empty = (wp->w_p_fdc == 1) ? 0 : 1; + // If there is only one column put more info in it. + empty = (fdc == 1) ? 0 : 1; - /* If the column is too narrow, we start at the lowest level that - * fits and use numbers to indicated the depth. */ - first_level = level - wp->w_p_fdc - closed + 1 + empty; - if (first_level < 1) + // If the column is too narrow, we start at the lowest level that + // fits and use numbers to indicated the depth. + first_level = level - fdc - closed + 1 + empty; + if (first_level < 1) { first_level = 1; + } - for (i = 0; i + empty < wp->w_p_fdc; ++i) { + for (i = 0; i + empty < fdc; i++) { if (win_foldinfo.fi_lnum == lnum - && first_level + i >= win_foldinfo.fi_low_level) + && first_level + i >= win_foldinfo.fi_low_level) { p[i] = '-'; - else if (first_level == 1) + } else if (first_level == 1) { p[i] = '|'; - else if (first_level + i <= 9) + } else if (first_level + i <= 9) { p[i] = '0' + first_level + i; - else + } else { p[i] = '>'; - if (first_level + i == level) + } + if (first_level + i == level) { break; + } } } - if (closed) - p[i >= wp->w_p_fdc ? i - 1 : i] = '+'; + if (closed) { + p[i >= fdc ? i - 1 : i] = '+'; + } } /* @@ -2629,11 +2647,13 @@ win_line ( } if (draw_state == WL_FOLD - 1 && n_extra == 0) { + int fdc = compute_foldcolumn(wp, 0); + draw_state = WL_FOLD; - if (wp->w_p_fdc > 0) { - /* Draw the 'foldcolumn'. */ - fill_foldcolumn(extra, wp, FALSE, lnum); - n_extra = wp->w_p_fdc; + if (fdc > 0) { + // Draw the 'foldcolumn'. + fill_foldcolumn(extra, wp, false, lnum); + n_extra = fdc; p_extra = extra; p_extra[n_extra] = NUL; c_extra = NUL; @@ -3459,7 +3479,7 @@ win_line ( c = ' '; } } else if (c == NUL - && ((wp->w_p_list && lcs_eol > 0) + && (wp->w_p_list || ((fromcol >= 0 || fromcol_prev >= 0) && tocol > vcol && VIsual_mode != Ctrl_V @@ -3469,11 +3489,11 @@ win_line ( && !(noinvcur && lnum == wp->w_cursor.lnum && (colnr_T)vcol == wp->w_virtcol))) - && lcs_eol_one >= 0) { - /* Display a '$' after the line or highlight an extra - * character if the line break is included. */ - /* For a diff line the highlighting continues after the - * "$". */ + && lcs_eol_one > 0) { + // Display a '$' after the line or highlight an extra + // character if the line break is included. + // For a diff line the highlighting continues after the + // "$". if (diff_hlf == (hlf_T)0 && line_attr == 0) { /* In virtualedit, visual selections may extend * beyond end of line. */ @@ -3486,10 +3506,11 @@ win_line ( c_extra = NUL; } } - if (wp->w_p_list) + if (wp->w_p_list && lcs_eol > 0) { c = lcs_eol; - else + } else { c = ' '; + } lcs_eol_one = -1; --ptr; /* put it back at the NUL */ if (!attr_pri) { diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 59ef2a0d28..dcdf2195f8 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -5,6 +5,7 @@ #include <stdint.h> #include <inttypes.h> #include <errno.h> +#include <fcntl.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 420e8e2b70..b2028109be 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1063,8 +1063,7 @@ static char_u *repl_to = NULL; // // Returns the length of the word in bytes, also when it's OK, so that the // caller can skip over the word. -size_t -spell_check ( +size_t spell_check( win_T *wp, // current window char_u *ptr, hlf_T *attrp, @@ -1082,12 +1081,14 @@ spell_check ( // A word never starts at a space or a control character. Return quickly // then, skipping over the character. - if (*ptr <= ' ') + if (*ptr <= ' ') { return 1; + } // Return here when loading language files failed. - if (GA_EMPTY(&wp->w_s->b_langp)) + if (GA_EMPTY(&wp->w_s->b_langp)) { return 1; + } memset(&mi, 0, sizeof(matchinf_T)); @@ -1095,10 +1096,13 @@ spell_check ( // 0X99FF. But always do check spelling to find "3GPP" and "11 // julifeest". if (*ptr >= '0' && *ptr <= '9') { - if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) + if (*ptr == '0' && (ptr[1] == 'b' || ptr[1] == 'B')) { + mi.mi_end = (char_u*) skipbin((char*) ptr + 2); + } else if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) { mi.mi_end = skiphex(ptr + 2); - else + } else { mi.mi_end = skipdigits(ptr); + } nrlen = (size_t)(mi.mi_end - ptr); } @@ -1113,12 +1117,14 @@ spell_check ( if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) { // Check word starting with capital letter. c = PTR2CHAR(ptr); - if (!SPELL_ISUPPER(c)) + if (!SPELL_ISUPPER(c)) { wrongcaplen = (size_t)(mi.mi_fend - ptr); + } } } - if (capcol != NULL) + if (capcol != NULL) { *capcol = -1; + } // We always use the characters up to the next non-word character, // also for bad words. @@ -1131,8 +1137,9 @@ spell_check ( // case-fold the word with one non-word character, so that we can check // for the word end. - if (*mi.mi_fend != NUL) + if (*mi.mi_fend != NUL) { mb_ptr_adv(mi.mi_fend); + } (void)spell_casefold(ptr, (int)(mi.mi_fend - ptr), mi.mi_fword, MAXWLEN + 1); mi.mi_fwordlen = (int)STRLEN(mi.mi_fword); @@ -1149,8 +1156,9 @@ spell_check ( // If reloading fails the language is still in the list but everything // has been cleared. - if (mi.mi_lp->lp_slang->sl_fidxs == NULL) + if (mi.mi_lp->lp_slang->sl_fidxs == NULL) { continue; + } // Check for a matching word in case-folded words. find_word(&mi, FIND_FOLDWORD); @@ -1181,18 +1189,18 @@ spell_check ( // If we found a number skip over it. Allows for "42nd". Do flag // rare and local words, e.g., "3GPP". if (nrlen > 0) { - if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED) + if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED) { return nrlen; - } + } + } else if (!spell_iswordp_nmw(ptr, wp)) { // When we are at a non-word character there is no error, just // skip over the character (try looking for a word after it). - else if (!spell_iswordp_nmw(ptr, wp)) { if (capcol != NULL && wp->w_s->b_cap_prog != NULL) { regmatch_T regmatch; // Check for end of sentence. regmatch.regprog = wp->w_s->b_cap_prog; - regmatch.rm_ic = FALSE; + regmatch.rm_ic = false; int r = vim_regexec(®match, ptr, 0); wp->w_s->b_cap_prog = regmatch.regprog; if (r) { @@ -1204,12 +1212,12 @@ spell_check ( return (size_t)(*mb_ptr2len)(ptr); } return 1; - } else if (mi.mi_end == ptr) + } else if (mi.mi_end == ptr) { // Always include at least one character. Required for when there // is a mixup in "midword". mb_ptr_adv(mi.mi_end); - else if (mi.mi_result == SP_BAD - && LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak) { + } else if (mi.mi_result == SP_BAD + && LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak) { char_u *p, *fp; int save_result = mi.mi_result; @@ -1219,11 +1227,12 @@ spell_check ( if (mi.mi_lp->lp_slang->sl_fidxs != NULL) { p = mi.mi_word; fp = mi.mi_fword; - for (;; ) { + for (;;) { mb_ptr_adv(p); mb_ptr_adv(fp); - if (p >= mi.mi_end) + if (p >= mi.mi_end) { break; + } mi.mi_compoff = (int)(fp - mi.mi_fword); find_word(&mi, FIND_COMPOUND); if (mi.mi_result != SP_BAD) { @@ -1235,12 +1244,13 @@ spell_check ( } } - if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED) + if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED) { *attrp = HLF_SPB; - else if (mi.mi_result == SP_RARE) + } else if (mi.mi_result == SP_RARE) { *attrp = HLF_SPR; - else + } else { *attrp = HLF_SPL; + } } if (wrongcaplen > 0 && (mi.mi_result == SP_OK || mi.mi_result == SP_RARE)) { diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index b4292dbd4b..aaa6f4b97e 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -14,7 +14,7 @@ SCRIPTS := test_eval.out \ test24.out \ test30.out \ test32.out test34.out \ - test36.out test37.out test39.out test40.out \ + test36.out test37.out test40.out \ test42.out test45.out \ test47.out test48.out test49.out \ test52.out test53.out test55.out \ @@ -29,7 +29,6 @@ SCRIPTS := test_eval.out \ test_charsearch.out \ test_close_count.out \ test_command_count.out \ - test_cdo.out \ NEW_TESTS = @@ -97,6 +96,7 @@ clean: *.rej \ *.orig \ test.log \ + messages \ $(RM_ON_RUN) \ $(RM_ON_START) \ valgrind.* \ @@ -149,7 +149,7 @@ test1.out: .gdbinit test1.in test49.out: test49.vim nolog: - -rm -f test.log + -rm -f test.log messages # New style of tests uses Vim script with assert calls. These are easier @@ -160,9 +160,9 @@ RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(VALGRIND) $(VIMPR newtests: newtestssilent @/bin/sh -c "if test -f messages && grep -q 'FAILED' messages; then \ cat messages && cat test.log; \ - fi" \ + fi" newtestssilent: $(NEW_TESTS) %.res: %.vim .gdbinit - $(RUN_VIMTEST) -u runtest.vim $*.vim + $(RUN_VIMTEST) -u NONE -S runtest.vim $*.vim diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 0dc142eb97..8314a45d0c 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -21,9 +21,7 @@ " It will be called after each Test_ function. " Without the +eval feature we can't run these tests, bail out. -if 0 - quit! -endif +so small.vim " Check that the screen size is at least 24 x 80 characters. if &lines < 24 || &columns < 80 @@ -38,7 +36,16 @@ endif " Source the test script. First grab the file name, in case the script " navigates away. let testname = expand('%') -source % +let done = 0 +let fail = 0 +let errors = [] +let messages = [] +try + source % +catch + let fail += 1 + call add(errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint) +endtry " Locate Test_ functions and execute them. redir @q @@ -46,14 +53,12 @@ function /^Test_ redir END let tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) -let done = 0 -let fail = 0 -let errors = [] for test in tests if exists("*SetUp") call SetUp() endif + call add(messages, 'Executing ' . test) let done += 1 try exe 'call ' . test @@ -89,9 +94,20 @@ if len(errors) > 0 write endif -echo 'Executed ' . done . (done > 1 ? ' tests': ' test') +let message = 'Executed ' . done . (done > 1 ? ' tests': ' test') +echo message +call add(messages, message) if fail > 0 - echo fail . ' FAILED' + let message = fail . ' FAILED' + echo message + call add(messages, message) endif +" Append messages to "messages" +split messages +call append(line('$'), '') +call append(line('$'), 'From ' . testname . ':') +call append(line('$'), messages) +write + qall! diff --git a/src/nvim/testdir/test39.in b/src/nvim/testdir/test39.in deleted file mode 100644 index ebbcbd6d0d..0000000000 --- a/src/nvim/testdir/test39.in +++ /dev/null @@ -1,106 +0,0 @@ - -Test Visual block mode commands -And test "U" in Visual mode, also on German sharp S. - -STARTTEST -:so small.vim -:so mbyte.vim -/^abcde -:" Test shift-right of a block -jlllljj>wlljlll> -:" Test shift-left of a block -G$hhhhkk< -:" Test block-insert -GklkkkIxyz -:" Test block-replace -Gllllkkklllrq -:" Test block-change -G$khhhhhkkcmno -:$-4,$w! test.out -:" Test block-insert using cursor keys for movement -/^aaaa/ -:exe ":norm! l\<C-V>jjjlllI\<Right>\<Right> \<Esc>" -:/^aa/,/^$/w >> test.out -/xaaa$/ -:exe ":norm! \<C-V>jjjI<>\<Left>p\<Esc>" -:/xaaa$/,/^$/w >> test.out -:" Test for Visual block was created with the last <C-v>$ -/^A23$/ -:exe ":norm! l\<C-V>j$Aab\<Esc>" -:.,/^$/w >> test.out -:" Test for Visual block was created with the middle <C-v>$ (1) -/^B23$/ -:exe ":norm! l\<C-V>j$hAab\<Esc>" -:.,/^$/w >> test.out -:" Test for Visual block was created with the middle <C-v>$ (2) -/^C23$/ -:exe ":norm! l\<C-V>j$hhAab\<Esc>" -:.,/^$/w >> test.out -:" Test for Visual block insert when virtualedit=all and utf-8 encoding -:set ve=all -:/\t\tline -:exe ":norm! 07l\<C-V>jjIx\<Esc>" -:.,/^$/w >> test.out -:" Test for Visual block append when virtualedit=all -:exe ":norm! 012l\<C-v>jjAx\<Esc>" -:set ve= -:.,/^$/w >> test.out -:" gUe must uppercase a whole word, also when ß changes to SS -Gothe youtußeuu endYpk0wgUe -:" gUfx must uppercase until x, inclusive. -O- youßtußexu -0fogUfx -:" VU must uppercase a whole line -YpkVU -:" same, when it's the last line in the buffer -YPGi111VUddP -:" Uppercase two lines -Oblah di -doh dutVkUj -:" Uppercase part of two lines -ddppi333k0i222fyllvjfuUk -:" visual replace using Enter or NL -G3o1234567892k05l2jr
G3o987652k02l2jr
-G3o1234567892k05l2jr -G3o987652k02l2jr -:" -:" Test cursor position. When ve=block and Visual block mode and $gj -:set ve=block -:exe ":norm! 2k\<C-V>$gj\<Esc>" -:let cpos=getpos("'>") -:$put ='col:'.cpos[2].' off:'.cpos[3] -:/^the/,$w >> test.out -:qa! -ENDTEST - - line1 - line2 - line3 - -aaaaaa -bbbbbb -cccccc -dddddd - -xaaa -bbbb -cccc -dddd - -yaaa -¿¿¿ -bbb - -A23 -4567 - -B23 -4567 - -C23 -4567 - -abcdefghijklm -abcdefghijklm -abcdefghijklm -abcdefghijklm -abcdefghijklm diff --git a/src/nvim/testdir/test39.ok b/src/nvim/testdir/test39.ok Binary files differdeleted file mode 100644 index 198e5b14dc..0000000000 --- a/src/nvim/testdir/test39.ok +++ /dev/null diff --git a/src/nvim/testdir/test_cdo.in b/src/nvim/testdir/test_cdo.in deleted file mode 100644 index fb80ea1164..0000000000 --- a/src/nvim/testdir/test_cdo.in +++ /dev/null @@ -1,107 +0,0 @@ -Tests for the :cdo, :cfdo, :ldo and :lfdo commands - -STARTTEST -:so small.vim -:if !has('quickfix') | e! test.ok | wq! test.out | endif - -:call writefile(["Line1", "Line2", "Line3"], 'Xtestfile1') -:call writefile(["Line1", "Line2", "Line3"], 'Xtestfile2') -:call writefile(["Line1", "Line2", "Line3"], 'Xtestfile3') - -:function RunTests(cchar) -: let nl="\n" - -: enew -: " Try with an empty list -: exe a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" - -: " Populate the list and then try -: exe a:cchar . "getexpr ['non-error 1', 'Xtestfile1:1:3:Line1', 'non-error 2', 'Xtestfile2:2:2:Line2', 'non-error 3', 'Xtestfile3:3:1:Line3']" -: exe a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" - -: " Run command only on selected error lines -: enew -: exe "2,3" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: " Boundary condition tests -: enew -: exe "1,1" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: enew -: exe "3" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: " Range test commands -: enew -: exe "%" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: enew -: exe "1,$" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: enew -: exe a:cchar . 'prev' -: exe "." . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: " Invalid error lines test -: enew -: exe "27" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "4,5" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" - -: " Run commands from an unsaved buffer -: let v:errmsg='' -: enew -: setlocal modified -: exe "2,2" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: if v:errmsg =~# 'No write since last change' -: let g:result .= 'Unsaved file change test passed' . nl -: else -: let g:result .= 'Unsaved file change test failed' . nl -: endif - -: " If the executed command fails, then the operation should be aborted -: enew! -: let subst_count = 0 -: exe a:cchar . "do s/Line/xLine/ | let subst_count += 1" -: if subst_count == 1 && getline('.') == 'xLine1' -: let g:result .= 'Abort command on error test passed' . nl -: else -: let g:result .= 'Abort command on error test failed' . nl -: endif - -: exe "2,2" . a:cchar . "do! let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" - -: " List with no valid error entries -: edit! +2 Xtestfile1 -: exe a:cchar . "getexpr ['non-error 1', 'non-error 2', 'non-error 3']" -: exe a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "2" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: let v:errmsg='' -: exe "%" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "1,$" . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "." . a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: let g:result .= v:errmsg - -: " List with only one valid entry -: exe a:cchar . "getexpr ['Xtestfile3:3:1:Line3']" -: exe a:cchar . "do let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" - -: " Tests for :cfdo and :lfdo commands -: exe a:cchar . "getexpr ['non-error 1', 'Xtestfile1:1:3:Line1', 'Xtestfile1:2:1:Line2', 'non-error 2', 'Xtestfile2:2:2:Line2', 'non-error 3', 'Xtestfile3:2:3:Line2', 'Xtestfile3:3:1:Line3']" -: exe a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "3" . a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "2,3" . a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "%" . a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe "1,$" . a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -: exe a:cchar . 'pfile' -: exe "." . a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" - -: " List with only one valid entry -: exe a:cchar . "getexpr ['Xtestfile2:2:5:Line2']" -: exe a:cchar . "fdo let g:result .= expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' . nl" -:endfunction - -:let result='' -:" Tests for the :cdo quickfix list command -:call RunTests('c') -:let result .= "\n" -:" Tests for the :ldo location list command -:call RunTests('l') - -:edit! test.out -:0put =result -:wq! -ENDTEST - diff --git a/src/nvim/testdir/test_cdo.ok b/src/nvim/testdir/test_cdo.ok deleted file mode 100644 index ddcff4bbb8..0000000000 --- a/src/nvim/testdir/test_cdo.ok +++ /dev/null @@ -1,66 +0,0 @@ -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile2 2L 2C -Unsaved file change test passed -Abort command on error test passed -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile3 2L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile2 2L 2C -Xtestfile2 2L 5C - -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile2 2L 2C -Unsaved file change test passed -Abort command on error test passed -Xtestfile2 2L 2C -Xtestfile3 3L 1C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile3 2L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile1 1L 3C -Xtestfile2 2L 2C -Xtestfile3 2L 3C -Xtestfile2 2L 2C -Xtestfile2 2L 5C - diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 69ac18ad54..6b60f95f22 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -77,6 +77,7 @@ #include <limits.h> #include <stdbool.h> #include <string.h> +#include <fcntl.h> #include "nvim/vim.h" #include "nvim/ascii.h" diff --git a/src/nvim/version.c b/src/nvim/version.c index 53a877b91a..4ac224fecb 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -133,7 +133,7 @@ static int included_patches[] = { // 994 NA // 993, // 992 NA - // 991, + 991, // 990 NA 989, // 988 NA @@ -143,10 +143,10 @@ static int included_patches[] = { // 984, // 983, // 982 NA - // 981, - // 980, + 981, + 980, // 979 NA - // 978, + 978, // 977, // 976 NA 975, @@ -395,7 +395,7 @@ static int included_patches[] = { // 732, // 731 NA // 730 NA - // 729, + 729, // 728 NA // 727 NA // 726 NA @@ -403,14 +403,14 @@ static int included_patches[] = { // 724 NA 723, // 722, - // 721, + 721, // 720 NA 719, 718, // 717, - // 716, - // 715, - // 714, + 716, + 715, + 714, 713, 712, 711, @@ -439,7 +439,7 @@ static int included_patches[] = { // 688, // 687 NA 686, - // 685, + 685, // 684, // 683 NA 682, @@ -508,9 +508,9 @@ static int included_patches[] = { // 619 NA // 618 NA 617, - // 616, + 616, 615, - // 614, + 614, // 613, 612, // 611 NA @@ -521,7 +521,7 @@ static int included_patches[] = { 606, 605, 604, - // 603, + 603, 602, 601, 600, diff --git a/src/nvim/vim.h b/src/nvim/vim.h index fa00d9efcf..2e20d48f90 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -27,9 +27,6 @@ Error: configure did not run properly.Check auto/config.log. # endif #endif -/* user ID of root is usually zero, but not for everybody */ -#define ROOT_UID 0 - /* Can't use "PACKAGE" here, conflicts with a Perl include file. */ #ifndef VIMPACKAGE @@ -38,9 +35,11 @@ Error: configure did not run properly.Check auto/config.log. #include "nvim/os/os_defs.h" /* bring lots of system header files */ -#define NUMBUFLEN 30 /* length of a buffer to store a number in ASCII */ +#define NUMBUFLEN 65 // length of a buffer to store a number in ASCII -# define MAX_TYPENR 65535 +#define MAX_TYPENR 65535 + +#define ROOT_UID 0 #include "nvim/keymap.h" #include "nvim/macros.h" @@ -232,15 +231,6 @@ enum { /* Size in bytes of the hash used in the undo file. */ #define UNDO_HASH_SIZE 32 -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif - - -#ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -#endif - /* * defines to avoid typecasts from (char_u *) to (char *) and back * (vim_strchr() and vim_strrchr() are now in alloc.c) |