Skip to content
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