-
Notifications
You must be signed in to change notification settings - Fork 305
Expand file tree
/
Copy pathtranslate.py
More file actions
executable file
·140 lines (97 loc) · 4.2 KB
/
Copy pathtranslate.py
File metadata and controls
executable file
·140 lines (97 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env -S uv run
import json
import os
import sys
from plumbum.cmd import mv, mkdir, sed, rustc, cargo, rm
from plumbum import local
# Path to the root of the json-c codebase
JSON_C_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'repo'))
sys.path.append(os.path.join(JSON_C_DIR, '../../../scripts'))
from common import *
# List of c2rust-refactor commands to run.
def mk_select(script, mark='target'):
return ['select', mark, script]
REFACTORINGS = [
['link_incomplete_types'],
mk_select(r'''
crate;
desc(
path(::arraylist::array_list) ||
path(::json_object::json_object) ||
path(::json_object_iterator::json_object_iterator) ||
path(::json_tokener::json_tokener) ||
path(::json_tokener::srec) ||
path(::linkhash::lh_entry) ||
path(::linkhash::lh_table) ||
path(::printbuf::printbuf)
);''') + [';', 'canonicalize_structs'],
['link_funcs'],
mk_select('crate; desc(fn && pub);') + [';', 'wrap_api'],
# Omit locale functions because the `libc`'s versions are unusable.
# (`libc::locale_t` is defined incorrectly.)
mk_select('crate; desc(foreign_item && fn && !name(".*locale.*"));') +
[';', 'canonicalize_externs', 'libc'],
mk_select(r'crate; desc(foreign_item && fn && name("__isnan(l|f)?"));') +
[';', 'mark_uses', 'target',
';', 'rewrite_expr', 'marked!(__e)(__f)', '__f.is_nan() as i32'],
mk_select(r'crate; desc(foreign_item && fn && name("__isinf(l|f)?"));') +
[';', 'mark_uses', 'target',
';', 'rewrite_expr', 'marked!(__e)(__f)', '__f.is_infinite() as i32'],
mk_select('crate; child(mod && !name("c_funcs")); desc(foreign_item);') +
[';', 'canonicalize_externs', 'c_funcs'],
]
refactor = get_cmd_or_die(config.RREF_BIN)
def run_refactor(args, mode='inplace'):
full_args = ['-r', mode] + args + [
'--', 'src/lib.rs', '--crate-type=dylib',
'--crate-name=json_c',
'-L{rust_libdir}/rustlib/{triple}/lib/'.format(
rust_libdir=get_rust_toolchain_libpath(),
triple=get_host_triplet())]
ld_lib_path = get_rust_toolchain_libpath()
# don't overwrite existing ld lib path if any...
if 'LD_LIBRARY_PATH' in local.env:
ld_lib_path += ':' + local.env['LD_LIBRARY_PATH']
# import ast
with local.env(RUST_BACKTRACE='1',
LD_LIBRARY_PATH=ld_lib_path):
with local.cwd(os.path.join(JSON_C_DIR, 'rust')):
refactor[full_args]()
def main():
os.chdir(JSON_C_DIR)
# Patch compile_commands to remove certain flags
with open('compile_commands.json') as f:
cc_json = json.load(f)
for entry in cc_json:
if 'arguments' not in entry:
continue
new_args = []
for arg in entry['arguments']:
if arg in ('-Werror', '-D_FORTIFY_SOURCE=2'):
continue
new_args.append(arg)
entry['arguments'] = new_args
with open('compile_commands.json', 'w') as f:
json.dump(cc_json, f, indent=4)
# Remove object files that will confuse `transpile`
rm['-f', local.path('.') // '*.o', local.path('.libs') // '*.o']()
# Actually translate
transpile_files('compile_commands.json', emit_build_files=False)
# Move rust files into rust/src
mkdir['-vp', 'rust/src']()
mv['-v', local.path('.') // '*.rs', 'rust/src/']()
# Apply some fixes
# 1. json-c uses `///` comments on some local assignment expressions, which
# turn into `///` doc comments in the translated Rust. But Rust doesn't
# allow doc comments in those places. We just globally replace `///` with
# `//` for now.
sed['-i', '-e', 's.///\+.//.g', local.path('rust/src') // '*.rs']()
# 2. transpiler omits _i8 annotation on the translations of certain
# string literals in places where the type can't be inferred.
sed['-i', '-e', r'/errno_str:/s/&\[\([0-9]\+\),/\&[\1i8,/',
'rust/src/strerror_override.rs']()
for refactor_args in REFACTORINGS:
print('REFACTOR: %r' % (refactor_args,))
run_refactor(refactor_args)
if __name__ == '__main__':
main()