{raw⇐1} •SH 𝕩
This commit is contained in:
parent
2666f25453
commit
905a9f78d4
@ -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/)).
|
||||
@ -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
|
||||
|
||||
2
src/ns.h
2
src/ns.h
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user