aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/getchar.c90
-rw-r--r--src/nvim/getchar.h8
-rw-r--r--src/nvim/globals.h4
-rw-r--r--src/nvim/main.c14
-rw-r--r--src/nvim/os/fileio.c48
-rw-r--r--src/nvim/os/os_defs.h3
-rw-r--r--src/nvim/os/win_defs.h4
7 files changed, 115 insertions, 56 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index bae8ae6d91..b6e235146e 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -44,6 +44,12 @@
#include "nvim/event/loop.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/fileio.h"
+
+
+/// Index in scriptin
+static int curscript = 0;
+FileDescriptor *scriptin[NSCRIPT] = { NULL };
/*
* These buffers are used for storing:
@@ -1244,10 +1250,13 @@ openscript (
++curscript;
/* use NameBuff for expanded name */
expand_env(name, NameBuff, MAXPATHL);
- if ((scriptin[curscript] = mch_fopen((char *)NameBuff, READBIN)) == NULL) {
- EMSG2(_(e_notopen), name);
- if (curscript)
- --curscript;
+ int error;
+ if ((scriptin[curscript] = file_open_new(&error, (char *)NameBuff,
+ kFileReadOnly, 0)) == NULL) {
+ emsgf(_(e_notopen_2), name, os_strerror(error));
+ if (curscript) {
+ curscript--;
+ }
return;
}
save_typebuf();
@@ -1297,7 +1306,7 @@ static void closescript(void)
free_typebuf();
typebuf = saved_typebuf[curscript];
- fclose(scriptin[curscript]);
+ file_free(scriptin[curscript]);
scriptin[curscript] = NULL;
if (curscript > 0)
--curscript;
@@ -2346,7 +2355,6 @@ inchar (
{
int len = 0; /* init for GCC */
int retesc = FALSE; /* return ESC with gotint */
- int script_char;
if (wait_time == -1L || wait_time > 100L) {
// flush output before waiting
@@ -2364,45 +2372,38 @@ inchar (
}
undo_off = FALSE; /* restart undo now */
- /*
- * Get a character from a script file if there is one.
- * If interrupted: Stop reading script files, close them all.
- */
- script_char = -1;
- while (scriptin[curscript] != NULL && script_char < 0
- && !ignore_script
- ) {
-
-
- if (got_int || (script_char = getc(scriptin[curscript])) < 0) {
- /* Reached EOF.
- * Careful: closescript() frees typebuf.tb_buf[] and buf[] may
- * point inside typebuf.tb_buf[]. Don't use buf[] after this! */
+ // Get a character from a script file if there is one.
+ // If interrupted: Stop reading script files, close them all.
+ ptrdiff_t read_size = -1;
+ while (scriptin[curscript] != NULL && read_size < 0 && !ignore_script) {
+ char script_char;
+ if (got_int
+ || (read_size = file_read(scriptin[curscript], &script_char, 1)) != 1) {
+ // Reached EOF or some error occurred.
+ // Careful: closescript() frees typebuf.tb_buf[] and buf[] may
+ // point inside typebuf.tb_buf[]. Don't use buf[] after this!
closescript();
- /*
- * When reading script file is interrupted, return an ESC to get
- * back to normal mode.
- * Otherwise return -1, because typebuf.tb_buf[] has changed.
- */
- if (got_int)
- retesc = TRUE;
- else
+ // When reading script file is interrupted, return an ESC to get
+ // back to normal mode.
+ // Otherwise return -1, because typebuf.tb_buf[] has changed.
+ if (got_int) {
+ retesc = true;
+ } else {
return -1;
+ }
} else {
buf[0] = (char_u)script_char;
len = 1;
}
}
- if (script_char < 0) { /* did not get a character from script */
- /*
- * If we got an interrupt, skip all previously typed characters and
- * return TRUE if quit reading script file.
- * Stop reading typeahead when a single CTRL-C was read,
- * fill_input_buf() returns this when not able to read from stdin.
- * Don't use buf[] here, closescript() may have freed typebuf.tb_buf[]
- * and buf may be pointing inside typebuf.tb_buf[].
- */
+ if (read_size < 0) { // Did not get a character from script.
+ // If we got an interrupt, skip all previously typed characters and
+ // return TRUE if quit reading script file.
+ // Stop reading typeahead when a single CTRL-C was read,
+ // fill_input_buf() returns this when not able to read from stdin.
+ // Don't use buf[] here, closescript() may have freed typebuf.tb_buf[]
+ // and buf may be pointing inside typebuf.tb_buf[].
if (got_int) {
#define DUM_LEN MAXMAPLEN * 3 + 3
char_u dum[DUM_LEN + 1];
@@ -2415,21 +2416,18 @@ inchar (
return retesc;
}
- /*
- * Always flush the output characters when getting input characters
- * from the user.
- */
+ // Always flush the output characters when getting input characters
+ // from the user.
ui_flush();
- /*
- * Fill up to a third of the buffer, because each character may be
- * tripled below.
- */
+ // Fill up to a third of the buffer, because each character may be
+ // tripled below.
len = os_inchar(buf, maxlen / 3, (int)wait_time, tb_change_cnt);
}
- if (typebuf_changed(tb_change_cnt))
+ if (typebuf_changed(tb_change_cnt)) {
return 0;
+ }
return fix_input_buffer(buf, len);
}
diff --git a/src/nvim/getchar.h b/src/nvim/getchar.h
index bdf65909b6..04517866ec 100644
--- a/src/nvim/getchar.h
+++ b/src/nvim/getchar.h
@@ -1,6 +1,8 @@
#ifndef NVIM_GETCHAR_H
#define NVIM_GETCHAR_H
+#include "nvim/os/fileio.h"
+
/* Values for "noremap" argument of ins_typebuf(). Also used for
* map->m_noremap and menu->noremap[]. */
#define REMAP_YES 0 /* allow remapping */
@@ -12,6 +14,12 @@
#define KEYLEN_PART_MAP -2 /* keylen value for incomplete mapping */
#define KEYLEN_REMOVED 9999 /* keylen value for removed sequence */
+/// Maximum number of streams to read script from
+enum { NSCRIPT = 15 };
+
+/// Streams to read script from
+extern FileDescriptor *scriptin[NSCRIPT];
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "getchar.h.generated.h"
#endif
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index f8c7c9d330..8babb06d56 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -913,9 +913,6 @@ EXTERN int do_redraw INIT(= FALSE); /* extra redraw once */
EXTERN int need_highlight_changed INIT(= true);
EXTERN char *used_shada_file INIT(= NULL); // name of the ShaDa file to use
-#define NSCRIPT 15
-EXTERN FILE *scriptin[NSCRIPT]; /* streams to read script from */
-EXTERN int curscript INIT(= 0); /* index in scriptin[] */
EXTERN FILE *scriptout INIT(= NULL); /* stream to write script to */
// volatile because it is used in a signal handler.
@@ -1151,6 +1148,7 @@ EXTERN char_u e_norange[] INIT(= N_("E481: No range allowed"));
EXTERN char_u e_noroom[] INIT(= N_("E36: Not enough room"));
EXTERN char_u e_notmp[] INIT(= N_("E483: Can't get temp file name"));
EXTERN char_u e_notopen[] INIT(= N_("E484: Can't open file %s"));
+EXTERN char_u e_notopen_2[] INIT(= N_("E484: Can't open file %s: %s"));
EXTERN char_u e_notread[] INIT(= N_("E485: Can't read file %s"));
EXTERN char_u e_nowrtmsg[] INIT(= N_(
"E37: No write since last change (add ! to override)"));
diff --git a/src/nvim/main.c b/src/nvim/main.c
index ce0426bd8e..da3ec4381e 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -1056,14 +1056,20 @@ scripterror:
mch_errmsg("\"\n");
mch_exit(2);
}
+ int error;
if (STRCMP(argv[0], "-") == 0) {
- const int stdin_dup_fd = os_dup(STDIN_FILENO);
- FILE *const stdin_dup = fdopen(stdin_dup_fd, "r");
+ const int stdin_dup_fd = os_dup(OS_STDIN_FILENO);
+ FileDescriptor *const stdin_dup = file_open_fd_new(
+ &error, stdin_dup_fd, false, 0);
+ assert(stdin_dup != NULL);
scriptin[0] = stdin_dup;
- } else if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL) {
+ } else if ((scriptin[0] = file_open_new(
+ &error, argv[0], kFileReadOnly, 0)) == NULL) {
mch_errmsg(_("Cannot open for reading: \""));
mch_errmsg(argv[0]);
- mch_errmsg("\"\n");
+ mch_errmsg("\": ");
+ mch_errmsg(os_strerror(error));
+ mch_errmsg("\n");
mch_exit(2);
}
save_typebuf();
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c
index 775f2bd449..3742fd53de 100644
--- a/src/nvim/os/fileio.c
+++ b/src/nvim/os/fileio.c
@@ -45,7 +45,6 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname,
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int os_open_flags = 0;
- int fd;
TriState wr = kNone;
#define FLAG(flags, flag, fcntl_flags, wrval, cond) \
do { \
@@ -70,13 +69,33 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname,
#endif
#undef FLAG
- fd = os_open(fname, os_open_flags, mode);
+ const int fd = os_open(fname, os_open_flags, mode);
if (fd < 0) {
return fd;
}
+ return file_open_fd(ret_fp, fd, (wr == kTrue), mode);
+}
- ret_fp->wr = (wr == kTrue);
+/// Wrap file descriptor with FileDescriptor structure
+///
+/// @warning File descriptor wrapped like this must not be accessed by other
+/// means.
+///
+/// @param[out] ret_fp Address where information needed for reading from or
+/// writing to a file is saved
+/// @param[in] fd File descriptor to wrap.
+/// @param[in] wr True if fd is opened for writing only, false if it is read
+/// only.
+/// @param[in] mode Permissions for the newly created file (ignored if flags
+/// does not have FILE_CREATE\*).
+///
+/// @return Error code (@see os_strerror()) or 0. Currently always returns 0.
+int file_open_fd(FileDescriptor *const ret_fp, const int fd,
+ const bool wr, const int mode)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ ret_fp->wr = wr;
ret_fp->fd = fd;
ret_fp->eof = false;
ret_fp->rv = rbuffer_new(kRWBufferSize);
@@ -110,6 +129,29 @@ FileDescriptor *file_open_new(int *const error, const char *const fname,
return fp;
}
+/// Like file_open_fd(), but allocate and return ret_fp
+///
+/// @param[out] error Error code, @see os_strerror(). Is set to zero on
+/// success.
+/// @param[in] fd File descriptor to wrap.
+/// @param[in] wr True if fd is opened for writing only, false if it is read
+/// only.
+/// @param[in] mode Permissions for the newly created file (ignored if flags
+/// does not have FILE_CREATE\*).
+///
+/// @return [allocated] Opened file or NULL in case of error.
+FileDescriptor *file_open_fd_new(int *const error, const int fd,
+ const bool wr, const int mode)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ FileDescriptor *const fp = xmalloc(sizeof(*fp));
+ if ((*error = file_open_fd(fp, fd, wr, mode)) != 0) {
+ xfree(fp);
+ return NULL;
+ }
+ return fp;
+}
+
/// Close file and free its buffer
///
/// @param[in,out] fp File to close.
diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h
index 14c210c69c..88d8f4b750 100644
--- a/src/nvim/os/os_defs.h
+++ b/src/nvim/os/os_defs.h
@@ -13,6 +13,9 @@
# include "nvim/os/unix_defs.h"
#endif
+/// File descriptor number used for STDIN
+enum { OS_STDIN_FILENO = STDIN_FILENO };
+
#define BASENAMELEN (NAME_MAX - 5)
// Use the system path length if it makes sense.
diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h
index 8de896c490..f3493a7eed 100644
--- a/src/nvim/os/win_defs.h
+++ b/src/nvim/os/win_defs.h
@@ -87,4 +87,8 @@ typedef SSIZE_T ssize_t;
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+
#endif // NVIM_OS_WIN_DEFS_H