{raw⇐1} •SH 𝕩

This commit is contained in:
dzaima 2022-08-23 20:28:41 +03:00
parent 2666f25453
commit 905a9f78d4
5 changed files with 63 additions and 29 deletions

View File

@ -24,7 +24,7 @@ See [the BQN specification](https://mlochbaum.github.io/BQN/spec/system.html) fo
| `•Repr` | |
| `•Fmt` | |
| `•term` | Fields: `Flush`, `RawMode`, `CharB`, `CharN`; has extensions |
| `•SH` | Left argument can be `{stdin⇐"input"}` |
| `•SH` | Left argument can be a namespace; `stdin⇐"input"` in it passes stdin, `raw⇐1` takes stdin & returns stdout/stderr as raw bytes represented as characters. These extensions may be changed/removed if different interfaces are standardized. |
| `•Type` | |
| `•Glyph` | |
| `•Decompose` | |
@ -106,6 +106,6 @@ Namespace of various internal functions. May change at any time.
# FFI
Currently, there is no support for structs, nested pointers, or constant-length arrays, aka the only supported types are scalars (e.g. `i8`, `u64`, `*`), pointers to those (e.g. `*i8`, `&u64`), and conversions of either of those (e.g. `u64:i32`, `**:c8`).
Currently, there is no support for structs, nested pointers, or constant-length arrays, aka the only supported types are scalars (e.g. `i8`, `u64`), pointers to those (e.g. `*i8`, `&u64`), and conversions of either those or opaque pointers (e.g. `u64:i32`, `*i64:i32`, `**:c8`).
Additionally, the `a` type maps to `BQNV` from [bqnffi.h](../include/bqnffi.h) (example usage in [FFI tests](../test/ffi/)).
The `a` type maps to `BQNV` from [bqnffi.h](../include/bqnffi.h) (example usage in [FFI tests](../test/ffi/)).

View File

@ -858,12 +858,15 @@ B sh_c2(B t, B w, B x) {
// parse options
B inObj = bi_N;
bool raw = false;
if (!q_N(w)) {
if (!isNsp(w)) thrM("•SH: 𝕨 must be a namespace");
inObj = ns_getC(w, "stdin");
if (!q_N(inObj) && !isArr(inObj)) thrM("•SH: Invalid stdin value");
B rawObj = ns_getC(w, "raw");
if (!q_N(rawObj)) raw = o2b(rawObj);
}
u64 iLen = q_N(inObj)? 0 : utf8lenB(inObj);
u64 iLen = q_N(inObj)? 0 : (raw? IA(inObj) : utf8lenB(inObj));
// allocate args
if (isAtm(x) || RNK(x)>1) thrM("•SH: 𝕩 must be a vector of strings");
@ -912,8 +915,20 @@ B sh_c2(B t, B w, B x) {
// allocate stdin
u64 iOff = 0;
TALLOC(char, iBuf, iLen);
if (iLen>0) toUTF8(inObj, iBuf);
char* iBuf;
CharBuf iBufRaw;
if (iLen>0) {
if (raw) {
iBufRaw = get_chars(inObj);
iBuf = iBufRaw.data;
} else {
TALLOC(char, iBufT, iLen);
toUTF8(inObj, iBufT);
iBuf = iBufT;
}
} else iBuf = NULL;
#define FREE_INPUT do { if (iLen>0) { if (raw) free_chars(iBufRaw); else TFREE(iBuf); } } while(0)
bool iDone = false;
// allocate output buffer
B s_out = emptyCVec();
@ -944,7 +959,7 @@ B sh_c2(B t, B w, B x) {
shDbg("written %zd/"N64u"\n", ww, iLen-iOff);
if (ww >= 0) {
iOff+= ww;
if (iOff==iLen) { iDone=true; shClose(p_in[1]); TFREE(iBuf); shDbg("writing done\n"); }
if (iOff==iLen) { iDone=true; shClose(p_in[1]); FREE_INPUT; shDbg("writing done\n"); }
any = true;
}
}
@ -960,7 +975,7 @@ B sh_c2(B t, B w, B x) {
assert(reusable(oBufObj));
mm_free(v(oBufObj));
// free our ends of pipes
if (!iDone) { shClose(p_in[1]); TFREE(iBuf); shDbg("only got to write "N64u"/"N64u"\n", iOff, iLen); }
if (!iDone) { shClose(p_in[1]); FREE_INPUT; shDbg("only got to write "N64u"/"N64u"\n", iOff, iLen); }
shClose(p_out[0]);
shClose(p_err[0]);
@ -970,8 +985,15 @@ B sh_c2(B t, B w, B x) {
dec(w); dec(x);
B s_outRaw = toC8Any(s_out);
B s_errRaw = toC8Any(s_err);
B s_outObj = utf8Decode((char*)c8any_ptr(s_outRaw), IA(s_outRaw)); dec(s_outRaw);
B s_errObj = utf8Decode((char*)c8any_ptr(s_errRaw), IA(s_errRaw)); dec(s_errRaw);
B s_outObj;
B s_errObj;
if (raw) {
s_outObj = s_outRaw;
s_errObj = s_errRaw;
} else {
s_outObj = utf8Decode((char*)c8any_ptr(s_outRaw), IA(s_outRaw)); dec(s_outRaw);
s_errObj = utf8Decode((char*)c8any_ptr(s_errRaw), IA(s_errRaw)); dec(s_errRaw);
}
return m_hVec3(m_i32(WEXITSTATUS(status)), s_outObj, s_errObj);
}
#else

View File

@ -18,7 +18,7 @@ B m_ns(Scope* sc, NSDesc* desc); // consumes both
B ns_getU(B ns, i32 gid); // doesn't consume, doesn't increment result
B ns_qgetU(B ns, i32 gid); // ns_getU but return bi_N on fail
B ns_getNU(B ns, B name, bool thrEmpty); // doesn't consume anything, doesn't increment result; returns bi_N if doesn't exist and !thrEmpty
B ns_getC(B ns, char* name); // get namespace field by C string; returns bi_N if doesn't exist
B ns_getC(B ns, char* name); // get namespace field by C string; returns bi_N if doesn't exist, otherwise doesn't increment result like ns_getU
void ns_set(B ns, B name, B val); // consumes val
i32 pos2gid(Body* body, i32 pos); // converts a variable position to a gid; errors on special name variables

View File

@ -165,6 +165,29 @@ B path_abs(B path) {
#endif
}
CharBuf get_chars(B x) {
char* buf;
bool alloc;
u64 len = IA(x);
u8 el = TI(x,elType);
if (el==el_i8 || el==el_c8) {
buf = tyany_ptr(x);
alloc = false;
} else {
TALLOC(char, val, len);
buf = val;
alloc = true;
SGetU(x)
for (u64 i = 0; i < len; i++) {
B c = GetU(x,i);
buf[i] = isNum(c)? o2iu(c) : o2c(c);
}
}
return (CharBuf){.data=buf, .alloc=alloc};
}
void free_chars(CharBuf b) {
if (b.alloc) TFREE(b.data);
}
void path_wChars(B path, B x) { // consumes path
FILE* f = file_open(path, "write to", "w");
@ -181,29 +204,14 @@ void path_wChars(B path, B x) { // consumes path
void file_wBytes(FILE* f, B name, B x) {
u64 len = IA(x);
bool newBuf = false;
char* buf;
CharBuf buf = get_chars(x);
u8 el = TI(x,elType);
if (el==el_i8 || el==el_c8) {
buf = tyany_ptr(x);
} else {
TALLOC(char, val, len);
buf = val;
newBuf = true;
SGetU(x)
for (u64 i = 0; i < len; i++) {
B c = GetU(x,i);
buf[i] = isNum(c)? o2iu(c) : o2c(c);
}
}
if (fwrite(buf, 1, len, f) != len) {
if (fwrite(buf.data, 1, len, f) != len) {
if (q_N(name)) thrM("Error writing to file");
else thrF("Error writing to file \"%R\"", name);
}
if (newBuf) TFREE(buf);
free_chars(buf);
}
void path_wBytes(B path, B x) { // consumes path
FILE* f = file_open(path, "write to", "w");

View File

@ -13,6 +13,10 @@ B path_lines(B path); // consumes
I8Arr* stream_bytes(FILE* f);
typedef struct { char* data; bool alloc; } CharBuf;
CharBuf get_chars(B x); // convert x to character data; expects x isn't freed before free_chars call. May error.
void free_chars(CharBuf b); // free the result of the above
B mmap_file(B path); // consumes
bool dir_create(B path); // doesn't consume
bool path_rename(B old_path, B new_path); // consumes only old_path