summaryrefslogtreecommitdiff
path: root/streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'streams.c')
-rw-r--r--streams.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/streams.c b/streams.c
new file mode 100644
index 0000000..d089b23
--- /dev/null
+++ b/streams.c
@@ -0,0 +1,204 @@
+#include <u.h>
+#include <libc.h>
+
+#include "dat.h"
+#include "fns.h"
+
+typedef struct Stream Stream;
+
+struct Stream
+{
+ ulong fd;
+ int type;
+ int mode;
+ int nalias;
+ Rune **aliases;
+ Stream *next;
+};
+
+enum {
+ TextStream,
+ BinaryStream,
+};
+
+enum {
+ ReadStream,
+ WriteStream,
+ AppendStream
+};
+
+static Stream *streams;
+static Stream *currentinput;
+static Stream *currentoutput;
+
+Stream *openstreamfd(int, int, int);
+Stream *getstreambyfd(int);
+Stream *getstreambyalias(Rune *);
+Stream *getstream(Term *);
+
+void
+initstreams(void)
+{
+ currentinput = openstreamfd(0, TextStream, ReadStream);
+ currentoutput = openstreamfd(1, TextStream, WriteStream);
+}
+
+int
+openstream(Rune *sourcesink, Rune *mode, Term *options, Term **stream)
+{
+ USED(options);
+ int omode;
+ int smode;
+ if(runestrcmp(mode, L"read") == 0){
+ omode = OREAD;
+ smode = ReadStream;
+ }else if(runestrcmp(mode, L"write") == 0){
+ omode = OWRITE;
+ smode = WriteStream;
+ }else if(runestrcmp(mode, L"append") == 0){
+ omode = OWRITE; /* Is this correct? */
+ smode = AppendStream;
+ }else{
+ *stream = existenceerror(L"source_sink", mkatom(sourcesink));
+ return 1;
+ }
+
+ char *filename = smprint("%S", sourcesink);
+ int fd = open(filename, omode);
+ if(fd < 0){
+ *stream = permissionerror(L"open", L"source_sink", mkatom(sourcesink));
+ return 1;
+ }
+ Stream *s = openstreamfd(fd, TextStream, smode);
+ *stream = mknumber(NumberInt, s->fd, 0);
+ return 0;
+}
+
+void
+closestream(Term *t)
+{
+ Stream *s = getstream(t);
+ if(s == nil)
+ return;
+
+ Stream *tmp;
+ Stream *prev = nil;
+ for(tmp = streams; tmp != nil; tmp = tmp->next){
+ if(tmp == s){
+ if(prev == nil)
+ streams = tmp->next;
+ else
+ prev->next = tmp->next;
+ break;
+ }
+ if(prev == nil)
+ prev = tmp;
+ }
+}
+
+Term *
+currentinputstream(void)
+{
+ return mknumber(NumberInt, currentinput->fd, 0);
+}
+
+Term *
+currentoutputstream(void)
+{
+ return mknumber(NumberInt, currentoutput->fd, 0);
+}
+
+void
+setcurrentinputstream(Term *t)
+{
+ Stream *s = getstream(t);
+ if(s)
+ currentinput = s;
+}
+
+void
+setcurrentoutputstream(Term *t)
+{
+ Stream *s = getstream(t);
+ if(s)
+ currentoutput = s;
+}
+
+int
+isopenstream(Term *t)
+{
+ Stream *s = getstream(t);
+ if(s)
+ return 1;
+ else
+ return 0;
+}
+
+int
+isinputstream(Term *t)
+{
+ Stream *s = getstream(t);
+ if(s && s->mode == ReadStream)
+ return 1;
+ else
+ return 0;
+}
+
+int
+isoutputstream(Term *t)
+{
+ Stream *s = getstream(t);
+ if(s && (s->mode == WriteStream || s->mode == AppendStream))
+ return 1;
+ else
+ return 0;
+}
+
+Stream *
+openstreamfd(int fd, int type, int mode)
+{
+ Stream *s = malloc(sizeof(Stream));
+ s->fd = fd;
+ s->type = type;
+ s->mode = mode;
+ s->nalias = 0;
+ s->aliases = nil;
+ s->next = streams;
+ streams = s;
+ return s;
+}
+
+Stream *
+getstreambyfd(int fd)
+{
+ Stream *s;
+ for(s = streams; s != nil; s = s->next)
+ if(s->fd == fd)
+ return s;
+ return nil;
+}
+
+Stream *
+getstreambyalias(Rune *alias)
+{
+ Stream *s;
+ for(s = streams; s != nil; s = s->next){
+ int i;
+ for(i = 0; i < s->nalias; i++){
+ if(runestrcmp(alias, s->aliases[i]) == 0)
+ return s;
+ }
+ }
+ return nil;
+}
+
+Stream *
+getstream(Term *t)
+{
+ Stream *s = nil;
+ if(t->tag == NumberTerm && t->numbertype == NumberInt)
+ s = getstreambyfd(t->ival);
+ else if(t->tag == AtomTerm)
+ s = getstreambyalias(t->text);
+ return s;
+} \ No newline at end of file