summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lexer.c4
-rw-r--r--quadnames.c166
2 files changed, 167 insertions, 3 deletions
diff --git a/lexer.c b/lexer.c
index 9971ecd..45f5f5f 100644
--- a/lexer.c
+++ b/lexer.c
@@ -194,7 +194,7 @@ get_digits:
*p = 0;
ungetrune(input);
stmt->toks[stmt->ntoks] = allocdatum(ArrayTag, 0);
- stmt->toks[stmt->ntoks]->array = floating ? mkscalarfloat(atof(buf)) : mkscalarint(atoll(buf));
+ stmt->toks[stmt->ntoks]->array = floating ? mkscalarfloat(atof(buf)) : mkscalarint(strtoull(buf, nil, 0));
}else if(runestrchr(L"⍺⍵⍶⍹", peek)){
Rune name[2] = {peek, 0};
stmt->toks[stmt->ntoks] = allocdatum(NameTag, 0);
@@ -216,7 +216,7 @@ get_digits:
Rune *p = buf;
*p++ = peek;
peek = getrune(input);
- while(isalpharune(peek)){
+ while(isalpharune(peek) || isdigitrune(peek)){
*p++ = toupperrune(peek);
peek = getrune(input);
}
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