diff --git a/Cargo.lock b/Cargo.lock index c2b4b65..07d0508 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "bin2hpp" -version = "0.2.5" +version = "0.3.0" dependencies = [ "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 8baba5f..7a2eb9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bin2hpp" -version = "0.2.5" +version = "0.3.0" authors = ["Adam Macdonald"] edition = "2024" license = "GPL-3.0-only" diff --git a/README.md b/README.md index e196bd0..e301bfd 100644 --- a/README.md +++ b/README.md @@ -17,20 +17,35 @@ The performance (but potentially not the executable size) can be further optimis `$ bin2hpp -i my_library.dll -o c_header.h` will generate a `c_header.h` file in your current working directory containing something similar to the following: ```c -// Generated by bin2hpp 0.2.5 -#ifndef C_HEADER_H -#define C_HEADER_H +// Generated by bin2hpp 0.3.0 +#ifdef MY_LIBRARY_DLL_INIT #define MY_LIBRARY_DLL_LEN 9728 const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN] = {77,90,144,0,3,0,0,0,4, ...}; #else +#define MY_LIBRARY_DLL_LEN 9728 extern const unsigned char MY_LIBRARY_DLL[MY_LIBRARY_DLL_LEN]; #endif ``` +Note how in **C mode** one must `#define MY_LIBRARY_DLL_INIT`, or whatever the corresponding implementation macro is for your generated header file, in exactly _one_ C source file (`*.c`, not in a `*.h` file). + +Example: + +`main.c` +```c +// In any other C source files other than the first: do not redefine +#define MY_LIBRARY_DLL_INIT +#include "c_header.h" + +int main() { + return MY_LIBRARY_DLL_LEN; +} +``` + Alternatively, in **C++ mode**: `bin2hpp -i my_library.dll -o cpp_header.hpp --cpp --constexpr --stdarray --i8` ```cpp -// Generated by bin2hpp 0.2.5 +// Generated by bin2hpp 0.3.0 #if !defined(CPP_HEADER_HPP) #define CPP_HEADER_HPP #include diff --git a/src/cfg.rs b/src/cfg.rs index e7eb8dc..a28de8d 100644 --- a/src/cfg.rs +++ b/src/cfg.rs @@ -22,7 +22,8 @@ pub struct Config { pub(crate) constness: Constness, pub(crate) symbol_name: String, pub(crate) namespace: Option, - pub(crate) guard_name: String, + pub(crate) impl_macro: String, + pub(crate) header_guard: String, pub(crate) container_type: ContainerType, } @@ -56,6 +57,54 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result { + if s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') { + s.to_string() + } else { + return Err(ProgramConfigError::InvalidSymbolName(s.to_string())); + } + } + _ => { + let mut stem: String = match args.input_file_path.file_stem() { + Some(s) => s.to_string_lossy().to_string(), + None => { + return Err(ProgramConfigError::InvalidPath( + args.input_file_path.to_string_lossy().to_string(), + )); + } + }; + stem.retain(|c| c.is_ascii_alphanumeric() || c == '_'); + + let mut ext: String = match args.input_file_path.extension() { + Some(s) => format!("_{}", s.to_string_lossy()), + None => "".to_string(), + }; + ext.retain(|c| c.is_ascii_alphanumeric() || c == '_'); + + format!("{}{}", stem.to_ascii_uppercase(), ext.to_ascii_uppercase()) + } + }; + + let header_guard = match output_path.file_stem() { + Some(stem) => { + format!( + "{}_{}", + stem.to_string_lossy().to_uppercase(), + if let Some(ext) = output_path.extension() { + ext.to_string_lossy().to_uppercase() + } else { + "".into() + } + ) + } + None => { + return Err(ProgramConfigError::InvalidPath( + output_path.to_string_lossy().to_string(), + )); + } + }; + Ok(Config { input_file_path: args.input_file_path.clone(), output_file_path: output_path.clone(), @@ -67,34 +116,7 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result { - if s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') { - s.to_string() - } else { - return Err(ProgramConfigError::InvalidSymbolName(s.to_string())); - } - } - _ => { - let mut stem: String = match args.input_file_path.file_stem() { - Some(s) => s.to_string_lossy().to_string(), - None => { - return Err(ProgramConfigError::InvalidPath( - args.input_file_path.to_string_lossy().to_string(), - )); - } - }; - stem.retain(|c| c.is_ascii_alphanumeric() || c == '_'); - - let mut ext: String = match args.input_file_path.extension() { - Some(s) => format!("_{}", s.to_string_lossy()), - None => "".to_string(), - }; - ext.retain(|c| c.is_ascii_alphanumeric() || c == '_'); - - format!("{}{}", stem.to_ascii_uppercase(), ext.to_ascii_uppercase()) - } - }, + symbol_name: symbol_name.clone(), namespace: match &args.namespace { Some(ns) => { if ns.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') { @@ -105,7 +127,7 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result None, }, - guard_name: match &args.guard_name { + impl_macro: match &args.impl_macro_name { Some(guard) => { if guard.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') { guard.clone() @@ -114,29 +136,10 @@ pub fn parse_config_from_args(args: &CliArgs) -> Result { - let mut stem: String = match output_path.file_stem() { - Some(s) => s.to_string_lossy().to_ascii_uppercase(), - None => { - return Err(ProgramConfigError::InvalidPath( - args.input_file_path.to_string_lossy().to_string(), - )); - } - }; - stem.retain(|c| c.is_ascii_alphanumeric() || c == '_'); - - let mut ext: String = match output_path.extension() { - Some(s) => s.to_string_lossy().to_ascii_uppercase(), - None => { - return Err(ProgramConfigError::InvalidPath( - args.input_file_path.to_string_lossy().to_string(), - )); - } - }; - ext.retain(|c| c.is_ascii_alphanumeric() || c == '_'); - - format!("{}_{}", stem, ext) + format!("{}_INIT", symbol_name.to_uppercase()) } }, + header_guard: header_guard, container_type: args.container_type, }) } diff --git a/src/cli.rs b/src/cli.rs index c402ab7..bc64bcb 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -81,7 +81,7 @@ pub struct CliArgs { pub(crate) constness: Constness, pub(crate) symbol_name: Option, pub(crate) namespace: Option, - pub(crate) guard_name: Option, + pub(crate) impl_macro_name: Option, pub(crate) container_type: ContainerType, } @@ -123,10 +123,10 @@ pub fn parse_cli_args(args: &[String]) -> Result { None => None, }; - let guard_name = match args.iter().position(|s| *s == "--guard") { + let impl_macro_name = match args.iter().position(|s| *s == "--impl") { Some(idx) => match args.get(idx + 1) { Some(s) => Some(s), - None => return Err(CliParseError::MissingOperand("--guard")), + None => return Err(CliParseError::MissingOperand("--impl")), }, None => None, }; @@ -237,7 +237,7 @@ pub fn parse_cli_args(args: &[String]) -> Result { constness: constness, symbol_name: symbol_name.cloned(), namespace: namespace.cloned(), - guard_name: guard_name.cloned(), + impl_macro_name: impl_macro_name.cloned(), container_type: container_type, }); } diff --git a/src/constants.rs b/src/constants.rs index ed0e870..2fd55ca 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -28,8 +28,8 @@ OUTPUT OPTIONS: --symname NAME Symbol name --namespace NAME Namespace in which the symbol will exist (C++ mode) ---guard NAME Preprocessor macro to use for the header guard (#ifndef ...) - (default: derive from output filename) +--impl NAME Preprocessor macro to use for the implementation guard + in C mode (default: derive from symbol name) CONTAINER TYPES: diff --git a/src/generate.rs b/src/generate.rs index 8fea73b..3ffcf65 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -33,18 +33,17 @@ pub fn header(config: &Config, in_data: &[u8]) -> Result Result<(), HeaderGenerationError> { + with_includes(config, buf); + + let length: usize = match config.container_type { + ContainerType::CString => in_data.len() + 1, // +1 for NUL terminator + _ => in_data.len(), + }; + + write!( + buf, + "{}{}", + length_define(config, length), + config.line_ending + ) + .unwrap(); + if config.language == Language::Cpp { // C++ mode @@ -73,8 +87,17 @@ pub fn with_contents( // C mode with_definition(config, in_data, buf)?; + write!(buf, "#else{}", config.line_ending).unwrap(); + with_includes(config, buf); + write!( + buf, + "{}{}", + length_define(config, length), + config.line_ending + ) + .unwrap(); with_declaration(config, buf); } @@ -154,21 +177,8 @@ pub fn with_definition( in_data: &[u8], buf: &mut String, ) -> Result<(), HeaderGenerationError> { - let length: usize = match config.container_type { - ContainerType::CString => in_data.len() + 1, // +1 for NUL terminator - _ => in_data.len(), - }; - let modifiers = definition_modifiers(config); - write!( - buf, - "{}{}", - length_define(config, length), - config.line_ending - ) - .unwrap(); - write!( buf, "{}{} = {};{}",