Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions c2rust-postprocess/postprocess/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,9 @@ def _transfer_comments_prompts(
logging.info(f"Loaded {len(c_definitions)} C definitions")

for identifier, rust_definition in rust_definitions.items():
if options.exclude_list.contains(
path=rust_source_file, identifier=identifier
):
logging.info(
f"Skipping Rust fn {identifier} in {rust_source_file}"
f" due to exclude file {options.exclude_list.src_path}"
)
continue
if ident_regex and not ident_regex.search(identifier):
logging.info(
f"Skipping Rust fn {identifier} in {rust_source_file}"
f"Skipping fn {identifier} in {rust_source_file}"
f" due to ident filter {options.ident_filter}"
)
continue
Expand Down Expand Up @@ -313,6 +305,24 @@ def _run_prompts(
rust_comments = get_rust_comments(rust_fn)
logging.debug(f"{rust_comments=}")

# Do the exclusion when checking if the comment transfer was successful,
# but don't skip actually trying the comment transfer and caching it.
excluded = options.exclude_list.contains(
path=prompt.rust_source_file, identifier=prompt.identifier
)
if excluded:
logging.info(
f"Skipping fn {prompt.identifier} in {prompt.rust_source_file}"
f" due to exclude file {options.exclude_list.src_path}"
)
if c_comments == rust_comments:
logging.warning(
f"Skipped fn {prompt.identifier} in {prompt.rust_source_file}"
f" due to exclude file {options.exclude_list.src_path},"
f" but the comments match, so exclusion is unnecessary"
)
continue

if c_comments != rust_comments:
yield CommentTransferFailure(
options=options,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
transform = "CommentTransfer"
identifier = "array_list_new"
model = "gemini-3-flash-preview"
response = """```rust
#[no_mangle]

pub unsafe extern "C" fn array_list_new(
mut free_fn: Option<crate::src::arraylist::array_list_free_fn>,
) -> *mut crate::src::arraylist::array_list {
let mut arr: *mut crate::src::arraylist::array_list = ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
arr = calloc(1 as size_t, ::core::mem::size_of::<crate::src::arraylist::array_list>() as size_t) as *mut crate::src::arraylist::array_list;
if arr.is_null() {
return ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
}
(*arr).size = crate::src::arraylist::ARRAY_LIST_DEFAULT_SIZE as size_t;
(*arr).length = 0 as size_t;
(*arr).free_fn = free_fn;
(*arr).array = calloc(
::core::mem::size_of::<*mut ::core::ffi::c_void>() as size_t,
(*arr).size,
) as *mut *mut ::core::ffi::c_void;
if (*arr).array.is_null() {
free(arr as *mut ::core::ffi::c_void);
return ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
}
return arr;
}
```"""

[[messages]]
role = "user"
content = """Transfer the comments from the following C function to the corresponding Rust function.
Do not add any comments that are not present in the C function.
Use Rust doc comment syntax (///) where appropriate (e.g., for function documentation).
Respond with the Rust function definition with the transferred comments; say nothing else.

C function:
```c
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
#define SIZE_T_MAX ULLONG_MAX
#else
#error Unable to determine size of size_t
#endif
#endif

#include "arraylist.h"

struct array_list*
array_list_new(array_list_free_fn *free_fn)
{
struct array_list *arr;

arr = (struct array_list*)calloc(1, sizeof(struct array_list));
if(!arr) return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
free(arr);
return NULL;
}
return arr;
}
```

Rust function:
```rust
#[no_mangle]

pub unsafe extern "C" fn array_list_new(
mut free_fn: Option<crate::src::arraylist::array_list_free_fn>,
) -> *mut crate::src::arraylist::array_list {
let mut arr: *mut crate::src::arraylist::array_list = ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
arr = calloc(1 as size_t, ::core::mem::size_of::<crate::src::arraylist::array_list>() as size_t) as *mut crate::src::arraylist::array_list;
if arr.is_null() {
return ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
}
(*arr).size = crate::src::arraylist::ARRAY_LIST_DEFAULT_SIZE as size_t;
(*arr).length = 0 as size_t;
(*arr).free_fn = free_fn;
(*arr).array = calloc(
::core::mem::size_of::<*mut ::core::ffi::c_void>() as size_t,
(*arr).size,
) as *mut *mut ::core::ffi::c_void;
if (*arr).array.is_null() {
free(arr as *mut ::core::ffi::c_void);
return ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
}
return arr;
}
```
"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
```rust
#[no_mangle]

pub unsafe extern "C" fn array_list_new(
mut free_fn: Option<crate::src::arraylist::array_list_free_fn>,
) -> *mut crate::src::arraylist::array_list {
let mut arr: *mut crate::src::arraylist::array_list = ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
arr = calloc(1 as size_t, ::core::mem::size_of::<crate::src::arraylist::array_list>() as size_t) as *mut crate::src::arraylist::array_list;
if arr.is_null() {
return ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
}
(*arr).size = crate::src::arraylist::ARRAY_LIST_DEFAULT_SIZE as size_t;
(*arr).length = 0 as size_t;
(*arr).free_fn = free_fn;
(*arr).array = calloc(
::core::mem::size_of::<*mut ::core::ffi::c_void>() as size_t,
(*arr).size,
) as *mut *mut ::core::ffi::c_void;
if (*arr).array.is_null() {
free(arr as *mut ::core::ffi::c_void);
return ::core::ptr::null_mut::<crate::src::arraylist::array_list>();
}
return arr;
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
transform = "CommentTransfer"
identifier = "get_string_component"
model = "gemini-3-flash-preview"
response = """/// helper for accessing the optimized string data component in json_object
unsafe extern "C" fn get_string_component(
mut jso: *const json_object,
) -> *const ::core::ffi::c_char {
return if (*jso).o.c_string.len < LEN_DIRECT_STRING_DATA {
&raw const (*jso).o.c_string.str_0.data as *const ::core::ffi::c_char
} else {
(*jso).o.c_string.str_0.ptr as *const ::core::ffi::c_char
};
}"""

[[messages]]
role = "user"
content = """Transfer the comments from the following C function to the corresponding Rust function.
Do not add any comments that are not present in the C function.
Use Rust doc comment syntax (///) where appropriate (e.g., for function documentation).
Respond with the Rust function definition with the transferred comments; say nothing else.

C function:
```c
/* ref count debugging */

#ifdef REFCOUNT_DEBUG

static struct lh_table *json_object_table;

static void json_object_init(void) __attribute__ ((constructor));
static void json_object_init(void) {
\tMC_DEBUG("json_object_init: creating object table\\n");
\tjson_object_table = lh_kptr_table_new(128, NULL);
}

static void json_object_fini(void) __attribute__ ((destructor));
static void json_object_fini(void)
{
\tstruct lh_entry *ent;
\tif (MC_GET_DEBUG())
\t{
\t\tif (json_object_table->count)
\t\t{
\t\t\tMC_DEBUG("json_object_fini: %d referenced objects at exit\\n",
\t\t\t json_object_table->count);
\t\t\tlh_foreach(json_object_table, ent)
\t\t\t{
\t\t\t\tstruct json_object* obj =
\t\t\t\t (struct json_object*) lh_entry_v(ent);
\t\t\t\tMC_DEBUG("\\t%s:%p\\n",
\t\t\t\t\t json_type_to_name(obj->o_type), obj);
\t\t\t}
\t\t}
\t}
\tMC_DEBUG("json_object_fini: freeing object table\\n");
\tlh_table_free(json_object_table);
}
#endif /* REFCOUNT_DEBUG */


/* helper for accessing the optimized string data component in json_object
*/
static const char *
get_string_component(const struct json_object *jso)
{
\treturn (jso->o.c_string.len < LEN_DIRECT_STRING_DATA) ?
\t\t jso->o.c_string.str.data : jso->o.c_string.str.ptr;
}
```

Rust function:
```rust
unsafe extern "C" fn get_string_component(
mut jso: *const json_object,
) -> *const ::core::ffi::c_char {
return if (*jso).o.c_string.len < LEN_DIRECT_STRING_DATA {
&raw const (*jso).o.c_string.str_0.data as *const ::core::ffi::c_char
} else {
(*jso).o.c_string.str_0.ptr as *const ::core::ffi::c_char
};
}
```
"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// helper for accessing the optimized string data component in json_object
unsafe extern "C" fn get_string_component(
mut jso: *const json_object,
) -> *const ::core::ffi::c_char {
return if (*jso).o.c_string.len < LEN_DIRECT_STRING_DATA {
&raw const (*jso).o.c_string.str_0.data as *const ::core::ffi::c_char
} else {
(*jso).o.c_string.str_0.ptr as *const ::core::ffi::c_char
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
transform = "CommentTransfer"
identifier = "get_time_seed"
model = "gemini-3-flash-preview"
response = """/// get_time_seed
unsafe extern "C" fn get_time_seed() -> ::core::ffi::c_int {
return time(::core::ptr::null_mut::<time_t>()) as ::core::ffi::c_int
* 433494437 as ::core::ffi::c_int;
}"""

[[messages]]
role = "user"
content = """Transfer the comments from the following C function to the corresponding Rust function.
Do not add any comments that are not present in the C function.
Use Rust doc comment syntax (///) where appropriate (e.g., for function documentation).
Respond with the Rust function definition with the transferred comments; say nothing else.

C function:
```c
#endif


/* get_cryptgenrandom_seed */

#ifdef WIN32

#define HAVE_CRYPTGENRANDOM 1

#include <windows.h>
#include <wincrypt.h>
#ifndef __GNUC__
#pragma comment(lib, "advapi32.lib")
#endif

static int get_cryptgenrandom_seed(void)
{
HCRYPTPROV hProvider = 0;
int r;

DEBUG_SEED("get_cryptgenrandom_seed");

if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
fprintf(stderr, "error CryptAcquireContextW");
exit(1);
}

if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) {
fprintf(stderr, "error CryptGenRandom");
exit(1);
}

CryptReleaseContext(hProvider, 0);

return r;
}

#endif


/* get_time_seed */

#include <time.h>

static int get_time_seed(void)
{
DEBUG_SEED("get_time_seed");

return (int)time(NULL) * 433494437;
}
```

Rust function:
```rust
unsafe extern "C" fn get_time_seed() -> ::core::ffi::c_int {
return time(::core::ptr::null_mut::<time_t>()) as ::core::ffi::c_int
* 433494437 as ::core::ffi::c_int;
}
```
"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// get_time_seed
unsafe extern "C" fn get_time_seed() -> ::core::ffi::c_int {
return time(::core::ptr::null_mut::<time_t>()) as ::core::ffi::c_int
* 433494437 as ::core::ffi::c_int;
}
Loading