summaryrefslogtreecommitdiff
path: root/quadnames.c
diff options
context:
space:
mode:
authorglenda <glenda@cirno>2022-09-18 12:02:10 +0000
committerglenda <glenda@cirno>2022-09-18 12:02:10 +0000
commit6430127cc4503e2e7e40f86ccc68594ced055274 (patch)
treec59362f84ac28e051a31ea48495e6d002e019e20 /quadnames.c
parent0719e6cf67a4644282f97431024f6a350b45ff46 (diff)
File IO (very simple)
Diffstat (limited to 'quadnames.c')
-rw-r--r--quadnames.c166
1 files changed, 165 insertions, 1 deletions
diff --git a/quadnames.c b/quadnames.c
index 143eef1..b7c04d0 100644
--- a/quadnames.c
+++ b/quadnames.c
@@ -34,6 +34,13 @@ Array *quaddl(Array *);
Array *quadthreads1(Array *);
Array *quadthreads2(Array *, Array *);
Array *quadserial(Array *, Array *);
+Array *quadopen(Array *, Array *);
+Array *quadcreate(Array *, Array *);
+Array *quadclose(Array *);
+Array *quadread(Array *, Array *);
+Array *quadwrite(Array *, Array *);
+Array *quadpipe(Array *);
+Array *quadfd2path(Array *);
static Rune *quadquotebuf = nil;
static Array *session = nil;
@@ -59,6 +66,13 @@ QuadnameDef quadnames[] = {
{L"⎕DL", FunctionTag, nil, nil, quaddl, nil},
{L"⎕THREADS", FunctionTag, nil, nil, quadthreads1, quadthreads2},
{L"⎕SERIAL", FunctionTag, nil, nil, nil, quadserial},
+ {L"⎕OPEN", FunctionTag, nil, nil, nil, quadopen},
+ {L"⎕CREATE", FunctionTag, nil, nil, nil, quadcreate},
+ {L"⎕CLOSE", FunctionTag, nil, nil, quadclose, nil},
+ {L"⎕READ", FunctionTag, nil, nil, nil, quadread},
+ {L"⎕WRITE", FunctionTag, nil, nil, nil, quadwrite},
+ {L"⎕PIPE", FunctionTag, nil, nil, quadpipe, nil},
+ {L"⎕FD2PATH", FunctionTag, nil, nil, quadfd2path, nil},
{nil, 0, nil, nil, nil, nil} /* MUST BE LAST */
};
@@ -589,5 +603,155 @@ quadserial(Array *mode, Array *a)
}
return result;
-}
+}
+
+/* ⎕OPEN */
+Array *
+quadopen(Array *file, Array *omode)
+{
+ if(GetType(file) != AtypeRune || GetRank(file) > 1)
+ throwerror(L"Invalid file name", EDomain);
+ if(GetType(omode) != AtypeInt || GetSize(omode) != 1)
+ throwerror(L"Invalid mode", EDomain);
+
+ Rune *tmp = pparray(file);
+ char *filename = smprint("%S", tmp);
+ int mode = omode->intdata[0];
+ int ret = open(filename, mode);
+ free(tmp);
+ free(filename);
+ return mkscalarint(ret);
+}
+
+/* ⎕CREATE */
+Array *
+quadcreate(Array *file, Array *arg)
+{
+ if(GetType(file) != AtypeRune || GetRank(file) > 1)
+ throwerror(L"Invalid file name", EDomain);
+ if(GetType(arg) != AtypeInt || GetRank(arg) != 1 || GetSize(arg) != 2)
+ throwerror(L"Invalid mode+perm", EDomain);
+
+ Rune *tmp = pparray(file);
+ char *filename = smprint("%S", tmp);
+ int ret = create(filename, arg->intdata[0], arg->intdata[1]);
+ free(tmp);
+ free(filename);
+ return mkscalarint(ret);
+}
+
+/* ⎕CLOSE */
+Array *
+quadclose(Array *fd)
+{
+ if(GetSize(fd) != 1 || GetType(fd) != AtypeInt)
+ throwerror(nil, EDomain);
+ int ret = close(fd->intdata[0]);
+ return mkscalarint(ret);
+}
+
+/* ⎕READ */
+Array *
+quadread(Array *fd, Array *nbytes)
+{
+ if(GetType(fd) != AtypeInt || GetSize(fd) != 1)
+ throwerror(L"Invalid fd", EDomain);
+ if(GetType(nbytes) != AtypeInt || GetSize(nbytes) != 1 || nbytes->intdata[0] < 1)
+ throwerror(L"Invalid byte coint", EDomain);
+
+ u8int *buf = emalloc(nbytes->intdata[0]);
+ long nread = read(fd->intdata[0], buf, nbytes->intdata[0]);
+ if(nread >= 0)
+ buf = erealloc(buf, nread);
+ else{
+ free(buf);
+ throwerror(L"Read failed", EDomain);
+ }
+ Array *res = allocarray(AtypeInt, 1, nread);
+ res->shape[0] = nread;
+ for(int i = 0; i < nread; i++)
+ res->intdata[i] = buf[i];
+ free(buf);
+ return res;
+}
+/* ⎕WRITE */
+Array *
+quadwrite(Array *fd, Array *data)
+{
+ if(GetType(fd) != AtypeInt || GetSize(fd) != 1)
+ throwerror(L"Invalid fd", EDomain);
+ if(GetType(data) != AtypeInt || GetRank(fd) > 1)
+ throwerror(L"Data must be a scalar or vector of bytes", EDomain);
+
+ u8int *raw = emalloc(GetSize(data));
+ for(int i = 0; i < GetSize(data); i++){
+ u64int v = data->intdata[i];
+ if(v > 255){
+ free(raw);
+ throwerror(L"Data values must be bytes", EDomain);
+ }else
+ raw[i] = v;
+ }
+ long ret = write(fd->intdata[0], raw, GetSize(data));
+ free(raw);
+ return mkscalarint(ret);
+}
+
+/* ⎕PIPE */
+Array *
+quadpipe(Array *name)
+{
+ Array *result;
+ int p[2];
+
+ if(GetSize(name) > 0 && (GetType(name) != AtypeRune || GetRank(name) > 1))
+ throwerror(L"Invalid pipe name", EDomain);
+
+ if(GetSize(name) == 0){ /* Unnamed pipe */
+ pipe(p);
+ result = allocarray(AtypeInt, 1, 2);
+ result->shape[0] = 2;
+ result->intdata[0] = p[0];
+ result->intdata[1] = p[1];
+ }else{
+ /* If the name exists, open that pipe, otherwise create a new one */
+ Rune *tmp = pparray(name);
+ char *name = smprint("/srv/%S", tmp);
+ free(tmp);
+
+ int fd = open(name, ORDWR);
+ if(fd > 0)
+ result = mkscalarint(fd);
+ else{
+ fd = create(name, OWRITE, 0666);
+ if(fd < 0)
+ throwerror(L"Named pipe could not be opened", EDomain);
+ pipe(p);
+ fprint(fd, "%d", p[0]);
+ close(fd);
+ close(p[0]);
+ result = mkscalarint(p[1]);
+ }
+ free(name);
+ }
+ return result;
+}
+
+/* ⎕FD2PATH */
+Array *
+quadfd2path(Array *fd)
+{
+ if(GetType(fd) != AtypeInt || GetSize(fd) != 1)
+ throwerror(L"Invalid fd", EDomain);
+ char *buf = emalloc(1024);
+ int ret = fd2path(fd->intdata[0], buf, 1024);
+ if(ret != 0)
+ throwerror(nil, EDomain);
+
+ Rune *path = runesmprint("%s", buf);
+ Array *res = mkrunearray(path);
+ free(buf);
+ free(path);
+ return res;
+} \ No newline at end of file