|
@@ -1,3 +1,4 @@
|
|
|
+use std::collections::HashMap;
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
use anyhow::Context;
|
|
@@ -17,6 +18,8 @@ fn main() {
|
|
|
fn generate() -> anyhow::Result<()> {
|
|
|
let mut output = String::new();
|
|
|
|
|
|
+ writeln!(output, "// Generated by JoltC-generate").unwrap();
|
|
|
+
|
|
|
for entry in WalkDir::new("JoltPhysics/Jolt") {
|
|
|
let entry = entry?;
|
|
|
let file_name = entry
|
|
@@ -25,61 +28,38 @@ fn generate() -> anyhow::Result<()> {
|
|
|
.context("invalid UTF-8 in file name")?;
|
|
|
|
|
|
if file_name.ends_with(".h") {
|
|
|
- println!("Processing {file_name}...");
|
|
|
+ eprintln!("Processing {file_name}...");
|
|
|
|
|
|
let header = fs::read_to_string(entry.path())?;
|
|
|
|
|
|
convert_enums(&header, &mut output);
|
|
|
- convert_classes(&header, &mut output);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- eprintln!();
|
|
|
- eprintln!();
|
|
|
- eprintln!();
|
|
|
- eprintln!("{output}");
|
|
|
+ println!("{output}");
|
|
|
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
-fn convert_classes(header: &str, output: &mut String) {
|
|
|
- let class = Regex::new(r"^\s*class\s*JPH_EXPORT\s*(\w+)").unwrap();
|
|
|
- let field = Regex::new(r"^([\w<>])").unwrap();
|
|
|
-
|
|
|
- struct WipClass {
|
|
|
- cpp_name: String,
|
|
|
- c_name: String,
|
|
|
- }
|
|
|
-
|
|
|
- let mut current_class = None;
|
|
|
-
|
|
|
- for line in header.lines() {
|
|
|
- if current_class.is_none() {
|
|
|
- if let Some(captures) = class.captures(line) {
|
|
|
- let name = &captures[1];
|
|
|
- println!("Found exported class: {name}");
|
|
|
-
|
|
|
- current_class = Some(WipClass {
|
|
|
- cpp_name: name.to_owned(),
|
|
|
- c_name: format!("{PREFIX}_{name}"),
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if let Some(current) = ¤t_class {}
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
fn convert_enums(header: &str, output: &mut String) {
|
|
|
struct WipEnum {
|
|
|
cpp_name: String,
|
|
|
c_name: String,
|
|
|
+ shouty_c_name: String,
|
|
|
+ next_value: u32,
|
|
|
+ num_variants: u32,
|
|
|
}
|
|
|
|
|
|
+ let enum_types: HashMap<&str, &str> = HashMap::from_iter([
|
|
|
+ ("int", "int"),
|
|
|
+ ("uint", "unsigned int"),
|
|
|
+ ("uint8", "uint8_t"),
|
|
|
+ ("uint16", "uint16_t"),
|
|
|
+ ("uint32", "uint32_t"),
|
|
|
+ ]);
|
|
|
+
|
|
|
let enum_class = Regex::new(r"^\s*enum\s+class\s+(\w+)(?:\s*:\s*(\w+))?").unwrap();
|
|
|
- let enum_member = Regex::new(r"^\s*(\w+)(?:\s*=\s*(.+?),)?").unwrap();
|
|
|
+ let enum_member = Regex::new(r"^\s*(\w+)(?:\s*=\s*(.+?)(?:,|/|$))?").unwrap();
|
|
|
let end_block = Regex::new(r"^\s*}").unwrap();
|
|
|
|
|
|
let mut current_enum = None;
|
|
@@ -88,24 +68,30 @@ fn convert_enums(header: &str, output: &mut String) {
|
|
|
if current_enum.is_none() {
|
|
|
if let Some(captures) = enum_class.captures(line) {
|
|
|
let mut name = &captures[1];
|
|
|
- let repr = captures.get(2).map(|m| m.as_str());
|
|
|
+ let given_repr = captures.get(2).map(|m| m.as_str()).unwrap_or("int");
|
|
|
+
|
|
|
+ let repr = enum_types
|
|
|
+ .get(given_repr)
|
|
|
+ .unwrap_or_else(|| panic!("unknown enum type {given_repr}"));
|
|
|
|
|
|
// EShapeSubType => ShapeSubType
|
|
|
if name.starts_with('E') && name.as_bytes()[1].is_ascii_uppercase() {
|
|
|
name = &name[1..];
|
|
|
}
|
|
|
|
|
|
- let c_name = format!("{PREFIX}_{}", AsShoutySnakeCase(name));
|
|
|
+ let c_name = format!("{PREFIX}_{}", name);
|
|
|
|
|
|
- if let Some(repr) = repr {
|
|
|
- writeln!(output, "typedef enum {c_name} : {repr} {{").unwrap();
|
|
|
- } else {
|
|
|
- writeln!(output, "typedef enum {c_name} {{").unwrap();
|
|
|
- }
|
|
|
+ let shouty_c_name =
|
|
|
+ format!("{}", AsShoutySnakeCase(&c_name)).replace("DO_FS", "DOFS");
|
|
|
+
|
|
|
+ writeln!(output, "typedef {repr} {c_name};").unwrap();
|
|
|
|
|
|
current_enum = Some(WipEnum {
|
|
|
cpp_name: name.to_owned(),
|
|
|
c_name,
|
|
|
+ shouty_c_name,
|
|
|
+ next_value: 0,
|
|
|
+ num_variants: 0,
|
|
|
});
|
|
|
|
|
|
continue;
|
|
@@ -114,24 +100,32 @@ fn convert_enums(header: &str, output: &mut String) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- if let Some(current) = ¤t_enum {
|
|
|
+ if let Some(current) = &mut current_enum {
|
|
|
if end_block.is_match(line) {
|
|
|
- writeln!(output, "}} {};", current.c_name).unwrap();
|
|
|
+ writeln!(output).unwrap();
|
|
|
+
|
|
|
current_enum = None;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if let Some(captures) = enum_member.captures(line) {
|
|
|
- let name = &captures[1];
|
|
|
- let value = captures.get(2).map(|m| m.as_str());
|
|
|
+ current.num_variants += 1;
|
|
|
|
|
|
- let c_name = format!("{}_{}", current.c_name, AsShoutySnakeCase(name));
|
|
|
+ let name = &captures[1];
|
|
|
+ let given_value = captures.get(2).map(|m| m.as_str().trim().to_string());
|
|
|
|
|
|
- if let Some(value) = value {
|
|
|
- writeln!(output, " {} = {value},", c_name).unwrap();
|
|
|
- } else {
|
|
|
- writeln!(output, " {},", c_name).unwrap();
|
|
|
+ if given_value.is_none() && current.num_variants > 1 && current.next_value == 0 {
|
|
|
+ panic!("Enum {} variant {name} did not have a value, but is set to use auto values", current.cpp_name);
|
|
|
}
|
|
|
+
|
|
|
+ let value = given_value.unwrap_or_else(|| {
|
|
|
+ let v = current.next_value;
|
|
|
+ current.next_value += 1;
|
|
|
+ v.to_string()
|
|
|
+ });
|
|
|
+
|
|
|
+ let c_name = format!("{}_{}", current.shouty_c_name, AsShoutySnakeCase(name));
|
|
|
+ writeln!(output, "static {} {c_name} = {value};", current.c_name).unwrap();
|
|
|
}
|
|
|
}
|
|
|
}
|