vi: some simplifications

function                                             old     new   delta
file_insert                                          301     315     +14
init_text_buffer                                     179     171      -8
colon                                               2889    2878     -11
file_size                                             37       -     -37
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/2 up/down: 14/-56)            Total: -42 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2014-04-05 22:57:46 +02:00
parent e7430867a8
commit 32afd3aa60

View File

@ -491,7 +491,6 @@ struct globals {
} while (0)
static int init_text_buffer(char *); // init from file or create new
static void edit_file(char *); // edit one file
static void do_cmd(int); // execute a command
static int next_tabstop(int);
@ -543,7 +542,6 @@ static void cookmode(void); // return to "cooked" mode on tty
static int mysleep(int);
static int readit(void); // read (maybe cursor) key from stdin
static int get_one_char(void); // read 1 char from stdin
static int file_size(const char *); // what is the byte size of "fn"
#if !ENABLE_FEATURE_VI_READONLY
#define file_insert(fn, p, update_ro_status) file_insert(fn, p)
#endif
@ -578,8 +576,8 @@ static char *char_search(char *, const char *, int, int); // search for pattern
#if ENABLE_FEATURE_VI_COLON
static char *get_one_address(char *, int *); // get colon addr, if present
static char *get_address(char *, int *, int *); // get two colon addrs, if present
static void colon(char *); // execute the "colon" mode cmds
#endif
static void colon(char *); // execute the "colon" mode cmds
#if ENABLE_FEATURE_VI_USE_SIGNALS
static void winch_sig(int); // catch window size changes
static void suspend_sig(int); // catch ctrl-Z
@ -725,32 +723,29 @@ int vi_main(int argc, char **argv)
static int init_text_buffer(char *fn)
{
int rc;
int size = file_size(fn); // file size. -1 means does not exist.
flush_undo_data();
modified_count = 0;
last_modified_count = -1;
#if ENABLE_FEATURE_VI_YANKMARK
/* init the marks */
memset(mark, 0, sizeof(mark));
#endif
/* allocate/reallocate text buffer */
free(text);
text_size = size + 10240;
text_size = 10240;
screenbegin = dot = end = text = xzalloc(text_size);
if (fn != current_filename) {
free(current_filename);
current_filename = xstrdup(fn);
}
if (size < 0) {
rc = file_insert(fn, text, 1);
if (rc < 0) {
// file doesnt exist. Start empty buf with dummy line
char_insert(text, '\n', NO_UNDO);
rc = 0;
} else {
rc = file_insert(fn, text, 1);
}
modified_count = 0;
last_modified_count = -1;
#if ENABLE_FEATURE_VI_YANKMARK
/* init the marks. */
memset(mark, 0, sizeof(mark));
#endif
return rc;
}
@ -1018,13 +1013,71 @@ static void setops(const char *args, const char *opname, int flg_no,
}
#endif
#endif /* FEATURE_VI_COLON */
// buf must be no longer than MAX_INPUT_LEN!
static void colon(char *buf)
{
#if !ENABLE_FEATURE_VI_COLON
/* Simple ":cmd" handler with minimal set of commands */
char *p = buf;
int cnt;
if (*p == ':')
p++;
cnt = strlen(p);
if (cnt == 0)
return;
if (strncmp(p, "quit", cnt) == 0
|| strncmp(p, "q!", cnt) == 0
) {
if (modified_count && p[1] != '!') {
status_line_bold("No write since last change (:%s! overrides)", p);
} else {
editing = 0;
}
return;
}
if (strncmp(p, "write", cnt) == 0
|| strncmp(p, "wq", cnt) == 0
|| strncmp(p, "wn", cnt) == 0
|| (p[0] == 'x' && !p[1])
) {
cnt = file_write(current_filename, text, end - 1);
if (cnt < 0) {
if (cnt == -1)
status_line_bold("Write error: %s", strerror(errno));
} else {
modified_count = 0;
last_modified_count = -1;
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'
) {
editing = 0;
}
}
return;
}
if (strncmp(p, "file", cnt) == 0) {
last_status_cksum = 0; // force status update
return;
}
if (sscanf(p, "%d", &cnt) > 0) {
dot = find_line(cnt);
dot_skip_over_ws();
return;
}
not_implemented(p);
#else
char c, *orig_buf, *buf1, *q, *r;
char *fn, cmd[MAX_INPUT_LEN], args[MAX_INPUT_LEN];
int i, l, li, ch, b, e;
int useforce, forced = FALSE;
int i, l, li, b, e;
int useforce;
// :3154 // if (-e line 3154) goto it else stay put
// :4,33w! foo // write a portion of buffer to file "foo"
@ -1046,7 +1099,7 @@ static void colon(char *buf)
if (*buf == ':')
buf++; // move past the ':'
li = ch = i = 0;
li = i = 0;
b = e = -1;
q = text; // assume 1,$ for the range
r = end - 1;
@ -1127,6 +1180,8 @@ static void colon(char *buf)
dot = yank_delete(q, r, 1, YANKDEL, ALLOW_UNDO); // save, then delete lines
dot_skip_over_ws();
} else if (strncmp(cmd, "edit", i) == 0) { // Edit a file
int size;
// don't edit, if the current file has been modified
if (modified_count && !useforce) {
status_line_bold("No write since last change (:%s! overrides)", cmd);
@ -1144,8 +1199,7 @@ static void colon(char *buf)
goto ret;
}
if (init_text_buffer(fn) < 0)
goto ret;
size = init_text_buffer(fn);
#if ENABLE_FEATURE_VI_YANKMARK
if (Ureg >= 0 && Ureg < 28) {
@ -1161,12 +1215,14 @@ static void colon(char *buf)
li = count_lines(text, end - 1);
status_line("'%s'%s"
IF_FEATURE_VI_READONLY("%s")
" %dL, %dC", current_filename,
(file_size(fn) < 0 ? " [New file]" : ""),
" %dL, %dC",
current_filename,
(size < 0 ? " [New file]" : ""),
IF_FEATURE_VI_READONLY(
((readonly_mode) ? " [Readonly]" : ""),
)
li, ch);
li, (int)(end - text)
);
} else if (strncmp(cmd, "file", i) == 0) { // what File is this
if (b != -1 || e != -1) {
status_line_bold("No address allowed on this command");
@ -1255,6 +1311,8 @@ static void colon(char *buf)
}
editing = 0;
} else if (strncmp(cmd, "read", i) == 0) { // read file into text[]
int size;
fn = args;
if (!fn[0]) {
status_line_bold("No filename given");
@ -1268,23 +1326,24 @@ static void colon(char *buf)
q = next_line(q);
{ // dance around potentially-reallocated text[]
uintptr_t ofs = q - text;
ch = file_insert(fn, q, 0);
size = file_insert(fn, q, /*update_ro:*/ 0);
q = text + ofs;
}
if (ch < 0)
if (size < 0)
goto ret; // nothing was inserted
// how many lines in text[]?
li = count_lines(q, q + ch - 1);
li = count_lines(q, q + size - 1);
status_line("'%s'"
IF_FEATURE_VI_READONLY("%s")
" %dL, %dC", fn,
" %dL, %dC",
fn,
IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
li, ch);
if (ch > 0) {
li, size
);
if (size > 0) {
// if the insert is before "dot" then we need to update
if (q <= dot)
dot += ch;
// modified_count++;
dot += size;
}
} else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args
if (modified_count && !useforce) {
@ -1409,6 +1468,9 @@ static void colon(char *buf)
|| strncmp(cmd, "wn", i) == 0
|| (cmd[0] == 'x' && !cmd[1])
) {
int size;
//int forced = FALSE;
// is there a file name to write to?
if (args[0]) {
fn = args;
@ -1421,34 +1483,33 @@ static void colon(char *buf)
#endif
// how many lines in text[]?
li = count_lines(q, r);
ch = r - q + 1;
// see if file exists- if not, its just a new file request
if (useforce) {
size = r - q + 1;
//if (useforce) {
// if "fn" is not write-able, chmod u+w
// sprintf(syscmd, "chmod u+w %s", fn);
// system(syscmd);
forced = TRUE;
}
// forced = TRUE;
//}
l = file_write(fn, q, r);
if (useforce && forced) {
//if (useforce && forced) {
// chmod u-w
// sprintf(syscmd, "chmod u-w %s", fn);
// system(syscmd);
forced = FALSE;
}
// forced = FALSE;
//}
if (l < 0) {
if (l == -1)
status_line_bold_errno(fn);
} else {
status_line("'%s' %dL, %dC", fn, li, l);
if (q == text && r == end - 1 && l == ch) {
if (q == text && r == end - 1 && l == size) {
modified_count = 0;
last_modified_count = -1;
}
if ((cmd[0] == 'x' || cmd[1] == 'q' || cmd[1] == 'n'
|| cmd[0] == 'X' || cmd[1] == 'Q' || cmd[1] == 'N'
)
&& l == ch
&& l == size
) {
editing = 0;
}
@ -1475,9 +1536,8 @@ static void colon(char *buf)
colon_s_fail:
status_line(":s expression missing delimiters");
#endif
}
#endif /* FEATURE_VI_COLON */
}
static void Hit_Return(void)
{
@ -2851,17 +2911,6 @@ static char *get_input_line(const char *prompt)
#undef buf
}
static int file_size(const char *fn) // what is the byte size of "fn"
{
struct stat st_buf;
int cnt;
cnt = -1;
if (fn && stat(fn, &st_buf) == 0) // see if file exists
cnt = (int) st_buf.st_size;
return cnt;
}
// might reallocate text[]!
static int file_insert(const char *fn, char *p, int update_ro_status)
{
@ -2869,42 +2918,40 @@ static int file_insert(const char *fn, char *p, int update_ro_status)
int fd, size;
struct stat statbuf;
/* Validate file */
if (stat(fn, &statbuf) < 0) {
status_line_bold_errno(fn);
goto fi0;
}
if (!S_ISREG(statbuf.st_mode)) {
// This is not a regular file
status_line_bold("'%s' is not a regular file", fn);
goto fi0;
}
if (p < text || p > end) {
status_line_bold("Trying to insert file outside of memory");
goto fi0;
return cnt;
}
// read file to buffer
fd = open(fn, O_RDONLY);
if (fd < 0) {
status_line_bold_errno(fn);
goto fi0;
return cnt;
}
/* Validate file */
if (fstat(fd, &statbuf) < 0) {
status_line_bold_errno(fn);
goto fi;
}
if (!S_ISREG(statbuf.st_mode)) {
status_line_bold("'%s' is not a regular file", fn);
goto fi;
}
size = (statbuf.st_size < INT_MAX ? (int)statbuf.st_size : INT_MAX);
p += text_hole_make(p, size);
cnt = safe_read(fd, p, size);
cnt = full_read(fd, p, size);
if (cnt < 0) {
status_line_bold_errno(fn);
p = text_hole_delete(p, p + size - 1, NO_UNDO); // 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 - 1, NO_UNDO); // un-do buffer insert
// There was a partial read, shrink unused space
p = text_hole_delete(p + cnt, p + size - 1, NO_UNDO);
status_line_bold("can't read '%s'", fn);
}
// if (cnt >= size)
// modified_count++;
fi:
close(fd);
fi0:
#if ENABLE_FEATURE_VI_READONLY
if (update_ro_status
&& ((access(fn, W_OK) < 0) ||
@ -3821,50 +3868,7 @@ static void do_cmd(int c)
break;
case ':': // :- the colon mode commands
p = get_input_line(":"); // get input line- use "status line"
#if ENABLE_FEATURE_VI_COLON
colon(p); // execute the command
#else
if (*p == ':')
p++; // move past the ':'
cnt = strlen(p);
if (cnt <= 0)
break;
if (strncmp(p, "quit", cnt) == 0
|| strncmp(p, "q!", cnt) == 0 // delete lines
) {
if (modified_count && p[1] != '!') {
status_line_bold("No write since last change (:%s! overrides)", p);
} else {
editing = 0;
}
} else if (strncmp(p, "write", cnt) == 0
|| strncmp(p, "wq", cnt) == 0
|| strncmp(p, "wn", cnt) == 0
|| (p[0] == 'x' && !p[1])
) {
cnt = file_write(current_filename, text, end - 1);
if (cnt < 0) {
if (cnt == -1)
status_line_bold("Write error: %s", strerror(errno));
} else {
modified_count = 0;
last_modified_count = -1;
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'
) {
editing = 0;
}
}
} else if (strncmp(p, "file", cnt) == 0) {
last_status_cksum = 0; // force status update
} else if (sscanf(p, "%d", &j) > 0) {
dot = find_line(j); // go to line # j
dot_skip_over_ws();
} else { // unrecognized cmd
not_implemented(p);
}
#endif /* !FEATURE_VI_COLON */
break;
case '<': // <- Left shift something
case '>': // >- Right shift something