Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hoon git #645

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
11 changes: 11 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,14 @@ alias(
name = "urbit",
actual = "//pkg/vere:urbit",
)

load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
refresh_compile_commands(
name = "refresh_compile_commands",

# Specify the targets of interest.
# For example, specify a dict of targets and any flags required to build.
targets = {
"//:urbit": "",
},
)
19 changes: 19 additions & 0 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,22 @@ container_pull(
registry = "docker.io",
repository = "alpine",
)


load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")


# Hedron's Compile Commands Extractor for Bazel
# https://github.com/hedronvision/bazel-compile-commands-extractor
http_archive(
name = "hedron_compile_commands",

# Replace the commit hash (daae6f40adfa5fdb7c89684cbe4d88b691c63b2d) in both places (below) with the latest (https://github.com/hedronvision/bazel-compile-commands-extractor/commits/main), rather than using the stale one here.
# Even better, set up Renovate and let it do the work for you (see "Suggestion: Updates" in the README).
url = "https://github.com/hedronvision/bazel-compile-commands-extractor/archive/eac41eefb5c19d9a2d2bcdd60d6989660288333d.tar.gz",
strip_prefix = "bazel-compile-commands-extractor-eac41eefb5c19d9a2d2bcdd60d6989660288333d",
# When you first run this tool, it'll recommend a sha256 hash to put here with a message like: "DEBUG: Rule 'hedron_compile_commands' indicated that a canonical reproducible form can be obtained by modifying arguments sha256 = ..."
)
load("@hedron_compile_commands//:workspace_setup.bzl", "hedron_compile_commands_setup")
hedron_compile_commands_setup()

1 change: 1 addition & 0 deletions pkg/noun/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ vere_library(
"@sigsegv",
"@softfloat",
"@urcrypt",
"@zlib",
] + select({
"@platforms//os:macos": ["//pkg/noun/platform/darwin"],
"@platforms//os:linux": ["//pkg/noun/platform/linux"],
Expand Down
352 changes: 352 additions & 0 deletions pkg/noun/jets/e/git.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
#include <stdbool.h>

#include "jets/q.h"
#include "jets/w.h"
#include "c3.h"

#include "allocate.h"
#include "noun.h"

static u3_atom _q_octs;

static inline c3_y _cord_cmp(u3_atom cord, const char* s)
{
u3a_atom* cord_p = u3a_to_ptr(cord);
const c3_y* c = (c3_y*)cord_p->buf_w;
c3_w len_w = u3r_met(3, cord);

if (len_w == 0 || *s == '\0' ) {
return (len_w == 0 && *s == '\0') ? c3y : c3n;
}

do {
if (*(c++) != *(s++)) {
return c3n;
}

} while (--len_w && *s != '\0');

return (len_w == 0 && *s == '\0') ? c3y : c3n;
}

static c3_y* _unpack_octs(u3_atom p_octs, u3_atom* q_octs_p, c3_w* len_wp) {

c3_y* buf_y;
c3_w len_w;

u3_atom q_octs = *q_octs_p;

u3_assert(c3y == u3a_is_cat(p_octs));

if (c3y == u3a_is_cat(q_octs)) {

buf_y = (c3_y*)q_octs_p;
len_w = sizeof(q_octs);
}
else {
u3a_atom* a = u3a_to_ptr(q_octs);
buf_y = (c3_y*)a->buf_w;
len_w = u3r_met(3, q_octs);
}

u3_assert(len_w <= p_octs);

*len_wp = len_w;

return buf_y;
}

static inline int _read_octs_byte(c3_y* buf_y, c3_w* pos_wp, c3_w buf_len_w, c3_w len_w) {

c3_w pos_w = *pos_wp;

u3_assert(buf_len_w <= len_w);
u3_assert(pos_w < len_w);

c3_y bat_y = 0;

if (pos_w < buf_len_w) {
bat_y = *(buf_y + pos_w);
}

(*pos_wp)++;

return bat_y;
}

static c3_w _read_size(c3_y* buf_y, c3_w* pos_wp, c3_w buf_len_w, c3_w len_w) {

c3_y bat_y = 0;
c3_w bits = 0;
c3_w size = 0;

c3_w pos_w = *pos_wp;

// fprintf(stderr, "_read_size: ***\r\n");
while (pos_w < len_w) {
bat_y = _read_octs_byte(buf_y, &pos_w, buf_len_w, len_w);

// fprintf(stderr, "_read_size [%d/%d]: 0x%hhx\r\n", pos_w, len_w, bat_y);

size += (bat_y & 0x7f) << bits;
bits += 7;

if (!(bat_y & 0x80)) break;
}

*pos_wp = pos_w;

return size;
}

u3_noun u3qe_git_pack_expand_delta_object(u3_noun base,
u3_noun delta) {

// +$ raw-object [type=object-type size=@ud data=octs]

/* +$ raw-object [type=object-type size=@ud data=octs]
+$ pack-object $% raw-object
[%ofs-delta pos=@ud base-offset=@ud =octs]
[%ref-delta pos=@ud =hash =octs]
==
+$ pack-delta-object $>(?(%ofs-delta %ref-delta) pack-object)
*/

// base=raw-object
//
u3_atom base_type;
u3_atom base_size;
u3_noun base_data;

u3_atom base_data_p_octs;
u3_atom base_data_q_octs;

u3x_trel(base, &base_type, &base_size, &base_data);
u3x_cell(base_data, &base_data_p_octs, &base_data_q_octs);

// delta=pack-object
//
u3_atom delta_type;
u3_noun delta_obj;

u3_atom delta_pos;
u3_atom delta_base_offset;
u3_noun delta_octs;

u3_atom delta_p_octs;
u3_atom delta_q_octs;

u3x_cell(delta, &delta_type, &delta_obj);

if (c3y == _cord_cmp(delta_type, "ref-delta")) {
return u3_none;
}
if (c3y == _cord_cmp(delta_type, "ofs-delta")) {
u3x_trel(delta_obj, &delta_pos, &delta_base_offset, &delta_octs);
}

u3x_cell(delta_octs, &delta_p_octs, &delta_q_octs);

c3_y* sea_y;
c3_y* sea_begin_y;
c3_w sea_pos_w;

c3_w sea_buf_len_w;
c3_w sea_len_w;

sea_y = _unpack_octs(delta_p_octs, &delta_q_octs, &sea_buf_len_w);
sea_begin_y = sea_y;
sea_len_w = delta_p_octs;
sea_pos_w = 0;

c3_y* bas_y;
c3_y* bas_begin_y;

c3_w bas_buf_len_w;
c3_w bas_len_w;

bas_y = _unpack_octs(base_data_p_octs, &base_data_q_octs, &bas_buf_len_w);
u3_assert(base_size == base_data_p_octs);
bas_begin_y = bas_y;
bas_len_w = base_data_p_octs;

/* Base object size (biz) and target
* object size (siz)
*/
// XX should exit cleanly
c3_w biz_w = _read_size(sea_y, &sea_pos_w, sea_buf_len_w, sea_len_w);
c3_w siz_w = _read_size(sea_y, &sea_pos_w, sea_buf_len_w, sea_len_w);

// fprintf(stderr, "u3qe__pack_expand_delta_object: biz_w = %d, siz_w = %d\r\n", biz_w, siz_w);

// Base size mismatch
//
if (biz_w != base_data_p_octs) {
fprintf(stderr, "bas_buf_len_w = %d, bas_len_w = %d\r\n", bas_buf_len_w, bas_len_w);
fprintf(stderr, "sea_pos = %d, sea_buf_len = %d, sea_len = %d\r\n", sea_pos_w, sea_buf_len_w, sea_len_w);
// u3_assert(false);
// _free();
return u3_none;
}

// Target buffer
u3i_slab sab_u;
u3i_slab_init(&sab_u, 3, siz_w);

c3_y* tar_y = sab_u.buf_y;
c3_w tar_len_w = siz_w;

c3_y bat_y;

while (sea_pos_w < sea_len_w) {

bat_y = _read_octs_byte(sea_y, &sea_pos_w, sea_buf_len_w, sea_len_w);

// XX ?> (lth pos.sea p.octs.sea)
if ( 0x0 == bat_y ) {
fprintf(stderr, "u3qe__pack_expand_delta_object: hit reserved instruction 0x0\r\n");

u3m_bail(c3__fail);
}
else {
/* ADD instruction
*/
if (!(bat_y & 0x80)) {

c3_w siz_w = bat_y & 0x7f;

if (sea_len_w - sea_pos_w < siz_w) {
fprintf(stderr, "u3qe__pack_expand_delta_object: invalid add instruction\r\n");

u3_assert(false);
return u3_none;
}

// fprintf(stderr, "u3qe__pack_expand_delta: ADD[siz_w = %d]\r\n", siz_w);

if (tar_len_w < siz_w) {
fprintf(stderr, "u3qe__pack_expand_delta: ADD overflowed\r\n");

u3_assert(false);
return u3_none;
}

// Some part to be copied falls inside
// the atom buffer
//
if (sea_buf_len_w > sea_pos_w) {

c3_w cin_w = (sea_buf_len_w - sea_pos_w);

if (siz_w < cin_w) {
memcpy(tar_y, sea_y + sea_pos_w, siz_w);
}
else {
memcpy(tar_y, sea_y + sea_pos_w, cin_w);
memset(tar_y+cin_w, 0, siz_w - cin_w);
}
}
else {
memset(tar_y, 0, siz_w);
}

sea_pos_w += siz_w;

tar_y += siz_w;
tar_len_w -= siz_w;
}
/* COPY instruction
*/
else {

/* Retrieve offset and size
*/
c3_w off_w = 0;
c3_w siz_w = 0;

#define _parse_cp_param(bit, var, shift) \
{ \
if (bat_y & (bit)) { \
if (!(sea_pos_w < sea_len_w)) { \
u3_assert(false); \
return u3_none; \
} \
var |= _read_octs_byte(sea_y, &sea_pos_w, sea_buf_len_w, sea_len_w) << shift; \
} \
} \

/* Parse offset
*/
_parse_cp_param(0x1, off_w, 0);
_parse_cp_param(0x2, off_w, 8);
_parse_cp_param(0x4, off_w, 16);
_parse_cp_param(0x8, off_w, 24);

/* Parse size
*/
_parse_cp_param(0x10, siz_w, 0);
_parse_cp_param(0x20, siz_w, 8);
_parse_cp_param(0x40, siz_w, 16);

if (siz_w == 0) {
siz_w = 0x10000;
}

if (tar_len_w < siz_w || (bas_len_w - off_w) < siz_w) {
fprintf(stderr, "u3qe__pack_expand_delta: copy out of range\r\n");
u3_assert(false);
return u3_none;
}

// fprintf(stderr, "u3qe__pack_expand_delta: COPY[siz_w = %d, off_w = %d]\r\n", siz_w, off_w);

// Region to be copied overlaps with the atom buffer
//
if (bas_buf_len_w > off_w) {

c3_w cin_w = (bas_buf_len_w - off_w);

// Region to be copied is wholly inside
//
if (siz_w < cin_w) {
memcpy(tar_y, bas_y + off_w, siz_w);
}
// Region to be copied is partially inside
//
else {
memcpy(tar_y, bas_y + off_w, cin_w);
memset(tar_y+cin_w, 0, siz_w - cin_w);
}
}
else {
memset(tar_y, 0, siz_w);
}

tar_y += siz_w;
tar_len_w -= siz_w;
}
}
}

if (tar_len_w) {
fprintf(stderr, "u3qe__pack_expand_delta: target object underfilled (%d bytes left)\r\n", tar_len_w);
u3_assert(false);
return u3_none;
}

u3_noun data = u3nc(u3i_chub(siz_w), u3i_slab_mint(&sab_u));
u3_noun rob = u3nt(u3k(base_type), u3i_chub(siz_w), data);

return rob;
}

u3_noun u3we_git_pack_expand_delta_object(u3_noun cor) {

u3_noun base;
u3_noun delta;

u3x_mean(cor, u3x_sam_2, &base,
u3x_sam_3, &delta, 0);

return u3qe_git_pack_expand_delta_object(base, delta);
}
Loading