summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--stream.c21
-rw-r--r--stream.h1
-rw-r--r--txr.136
-rw-r--r--utf8.c8
-rw-r--r--utf8.h1
6 files changed, 84 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index c9decb79..bdbb1a53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2015-04-10 Kaz Kylheku <kaz@kylheku.com>
+ Functions open-fileno and fileno.
+
+ * stream.c (fd_k): New keyword variable.
+ (stdio_get_prop): Handle the :fd property by returning
+ the file descriptor.
+ (open_fileno): New function.
+ (stream_init): Initialize fd_k, and register fileno and open-fileno.
+
+ * stream.h (open_fileno): Declared.
+
+ * txr.1: Documented open-fileno and fileno.
+
+ * utf8.c (w_fdopen): New function.
+
+ * utf8.h (w_fdopen): Declared.
+
+2015-04-10 Kaz Kylheku <kaz@kylheku.com>
+
* gc.c (sweep): Fix comment referring to nonexistent identifier.
2015-04-10 Kaz Kylheku <kaz@kylheku.com>
diff --git a/stream.c b/stream.c
index 136fb3dc..ef91a07d 100644
--- a/stream.c
+++ b/stream.c
@@ -64,7 +64,7 @@ val dev_k, ino_k, mode_k, nlink_k, uid_k;
val gid_k, rdev_k, size_k, blksize_k, blocks_k;
val atime_k, mtime_k, ctime_k;
val from_start_k, from_current_k, from_end_k;
-val real_time_k, name_k;
+val real_time_k, name_k, fd_k;
val format_s;
static void common_destroy(val obj)
@@ -291,6 +291,8 @@ static val stdio_get_prop(val stream, val ind)
return h->is_real_time ? t : nil;
} else if (ind == name_k) {
return h->descr;
+ } else if (ind == fd_k) {
+ return h->f ? num(fileno(h->f)) : nil;
}
return nil;
}
@@ -2310,6 +2312,20 @@ val open_file(val path, val mode_str)
return set_mode_props(m, make_stdio_stream(f, path));
}
+val open_fileno(val fd, val mode_str)
+{
+ struct stdio_mode m;
+ FILE *f = w_fdopen(c_num(fd), c_str(normalize_mode(&m, mode_str)));
+
+ if (!f)
+ uw_throwf(file_error_s, lit("error opening descriptor ~a: ~a/~s"),
+ fd, num(errno), string_utf8(strerror(errno)), nao);
+
+ return set_mode_props(m, make_stdio_stream(f, format(nil,
+ lit("fd ~a"),
+ fd, nao)));
+}
+
val open_tail(val path, val mode_str, val seek_end_p)
{
struct stdio_mode m;
@@ -2821,6 +2837,7 @@ void stream_init(void)
from_end_k = intern(lit("from-end"), keyword_package);
real_time_k = intern(lit("real-time"), keyword_package);
name_k = intern(lit("name"), keyword_package);
+ fd_k = intern(lit("fd"), keyword_package);
format_s = intern(lit("format"), user_package);
reg_var(stdin_s = intern(lit("*stdin*"), user_package),
@@ -2868,10 +2885,12 @@ void stream_init(void)
reg_fun(intern(lit("real-time-stream-p"), user_package), func_n1(real_time_stream_p));
reg_fun(intern(lit("stream-set-prop"), user_package), func_n3(stream_set_prop));
reg_fun(intern(lit("stream-get-prop"), user_package), func_n2(stream_get_prop));
+ reg_fun(intern(lit("fileno"), user_package), curry_12_1(func_n2(stream_get_prop), fd_k));
reg_fun(intern(lit("make-catenated-stream"), user_package), func_n0v(make_catenated_stream));
reg_fun(intern(lit("cat-streams"), user_package), func_n1(make_catenated_stream));
reg_fun(intern(lit("open-directory"), user_package), func_n1(open_directory));
reg_fun(intern(lit("open-file"), user_package), func_n2o(open_file, 1));
+ reg_fun(intern(lit("open-fileno"), user_package), func_n2o(open_fileno, 1));
reg_fun(intern(lit("open-tail"), user_package), func_n3o(open_tail, 1));
reg_fun(intern(lit("open-command"), user_package), func_n2o(open_command, 1));
reg_fun(intern(lit("open-pipe"), user_package), func_n2(open_command));
diff --git a/stream.h b/stream.h
index b6fc957f..48432e9f 100644
--- a/stream.h
+++ b/stream.h
@@ -117,6 +117,7 @@ val get_string(val stream, val nchars, val close_after_p);
val statf(val path);
val open_directory(val path);
val open_file(val path, val mode_str);
+val open_fileno(val fd, val mode_str);
val open_tail(val path, val mode_str, val seek_end_p);
val open_command(val path, val mode_str);
val open_process(val path, val mode_str, val args);
diff --git a/txr.1 b/txr.1
index 5dd3e1f5..4537885c 100644
--- a/txr.1
+++ b/txr.1
@@ -24816,6 +24816,42 @@ or
.codn nil ,
rather than zero or nonzero. The others return integer values.
+.SS* Unix File Descriptors
+
+.coNP Function @ open-fileno
+.synb
+.mets (open-fileno < file-descriptor <> [ mode-string ])
+.syne
+The
+.code open-fileno
+function creates a \*(TX stream over a file descriptor. The
+.meta file-descriptor
+argument must be an integer denoting a valid file descriptor.
+
+For a description of
+.metn mode-string ,
+see the
+.code open-file
+function.
+
+.coNP Function @ fileno
+.synb
+.mets (fileno << stream )
+.syne
+.desc
+The
+.code fileno
+function returns the underlying file descriptor of
+.metn stream ,
+if it has one. Otherwise, it returns
+.codn nil.
+
+This is equivalent to querying the stream using
+.code stream-get-prop
+for the
+.code :fd
+property.
+
.SS* Unix Itimers
Itimers ("interval timers") can be used in combination with signal handling to
execute asynchronous actions. Itimers deliver delayed, one-time signals,
diff --git a/utf8.c b/utf8.c
index 39d8a7f8..03aefa2e 100644
--- a/utf8.c
+++ b/utf8.c
@@ -387,6 +387,14 @@ FILE *w_freopen(const wchar_t *wname, const wchar_t *wmode, FILE *fold)
return f;
}
+FILE *w_fdopen(int fd, const wchar_t *wmode)
+{
+ char *mode = utf8_dup_to(wmode);
+ FILE *f = fdopen(fd, mode);
+ free(mode);
+ return f;
+}
+
int w_remove(const wchar_t *wpath)
{
char *path = utf8_dup_to(wpath);
diff --git a/utf8.h b/utf8.h
index 9380780f..05502382 100644
--- a/utf8.h
+++ b/utf8.h
@@ -52,5 +52,6 @@ wint_t utf8_decode(utf8_decoder_t *,int (*get)(mem_t *ctx), mem_t *ctx);
FILE *w_fopen(const wchar_t *, const wchar_t *);
FILE *w_popen(const wchar_t *, const wchar_t *);
FILE *w_freopen(const wchar_t *, const wchar_t *, FILE *);
+FILE *w_fdopen(int, const wchar_t *);
int w_remove(const wchar_t *);
int w_rename(const wchar_t *, const wchar_t *);