Various fixes and improvements.

This commit is contained in:
C. Guy Yarvin 2014-08-10 20:09:56 -07:00
parent 604c65e58e
commit 4f1377a91c
6 changed files with 589 additions and 600 deletions

View File

@ -78,6 +78,7 @@ CWFLAGS=-Wall
F_OFILES=\
f/rail.o \
f/meme.o \
f/loom.o \
f/wire.o \
f/chad.o \

593
f/meme.c
View File

@ -2,14 +2,7 @@
**
** This file is in the public domain.
*/
#include "all.h"
#include <sys/uio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sigsegv.h>
#include <termios.h>
#include <uv.h>
#include "v/vere.h"
#include "f/meme.h"
/* _me_boot_north(): install a north road.
*/
@ -63,49 +56,70 @@ u2_me_boot(void* mem_v, c3_w len_w)
u2H = u2R = _me_boot_north(mem_v, len_w);
}
/* _me_road_all_hat(): in u2R, allocate directly on the hat.
/* _me_road_all_hat(): in u2R, allocate directly on the hat_w.
*/
static c3_w*
_me_road_all_hat(c3_w len_w)
{
if ( len_w > u2_me_open ) {
return u2_me_bail(c3__meme);
u2_me_bail(c3__meme); return 0;
}
if ( u2_yes == u2_me_is_north ) {
c3_w* all_w;
all_w = u2R->hat;
u2R->hat += len_w;
all_w = u2R->hat_w;
u2R->hat_w += len_w;
return all_w;
}
else {
u2R->hat -= len_w;
return u2R->hat;
u2R->hat_w -= len_w;
return u2R->hat_w;
}
}
#if 0 // not yet used
/* _me_road_all_cap(): in u2R, allocate directly on the cap.
*/
static c3_w*
_me_road_all_hat(c3_w len_w)
_me_road_all_cap(c3_w len_w)
{
if ( len_w > u2_me_open ) {
return u2_me_bail(c3__meme);
u2_me_bail(c3__meme); return 0;
}
if ( u2_yes == u2_me_is_north ) {
u2R->cap -= len_w;
return u2R->cap;
u2R->cap_w -= len_w;
return u2R->cap_w;
}
else {
c3_w* all_w;
all_w = u2R->cap;
u2R->cap += len_w;
all_w = u2R->cap_w;
u2R->cap_w += len_w;
return all_w;
}
}
#endif
/* u2_me_bail(): bail out. Does not return.
**
** Bail motes:
**
** %evil :: erroneous cryptography
** %exit :: semantic failure
** %oops :: assertion failure
** %intr :: interrupt
** %fail :: computability failure
** %need :: namespace block
** %meme :: out of memory
*/
c3_i
u2_me_bail(c3_m how_m)
{
_longjmp(u2R->esc.buf, how_m);
return how_m;
}
/* u2_me_leap(): in u2R, create a new road within the existing one.
*/
@ -134,40 +148,40 @@ u2_me_fall()
{
c3_assert(0 != u2R->par_u);
u2R->par_u->cap_w = u2R->hat_u;
u2R->par_u->cap_w = u2R->hat_w;
u2R = u2R->par_u;
}
/* u2_me_golf(): record cap length for u2_flog().
/* u2_me_golf(): record cap_w length for u2_flog().
*/
c3_w
u2_me_golf(void)
{
if ( u2_yes == u2_me_is_north ) {
return u2R->mat - u2R->cap;
return u2R->mat_w - u2R->cap_w;
}
else {
return u2R->cap - u2R->mat;
return u2R->cap_w - u2R->mat_w;
}
}
/* u2_me_flog(): reset cap.
/* u2_me_flog(): reset cap_w.
*/
void
u2_me_flog(c3_w gof_w)
{
if ( u2_yes == u2_me_is_north ) {
u2R->cap = u2R->mat - gof_w;
u2R->cap_w = u2R->mat_w - gof_w;
} else {
u2R->cap = u2R->mat + gof_w;
u2R->cap_w = u2R->mat_w + gof_w;
}
}
/* u2_me_water(): produce watermarks.
*/
void
u2_me_water(c3_w* low_w, c3_w* hig_w);
u2_me_water(c3_w* low_w, c3_w* hig_w)
{
c3_assert(u2R == u2H);
@ -187,7 +201,7 @@ _me_box_slot(c3_w siz_w)
c3_w i_w = 1;
while ( 1 ) {
if ( i_w == u2_me_free_no ) {
if ( i_w == u2_me_fbox_no ) {
return (i_w - 1);
}
if ( siz_w < 16 ) {
@ -202,19 +216,19 @@ _me_box_slot(c3_w siz_w)
/* _me_box_make(): construct a box.
*/
u2_me_box*
_me_box_make(c3_v* box_v, c3_w siz_w, c3_w use_w)
_me_box_make(void* box_v, c3_w siz_w, c3_w use_w)
{
u2_me_box* box_u = box_v;
c3_w* box_w = box_v;
box_w[0] = siz_w;
box_w[siz_w - 1] = siz_w;
#ifdef U2_MEMORY_DEBUG
box_u->cod_w = COD_w;
#endif
box_u->use_w = use_w;
# ifdef U2_MEMORY_DEBUG
box_u->cod_w = COD_w;
# endif
return box_u;
}
@ -223,11 +237,11 @@ _me_box_make(c3_v* box_v, c3_w siz_w, c3_w use_w)
void
_me_box_attach(u2_me_box* box_u)
{
c3_assert(box_u->siz_w >= (1 + c3_wiseof(u2_me_free)));
c3_assert(box_u->siz_w >= (1 + c3_wiseof(u2_me_fbox)));
{
c3_w sel_w = _me_box_slot(box_u->siz_w);
u2_me_free* fre_u = (void *)box_u;
u2_me_free** pfr_u = &u2R->all.fre_u[sel_w];
u2_me_fbox* fre_u = (void *)box_u;
u2_me_fbox** pfr_u = &u2R->all.fre_u[sel_w];
fre_u->pre_u = 0;
fre_u->nex_u = (*pfr_u);
@ -240,7 +254,7 @@ _me_box_attach(u2_me_box* box_u)
void
_me_box_detach(u2_me_box* box_u)
{
u2_me_free* fre_u = (void*) box_u;
u2_me_fbox* fre_u = (void*) box_u;
if ( fre_u->pre_u ) {
fre_u->pre_u->nex_u = fre_u->nex_u;
@ -252,7 +266,7 @@ _me_box_detach(u2_me_box* box_u)
}
}
/* u2_me_walloc(): allocate storage words on hat.
/* u2_me_walloc(): allocate storage words on hat_w.
*/
void*
u2_me_walloc(c3_w len_w)
@ -262,27 +276,27 @@ u2_me_walloc(c3_w len_w)
// XX: this logic is totally bizarre, but preserve it.
//
if ( (sel_w != 0) && (sel_w != u2_me_free_no - 1) ) {
if ( (sel_w != 0) && (sel_w != u2_me_fbox_no - 1) ) {
sel_w += 1;
}
while ( 1 ) {
u2_me_free** pfr_u = &u2R->all.fre_u[sel_w];
u2_me_fbox** pfr_u = &u2R->all.fre_u[sel_w];
while ( 1 ) {
if ( 0 == *pfr_u ) {
if ( sel_w < (u2_me_free_no - 1) ) {
if ( sel_w < (u2_me_fbox_no - 1) ) {
sel_w += 1;
break;
}
else {
/* Nothing in top free list. Chip away at the hat.
/* Nothing in top free list. Chip away at the hat_w.
*/
return u2_me_boxto(_me_box_make(_me_road_all_hat(siz_w), siz_w, 1));
}
}
else {
if ( siz_w > (*pfr_u)->box_u->siz_w ) {
if ( siz_w > (*pfr_u)->box_u.siz_w ) {
/* This free block is too small. Continue searching.
*/
pfr_u = &((*pfr_u)->nex_u);
@ -309,10 +323,10 @@ u2_me_walloc(c3_w len_w)
/* If we can chop off another block, do it.
*/
if ( (siz_w + c3_wiseof(u2_me_free) + 1) <= box_u->siz_w ) {
if ( (siz_w + c3_wiseof(u2_me_fbox) + 1) <= box_u->siz_w ) {
/* Split the block.
*/
c3_w* box_w = ((c3_w *)(void *)box_uy);
c3_w* box_w = ((c3_w *)(void *)box_u);
c3_w* end_w = box_w + siz_w;
c3_w lef_w = (box_u->siz_w - siz_w);
@ -325,13 +339,13 @@ u2_me_walloc(c3_w len_w)
box_u->cod_w = COD_w;
#endif
return u2_me_boxto(box_u);
}
}
}
}
}
}
/* u2_me_malloc(): allocate storage measured in bytes.
*/
void*
@ -343,7 +357,7 @@ u2_me_malloc(c3_w len_w)
/* u2_me_free(): free storage.
*/
void
u2_me_free(void* tox_v);
u2_me_free(void* tox_v)
{
u2_me_box* box_u = u2_me_botox(tox_v);
c3_w* box_w = (c3_w *)(void *)box_u;
@ -363,10 +377,7 @@ u2_me_free(void* tox_v);
}
if ( u2_yes == u2_me_is_north ) {
c3_w* bot_w = u2R->rut_w;
c3_w* top_w = u2R->hat_w;
/* Try to coalesce with the previous block.
/* Try to coalesce with the block below.
*/
if ( box_w != u2R->rut_w ) {
c3_w laz_w = *(box_w - 1);
@ -377,124 +388,440 @@ u2_me_free(void* tox_v);
_me_box_make(pox_u, (laz_w + box_u->siz_w), 0);
box_u = pox_u;
box_w = (c3_w*)(void *)box_u;
box_w = (c3_w*)(void *)pox_u;
}
}
/* Try to coalesce with the next block, or the wilderness.
/* Try to coalesce with the block above, or the wilderness.
*/
if ( (box_w + siz_w) == u2R->hat_w ) {
if ( (box_w + box_u->siz_w) == u2R->hat_w ) {
u2R->hat_w = box_w;
}
else {
u2_me_box* nox_u = (u2_me_box*)(void *)(box_w + box_u->siz_w);
if ( 0 == nox_u->use_w ) {
_me_nox_detach(nox_u);
_me_box_make(box_u, (nox_u->siz_w + box_u->siz_w));
_me_box_detach(nox_u);
_me_box_make(box_u, (box_u->siz_w + nox_u->siz_w), 0);
}
_me_box_attach(box_u);
}
}
else {
if (
}
/* Try to coalesce with the block above.
*/
if ( (box_w + box_u->siz_w) != u2R->rut_w ) {
u2_me_box* nox_u = (u2_me_box*)(void *)(box_w + box_u->siz_w);
if ( ((c3_w*) tox_v) == u2
if ( box_r != beg_r ) {
c3_w las_w = *u2_at_ray(box_r - 1);
u2_ray tod_r = (box_r - las_w);
if ( 0 == nox_u->use_w ) {
_me_box_detach(nox_u);
_me_box_make(box_u, (box_u->siz_w + nox_u->siz_w), 0);
if ( 0 == u2_rail_hut_use(tod_r) ) {
_rl_bloq_detach(ral_r, tod_r);
_rl_bloq_make(ral_r, tod_r, (las_w + u2_rail_hut_siz(box_r)), 0);
box_r = tod_r;
box_u = nox_u;
box_w = (c3_w*)(void *)nox_u;
}
}
}
/* Try to coalesce with the next block, or with the wilderness.
*/
{
c3_w siz_w = u2_rail_hut_siz(box_r);
if ( (box_r + siz_w == hat_r) ) {
u2_rail_hat_r(ral_r) = box_r;
/* Try to coalesce with the block below, or with the wilderness.
*/
if ( box_w == u2R->hat_w ) {
u2R->hat_w = (box_w + box_u->siz_w);
}
else {
u2_ray hob_r = (box_r + siz_w);
c3_w laz_w = *(box_w - 1);
u2_me_box* pox_u = (u2_me_box*)(void *)(box_w - laz_w);
if ( 0 == u2_rail_hut_use(hob_r) ) {
_rl_bloq_detach(ral_r, hob_r);
_rl_bloq_make(ral_r, box_r, (siz_w + u2_rail_hut_siz(hob_r)), 0);
if ( 0 == pox_u->use_w ) {
_me_box_detach(pox_u);
_me_box_make(pox_u, (laz_w + box_u->siz_w), 0);
}
/* Add to the appropriate free list.
*/
_rl_bloq_attach(ral_r, box_r);
_me_box_attach(box_u);
}
}
}
//////// Atoms from proto-atoms.
/* Basic allocation.
*/
/* u2_me_walloc(): allocate storage measured in words.
*/
void*
u2_me_walloc(c3_w len_w);
/* u2_me_malloc(): allocate storage measured in bytes.
*/
void*
u2_me_malloc(c3_w len_w);
/* u2_me_free(): free storage.
*/
void
u2_me_free(void* lag_v);
/* u2_me_slab(): create a length-bounded proto-atom.
/* _me_north_senior(): yes iff only in the senior region.
*/
c3_w*
u2_me_slab(c3_w len_w)
static u2_bean
_me_north_senior(u2_noun dog)
{
u2_ray nov_r = u2_rl_ralloc(ral_r, (len_w + c3_wiseof(u2_loom_atom)));
u2_atom nov = u2_pug_of(nov_r, 0);
c3_w* dog_w = u2_me_to_ptr(dog);
*u2_at_dog_mug(nov) = 0;
*u2_at_pug_len(nov) = len_w;
return u2_say((dog_w < u2R->rut_w) || (dog_w >= u2R->mat_w));
}
/* Clear teh slab.
*/
/* _me_north_junior(): yes iff only in the junior section.
*/
static u2_bean
_me_north_junior(u2_noun dog)
{
c3_w* dog_w = u2_me_to_ptr(dog);
return u2_say((dog_w >= u2R->cap_w) && (dog_w < u2R->mat_w));
}
/* _me_north_normal(): yes iff only in the normal heap.
*/
static u2_bean
_me_north_normal(u2_noun dog)
{
return u2_and(u2_not(_me_north_senior(dog)),
u2_not(_me_north_junior(dog)));
}
/* _me_south_senior(): yes iff only in the senior region.
*/
static u2_bean
_me_south_senior(u2_noun dog)
{
c3_w* dog_w = u2_me_to_ptr(dog);
return u2_say((dog_w >= u2R->mat_w) || (dog_w < u2R->cap_w));
}
/* _me_south_junior(): yes iff only in the junior section.
*/
static u2_bean
_me_south_junior(u2_noun dog)
{
c3_w* dog_w = u2_me_to_ptr(dog);
return u2_say((dog_w >= u2R->cap_w) && (dog_w < u2R->mat_w));
}
/* _me_south_normal(): yes iff only in the normal heap.
*/
static u2_bean
_me_south_normal(u2_noun dog)
{
return u2_and(u2_not(_me_south_senior(dog)),
u2_not(_me_south_junior(dog)));
}
/* _me_wash_north(): clean up mug slots after copy.
*/
static void _me_wash_north(u2_noun dog);
static void
_me_wash_north_in(u2_noun som)
{
if ( u2_so(u2_me_is_cat(som)) ) return;
if ( u2_ne(_me_north_junior(som)) ) return;
_me_wash_north(som);
}
static void
_me_wash_north(u2_noun dog)
{
c3_assert(u2_me_is_dog(dog));
c3_assert(u2_yes == _me_north_junior(dog));
{
c3_w i_w;
u2_me_noun* dog_u = u2_me_to_ptr(dog);
for ( i_w=0; i_w < len_w; i_w++ ) {
*u2_at_pug_buf(nov, i_w) = 0;
if ( dog_u->mug_w >> 31 ) { dog_u->mug_w = 0; }
if ( u2_so(u2_me_is_pom(dog)) ) {
u2_me_cell* god_u = (u2_me_cell *)(void *)dog_u;
_me_wash_north_in(god_u->hed);
_me_wash_north_in(god_u->tel);
}
}
}
/* _me_wash_south(): clean up mug slots after copy.
*/
static void _me_wash_south(u2_noun dog);
static void
_me_wash_south_in(u2_noun som)
{
if ( u2_so(u2_me_is_cat(som)) ) return;
if ( u2_ne(_me_south_junior(som)) ) return;
_me_wash_south(som);
}
static void
_me_wash_south(u2_noun dog)
{
c3_assert(u2_me_is_dog(dog));
c3_assert(u2_yes == _me_south_junior(dog));
{
u2_me_noun* dog_u = u2_me_to_ptr(dog);
if ( dog_u->mug_w >> 31 ) { dog_u->mug_w = 0; }
if ( u2_so(u2_me_is_pom(dog)) ) {
u2_me_cell* god_u = (u2_me_cell *)(void *)dog_u;
_me_wash_south_in(god_u->hed);
_me_wash_south_in(god_u->tel);
}
}
}
/* _me_gain_use(): increment use count.
*/
static void
_me_gain_use(u2_noun dog)
{
c3_w* dog_w = u2_me_to_ptr(dog);
u2_me_box* box_u = u2_me_botox(dog_w);
box_u = u2_me_botox(dog_w);
if ( 0xffffffff == box_u->use_w ) {
u2_me_bail(c3__fail);
}
else {
box_u->use_w += 1;
}
}
/* _me_copy_north_in(): copy subjuniors on a north road.
*/
static u2_noun _me_copy_north(u2_noun);
static u2_noun
_me_copy_north_in(u2_noun som)
{
c3_assert(u2_none != som);
if ( u2_so(u2_me_is_cat(som)) ) {
return som;
}
else {
u2_noun dog = som;
if ( u2_so(_me_north_senior(dog)) ) {
return dog;
}
else if ( u2_so(_me_north_junior(dog)) ) {
return _me_copy_north(dog);
}
else {
_me_gain_use(dog);
return dog;
}
}
return (nov_r + c3_wiseof(u2_loom_atom));
/* u2_me_slaq(): u2_me_slaq() with a defined blocksize.
}
/* _me_copy_north(): copy juniors on a north road.
*/
c3_w*
u2_me_slaq(c3_g met_g, c3_w len_w);
static u2_noun
_me_copy_north(u2_noun dog)
{
c3_assert(u2_yes == _me_north_junior(dog));
/* u2_me_malt(): measure and finish a proto-atom.
if ( u2_ne(_me_north_junior(dog)) ) {
if ( u2_ne(_me_north_senior(dog)) ) {
_me_gain_use(dog);
}
return dog;
}
else {
u2_me_noun* dog_u = u2_me_to_ptr(dog);
/* Borrow mug slot to record new destination.
*/
if ( dog_u->mug_w >> 31 ) {
u2_noun nov = (u2_noun) dog_u->mug_w;
c3_assert(u2_so(_me_north_normal(nov)));
_me_gain_use(nov);
return nov;
}
else {
if ( u2_yes == u2_me_is_pom(dog) ) {
u2_me_cell* old_u = u2_me_to_ptr(dog);
c3_w* new_w = u2_me_walloc(c3_wiseof(u2_me_cell));
u2_noun new = u2_me_de_twin(dog, new_w);
u2_me_cell* new_u = (u2_me_cell*)(void *)new_w;
new_u->mug_w = old_u->mug_w;
new_u->hed = _me_copy_north_in(old_u->hed);
new_u->tel = _me_copy_north_in(old_u->tel);
/* Borrow mug slot to record new destination.
*/
old_u->mug_w = new;
return new;
}
else {
u2_me_atom* old_u = u2_me_to_ptr(dog);
c3_w* new_w = u2_me_walloc(old_u->len_w + c3_wiseof(u2_me_atom));
u2_noun new = u2_me_de_twin(dog, new_w);
u2_me_atom* new_u = (u2_me_atom*)(void *)new_w;
new_u->mug_w = old_u->mug_w;
new_u->len_w = old_u->len_w;
{
c3_w i_w;
for ( i_w=0; i_w < old_u->len_w; i_w++ ) {
new_u->buf_w[i_w] = old_u->buf_w[i_w];
}
}
/* Borrow mug slot to record new destination.
*/
old_u->mug_w = new;
return new;
}
}
}
}
/* _me_copy_south_in(): copy subjuniors on a south road.
*/
static u2_noun _me_copy_south(u2_noun);
static u2_noun
_me_copy_south_in(u2_noun som)
{
c3_assert(u2_none != som);
if ( u2_so(u2_me_is_cat(som)) ) {
return som;
}
else {
u2_noun dog = som;
if ( u2_so(_me_south_senior(dog)) ) {
return dog;
}
else if ( u2_so(_me_south_junior(dog)) ) {
return _me_copy_south(dog);
}
else {
_me_gain_use(dog);
return dog;
}
}
}
/* _me_copy_south(): copy juniors on a south road.
*/
static u2_noun
_me_copy_south(u2_noun dog)
{
c3_assert(u2_yes == _me_south_junior(dog));
if ( u2_ne(_me_south_junior(dog)) ) {
if ( u2_ne(_me_south_senior(dog)) ) {
_me_gain_use(dog);
}
return dog;
}
else {
u2_me_noun* dog_u = u2_me_to_ptr(dog);
/* Borrow mug slot to record new destination.
*/
if ( dog_u->mug_w >> 31 ) {
u2_noun nov = (u2_noun) dog_u->mug_w;
c3_assert(u2_so(_me_south_normal(nov)));
_me_gain_use(nov);
return nov;
}
else {
if ( u2_yes == u2_me_is_pom(dog) ) {
u2_me_cell* old_u = u2_me_to_ptr(dog);
c3_w* new_w = u2_me_walloc(c3_wiseof(u2_me_cell));
u2_noun new = u2_me_de_twin(dog, new_w);
u2_me_cell* new_u = (u2_me_cell*)(void *)new_w;
new_u->mug_w = old_u->mug_w;
new_u->hed = _me_copy_south_in(old_u->hed);
new_u->tel = _me_copy_south_in(old_u->tel);
/* Borrow mug slot to record new destination.
*/
old_u->mug_w = new;
return new;
}
else {
u2_me_atom* old_u = u2_me_to_ptr(dog);
c3_w* new_w = u2_me_walloc(old_u->len_w + c3_wiseof(u2_me_atom));
u2_noun new = u2_me_de_twin(dog, new_w);
u2_me_atom* new_u = (u2_me_atom*)(void *)new_w;
new_u->mug_w = old_u->mug_w;
new_u->len_w = old_u->len_w;
{
c3_w i_w;
for ( i_w=0; i_w < old_u->len_w; i_w++ ) {
new_u->buf_w[i_w] = old_u->buf_w[i_w];
}
}
/* Borrow mug slot to record new destination.
*/
old_u->mug_w = new;
return new;
}
}
}
}
/* _me_gain_north(): gain on a north road.
*/
static u2_noun
_me_gain_north(u2_noun dog)
{
c3_assert(u2_none != dog);
if ( u2_yes == _me_north_senior(dog) ) {
/* senior pointers are not refcounted
*/
return dog;
}
else if ( u2_yes == _me_north_junior(dog) ) {
/* junior pointers are copied
*/
u2_noun mos = _me_copy_north(dog);
_me_wash_north(dog);
return mos;
}
else {
/* normal pointers are refcounted
*/
_me_gain_use(dog);
return dog;
}
}
/* _me_gain_south(): gain on a south road.
*/
static u2_noun
_me_gain_south(u2_noun dog)
{
if ( u2_yes == _me_south_senior(dog) ) {
/* senior pointers are not refcounted
*/
return dog;
}
else if ( u2_yes == _me_south_junior(dog) ) {
/* junior pointers are copied
*/
u2_noun mos = _me_copy_south(dog);
_me_wash_south(dog);
return mos;
}
else {
/* normal pointers are refcounted
*/
_me_gain_use(dog);
return dog;
}
}
/* u2_me_gain(): gain and/or copy juniors.
*/
u2_noun
u2_me_malt(c3_w* sal_w);
u2_me_gain(u2_noun som)
{
c3_assert(u2_none != som);
/* u2_me_moot(): finish a pre-measured proto-atom; dangerous.
*/
u2_noun
u2_me_moot(c3_w* sal_w);
/* u2_me_mint(): finish a measured proto-atom.
*/
u2_noun
u2_me_mint(c3_w* sal_w, c3_w len_w);
if ( u2_so(u2_me_is_cat(som)) ) {
return som;
}
else {
return u2_so(u2_me_is_north)
? _me_gain_north(som)
: _me_gain_south(som);
}
}

View File

@ -647,6 +647,7 @@
# define c3__meh c3_s3('m','e','h')
# define c3__meld c3_s4('m','e','l','d')
# define c3__melt c3_s4('m','e','l','t')
# define c3__meme c3_s4('m','e','m','e')
# define c3__memo c3_s4('m','e','m','o')
# define c3__menu c3_s4('m','e','n','u')
# define c3__mesh c3_s4('m','e','s','h')

View File

@ -387,6 +387,7 @@
/* Tools for Martian booleans.
*/
# define u2_na(x) (u2_no == (x))
# define u2_so(x) (u2_yes == (x))
# define u2_say(x) ( (x) ? u2_yes : u2_no )
# define u2_not(x) ( (x == u2_yes) ? u2_no : u2_yes )

View File

@ -2,9 +2,21 @@
**
** This file is in the public domain.
*/
/** Subordinate includes.
**/
/** c3: the C layer.
**/
# include "c/portable.h"
# include "c/tune.h"
# include "c/types.h"
# include "c/defs.h"
# include "c/motes.h"
# include "c/comd.h"
/** Tuning and configuration.
**/
# define u2_me_free_no 28
# define u2_me_fbox_no 28
# undef U2_MEMORY_DEBUG
# ifdef U2_MEMORY_DEBUG
@ -16,6 +28,84 @@
/** Data structures.
**/
/* u2_noun: tagged pointer.
**
** If bit 31 is 0, a u2_noun is a direct 31-bit atom ("cat").
** If bit 31 is 1 and bit 30 0, an indirect atom ("pug").
** If bit 31 is 1 and bit 30 1, an indirect cell ("pom").
**
** Bits 0-29 are a word offset against u2_Loom.
*/
typedef c3_w u2_noun;
/* u2_none - out-of-band noun.
*/
# define u2_none (u2_noun)0xffffffff
/* u2_atom, u2_cell: logical atom and cell structures.
*/
typedef struct {
c3_w mug_w;
} u2_me_noun;
typedef struct {
c3_w mug_w;
c3_w len_w;
c3_w buf_w[0];
} u2_me_atom;
typedef struct _u2_loom_cell {
c3_w mug_w;
u2_noun hed;
u2_noun tel;
} u2_me_cell;
/* u2_yes, u2_no, u2_nul;
**
** Our Martian booleans and list terminator; empty string; not a nonu.
*/
# define u2_yes 0
# define u2_no 1
# define u2_nul 0
# define u2_blip 0
/* Tools for Martian booleans.
*/
# define u2_so(x) (u2_yes == (x))
# define u2_ne(x) (u2_no == (x))
# define u2_say(x) ( (x) ? u2_yes : u2_no )
# define u2_not(x) ( (x == u2_yes) ? u2_no : u2_yes )
# define u2_and(x, y) ( (u2_so(x) && u2_so(y)) ? u2_yes : u2_no )
# define u2_or(x, y) ( (u2_so(x) || u2_so(y)) ? u2_yes : u2_no )
/* Inside a noun.
*/
# define u2_me_is_cat(som) (((som) >> 31) ? u2_no : u2_yes)
# define u2_me_is_dog(som) (((som) >> 31) ? u2_yes : u2_no)
# define u2_me_is_pug(som) (2 == (som >> 30))
# define u2_me_is_pom(som) (3 == (som >> 30))
# define u2_me_to_ptr(som) ((void *)(u2_me_into(som & 0x3fffffff)))
# define u2_me_is_atom(som) u2_or(u2_noun_is_cat(som), \
u2_noun_is_pug(som))
# define u2_me_is_cell(som) u2_noun_is_pom(som)
# define u2_me_de_twin(dog, dog_w) ((dog & 0xc0000000) | u2_me_outa(dog_w))
/* More typedefs.
*/
typedef u2_noun u2_atom; // must be atom
typedef u2_noun u2_term; // @tas
typedef u2_noun u2_mote; // @tas
typedef u2_noun u2_cell; // must be cell
typedef u2_noun u2_trel; // must be triple
typedef u2_noun u2_qual; // must be quadruple
typedef u2_noun u2_quin; // must be quintuple
typedef u2_noun u2_bean; // loobean: 0 == u2_yes, 1 == u2_no
typedef u2_noun u2_weak; // may be u2_none
/* u2_me_box: classic allocation box.
**
** The box size is also stored at the end of the box in classic
@ -40,7 +130,6 @@
} u2_me_box;
# define u2_me_boxed(len_w) (len_w + c3_wiseof(u2_me_box) + 1)
# define u2_me_boxof(box_v) ( (void *) \
# define u2_me_boxto(box_v) ( (void *) \
( ((c3_w *)(void*)(box_v)) + \
c3_wiseof(u2_me_box) ) )
@ -49,18 +138,16 @@
( ((c3_w *)(void*)(tox_v)) - \
c3_wiseof(u2_me_box) ) )
((box_w) + c3_wiseof(u2_me_box))
/* u2_me_free: free node in heap. Sets minimum node size.
/* u2_me_fbox: free node in heap. Sets minimum node size.
**
*/
typedef struct _u2_me_free {
typedef struct _u2_me_fbox {
u2_me_box box_u;
struct _u2_me_free* pre_u;
struct _u2_me_free* nex_u;
} u2_me_free;
struct _u2_me_fbox* pre_u;
struct _u2_me_fbox* nex_u;
} u2_me_fbox;
# define u2_me_minimum (c3_wiseof(u2_me_free))
# define u2_me_minimum (c3_wiseof(u2_me_fbox))
/* u2_me_road: contiguous allocation and execution context.
**
@ -103,17 +190,16 @@
struct _u2_me_road* kid_u; // child road list
struct _u2_me_road* nex_u; // sibling road
struct { // layout information
c3_w* cap_w; // top of transient region
c3_w* hat_w; // top of durable region
c3_w* mat_w; // bottom of transient region
c3_w* rut_w; // bottom of durable region
c3_w* cap_w; // top of transient region
c3_w* hat_w; // top of durable region
c3_w* mat_w; // bottom of transient region
c3_w* rut_w; // bottom of durable region
#if 0
c3_w* gar_w; // bottom of guard region (future)
c3_w* rag_w; // top of guard region (future)
c3_w pad_w[4]; // future interesting info
} lay;
#endif
struct { // escape buffer
union {
@ -123,7 +209,7 @@
} esc;
struct { // allocation pools
u2_me_free* fre_u[u2_me_free_no]; // heap by node size log
u2_me_fbox* fre_u[u2_me_fbox_no]; // heap by node size log
# ifdef U2_MEMORY_DEBUG
c3_w liv_w; // number of live words
# endif
@ -175,15 +261,15 @@
/** Macros.
**/
# define u2_me_is_north ((u2R->cap > u2R->hat) ? u2_yes : u2_no)
# define u2_me_is_north ((u2R->cap_w > u2R->hat_w) ? u2_yes : u2_no)
# define u2_me_is_south ((u2_yes == u2_me_is_north) ? u2_no : u2_yes)
# define u2_me_open ( (u2_yes == u2_me_is_north) \
? (c3_w)(u2R->cap - u2R->hat) \
: (c3_w)(u2R->hat - u2R->cap) )
? (c3_w)(u2R->cap_w - u2R->hat_w) \
: (c3_w)(u2R->hat_w - u2R->cap_w) )
# define u2_me_into(x) (((c3_w*)(void*)u2H) + (x))
# define u2_me_outa(p) (((c3_w*)(void*)(p)) - (c3w*)(void*)u2H)
# define u2_me_into(x) (u2_Loom + (x))
# define u2_me_outa(p) (((c3_w*)(void*)(p)) - u2_Loom)
/** Functions.
@ -196,10 +282,10 @@
/* u2_me_trap(): setjmp within road.
*/
#if 0
u2_noun
u2_bean
u2_me_trap(void);
#else
# define u2_me_trap() (u2_noun)(setjmp(u2R->esc.buf))
# define u2_me_trap() (u2_bean)(setjmp(u2R->esc.buf))
#endif
/* u2_me_bail(): bail out. Does not return.
@ -228,7 +314,7 @@
/* u2_me_fall(): return to parent road.
*/
void
u2_me_fall(void):
u2_me_fall(void);
/* u2_me_leap(): advance to inner road.
*/
@ -249,18 +335,19 @@
** // allocate some inner stuff...
** u2_me_fall();
** // inner stuff is still valid, but on cap
** u2_me_
** u2_me_flog(gof_w);
**
** u2_me_flog(0) simply clears the cap.
*/
void
u2_me_flog(void);
u2_me_flog(c3_w gof_w);
/* u2_me_water(): produce high and low watermarks. Asserts u2R == u2H.
*/
void
u2_me_water(c3_w *low_w, c3_w *hig_w);
/** Allocation.
**/
/* Basic allocation.
@ -283,11 +370,6 @@
/* Reference and arena control.
*/
/* u2_me_open(): u2_yes iff a free block is available.
*/
u2_bean
u2_me_open(c3_w len_w);
/* u2_me_gain(): gain and/or copy juniors.
*/
u2_weak
@ -415,436 +497,3 @@
u2_weak
u2_me_uniq(u2_noun som);
/* u2_rl_find():
**
** Cache search for function (0 means nock) and sample.
*/
u2_weak // transfer
u2_rl_find(u2_ray ral_r,
u2_mote fun_m,
u2_noun sam); // retain
/* u2_rl_save():
**
** Cache store for function (0 means nock), sample and product.
*/
u2_weak // transfer
u2_rl_save(u2_ray ral_r,
u2_mote fun_m, // retain
u2_noun sam, // retain
u2_noun pro); // transfer
/* u2_rl_uniq():
**
** Use cache to render object unique.
*/
u2_noun // produce
u2_rl_uniq(u2_ray ral_r,
u2_noun som); // submit
/* u2_rl_find_cell(): as u2_rl_find(), for `sam=[a b]`.
** u2_rl_find_trel(): as u2_rl_find(), for `sam=[a b c]`.
** u2_rl_find_qual(): as u2_rl_find(), for `sam=[a b d]`.
** u2_rl_find_quil(): as u2_rl_find(), for `sam=[a b c d e]`.
**
** Extend as needed...
*/
u2_weak // transfer
u2_rl_find_cell(u2_ray, u2_mote, u2_noun, // retain
u2_noun); // retain
u2_weak // transfer
u2_rl_find_trel(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun); // retain
u2_weak // transfer
u2_rl_find_qual(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // retain
u2_weak // transfer
u2_rl_find_quil(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // retain
/* u2_rl_save_cell(): as u2_rl_save(), for `sam=[a b]`.
** u2_rl_save_trel(): as u2_rl_save(), for `sam=[a b c]`.
** u2_rl_save_qual(): as u2_rl_save(), for `sam=[a b c d]`.
** u2_rl_save_quil(): as u2_rl_save(), for `sam=[a b c d e]`.
**
** Extended
*/
u2_weak // transfer
u2_rl_save_cell(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
u2_weak // transfer
u2_rl_save_trel(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
u2_weak // transfer
u2_rl_save_qual(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
u2_weak // transfer
u2_rl_save_quil(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
/** Abbreviations.
**/
# define u2_rc(ral_r, a, b) u2_rl_cell(ral_r, a, b)
# define u2_rt(ral_r, a, b, c) u2_rl_trel(ral_r, a, b, c)
# define u2_rq(ral_r, a, b, c, d) u2_rl_qual(ral_r, a, b, c, d)
# define u2_ri(ral_r, a, b, c, d, e) u2_rl_quil(ral_r, a, b, c, d, e)
# define u2_ro(ral_r, a) u2_rl_lone(ral_r, a)
# define u2_ru(ral_r, a) u2_rl_unit(ral_r, a)
# define u2_rx(ral_r, a) u2_rl_take(ral_r, a)
# define u2_rz(ral_r, a) u2_rl_lose(ral_r, a)
# define u2_rl u2_rl_list
# define u2_rk u2_rl_rack
/** Functions.
**/
/* u2_rl_malloc():
**
** Allocate `sib_w` *bytes* of raw C storage.
*/
void*
u2_rl_malloc(u2_ray ral_r,
c3_w sib_w);
/* u2_rl_open():
**
** Yes iff [a] more words remain in the pad.
*/
u2_bean
u2_rl_open(u2_ray ral_r,
c3_w a_w);
/* u2_rl_ralloc():
**
** Allocate `siz_w` words of raw ray storage.
*/
u2_ray
u2_rl_ralloc(u2_ray ral_r,
c3_w siz_w);
/* u2_rl_rfree():
**
** Free raw ray storage allocated by `u2_rl_ralloc()`.
*/
void
u2_rl_rfree(u2_ray ral_r,
u2_ray nov_r);
/* u2_rl_senior():
**
** Yes iff `dus` is senior in `ral` - ie, does not
** require reference counting.
*/
u2_bean
u2_rl_senior(u2_ray ral_r,
u2_noun dus); // retain
/* u2_rl_refs():
**
** Return the reference count of (som). For debugging, etc.
*/
c3_w
u2_rl_refs(u2_ray ral_r,
u2_noun som);
/* u2_rl_copy():
**
** Copy indirect noun `fiz` into main storage, preserving dags.
** Must be followed by `rl_wash(fiz)` if `fiz` is to be preserved.
*/
u2_weak // transfer
u2_rl_copy(u2_ray ral_r,
u2_dog fiz); // retain
/* u2_rl_take():
**
** Produce `a`, as eligible result. Copy juniors; reference peers.
*/
u2_weak // transfer
u2_rl_take(u2_ray ral_r,
u2_weak a); // retain
# define u2_rl_ice(ral_r, a) \
u2_rl_take(ral_r, a)
/* u2_rl_tamp():
**
** Tamp, eliding the segment from `net` up to `bat`,
** preserving the root `lef`.
**
** Assumes u2_rl_clear() with the same arguments.
*/
u2_noun
u2_rl_tamp(u2_ray ral_r,
u2_noun lef,
u2_ray net_r,
u2_ray bat_r);
/* u2_rl_valid():
**
** Validate rail for memory bugs.
*/
void
u2_rl_valid(u2_ray ral_r);
/* u2_rl_water():
**
** Return east and west watermarks, respectively.
*/
void
u2_rl_water(u2_ray ral_r,
c3_w* maz_w,
c3_w* buc_w);
/** Basic noun fabrication.
**/
/* u2_rl_bytes():
**
** Copy `a` bytes from `b` to an LSB first atom.
*/
u2_weak // transfer
u2_rl_bytes(u2_ray ral_r,
c3_w a_w,
const c3_y* b_y);
/* u2_rl_cell():
**
** Produce the cell `[a b]`.
*/
u2_weak // transfer
u2_rl_cell(u2_ray ral_r,
u2_weak a, // transfer
u2_weak b); // transfer
/* u2_rl_list():
**
** Produce a null-terminated list, terminating `...` with `u2_none`.
*/
u2_weak // transfer
u2_rl_list(u2_rail ral_r,
...); // transfer
/* u2_rl_lone():
**
** Create the unit `[0 a]`.
*/
#if 0
u2_weak // transfer
u2_rl_lone(u2_rail ral_r,
u2_weak a); // transfer
#else
# define u2_rl_lone(ral_r, a) \
u2_rc(ral_r, a, u2_nul)
#endif
/* u2_rl_molt():
**
** Mutate `som` with a 0-terminated list of axis, noun pairs.
** Axes must be cats (31 bit).
*/
u2_weak // transfer
u2_rl_molt(u2_rail ral_r,
u2_weak som, // retain
...); // transfer
/* u2_rl_molv():
**
** As u2_rl_molt(), by argument pointer.
*/
u2_weak // transfer
u2_rl_molv(u2_rail ral_r,
u2_weak som, // retain
va_list vap); // transfer
/* u2_rl_mp():
**
** Copy the GMP integer [a] into an atom.
*/
u2_weak // transfer
u2_rl_mp(u2_ray ral_r,
mpz_t a_mp); // transfer
/* u2_rl_qual():
**
** Produce the triple `[a b c d]`.
*/
#if 0
u2_weak // transfer
u2_rl_qual(u2_rail ral_r,
u2_weak a, // transfer
u2_weak b, // transfer
u2_weak c, // transfer
u2_weak d); // transfer
#else
# define u2_rl_qual(ral_r, a, b, c, d) \
u2_rc(ral_r, a, u2_rt(ral_r, b, c, d))
#endif
/* u2_rl_rack():
**
** Produce an n-tuple, terminating `...` with `u2_none`.
*/
u2_weak // transfer
u2_rl_rack(u2_rail ral_r,
...); // transfer
/* u2_rl_string():
**
** Produce an LSB-first atom from the C string `a`.
*/
u2_weak // transfer
u2_rl_string(u2_ray ral_r,
const c3_c* a_c);
/* u2_rl_trel():
**
** Create the triple `[a b c]`.
*/
#if 0
u2_weak // transfer
u2_rl_trel(u2_rail ral_r,
u2_weak a, // transfer
u2_weak b, // transfer
u2_weak c); // transfer
#else
# define u2_rl_trel(ral_r, a, b, c) \
u2_rc(ral_r, a, u2_rc(ral_r, b, c))
#endif
/* u2_rl_unit():
**
** Create the unit `[0 a]`.
*/
#if 0
u2_weak // transfer
u2_rl_unit(u2_rail ral_r,
u2_weak a); // transfer
#else
# define u2_rl_unit(ral_r, a) \
u2_rc(ral_r, u2_nul, a)
#endif
/* u2_rl_vint():
**
** Create `a + 1`.
*/
u2_weak // transfer
u2_rl_vint(u2_rail ral_r,
u2_weak a); // transfer
/* u2_rl_words():
**
** Copy [a] words from [b] into an atom.
*/
u2_weak // transfer
u2_rl_words(u2_ray ral_r,
c3_w a_w,
const c3_w* b_w);
/** Caching.
**/
/* u2_rl_find():
**
** Cache search for function (0 means nock) and sample.
*/
u2_weak // transfer
u2_rl_find(u2_ray ral_r,
u2_mote fun_m,
u2_noun sam); // retain
/* u2_rl_save():
**
** Cache store for function (0 means nock), sample and product.
*/
u2_weak // transfer
u2_rl_save(u2_ray ral_r,
u2_mote fun_m, // retain
u2_noun sam, // retain
u2_noun pro); // transfer
/* u2_rl_uniq():
**
** Use cache to render object unique.
*/
u2_noun // produce
u2_rl_uniq(u2_ray ral_r,
u2_noun som); // submit
/* u2_rl_find_cell(): as u2_rl_find(), for `sam=[a b]`.
** u2_rl_find_trel(): as u2_rl_find(), for `sam=[a b c]`.
** u2_rl_find_qual(): as u2_rl_find(), for `sam=[a b d]`.
** u2_rl_find_quil(): as u2_rl_find(), for `sam=[a b c d e]`.
**
** Extend as needed...
*/
u2_weak // transfer
u2_rl_find_cell(u2_ray, u2_mote, u2_noun, // retain
u2_noun); // retain
u2_weak // transfer
u2_rl_find_trel(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun); // retain
u2_weak // transfer
u2_rl_find_qual(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // retain
u2_weak // transfer
u2_rl_find_quil(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // retain
/* u2_rl_save_cell(): as u2_rl_save(), for `sam=[a b]`.
** u2_rl_save_trel(): as u2_rl_save(), for `sam=[a b c]`.
** u2_rl_save_qual(): as u2_rl_save(), for `sam=[a b c d]`.
** u2_rl_save_quil(): as u2_rl_save(), for `sam=[a b c d e]`.
**
** Extended
*/
u2_weak // transfer
u2_rl_save_cell(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
u2_weak // transfer
u2_rl_save_trel(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
u2_weak // transfer
u2_rl_save_qual(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer
u2_weak // transfer
u2_rl_save_quil(u2_ray, u2_mote, u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun, // retain
u2_noun); // transfer

View File

@ -32,6 +32,8 @@
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
#define CTTP_NO_PIPELINE
/* Forward declarations.
*/
static void _cttp_ccon_kick(u2_ccon* coc_u);
@ -638,6 +640,7 @@ _cttp_message_complete(http_parser* par_u)
if ( u2_yes == coc_u->sec ) {
SSL_shutdown(coc_u->ssl.ssl_u);
_cttp_ccon_cryp_rout(coc_u);
uL(fprintf(uH, "cttp: close b: %p\n", coc_u));
uv_close((uv_handle_t*)&coc_u->wax_u, _cttp_ccon_fail_cb);
}
return 0;
@ -806,6 +809,7 @@ _cttp_ccon_reboot(u2_ccon* coc_u)
/* Begin again.
*/
uL(fprintf(uH, "ccon: rekick\r\n"));
_cttp_ccon_kick(coc_u);
}
break;
@ -836,6 +840,7 @@ _cttp_ccon_fail(u2_ccon* coc_u, u2_bean say)
_cttp_ccon_reboot(coc_u);
}
else {
uL(fprintf(uH, "cttp: close: %p\n", coc_u));
uv_close((uv_handle_t*)&coc_u->wax_u, _cttp_ccon_fail_cb);
}
}
@ -1319,6 +1324,7 @@ _cttp_ccon_new(u2_bean sec, c3_s por_s, c3_c* hot_c)
return coc_u;
}
#ifndef CTTP_NO_PIPELINE
/* _cttp_ccon_find(): find existing connection for remote server.
*/
static u2_ccon*
@ -1335,19 +1341,23 @@ _cttp_ccon_find(u2_bean sec, c3_s por_s, c3_c* hot_c)
}
return 0;
}
#endif
/* _cttp_ccon(): create or find persistent client connection.
*/
static u2_ccon*
_cttp_ccon(u2_bean sec, c3_s por_s, c3_c* hot_c)
{
#ifndef CTTP_NO_PIPELINE
u2_ccon* coc_c = _cttp_ccon_find(sec, por_s, hot_c);
if ( 0 != coc_c ) {
free(hot_c);
return coc_c;
}
else return _cttp_ccon_new(sec, por_s, hot_c);
else
#endif
return _cttp_ccon_new(sec, por_s, hot_c);
}
/* _cttp_creq(): cttp request from noun.