import subprocess
import os
import re
import argparse
LBFGSB_C_FILES = [
"driver1.rs",
"driver2.rs",
"driver3.rs",
"linesearch.rs",
"miniCBLAS.rs",
"subalgorithms.rs",
"lbfgsb.rs",
"linpack.rs",
"print.rs",
"timer.rs"
]
p_sizeof = re.compile(r'(.*)(std::mem::size_of::)(.*)(as u64)(.*)')
def massage_line(line):
line = line.rstrip()
if line == "#![register_tool(c2rust)]":
return ""
if line == "use core::arch::asm;":
return ""
if line.startswith("#![feature("):
return ""
if line.startswith("#![allow("):
return ""
line = line.replace("std::os::raw::c_int", "i32")
line = line.replace("std::os::raw::c_ulonglong", "u64")
line = line.replace("std::os::raw::c_longlong", "i64")
line = line.replace("std::os::raw::c_uint", "u32")
line = line.replace("std::os::raw::c_char", "u8")
line = line.replace("std::os::raw::c_uchar", "u8")
line = line.replace("std::os::raw::c_schar", "i8")
line = line.replace("std::os::raw::c_void", "u8")
line = line.replace("::std::mem::transmute", "core::mem::transmute")
line = line.replace("libc::c_char", "core::ffi::c_char")
line = line.replace("libc::c_schar", "core::ffi::c_schar")
line = line.replace("libc::c_uchar", "core::ffi::c_uchar")
line = line.replace("libc::c_int", "core::ffi::c_int")
line = line.replace("libc::c_uint", "core::ffi::c_uint")
line = line.replace("libc::c_double", "f64")
line = line.replace("libc::c_ulonglong", "u64")
line = line.replace("libc::c_longlong", "i64")
line = line.replace("libc::c_ulong", "u32") line = line.replace("libc::c_long", "i32")
line = line.replace("libc::c_void", "core::ffi::c_void")
line = line.replace("::std::mem::size_of", "core::mem::size_of")
line = line.replace("::std::vec::", "alloc::vec::")
line = line.replace(": Vec::", ": alloc::vec::Vec::")
line = line.replace("use std::arch::asm;", "")
if p_sizeof.search(line):
line = p_sizeof.sub(r'\g<1>\g<2>\g<3>as u32\g<5>', line)
compiler_fence = (
"core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);"
)
line = line.replace(
'asm!("", inlateout(reg) a, options(preserves_flags, pure, readonly));',
compiler_fence,
)
return line
def lint():
build = subprocess.run(
["rustup", "run", "nightly", "cargo", "build", "--target=aarch64-apple-darwin"],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
state = "SEARCHING"
subs = {}
warntype = ""
token = ""
p_token = re.compile(r'(.*)`(.*)`(.*)')
p_line = re.compile(r'(.*)--> (.*):([0-9]*):([0-9]*)')
for line in build.stdout.decode('utf8').split('\n'):
if line.startswith("warning:"):
if "value assigned to" in line and "is never read":
warntype = "unused init"
token = p_token.search(line).group(2)
state = "FOUND"
elif "unused variable" in line:
warntype = "unused variable"
token = p_token.search(line).group(2)
state = "FOUND"
elif "variable does not need to be mutable" in line:
warntype = "remove mut"
token = 'mut'
state = "FOUND"
elif "function" in line and "is never used in line":
warntype = "unused func"
token = p_token.search(line).group(2)
state = "FOUND"
else:
state = "SEARCHING"
pass
if state == "FOUND":
p = p_line.search(line)
if p:
fname = p.group(2)
fline = int(p.group(3))
fcol = int(p.group(4))
if fname in subs:
subs[fname][fline] = [warntype, token, fcol]
else:
subs[fname] = {fline: [warntype, token, fcol]}
state = "SEARCHING"
warntype = ""
for fname in subs.keys():
if 'src' in fname:
with open(fname, "r") as src_file:
sfile = src_file.readlines()
with open(fname, "w") as dst_file:
line_no = 1
for line in sfile:
if line_no in subs[fname]:
warn = subs[fname][line_no]
if "unused init" in warn[0]:
if " = 0" in line:
line = line.replace(" = 0", "")
else:
line = line[:warn[2] - 1] + 'let _' + line[warn[2] - 1:]
elif "unused variable" in warn[0]:
line = line[:warn[2]-1] + '_' + line[warn[2]-1:]
elif "remove mut":
line = line[:warn[2]-1] + line[warn[2]+3:]
elif "unused func":
line = line[:warn[2]-1] + '_' + line[warn[2]-1:]
else:
print("TODO: {}".format(subs[fname][line_no]))
line_no += 1
print(line, file=dst_file, end="")
def process_files(source_directory):
for file in LBFGSB_C_FILES:
rs_file = source_directory + "/" + file
mod_name = file.split(".")[0]
print(f" pub mod {mod_name};")
with open(rs_file, "r") as src_file:
with open(f"{mod_name}.rs", "w") as dest_file:
for line in src_file:
print(massage_line(line), file=dest_file)
def main():
parser = argparse.ArgumentParser(description="A simple script to lint and/or massage files in a source directory.")
parser.add_argument('-l', '--lint', action='store_true', help="Flag to lint the files.")
parser.add_argument('-d', '--source_directory', type=str, required=True, help="The source directory to lint.")
parser.add_argument('-m', '--massage_line', action='store_true', help="Flag to massage each line of the files.")
args = parser.parse_args()
if args.lint:
lint()
if args.massage_line:
process_files(args.source_directory)
elif not args.lint:
print("No action specified. Use -l for linting or -m for massage.")
if __name__ == "__main__":
main()