urbit/f/coal.c
Steven Dee 324c6a235d Remove most instances of strcpy and sprintf
OpenBSD whines about these and recommends using strlcpy / snprintf
instead. Since strlcpy isn't quite universal yet, we use strncpy instead
and be careful about terminating the string. We could implement a
portable strlcpy in terms of strncpy, but that'd add another function to
the namespace.

Yes, usually the length is obviously bounded. Still, pretending
strcpy/sprintf don't exist seems like a great strategy.

N.B. there are still a few occurrences of strcpy and sprintf under f/
and in libuv, but I don't have time to tackle them right now.
2013-10-30 15:25:22 -04:00

1062 lines
20 KiB
C

/* f/coal.c
**
** This file is in the public domain.
*/
#include "all.h"
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <dirent.h>
#include "../gen191/pit.h"
/** Jet dependencies. Minimize these.
**/
# define Pt5Y k_191__mood__hoon
/** Jet dependencies. Minimize these.
**/
# define Pt3Y k_191__mood__hoon
# define Pt4Y k_191__mood__hoon
# define Pt5Y k_191__mood__hoon
u2_noun j2_mbc(Pt3Y, gor)(u2_wire, u2_noun a, u2_noun b);
u2_noun j2_mcc(Pt4Y, by, get)(u2_wire, u2_noun a, u2_noun b);
u2_noun j2_mcc(Pt4Y, by, put)(u2_wire, u2_noun a, u2_noun b, u2_noun c);
u2_noun j2_mby(Pt5Y, jam)(u2_wire, u2_noun a);
u2_noun j2_mby(Pt5Y, trip)(u2_wire, u2_noun a);
# define _coal_cue j2_mby(Pt5Y, cue)
# define _coal_jam j2_mby(Pt5Y, jam)
# define _coal_trip j2_mby(Pt5Y, trip)
# define _coal_gor j2_mbc(Pt3Y, gor)
# define _coal_by_gas j2_mcc(Pt4Y, by, gas)
# define _coal_by_get j2_mcc(Pt4Y, by, get)
# define _coal_by_has j2_mcc(Pt4Y, in, has)
# define _coal_by_put j2_mcc(Pt4Y, by, put)
# define _coal_in_gas j2_mcc(Pt4Y, in, gas)
# define _coal_in_has j2_mcc(Pt4Y, in, has)
# define _coal_in_tap j2_mcc(Pt4Y, in, tap)
/* u2_cf_path(): assemble local path with noun thap and ext.
*/
/* _cf_path_1: write at/inpath.
*/
static c3_w
_cf_path_1(c3_c* buf_c,
c3_w pos_w,
u2_noun hut) // retain
{
if ( u2_no == u2_cr_du(hut) ) {
c3_w met_w = u2_cr_met(3, hut);
if ( buf_c ) u2_cr_bytes(0, met_w, (c3_y*)(buf_c + pos_w), hut);
return (pos_w + met_w);
}
else {
c3_w met_w = u2_cr_met(3, u2h(hut));
c3_w end_w = _cf_path_1(buf_c, pos_w, u2t(hut));
u2_noun san = u2h(hut);
if ( buf_c ) buf_c[end_w] = '/';
end_w++;
// little security thing - last ditch
//
if ( c3_s2('.', '.') == san ) {
san = c3_s3('.','.','.');
}
if ( buf_c ) u2_cr_bytes(0, met_w, (c3_y*)(buf_c + end_w), san);
end_w += met_w;
return end_w;
}
}
u2_noun
u2_cf_path(c3_c* top_c,
c3_c* ext_c,
u2_noun tah)
{
c3_w top_w = strlen(top_c);
c3_w len_w = _cf_path_1(0, (top_w + 1), tah);
c3_w buf_w = len_w + (ext_c ? (1 + strlen(ext_c)) : 0);
c3_c* buf_c = malloc(buf_w + 1);
c3_w pos_w;
u2_noun pas;
strncpy(buf_c, top_c, buf_w);
buf_c[buf_w] = '\0';
pos_w = top_w;
buf_c[pos_w++] = '/';
pos_w = _cf_path_1(buf_c, pos_w, tah);
if ( ext_c ) {
buf_c[pos_w++] = '.';
strncpy(buf_c + pos_w, ext_c, buf_w - pos_w);
} else {
buf_c[pos_w] = 0;
}
pas = u2_ci_string(buf_c);
free(buf_c);
u2_cz(tah);
return pas;
}
/* u2_cf_flat_date(): date for `pas`. Unix time * 10^6, or 0.
*/
c3_d
u2_cf_flat_date(u2_noun pas)
{
c3_c* pas_c = u2_cr_string(pas);
struct stat pas_s;
u2_cz(pas);
if ( stat(pas_c, &pas_s) < 0 ) {
free(pas_c);
return 0;
} else {
free(pas_c);
#if defined(U2_OS_linux)
return ( ((c3_d)pas_s.st_mtime) );
#elif defined(U2_OS_osx)
return ( ((c3_d)pas_s.st_mtimespec.tv_sec) +
((c3_d)(pas_s.st_mtimespec.tv_nsec / 1000)) );
#elif defined(U2_OS_bsd)
return ( ((c3_d)pas_s.st_mtim.tv_sec) +
((c3_d)(pas_s.st_mtim.tv_nsec / 1000)) );
#else
#error "port: filetime"
#endif
}
}
/* u2_cf_flat_load(): load `mod` at `pas`. Bail on error.
*/
u2_weak
u2_cf_flat_load(u2_noun mod,
u2_noun pas)
{
c3_assert(c3__atom == mod);
{
c3_c* pas_c = u2_cr_string(pas);
c3_i fid_i;
struct stat sat_s;
c3_w fln_w;
c3_c* fil_c;
u2_atom fil;
fid_i = open(pas_c, O_RDONLY, 0644);
free(pas_c);
u2_cz(pas);
if ( (fid_i < 0) || (fstat(fid_i, &sat_s) < 0) ) {
perror(pas_c);
return u2_none;
}
fln_w = sat_s.st_size;
fil_c = malloc(sat_s.st_size);
if ( fln_w != read(fid_i, fil_c, fln_w) ) {
return u2_none;
}
close(fid_i);
fil = u2_ci_bytes(fln_w, (c3_y *)fil_c);
free(fil_c);
return fil;
}
}
/* u2_cf_list(): list all the files in directory `pas`. List of cask.
*/
u2_noun
u2_cf_list(u2_noun pas)
{
c3_c* pas_c = u2_cr_string(pas);
u2z(pas);
{
u2_noun lis = u2_nul;
DIR *dir_d = opendir(pas_c);
if ( !dir_d ) {
free(pas_c);
return u2_nul;
}
else {
while ( 1 ) {
struct dirent ent_n;
struct dirent *out_n;
if ( readdir_r(dir_d, &ent_n, &out_n) != 0 ) {
perror(pas_c);
return u2_cm_bail(c3__fail);
}
else if ( !out_n ) {
break;
}
else lis = u2nc(u2_ci_string(out_n->d_name), lis);
}
free(pas_c);
return lis;
}
}
}
/* u2_cf_flat_save(): save `som` as `mod` at `pas`.
*/
u2_bean
u2_cf_flat_save(u2_noun mod,
u2_noun pas,
u2_noun som)
{
c3_assert(c3__atom == mod);
{
c3_c* pas_c = u2_cr_string(pas);
c3_i fid_i;
c3_w fln_w;
c3_y* fil_y;
fid_i = open(pas_c, O_WRONLY | O_CREAT, 0666);
free(pas_c);
u2_cz(pas);
if ( fid_i < 0 ) {
perror(pas_c);
u2_cz(som);
return u2_no;
}
fln_w = u2_met(3, som);
fil_y = malloc(fln_w);
u2_cr_bytes(0, fln_w, fil_y, som);
u2_cz(som);
if ( fln_w != write(fid_i, fil_y, fln_w) ) {
return u2_no;
}
close(fid_i);
return u2_yes;
}
}
#if 1
/* u2_cn_mung():
**
** Call `(function sample)`.
*/
u2_noun
u2_cn_mung(u2_noun fun,
u2_noun sam)
{
u2_noun pro = u2_bn_mong(u2_Wire, fun, sam);
u2_cz(fun);
return pro;
}
#endif
/* u2_ci_string():
**
** u2_ci_bytes(strlen(a_c), (c3_y *)a_c);
*/
u2_atom
u2_ci_string(const c3_c* a_c)
{
return u2_bn_string(u2_Wire, a_c);
}
/* u2_ci_mp(): construct atom from GMP. Caller transfers a_mp.
*/
u2_atom
u2_ci_mp(mpz_t a_mp)
{
return u2_rl_mp(u2_Wire, a_mp);
}
/* u2_ci_tape(): from a C string, to a list of bytes.
*/
u2_atom
u2_ci_tape(const c3_c* txt_c)
{
if ( !*txt_c ) {
return u2_nul;
} else return u2nc(*txt_c, u2_ci_tape(txt_c + 1));
}
/* u2_cr_string(): `a` as malloced C string.
*/
c3_c*
u2_cr_string(u2_atom a)
{
c3_w met_w = u2_cr_met(3, a);
c3_c* str_c = malloc(met_w + 1);
u2_cr_bytes(0, met_w, (c3_y*)str_c, a);
str_c[met_w] = 0;
return str_c;
}
/* u2_cr_tape(): `a`, a list of bytes, as malloced C string.
*/
c3_y*
u2_cr_tape(u2_noun a)
{
u2_noun b;
c3_w i_w;
c3_y *a_y;
for ( i_w = 0, b=a; u2_yes == u2du(b); i_w++, b=u2t(b) )
;
a_y = malloc(i_w + 1);
for ( i_w = 0, b=a; u2_yes == u2du(b); i_w++, b=u2t(b) ) {
a_y[i_w] = u2h(b);
}
a_y[i_w] = 0;
return a_y;
}
/* u2_ci_bytes():
**
** Construct `a` bytes from `b`, LSB first, as an atom.
*/
u2_atom
u2_ci_bytes(c3_w a_w,
const c3_y* b_y)
{
return u2_bn_bytes(u2_Wire, a_w, b_y);
}
/* u2_ci_words():
**
** Construct `a` words from `b`, LSW first, as an atom.
*/
u2_atom
u2_ci_words(c3_w a_w,
const c3_w* b_w)
{
return u2_bn_words(u2_Wire, a_w, b_w);
}
/* u2_ci_chubs():
**
** Construct `a` double-words from `b`, LSD first, as an atom.
*/
u2_atom
u2_ci_chubs(c3_w a_w,
const c3_d* b_d)
{
// XX considerably suboptimal
{
c3_w *b_w = malloc(a_w * 8);
c3_w i_w;
u2_atom p;
for ( i_w = 0; i_w < a_w; i_w++ ) {
b_w[(2 * i_w)] = b_d[i_w] & 0xffffffffULL;
b_w[(2 * i_w) + 1] = b_d[i_w] >> 32ULL;
}
p = u2_ci_words((a_w * 2), b_w);
free(b_w);
return p;
}
}
/* u2_cm_trip(): descend into a memory region.
**
** Memory allocated in the heap above is senior & frozen.
*/
void
u2_cm_trip()
{
#if 0
if ( u2_no == u2_rl_leap(u2_Wire, c3__rock) ) {
u2_cm_bail(c3__fail);
}
#endif
}
/* u2_cm_chin(): ascend out of a memory region.
**
** Memory allocated in the heap below is junior & volatile.
*/
void
u2_cm_chin()
{
#if 0
u2_rl_fall(u2_Wire);
#endif
}
/* u2_cm_bury(): store fresh or volatile noun `som` to freezer.
*/
u2_weak
u2_cm_bury(u2_weak som)
{
if ( u2_none == som ) return som;
if ( u2_no == u2_rl_junior(u2_wire_bas_r(u2_Wire), som) ) {
return som;
}
else {
u2_noun pro = u2_rl_take(u2_wire_bas_r(u2_Wire), som);
u2_cz(som);
return pro;
}
}
/* u2_cm_rind(): open and produce a new jump buffer.
*/
void*
u2_cm_rind()
{
u2_ray kit_r = u2_rl_ralloc(u2_Wire, c3_wiseof(u2_loom_kite));
u2_kite_par_r(kit_r) = u2_wire_kit_r(u2_Wire);
u2_wire_kit_r(u2_Wire) = kit_r;
// Save the old stack and actions.
//
u2_kite_tax(kit_r) = u2k(u2_wire_tax(u2_Wire));
u2_kite_don(kit_r) = u2k(u2_wrac_at(u2_Wire, duz.don));
return u2_at_cord(u2_kite_buf_r(kit_r), c3_wiseof(jmp_buf));
}
/* _cm_jack(): steal the trace as of the current kite.
*/
static u2_noun
_cm_jack(u2_noun old, u2_noun nuw)
{
u2_noun cur = nuw;
if ( nuw == old ) {
u2z(old); return u2_nul;
}
else while ( 1 ) {
if ( u2ft(cur) == old ) {
u2z(old);
u2ft(cur) = u2_nul;
return nuw;
} else {
cur = u2ft(cur);
}
}
}
/* _cm_depth()
*/
static c3_w
_cm_depth(u2_noun old, u2_noun nuw)
{
c3_w dep_w = 0;
while ( nuw != old ) {
c3_assert(u2_yes == u2du(nuw));
nuw = u2t(nuw);
dep_w++;
}
return dep_w;
}
/* u2_cm_wail(): produce and reset the local trace, without bailing.
*/
u2_noun
u2_cm_wail()
{
u2_ray kit_r = u2_wire_kit_r(u2_Wire);
u2_noun old = u2_kite_tax(u2_wire_kit_r(u2_Wire));
u2_noun nuw = u2_wire_tax(u2_Wire);
u2_noun jaq;
jaq = _cm_jack(old, nuw);
// c3_assert(1 == u2_rl_refs(u2_Wire, old));
u2_wire_tax(u2_Wire) = old;
u2_kite_tax(kit_r) = u2k(old);
// c3_assert(1 == u2_rl_refs(u2_Wire, jaq));
return jaq;
}
static c3_w _num = 0;
/* u2_cm_bail(): bail out to the local trap. Does not return.
*/
extern u2_noun u2_Flag_Abort;
u2_noun
u2_cm_bail(c3_l how_l)
{
u2_ray kit_r = u2_wire_kit_r(u2_Wire);
if ( u2_yes == u2_Flag_Abort ) {
if ( c3__fail == how_l ) { c3_assert(0); }
c3_assert(0);
}
u2_tx_sys_bit(u2_Wire, u2_yes);
// fprintf(stderr, "bail\n");
// if ( _num == 0 ) { c3_assert(0); } else _num--;
{
u2_noun jaq;
jmp_buf buf_f;
// Reset the old stack trace, pulling off the local top.
//
jaq = u2_cm_wail();
// Reset the old action trace.
{
u2z(u2_wrac_at(u2_Wire, duz.don));
u2_wrac_at(u2_Wire, duz.don) = u2_kite_don(kit_r);
}
// Copy out the jump buffer; free the old kite.
{
memcpy((void *)buf_f,
u2_at_cord(u2_kite_buf_r(kit_r), c3_wiseof(jmp_buf)),
sizeof(jmp_buf));
u2_wire_kit_r(u2_Wire) = u2_kite_par_r(kit_r);
u2_rl_rfree(u2_Wire, kit_r);
}
// Longjmp with the how-trace pair. XX: no workee with 64-bit nouns.
//
{
_longjmp(buf_f, u2nc(how_l, jaq));
}
}
return 0;
}
/* u2_cm_bowl(): bail out with preset report.
*/
u2_noun
u2_cm_bowl(u2_noun how)
{
u2_ray kit_r = u2_wire_kit_r(u2_Wire);
u2_tx_sys_bit(u2_Wire, u2_yes);
{
u2_noun jaq;
jmp_buf buf_f;
// Reset the old stack trace, pulling off the local top.
//
jaq = u2_cm_wail();
// Reset the old action trace.
{
u2z(u2_wrac_at(u2_Wire, duz.don));
u2_wrac_at(u2_Wire, duz.don) = u2_kite_don(kit_r);
}
// Copy out the jump buffer; free the old kite.
{
memcpy((void *)buf_f,
u2_at_cord(u2_kite_buf_r(kit_r), c3_wiseof(jmp_buf)),
sizeof(jmp_buf));
u2_wire_kit_r(u2_Wire) = u2_kite_par_r(kit_r);
u2_rl_rfree(u2_Wire, kit_r);
}
// Longjmp with the how-trace pair. XX: no workee with 64-bit nouns.
//
{
u2z(jaq);
_longjmp(buf_f, how);
}
}
return 0;
}
/* u2_cm_done(): terminate trap.
*/
void
u2_cm_done()
{
u2_ray kit_r = u2_wire_kit_r(u2_Wire);
c3_assert(kit_r != 0);
u2z(u2_kite_tax(kit_r));
u2z(u2_kite_don(kit_r));
u2_wire_kit_r(u2_Wire) = u2_kite_par_r(kit_r);
u2_rl_rfree(u2_Wire, kit_r);
}
/* u2_cm_sweep(): return bytes leaked; match bytes saved.
*/
c3_w
u2_cm_sweep(c3_w sav_w)
{
return u2_rl_gc_sweep(u2_Wire, sav_w);
}
/* u2_cm_purge(): purge memo cache.
*/
void
u2_cm_purge()
{
u2_rl_drain(u2_Wire);
}
/* u2_cm_mark_noun(): mark individual noun.
*/
c3_w
u2_cm_mark_noun(u2_noun som)
{
return u2_rl_gc_mark_noun(u2_Wire, som);
}
/* u2_cm_mark_ray(): mark a root for gc (do not use again before gc)
*/
c3_w
u2_cm_mark_ray(u2_ray ray_r)
{
return u2_rl_gc_mark_ptr(u2_Wire, ray_r);
}
/* u2_cm_mark_internal(): mark all coal internals
*/
c3_w
u2_cm_mark_internal()
{
return u2_wr_mark(u2_Wire);
}
/* u2_cm_trac(): extract and clear stack trace.
*/
u2_noun
u2_cm_trac()
{
u2_noun tax = u2_wire_tax(u2_Wire);
u2_wire_tax(u2_Wire) = u2_nul;
return tax;
}
/* u2_cm_push(): push `mon` on trace stack.
*/
void
u2_cm_push(u2_noun mon)
{
u2_wire_tax(u2_Wire) = u2nc(mon, u2_wire_tax(u2_Wire));
}
/* u2_cm_bean(): push `[%bean roc]` on trace stack.
*/
void
u2_cm_bean(u2_noun roc)
{
u2_cm_push(u2nc(c3__bean, roc));
}
/* u2_cm_drop(): drop from meaning stack.
*/
void
u2_cm_drop()
{
u2_noun tax = u2_wire_tax(u2_Wire);
c3_assert(u2_nul != tax);
u2_wire_tax(u2_Wire) = u2_ct(u2t(tax));
u2_cz(tax);
}
/* u2_cm_foul():
*/
u2_noun
u2_cm_foul(const c3_c* err_c)
{
u2_cm_bean(u2_ci_string(err_c));
fprintf(stderr, "foul: %s\n", err_c);
return u2_bl_error(u2_Wire, err_c);
}
/* u2_cn_cell(): produce the cell `[a b]`.
*/
u2_noun
u2_cn_cell(u2_noun a,
u2_noun b)
{
return u2_bn_cell(u2_Wire, a, b);
}
/* u2_cn_trel(): produce the cell `[a b c]`.
*/
u2_noun
u2_cn_trel(u2_noun a,
u2_noun b,
u2_noun c)
{
return u2_bn_trel(u2_Wire, a, b, c);
}
/* u2_cn_qual(): produce the cell `[a b c d]`.
*/
u2_noun
u2_cn_qual(u2_noun a,
u2_noun b,
u2_noun c,
u2_noun d)
{
return u2_bn_qual(u2_Wire, a, b, c, d);
}
/* u2_cka_add(): a + b.
*/
u2_noun
u2_cka_add(u2_noun a, u2_noun b)
{
u2_noun c = j2_mbc(Pt1, add)(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
return c;
}
/* u2_cka_sub(): a + b.
*/
u2_noun
u2_cka_sub(u2_noun a, u2_noun b)
{
u2_noun c = j2_mbc(Pt1, sub)(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
return c;
}
/* u2_cka_gth(): a + b.
*/
u2_noun
u2_cka_gth(u2_noun a, u2_noun b)
{
u2_noun c = j2_mbc(Pt1, gth)(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
return c;
}
/* u2_cka_mul(): a * b.
*/
u2_noun
u2_cka_mul(u2_noun a, u2_noun b)
{
u2_noun c = j2_mbc(Pt1, mul)(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
return c;
}
/* u2_cka_lte(): a * b.
*/
u2_noun
u2_cka_lte(u2_noun a, u2_noun b)
{
u2_noun c = j2_mbc(Pt1, lte)(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
return c;
}
/* u2_ckb_lent(): length of list `a`.
*/
u2_noun
u2_ckb_lent(u2_noun a)
{
u2_noun b = j2_mbc(Pt2, lent)(u2_Wire, a);
u2_cz(a);
return b;
}
/* u2_ckb_flop(): reverse list `a`.
*/
u2_noun
u2_ckb_flop(u2_noun a)
{
u2_noun b = j2_mbc(Pt2, flop)(u2_Wire, a);
u2_cz(a);
return b;
}
/* u2_ckb_weld(): concatenate lists `a` before `b`.
*/
u2_noun
u2_ckb_weld(u2_noun a, u2_noun b)
{
u2_noun c = j2_mbc(Pt2, weld)(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
return c;
}
/* u2_ckc_lsh(): left shift.
*/
u2_noun
u2_ckc_lsh(u2_noun a, u2_noun b, u2_noun c)
{
u2_noun d = j2_mbc(Pt3, lsh)(u2_Wire, a, b, c);
u2_cz(a); u2_cz(b); u2_cz(c);
return d;
}
/* u2_ckc_rsh(): right shift.
*/
u2_noun
u2_ckc_rsh(u2_noun a, u2_noun b, u2_noun c)
{
u2_noun d = j2_mbc(Pt3, rsh)(u2_Wire, a, b, c);
u2_cz(a); u2_cz(b); u2_cz(c);
return d;
}
/* u2_ckd_by_get(): map get for key `b` in map `a` with u2_none.
*/
u2_weak
u2_ckd_by_get(u2_noun a, u2_noun b)
{
u2_noun c = _coal_by_get(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
if ( u2_no == u2_cr_du(c) ) {
u2_cz(c);
return u2_none;
} else {
u2_noun pro = u2_ct(u2t(c));
u2_cz(c);
return pro;
}
}
/* u2_ckd_by_got(): map get for key `b` in map `a` with fail.
*/
u2_noun
u2_ckd_by_got(u2_noun a, u2_noun b)
{
u2_weak c = u2_ckd_by_get(a, b);
if ( u2_none == c ) {
return u2_cm_bail(c3__exit);
}
else return c;
}
/* u2_ckd_by_put(): map put for key `b`, value `c` in map `a`.
*/
u2_weak
u2_ckd_by_put(u2_noun a, u2_noun b, u2_noun c)
{
// Bizarre asymmetry in old jets.
//
// (Mysterious comment in old glue code.)
//
u2_noun pro = _coal_by_put(u2_Wire, a, b, c);
u2_cz(a); u2_cz(b); u2_cz(c);
return pro;
}
/* u2_ckd_by_gas(): list to map.
*/
u2_noun
u2_ckd_by_gas(u2_noun a, u2_noun b)
{
u2_weak c = _coal_by_gas(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
if ( u2_none == c ) {
return u2_cm_bail(c3__exit);
}
else return c;
}
/* u2_ckd_in_gas(): list to map.
*/
u2_noun
u2_ckd_in_gas(u2_noun a, u2_noun b)
{
u2_weak c = _coal_in_gas(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
if ( u2_none == c ) {
return u2_cm_bail(c3__exit);
}
else return c;
}
/* u2_ckd_by_has(): test for presence.
*/
u2_bean
u2_ckd_by_has(u2_noun a, u2_noun b)
{
u2_weak c = _coal_by_has(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
if ( u2_none == c ) {
return u2_cm_bail(c3__exit);
}
else return c;
}
/* u2_ckd_in_has(): test for presence.
*/
u2_bean
u2_ckd_in_has(u2_noun a, u2_noun b)
{
u2_weak c = _coal_in_has(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
if ( u2_none == c ) {
return u2_cm_bail(c3__exit);
}
else return c;
}
/* u2_ckd_in_tap(): map/set convert to list. (solves by_tap also.)
*/
u2_noun
u2_ckd_in_tap(u2_noun a, u2_noun b)
{
u2_weak c = _coal_in_tap(u2_Wire, a, b);
u2_cz(a); u2_cz(b);
if ( u2_none == c ) {
return u2_cm_bail(c3__exit);
}
else return c;
}
/* u2_cke_cue(): expand saved pill.
*/
static u2_noun // produce
_cue_in(u2_wire wir_r,
u2_atom a, // retain
u2_atom b, // retain
u2_ray t_r) // retain
{
u2_noun p, q;
if ( _0 == j2_mbc(Pt3, cut)(wir_r, 0, b, 1, a) ) {
u2_noun x = j2_mbc(Pt1, inc)(wir_r, b);
u2_noun c = j2_mby(Pt5, rub)(wir_r, x, a);
p = j2_mbc(Pt1, inc)(wir_r, u2_h(c));
q = u2_rx(wir_r, u2_t(c));
q = u2_cs_save(wir_r, t_r, 0, b, q);
u2_rz(wir_r, c);
u2_rz(wir_r, x);
}
else {
u2_noun c = j2_mbc(Pt1, add)(wir_r, _2, b);
u2_noun l = j2_mbc(Pt1, inc)(wir_r, b);
if ( _0 == j2_mbc(Pt3, cut)(wir_r, 0, l, 1, a) ) {
u2_noun u, v, w;
u2_noun x, y;
u = _cue_in(wir_r, a, c, t_r);
x = j2_mbc(Pt1, add)(wir_r, u2_h(u), c);
v = _cue_in(wir_r, a, x, t_r);
w = u2_bc(wir_r, u2_rx(wir_r, u2_t(u)),
u2_rx(wir_r, u2_t(v)));
y = j2_mbc(Pt1, add)(wir_r, u2_h(u), u2_h(v));
p = j2_mbc(Pt1, add)(wir_r, _2, y);
q = u2_cs_save(wir_r, t_r, 0, b, w);
u2_rz(wir_r, u); u2_rz(wir_r, v); u2_rz(wir_r, x); u2_rz(wir_r, y);
}
else {
u2_noun d = j2_mby(Pt5, rub)(wir_r, c, a);
u2_weak x = u2_cs_find(wir_r, t_r, 0, u2_t(d));
p = j2_mbc(Pt1, add)(wir_r, _2, u2_h(d));
if ( u2_none == x ) {
return u2_bl_bail(wir_r, c3__fail);
}
q = u2_rx(wir_r, x);
u2_rz(wir_r, d);
}
u2_rz(wir_r, l);
u2_rz(wir_r, c);
}
return u2_bc(wir_r, p, q);
}
u2_noun // transfer
_cue_internal(u2_wire wir_r,
u2_atom a) // retain
{
u2_ray t_r = u2_cs_make(wir_r);
u2_noun x = _cue_in(wir_r, a, _0, t_r);
u2_noun y = u2_rx(wir_r, u2_t(x));
u2_rz(wir_r, x);
u2_cs_free(wir_r, t_r);
return y;
}
u2_noun
u2_cke_cue(u2_atom a)
{
u2_noun b = _cue_internal(u2_Wire, a);
u2_cz(a);
return b;
}
/* u2_cke_jam(): pack noun as atom.
*/
u2_atom
u2_cke_jam(u2_noun a)
{
u2_atom b = _coal_jam(u2_Wire, a);
u2_cz(a);
return b;
}
/* u2_cke_trip(): atom to tape.
*/
u2_atom
u2_cke_trip(u2_noun a)
{
u2_atom b = _coal_trip(u2_Wire, a);
u2_cz(a);
return b;
}