From 0ba4d392285d5b17606408476fa699ac4901b80a Mon Sep 17 00:00:00 2001 From: Isaac Gelado Date: Fri, 27 Oct 2023 19:55:03 -0700 Subject: [PATCH 1/5] Add callback to modify contents of macro --- bindgen/callbacks.rs | 6 ++++++ bindgen/ir/var.rs | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs index cd7bb9773d..d2ef4f1245 100644 --- a/bindgen/callbacks.rs +++ b/bindgen/callbacks.rs @@ -4,6 +4,8 @@ pub use crate::ir::analysis::DeriveTrait; pub use crate::ir::derive::CanDerive as ImplementsTrait; pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue}; pub use crate::ir::int::IntKind; +pub use cexpr::token::Kind as TokenKind; +pub use cexpr::token::Token; use std::fmt; /// An enum to allow ignoring parsing of macros. @@ -49,6 +51,10 @@ pub trait ParseCallbacks: fmt::Debug { None } + /// Modify the contents of a macro + fn modify_macro(&self, _name: &str, _tokens: &mut Vec) { + } + /// The integer kind an integer macro should have, given a name and the /// value of that macro, or `None` if you want the default to be chosen. fn int_macro(&self, _name: &str, _value: i64) -> Option { diff --git a/bindgen/ir/var.rs b/bindgen/ir/var.rs index 85e127fdbc..19c454f06b 100644 --- a/bindgen/ir/var.rs +++ b/bindgen/ir/var.rs @@ -429,6 +429,10 @@ fn parse_macro( let cexpr_tokens = cursor.cexpr_tokens(); + if let Some(callbacks) = ctx.parse_callbacks() { + callbacks.modify_macro(cursor.spelling(), &mut cexpr_tokens); + } + let parser = expr::IdentifierParser::new(ctx.parsed_macros()); match parser.macro_definition(&cexpr_tokens) { From 5a9da9576e1271c49a5df022abf8639370b41479 Mon Sep 17 00:00:00 2001 From: Isaac Gelado Date: Fri, 27 Oct 2023 19:59:44 -0700 Subject: [PATCH 2/5] Use parse_callbacks from options --- bindgen/ir/var.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindgen/ir/var.rs b/bindgen/ir/var.rs index 19c454f06b..e227a772e7 100644 --- a/bindgen/ir/var.rs +++ b/bindgen/ir/var.rs @@ -429,7 +429,7 @@ fn parse_macro( let cexpr_tokens = cursor.cexpr_tokens(); - if let Some(callbacks) = ctx.parse_callbacks() { + if let Some(callbacks) = ctx.options.parse_callbacks() { callbacks.modify_macro(cursor.spelling(), &mut cexpr_tokens); } From 4df32237a9b751af28d7aa3c451c739b5c206829 Mon Sep 17 00:00:00 2001 From: Isaac Gelado Date: Fri, 27 Oct 2023 20:03:12 -0700 Subject: [PATCH 3/5] Use callbacks properly --- bindgen/ir/var.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bindgen/ir/var.rs b/bindgen/ir/var.rs index e227a772e7..45f4ba1ba0 100644 --- a/bindgen/ir/var.rs +++ b/bindgen/ir/var.rs @@ -427,10 +427,10 @@ fn parse_macro( ) -> Option<(Vec, cexpr::expr::EvalResult)> { use cexpr::expr; - let cexpr_tokens = cursor.cexpr_tokens(); + let mut cexpr_tokens = cursor.cexpr_tokens(); - if let Some(callbacks) = ctx.options.parse_callbacks() { - callbacks.modify_macro(cursor.spelling(), &mut cexpr_tokens); + for callbacks in &ctx.options().parse_callbacks { + callbacks.modify_macro(&cursor.spelling(), &mut cexpr_tokens); } let parser = expr::IdentifierParser::new(ctx.parsed_macros()); From aeb3af642c8570e7fb8b5516eb49e720b056dd74 Mon Sep 17 00:00:00 2001 From: Isaac Gelado Date: Fri, 23 May 2025 21:31:18 +0200 Subject: [PATCH 4/5] Add test --- bindgen-integration/build.rs | 50 +++++++++++++++++++++++++++++++--- bindgen-integration/cpp/Test.h | 2 ++ bindgen-integration/src/lib.rs | 6 ++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/bindgen-integration/build.rs b/bindgen-integration/build.rs index 583f46ea93..1c37448d77 100644 --- a/bindgen-integration/build.rs +++ b/bindgen-integration/build.rs @@ -1,7 +1,7 @@ extern crate bindgen; use bindgen::callbacks::{ - DeriveInfo, IntKind, MacroParsingBehavior, ParseCallbacks, + DeriveInfo, IntKind, MacroParsingBehavior, ParseCallbacks, Token, TokenKind, }; use bindgen::{Builder, EnumVariation, Formatter}; use std::collections::HashSet; @@ -44,9 +44,9 @@ impl ParseCallbacks for MacroCallback { assert_eq!(value, b"string"); *self.seen_hellos.lock().unwrap() += 1; } - "TESTMACRO_STRING_EXPANDED" | - "TESTMACRO_STRING" | - "TESTMACRO_INTEGER" => { + "TESTMACRO_STRING_EXPANDED" + | "TESTMACRO_STRING" + | "TESTMACRO_INTEGER" => { // The integer test macro is, actually, not expected to show up here at all -- but // should produce an error if it does. assert_eq!( @@ -145,6 +145,48 @@ impl ParseCallbacks for MacroCallback { vec![] } } + + fn modify_macro(&self, _name: &str, tokens: &mut Vec) { + // Handle macros dealing with bit positions of the format HI:LO + if tokens.len() == 4 && tokens[2].kind == TokenKind::Punctuation { + if let Ok(colon) = std::str::from_utf8(&tokens[2].raw) { + if colon != ":" { + return; + } + let high = match std::str::from_utf8(&tokens[1].raw) { + Ok(s) => { + if let Ok(val) = s.parse::() { + val + } else { + return; + } + } + Err(_) => { + return; + } + }; + + let low = match std::str::from_utf8(&tokens[3].raw) { + Ok(s) => { + if let Ok(val) = s.parse::() { + val + } else { + return; + } + } + Err(_) => { + return; + } + }; + let value: u32 = ((high as u32) << 16) | low as u32; + tokens[1] = Token::from(( + TokenKind::Literal, + value.to_string().as_bytes(), + )); + tokens.truncate(2); + } + } + } } impl Drop for MacroCallback { diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h index 81a921b5f8..7f71210cdd 100644 --- a/bindgen-integration/cpp/Test.h +++ b/bindgen-integration/cpp/Test.h @@ -22,6 +22,8 @@ #define TESTMACRO_STRING_EXPR ("string") #define TESTMACRO_STRING_FUNC_NON_UTF8(x) (x "ÿÿ") /* invalid UTF-8 on purpose */ +#define TESTMACRO_COLON_VALUE 1:2 + enum { MY_ANNOYING_MACRO = #define MY_ANNOYING_MACRO 1 diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 13f5bd889a..64f4926a8b 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -345,3 +345,9 @@ fn test_wrap_static_fns() { extern_bindings::wrap_as_variadic_fn2_wrapped(1, 2); } } + +#[test] +fn test_colon_define() { + let gold: u32 = (1u32 << 16) | 2; + assert_eq!(gold, bindings::TESTMACRO_COLON_VALUE); +} From 9746079243156de304353d16df466c9e764ba708 Mon Sep 17 00:00:00 2001 From: Isaac Gelado Date: Fri, 23 May 2025 21:54:20 +0200 Subject: [PATCH 5/5] Fix rustfmt errors --- bindgen-integration/build.rs | 6 +++--- bindgen/callbacks.rs | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/bindgen-integration/build.rs b/bindgen-integration/build.rs index 1c37448d77..0d8fa33c93 100644 --- a/bindgen-integration/build.rs +++ b/bindgen-integration/build.rs @@ -44,9 +44,9 @@ impl ParseCallbacks for MacroCallback { assert_eq!(value, b"string"); *self.seen_hellos.lock().unwrap() += 1; } - "TESTMACRO_STRING_EXPANDED" - | "TESTMACRO_STRING" - | "TESTMACRO_INTEGER" => { + "TESTMACRO_STRING_EXPANDED" | + "TESTMACRO_STRING" | + "TESTMACRO_INTEGER" => { // The integer test macro is, actually, not expected to show up here at all -- but // should produce an error if it does. assert_eq!( diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs index d2ef4f1245..f7f2f6cc9d 100644 --- a/bindgen/callbacks.rs +++ b/bindgen/callbacks.rs @@ -52,8 +52,7 @@ pub trait ParseCallbacks: fmt::Debug { } /// Modify the contents of a macro - fn modify_macro(&self, _name: &str, _tokens: &mut Vec) { - } + fn modify_macro(&self, _name: &str, _tokens: &mut Vec) {} /// The integer kind an integer macro should have, given a name and the /// value of that macro, or `None` if you want the default to be chosen.