1
0
forked from aniani/vim

updated for version 7.0051

This commit is contained in:
Bram Moolenaar
2005-02-22 08:39:57 +00:00
parent 6bdcfc08cb
commit df177f679e
29 changed files with 1272 additions and 349 deletions

View File

@@ -165,6 +165,7 @@ static int sig_alarm_called;
#endif
static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
static void catch_int_signal __ARGS((void));
static void set_signals __ARGS((void));
static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
#ifndef __EMX__
@@ -175,6 +176,14 @@ static int have_dollars __ARGS((int, char_u **));
#ifndef NO_EXPANDPATH
static int pstrcmp __ARGS((const void *, const void *));
static int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags));
# if defined(MACOS_X) && defined(FEAT_MBYTE)
extern char_u *mac_precompose_path __ARGS((char_u *decompPath, size_t decompLen, size_t *precompLen));
# endif
#endif
#if defined(MACOS_X) && defined(FEAT_MBYTE)
extern void mac_conv_init __ARGS((void));
extern void mac_conv_cleanup __ARGS((void));
#endif
#ifndef __EMX__
@@ -1083,6 +1092,10 @@ mch_init()
out_flush();
set_signals();
#if defined(MACOS_X) && defined(FEAT_MBYTE)
mac_conv_init();
#endif
}
static void
@@ -1113,11 +1126,8 @@ set_signals()
signal(SIGPIPE, SIG_IGN);
#endif
/*
* We want to catch CTRL-C (only works while in Cooked mode).
*/
#ifdef SIGINT
signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
catch_int_signal();
#endif
/*
@@ -1149,6 +1159,17 @@ set_signals()
#endif
}
#if defined(SIGINT) || defined(PROTO)
/*
* Catch CTRL-C (only works while in Cooked mode).
*/
static void
catch_int_signal()
{
signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
}
#endif
void
reset_signals()
{
@@ -2694,6 +2715,8 @@ static void exit_scroll __ARGS((void));
static void
exit_scroll()
{
if (silent_mode)
return;
if (newline_on_exit || msg_didout)
{
if (msg_use_printf())
@@ -2764,6 +2787,11 @@ mch_exit(r)
if (gui.in_use)
gui_exit(r);
#endif
#if defined(MACOS_X) && defined(FEAT_MBYTE)
mac_conv_cleanup();
#endif
#ifdef __QNX__
/* A core dump won't be created if the signal handler
* doesn't return, so we can't call exit() */
@@ -3282,6 +3310,27 @@ mch_new_shellsize()
/* Nothing to do. */
}
#ifndef USE_SYSTEM
static void append_ga_line __ARGS((garray_T *gap));
/*
* Append the text in "gap" below the cursor line and clear "gap".
*/
static void
append_ga_line(gap)
garray_T *gap;
{
/* Remove trailing CR. */
if (gap->ga_len > 0
&& !curbuf->b_p_bin
&& ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
--gap->ga_len;
ga_append(gap, NUL);
ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
gap->ga_len = 0;
}
#endif
int
mch_call_shell(cmd, options)
char_u *cmd;
@@ -3398,11 +3447,12 @@ mch_call_shell(cmd, options)
#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
#define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
127, some shell use that already */
# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
127, some shells use that already */
char_u *newcmd = NULL;
pid_t pid;
pid_t wpid = 0;
pid_t wait_pid = 0;
# ifdef HAVE_UNION_WAIT
union wait status;
@@ -3415,19 +3465,19 @@ mch_call_shell(cmd, options)
int i;
char_u *p;
int inquote;
# ifdef FEAT_GUI
int pty_master_fd = -1; /* for pty's */
# ifdef FEAT_GUI
int pty_slave_fd = -1;
char *tty_name;
# endif
int fd_toshell[2]; /* for pipes */
int fd_fromshell[2];
int pipe_error = FALSE;
# ifdef HAVE_SETENV
# ifdef HAVE_SETENV
char envbuf[50];
# else
# else
static char envbuf_Rows[20];
static char envbuf_Columns[20];
# endif
# endif
int did_settmode = FALSE; /* TRUE when settmode(TMODE_RAW) called */
@@ -3480,19 +3530,24 @@ mch_call_shell(cmd, options)
}
argv[argc] = NULL;
# ifdef FEAT_GUI
/*
* For the GUI: Try using a pseudo-tty to get the stdin/stdout of the
* executed command into the Vim window. Or use a pipe.
* For the GUI, when writing the output into the buffer and when reading
* input from the buffer: Try using a pseudo-tty to get the stdin/stdout
* of the executed command into the Vim window. Or use a pipe.
*/
if (gui.in_use && show_shell_mess)
if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI
|| (gui.in_use && show_shell_mess)
# endif
)
{
# ifdef FEAT_GUI
/*
* Try to open a master pty.
* If this works, open the slave pty.
* If the slave can't be opened, close the master pty.
*/
if (p_guipty)
if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
{
pty_master_fd = OpenPTY(&tty_name); /* open pty */
if (pty_master_fd >= 0 && ((pty_slave_fd =
@@ -3506,6 +3561,7 @@ mch_call_shell(cmd, options)
* If not opening a pty or it didn't work, try using pipes.
*/
if (pty_master_fd < 0)
# endif
{
pipe_error = (pipe(fd_toshell) < 0);
if (!pipe_error) /* pipe create OK */
@@ -3526,8 +3582,6 @@ mch_call_shell(cmd, options)
}
if (!pipe_error) /* pty or pipe opened or not used */
# endif
{
# ifdef __BEOS__
beos_cleanup_read_thread();
@@ -3535,15 +3589,20 @@ mch_call_shell(cmd, options)
if ((pid = fork()) == -1) /* maybe we should use vfork() */
{
MSG_PUTS(_("\nCannot fork\n"));
if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI
if (gui.in_use && show_shell_mess)
|| (gui.in_use && show_shell_mess)
# endif
)
{
# ifdef FEAT_GUI
if (pty_master_fd >= 0) /* close the pseudo tty */
{
close(pty_master_fd);
close(pty_slave_fd);
}
else /* close the pipes */
# endif
{
close(fd_toshell[0]);
close(fd_toshell[1]);
@@ -3551,7 +3610,6 @@ mch_call_shell(cmd, options)
close(fd_fromshell[1]);
}
}
# endif
}
else if (pid == 0) /* child */
{
@@ -3593,13 +3651,17 @@ mch_call_shell(cmd, options)
close(fd);
}
}
else if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI
else if (gui.in_use)
|| gui.in_use
# endif
)
{
# ifdef HAVE_SETSID
# ifdef HAVE_SETSID
(void)setsid();
# endif
# endif
# ifdef FEAT_GUI
/* push stream discipline modules */
if (options & SHELL_COOKED)
SetupSlavePTY(pty_slave_fd);
@@ -3608,8 +3670,9 @@ mch_call_shell(cmd, options)
* unless run by root) */
ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
# endif
# endif
/* Simulate to have a dumb terminal (for now) */
# ifdef HAVE_SETENV
# ifdef HAVE_SETENV
setenv("TERM", "dumb", 1);
sprintf((char *)envbuf, "%ld", Rows);
setenv("ROWS", (char *)envbuf, 1);
@@ -3617,7 +3680,7 @@ mch_call_shell(cmd, options)
setenv("LINES", (char *)envbuf, 1);
sprintf((char *)envbuf, "%ld", Columns);
setenv("COLUMNS", (char *)envbuf, 1);
# else
# else
/*
* Putenv does not copy the string, it has to remain valid.
* Use a static array to avoid loosing allocated memory.
@@ -3629,8 +3692,9 @@ mch_call_shell(cmd, options)
putenv(envbuf_Rows);
sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
putenv(envbuf_Columns);
# endif
# endif
# ifdef FEAT_GUI
if (pty_master_fd >= 0)
{
close(pty_master_fd); /* close master side of pty */
@@ -3646,6 +3710,7 @@ mch_call_shell(cmd, options)
close(pty_slave_fd); /* has been dupped, close it now */
}
else
# endif
{
/* set up stdin for the child */
close(fd_toshell[1]);
@@ -3664,7 +3729,7 @@ mch_call_shell(cmd, options)
dup(1);
}
}
# endif /* FEAT_GUI */
/*
* There is no type cast for the argv, because the type may be
* different on different machines. This may cause a warning
@@ -3679,21 +3744,27 @@ mch_call_shell(cmd, options)
{
/*
* While child is running, ignore terminating signals.
* Do catch CTRL-C, so that "got_int" is set.
*/
catch_signals(SIG_IGN, SIG_ERR);
# ifdef FEAT_GUI
catch_int_signal();
/*
* For the GUI we redirect stdin, stdout and stderr to our window.
* This is also used to pipe stdin/stdout to/from the external
* command.
*/
if (gui.in_use && show_shell_mess)
if ((options & (SHELL_READ|SHELL_WRITE))
# ifdef FEAT_GUI
|| (gui.in_use && show_shell_mess)
# endif
)
{
# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
char_u buffer[BUFLEN + 1];
# ifdef FEAT_MBYTE
# ifdef FEAT_MBYTE
int buffer_off = 0; /* valid bytes in buffer[] */
# endif
# endif
char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
int ta_len = 0; /* valid bytes in ta_buf[] */
int len;
@@ -3702,7 +3773,10 @@ mch_call_shell(cmd, options)
int c;
int toshell_fd;
int fromshell_fd;
garray_T ga;
int noread_cnt;
# ifdef FEAT_GUI
if (pty_master_fd >= 0)
{
close(pty_slave_fd); /* close slave side of pty */
@@ -3710,6 +3784,7 @@ mch_call_shell(cmd, options)
toshell_fd = dup(pty_master_fd);
}
else
# endif
{
close(fd_toshell[0]);
close(fd_fromshell[1]);
@@ -3738,6 +3813,76 @@ mch_call_shell(cmd, options)
old_State = State;
State = EXTERNCMD; /* don't redraw at window resize */
if (options & SHELL_WRITE && toshell_fd >= 0)
{
/* Fork a process that will write the lines to the
* external program. */
if ((wpid = fork()) == -1)
{
MSG_PUTS(_("\nCannot fork\n"));
}
else if (wpid == 0)
{
linenr_T lnum = curbuf->b_op_start.lnum;
int written = 0;
char_u *p = ml_get(lnum);
char_u *s;
size_t l;
/* child */
for (;;)
{
l = STRLEN(p + written);
if (l == 0)
len = 0;
else if (p[written] == NL)
/* NL -> NUL translation */
len = write(toshell_fd, "", (size_t)1);
else
{
s = vim_strchr(p + written, NL);
len = write(toshell_fd, (char *)p + written,
s == NULL ? l : s - (p + written));
}
if (len == l)
{
/* Finished a line, add a NL, unless this line
* should not have one. */
if (lnum != curbuf->b_op_end.lnum
|| !curbuf->b_p_bin
|| (lnum != write_no_eol_lnum
&& (lnum !=
curbuf->b_ml.ml_line_count
|| curbuf->b_p_eol)))
write(toshell_fd, "\n", (size_t)1);
++lnum;
if (lnum > curbuf->b_op_end.lnum)
{
/* finished all the lines, close pipe */
close(toshell_fd);
toshell_fd = -1;
break;
}
p = ml_get(lnum);
written = 0;
}
else if (len > 0)
written += len;
}
_exit(0);
}
else
{
close(toshell_fd);
toshell_fd = -1;
}
}
if (options & SHELL_READ)
ga_init2(&ga, 1, BUFLEN);
noread_cnt = 0;
for (;;)
{
/*
@@ -3745,12 +3890,15 @@ mch_call_shell(cmd, options)
* if there are any. Don't do this if we are expanding
* wild cards (would eat typeahead). Don't get extra
* characters when we already have one.
* Don't read characters unless we didn't get output for a
* while, avoids that ":r !ls" eats typeahead.
*/
len = 0;
if (!(options & SHELL_EXPAND)
&& (ta_len > 0
|| (len = ui_inchar(ta_buf, BUFLEN, 10L,
0)) > 0))
|| (noread_cnt > 4
&& (len = ui_inchar(ta_buf,
BUFLEN, 10L, 0)) > 0)))
{
/*
* For pipes:
@@ -3759,19 +3907,23 @@ mch_call_shell(cmd, options)
*/
if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
{
# ifdef SIGINT
# ifdef SIGINT
/*
* Send SIGINT to the child's group or all
* processes in our group.
*/
if (ta_buf[ta_len] == Ctrl_C
|| ta_buf[ta_len] == intr_char)
# ifdef HAVE_SETSID
{
# ifdef HAVE_SETSID
kill(-pid, SIGINT);
# else
# else
kill(0, SIGINT);
# endif
# endif
if (wpid > 0)
kill(wpid, SIGINT);
}
# endif
if (pty_master_fd < 0 && toshell_fd >= 0
&& ta_buf[ta_len] == Ctrl_D)
{
@@ -3799,10 +3951,10 @@ mch_call_shell(cmd, options)
}
else if (ta_buf[i] == '\r')
ta_buf[i] = '\n';
# ifdef FEAT_MBYTE
# ifdef FEAT_MBYTE
if (has_mbyte)
i += (*mb_ptr2len_check)(ta_buf + i) - 1;
# endif
# endif
}
/*
@@ -3815,7 +3967,7 @@ mch_call_shell(cmd, options)
{
if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
msg_putchar(ta_buf[i]);
# ifdef FEAT_MBYTE
# ifdef FEAT_MBYTE
else if (has_mbyte)
{
int l = (*mb_ptr2len_check)(ta_buf + i);
@@ -3823,7 +3975,7 @@ mch_call_shell(cmd, options)
msg_outtrans_len(ta_buf + i, l);
i += l - 1;
}
# endif
# endif
else
msg_outtrans_len(ta_buf + i, 1);
}
@@ -3837,18 +3989,37 @@ mch_call_shell(cmd, options)
* Write the characters to the child, unless EOF has
* been typed for pipes. Write one character at a
* time, to avoid loosing too much typeahead.
* When writing buffer lines, drop the typed
* characters (only check for CTRL-C).
*/
if (toshell_fd >= 0)
if (options & SHELL_WRITE)
ta_len = 0;
else if (toshell_fd >= 0)
{
len = write(toshell_fd, (char *)ta_buf, (size_t)1);
if (len > 0)
{
ta_len -= len;
mch_memmove(ta_buf, ta_buf + len, ta_len);
noread_cnt = 0;
}
}
}
if (got_int)
{
/* CTRL-C sends a signal to the child, we ignore it
* ourselves */
# ifdef HAVE_SETSID
kill(-pid, SIGINT);
# else
kill(0, SIGINT);
# endif
if (wpid > 0)
kill(wpid, SIGINT);
got_int = FALSE;
}
/*
* Check if the child has any characters to be printed.
* Read them and write them to our window. Repeat this as
@@ -3858,24 +4029,42 @@ mch_call_shell(cmd, options)
* TODO: This should handle escape sequences, compatible
* to some terminal (vt52?).
*/
++noread_cnt;
while (RealWaitForChar(fromshell_fd, 10L, NULL))
{
len = read(fromshell_fd, (char *)buffer
# ifdef FEAT_MBYTE
# ifdef FEAT_MBYTE
+ buffer_off, (size_t)(BUFLEN - buffer_off)
# else
# else
, (size_t)BUFLEN
# endif
# endif
);
if (len <= 0) /* end of file or error */
goto finished;
# ifdef FEAT_MBYTE
len += buffer_off;
buffer[len] = NUL;
if (has_mbyte)
noread_cnt = 0;
if (options & SHELL_READ)
{
/* Do NUL -> NL translation, append NL separated
* lines to the current buffer. */
for (i = 0; i < len; ++i)
{
if (buffer[i] == NL)
append_ga_line(&ga);
else if (buffer[i] == NUL)
ga_append(&ga, NL);
else
ga_append(&ga, buffer[i]);
}
}
# ifdef FEAT_MBYTE
else if (has_mbyte)
{
int l;
len += buffer_off;
buffer[len] = NUL;
/* Check if the last character in buffer[] is
* incomplete, keep these bytes for the next
* round. */
@@ -3913,8 +4102,8 @@ mch_call_shell(cmd, options)
}
buffer_off = 0;
}
# endif /* FEAT_MBYTE */
else
# endif /* FEAT_MBYTE */
{
buffer[len] = NUL;
msg_puts(buffer);
@@ -3931,11 +4120,11 @@ mch_call_shell(cmd, options)
* Check if the child still exists, before checking for
* typed characters (otherwise we would loose typeahead).
*/
# ifdef __NeXT__
# ifdef __NeXT__
wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
# else
# else
wait_pid = waitpid(pid, &status, WNOHANG);
# endif
# endif
if ((wait_pid == (pid_t)-1 && errno == ECHILD)
|| (wait_pid == pid && WIFEXITED(status)))
{
@@ -3946,20 +4135,29 @@ mch_call_shell(cmd, options)
}
finished:
p_more = p_more_save;
if (options & SHELL_READ)
{
if (ga.ga_len > 0)
{
append_ga_line(&ga);
/* remember that the NL was missing */
write_no_eol_lnum = curwin->w_cursor.lnum;
}
else
write_no_eol_lnum = 0;
ga_clear(&ga);
}
# ifndef MACOS_X_UNIX /* TODO: Is it needed for MACOS_X ? */
/*
* Give all typeahead that wasn't used back to ui_inchar().
*/
if (ta_len)
ui_inchar_undo(ta_buf, ta_len);
# endif
State = old_State;
if (toshell_fd >= 0)
close(toshell_fd);
close(fromshell_fd);
}
# endif /* FEAT_GUI */
/*
* Wait until our child has exited.
@@ -3970,7 +4168,7 @@ finished:
*/
while (wait_pid != pid)
{
#ifdef _THREAD_SAFE
# ifdef _THREAD_SAFE
/* Ugly hack: when compiled with Python threads are probably
* used, in which case wait() sometimes hangs for no obvious
* reason. Use waitpid() instead and loop (like the GUI). */
@@ -3985,9 +4183,9 @@ finished:
mch_delay(10L, TRUE);
continue;
}
#else
# else
wait_pid = wait(&status);
#endif
# endif
if (wait_pid <= 0
# ifdef ECHILD
&& errno == ECHILD
@@ -3996,6 +4194,11 @@ finished:
break;
}
/* Make sure the child that writes to the external program is
* dead. */
if (wpid > 0)
kill(wpid, SIGKILL);
/*
* Set to raw mode right now, otherwise a CTRL-C after
* catch_signals() will kill Vim.
@@ -4656,7 +4859,19 @@ unix_expandpath(gap, path, wildoff, flags)
if (*path_end != NUL)
backslash_halve(buf + len + 1);
if (mch_getperm(buf) >= 0) /* add existing file */
{
#if defined(MACOS_X) && defined(FEAT_MBYTE)
size_t precomp_len = STRLEN(buf)+1;
char_u *precomp_buf =
mac_precompose_path(buf, precomp_len, &precomp_len);
if (precomp_buf)
{
mch_memmove(buf, precomp_buf, precomp_len);
vim_free(precomp_buf);
}
#endif
addfile(gap, buf, flags);
}
}
}
}