-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.rs
163 lines (133 loc) · 4.63 KB
/
build.rs
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// build.rs
use std::env;
use std::fs;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use std::string::String;
// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
fn remove_whitespace(s: &mut String) {
s.retain(|c| !c.is_whitespace());
}
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("vsvc_gen.rs");
let mut output = String::new();
let mut handlers: Vec<String> = Vec::new();
let mut svcs: Vec<(String, String)> = Vec::new();
let mut ignore_commented = false;
if let Ok(lines) = read_lines("src/vm/vsvc.rs") {
for line_try in lines {
if let Ok(line) = line_try {
if line.contains("/*") {
ignore_commented = true;
}
if line.contains("*/") {
ignore_commented = false;
}
if ignore_commented { continue; }
if line.contains("impl") {
let split: Vec<&str> = line.split(' ').collect();
if split[1] != "SvcHandler" { continue; }
handlers.push(String::from(split[3]));
}
}
}
}
let mut found_enum = false;
if let Ok(lines) = read_lines("src/hos/svc.rs") {
for line_try in lines {
if let Ok(line) = line_try {
if line.contains("/*") {
ignore_commented = true;
}
if line.contains("*/") {
ignore_commented = false;
}
if ignore_commented { continue; }
if line.contains("enum HorizonSvc") {
found_enum = true;
}
if !found_enum { continue; }
if line.contains("}") {
found_enum = false;
}
let split: Vec<&str> = line.split('(').collect();
if split.len() < 2 { continue; }
let name = split[0];
let split2: Vec<&str> = split[1].split(')').collect();
let handler = split2[0];
let mut name_str = String::from(name);
remove_whitespace(&mut name_str);
if name_str.contains("//") || name_str.contains("/*") { continue; }
svcs.push((name_str, String::from(handler)));
}
}
}
for _handler in &handlers
{
let handler = &_handler;
output += "#[allow(non_snake_case)]\n";
output += "async fn _svc_shim_";
output += handler;
output += "(ctx: [u64; 32]) -> [u64; 32] {
let handler = ";
output += handler;
output += ";
return handler.handle(ctx).await;
}
";
}
output += "fn _svc_gen_pre(iss: u32, thread_ctx: u64, ctx: [u64; 32]) -> bool {
let svc = HorizonSvc::from_iss(iss);
let id = match svc {\n";
for _svc in &svcs
{
let svc = &_svc.0;
let handler = &_svc.1;
output += " HorizonSvc::";
output += svc;
output += "(_) => {";
if handler != "SvcDefaultHandler" {
output += "task_run_svc(thread_ctx, _svc_shim_";
output += handler;
output += "(ctx))";
}
else
{
output += "return true;";
}
output += "},\n";
}
output += " _ => {task_run_svc(thread_ctx, _svc_shim_SvcInvalid(ctx))},
};
return false;
}
";
fs::write(
&dest_path,
output
).unwrap();
output = String::new();
let dest_path = Path::new(&out_dir).join("svc_gen.rs");
for _handler in &handlers
{
let handler = &_handler;
output += "#[derive(Copy, Clone)]\n";
output += "pub struct ";
output += handler;
output += ";\n\n";
}
fs::write(
&dest_path,
output
).unwrap();
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/vm/vsvc.rs");
}