Bump to version 1.22.1
[platform/upstream/busybox.git] / editors / vi.c
index b1776c6..097f309 100644 (file)
@@ -478,6 +478,7 @@ static void flash(int);             // flash the terminal screen
 static void show_status_line(void);    // put a message on the bottom line
 static void status_line(const char *, ...);     // print to status buf
 static void status_line_bold(const char *, ...);
+static void status_line_bold_errno(const char *fn);
 static void not_implemented(const char *); // display "Not implemented" message
 static int format_edit_status(void);   // format file status on status line
 static void redraw(int);       // force a full screen refresh
@@ -1049,7 +1050,7 @@ static void colon(char *buf)
 #endif
                // how many lines in text[]?
                li = count_lines(text, end - 1);
-               status_line("\"%s\"%s"
+               status_line("'%s'%s"
                        IF_FEATURE_VI_READONLY("%s")
                        " %dL, %dC", current_filename,
                        (file_size(fn) < 0 ? " [New file]" : ""),
@@ -1165,7 +1166,7 @@ static void colon(char *buf)
                        goto ret;       // nothing was inserted
                // how many lines in text[]?
                li = count_lines(q, q + ch - 1);
-               status_line("\"%s\""
+               status_line("'%s'"
                        IF_FEATURE_VI_READONLY("%s")
                        " %dL, %dC", fn,
                        IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
@@ -1298,7 +1299,7 @@ static void colon(char *buf)
                }
 #if ENABLE_FEATURE_VI_READONLY
                if (readonly_mode && !useforce) {
-                       status_line_bold("\"%s\" File is read only", fn);
+                       status_line_bold("'%s' is read only", fn);
                        goto ret;
                }
 #endif
@@ -1321,9 +1322,9 @@ static void colon(char *buf)
                }
                if (l < 0) {
                        if (l == -1)
-                               status_line_bold("\"%s\" %s", fn, strerror(errno));
+                               status_line_bold_errno(fn);
                } else {
-                       status_line("\"%s\" %dL, %dC", fn, li, l);
+                       status_line("'%s' %dL, %dC", fn, li, l);
                        if (q == text && r == end - 1 && l == ch) {
                                file_modified = 0;
                                last_file_modified = -1;
@@ -1706,65 +1707,53 @@ static char *new_screen(int ro, int co)
 // search for pattern starting at p
 static char *char_search(char *p, const char *pat, int dir, int range)
 {
-       char *q;
        struct re_pattern_buffer preg;
+       const char *err;
+       char *q;
        int i;
        int size;
 
        re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
-       preg.translate = 0;
-       preg.fastmap = 0;
-       preg.buffer = 0;
-       preg.allocated = 0;
+       if (ignorecase)
+               re_syntax_options = RE_SYNTAX_POSIX_EXTENDED | RE_ICASE;
+
+       memset(&preg, 0, sizeof(preg));
+       err = re_compile_pattern(pat, strlen(pat), &preg);
+       if (err != NULL) {
+               status_line_bold("bad search pattern '%s': %s", pat, err);
+               return p;
+       }
 
        // assume a LIMITED forward search
-       q = next_line(p);
-       q = end_line(q);
        q = end - 1;
-       if (dir == BACK) {
-               q = prev_line(p);
+       if (dir == BACK)
                q = text;
-       }
-       // count the number of chars to search over, forward or backward
-       size = q - p;
-       if (size < 0)
-               size = p - q;
        // RANGE could be negative if we are searching backwards
        range = q - p;
-
-       q = (char *)re_compile_pattern(pat, strlen(pat), (struct re_pattern_buffer *)&preg);
-       if (q != 0) {
-               // The pattern was not compiled
-               status_line_bold("bad search pattern: \"%s\": %s", pat, q);
-               i = 0;                  // return p if pattern not compiled
-               goto cs1;
-       }
-
        q = p;
+       size = range;
        if (range < 0) {
+               size = -size;
                q = p - size;
                if (q < text)
                        q = text;
        }
        // search for the compiled pattern, preg, in p[]
-       // range < 0 search backward
-       // range > 0 search forward
+       // range < 0: search backward
+       // range > 0: search forward
        // 0 < start < size
-       // re_search() < 0  not found or error
-       // re_search() > 0  index of found pattern
-       //            struct pattern    char     int    int    int     struct reg
-       // re_search (*pattern_buffer,  *string, size,  start, range,  *regs)
-       i = re_search(&preg, q, size, 0, range, 0);
-       if (i == -1) {
-               p = 0;
-               i = 0;                  // return NULL if pattern not found
-       }
- cs1:
-       if (dir == FORWARD) {
+       // re_search() < 0: not found or error
+       // re_search() >= 0: index of found pattern
+       //           struct pattern   char     int   int    int    struct reg
+       // re_search(*pattern_buffer, *string, size, start, range, *regs)
+       i = re_search(&preg, q, size, /*start:*/ 0, range, /*struct re_registers*:*/ NULL);
+       regfree(&preg);
+       if (i < 0)
+               return NULL;
+       if (dir == FORWARD)
                p = p + i;
-       } else {
+       else
                p = p - i;
-       }
        return p;
 }
 
@@ -1789,7 +1778,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
 
        len = strlen(pat);
        if (dir == FORWARD) {
-               stop = end - 1; // assume range is p - end-1
+               stop = end - 1; // assume range is p..end-1
                if (range == LIMITED)
                        stop = next_line(p);    // range is to next line
                for (start = p; start < stop; start++) {
@@ -1798,7 +1787,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
                        }
                }
        } else if (dir == BACK) {
-               stop = text;    // assume range is text - p
+               stop = text;    // assume range is text..p
                if (range == LIMITED)
                        stop = prev_line(p);    // range is to prev line
                for (start = p - len; start >= stop; start--) {
@@ -1929,11 +1918,11 @@ static int find_range(char **start, char **stop, char c)
                dot_end();              // find NL
                q = dot;
        } else {
-           // nothing -- this causes any other values of c to
-           // represent the one-character range under the
-           // cursor.  this is correct for ' ' and 'l', but
-           // perhaps no others.
-           //
+               // nothing -- this causes any other values of c to
+               // represent the one-character range under the
+               // cursor.  this is correct for ' ' and 'l', but
+               // perhaps no others.
+               //
        }
        if (q < p) {
                t = q;
@@ -2503,12 +2492,12 @@ static int file_insert(const char *fn, char *p, int update_ro_status)
 
        /* Validate file */
        if (stat(fn, &statbuf) < 0) {
-               status_line_bold("\"%s\" %s", fn, strerror(errno));
+               status_line_bold_errno(fn);
                goto fi0;
        }
        if (!S_ISREG(statbuf.st_mode)) {
                // This is not a regular file
-               status_line_bold("\"%s\" Not a regular file", fn);
+               status_line_bold("'%s' is not a regular file", fn);
                goto fi0;
        }
        if (p < text || p > end) {
@@ -2519,19 +2508,19 @@ static int file_insert(const char *fn, char *p, int update_ro_status)
        // read file to buffer
        fd = open(fn, O_RDONLY);
        if (fd < 0) {
-               status_line_bold("\"%s\" %s", fn, strerror(errno));
+               status_line_bold_errno(fn);
                goto fi0;
        }
-       size = statbuf.st_size;
+       size = (statbuf.st_size < INT_MAX ? (int)statbuf.st_size : INT_MAX);
        p += text_hole_make(p, size);
        cnt = safe_read(fd, p, size);
        if (cnt < 0) {
-               status_line_bold("\"%s\" %s", fn, strerror(errno));
+               status_line_bold_errno(fn);
                p = text_hole_delete(p, p + size - 1);  // un-do buffer insert
        } else if (cnt < size) {
                // There was a partial read, shrink unused space text[]
-               p = text_hole_delete(p + cnt, p + (size - cnt) - 1);    // un-do buffer insert
-               status_line_bold("can't read all of file \"%s\"", fn);
+               p = text_hole_delete(p + cnt, p + size - 1);    // un-do buffer insert
+               status_line_bold("can't read '%s'", fn);
        }
        if (cnt >= size)
                file_modified++;
@@ -2717,6 +2706,11 @@ static void status_line_bold(const char *format, ...)
        have_status_msg = 1 + sizeof(ESC_BOLD_TEXT) + sizeof(ESC_NORM_TEXT) - 2;
 }
 
+static void status_line_bold_errno(const char *fn)
+{
+       status_line_bold("'%s' %s", fn, strerror(errno));
+}
+
 // format status buffer
 static void status_line(const char *format, ...)
 {
@@ -3469,7 +3463,7 @@ static void do_cmd(int c)
                        } else {
                                file_modified = 0;
                                last_file_modified = -1;
-                               status_line("\"%s\" %dL, %dC", current_filename, count_lines(text, end - 1), cnt);
+                               status_line("'%s' %dL, %dC", current_filename, count_lines(text, end - 1), cnt);
                                if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n'
                                 || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N'
                                ) {
@@ -3667,7 +3661,7 @@ static void do_cmd(int c)
                }
                if (file_modified) {
                        if (ENABLE_FEATURE_VI_READONLY && readonly_mode) {
-                               status_line_bold("\"%s\" File is read only", current_filename);
+                               status_line_bold("'%s' is read only", current_filename);
                                break;
                        }
                        cnt = file_write(current_filename, text, end - 1);