From 06fe031dffd1e37920ae94a5d4c66e8a876da687 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 9 Nov 2024 16:04:34 +0000 Subject: [PATCH] preprocessor: prevent usage of unsupported macros --- libs/preprocessor/README.md | 31 -------------- libs/preprocessor/src/codes/pe25_exec.rs | 10 +---- .../src/codes/pe26_unsupported_builtin.rs | 42 +++++++++++++++++++ libs/preprocessor/src/defines.rs | 15 +++++-- libs/preprocessor/src/processor/mod.rs | 5 ++- libs/preprocessor/tests/errors.rs | 1 + .../pe26_unsupported_builtin/source.hpp | 3 ++ .../pe26_unsupported_builtin/stderr.ansi | 9 ++++ 8 files changed, 73 insertions(+), 43 deletions(-) delete mode 100644 libs/preprocessor/README.md create mode 100644 libs/preprocessor/src/codes/pe26_unsupported_builtin.rs create mode 100644 libs/preprocessor/tests/errors/pe26_unsupported_builtin/source.hpp create mode 100644 libs/preprocessor/tests/errors/pe26_unsupported_builtin/stderr.ansi diff --git a/libs/preprocessor/README.md b/libs/preprocessor/README.md deleted file mode 100644 index 9b53708d..00000000 --- a/libs/preprocessor/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Preprocessor - -## Differences from BI Preprocessor - -- The following built-in macros are not supported: - - `__has_include()` - - `__GAME_VER__` - - `__GAME_VER_MAJ__` - - `__GAME_VER_MIN__` - - `__GAME_BUILD__` - - `__A3_DEBUG__` - - `__EXEC()` - - `__EVAL()` - -- Tabs after `#define` are ignored. - - ```cpp - #define EXAMPLE 1 - ``` - - BI: - - ```cpp - value = 1; - ``` - - HEMTT: - - ```cpp - value = 1; - ``` diff --git a/libs/preprocessor/src/codes/pe25_exec.rs b/libs/preprocessor/src/codes/pe25_exec.rs index 0b6cbbe5..5bce07d4 100644 --- a/libs/preprocessor/src/codes/pe25_exec.rs +++ b/libs/preprocessor/src/codes/pe25_exec.rs @@ -5,15 +5,9 @@ use hemtt_workspace::reporting::{Code, Token}; use crate::Error; #[allow(unused)] -/// The EOI was reached while reading an `#if` [`IfState`] -/// -/// ```cpp -/// #if 1 -/// #else -/// EOI -/// ``` +/// __EXEC is not a supported macro pub struct ExecNotSupported { - /// The [`Token`] of the last `#if` + /// The [`Token`] of the __EXEC macro token: Box, } diff --git a/libs/preprocessor/src/codes/pe26_unsupported_builtin.rs b/libs/preprocessor/src/codes/pe26_unsupported_builtin.rs new file mode 100644 index 00000000..5b70c040 --- /dev/null +++ b/libs/preprocessor/src/codes/pe26_unsupported_builtin.rs @@ -0,0 +1,42 @@ +use std::sync::Arc; + +use hemtt_workspace::reporting::{Code, Token}; + +use crate::Error; + +#[allow(unused)] +/// Built-in macro is not supported by HEMTT +pub struct BuiltInNotSupported { + /// The [`Token`] of the built-in macro + token: Box, +} + +impl Code for BuiltInNotSupported { + fn ident(&self) -> &'static str { + "PE26" + } + + fn token(&self) -> Option<&Token> { + Some(&self.token) + } + + fn message(&self) -> String { + format!("built-in macro `{}` is not supported by HEMTT", self.token.symbol()) + } + + fn note(&self) -> Option { + Some("certain built-in macros can not be rapified at build time\nHEMTT does not support them to prevent unexpected behaviour".to_string()) + } +} + +impl BuiltInNotSupported { + #[must_use] + pub const fn new(token: Box) -> Self { + Self { token } + } + + #[must_use] + pub fn code(token: Token) -> Error { + Error::Code(Arc::new(Self::new(Box::new(token)))) + } +} diff --git a/libs/preprocessor/src/defines.rs b/libs/preprocessor/src/defines.rs index f537de16..ed251911 100644 --- a/libs/preprocessor/src/defines.rs +++ b/libs/preprocessor/src/defines.rs @@ -23,7 +23,6 @@ type InnerDefines = HashMap, (Arc, Definition, DefineSource)>; pub struct Defines { global: InnerDefines, stack: Vec<(Arc, InnerDefines)>, - counter: u16, } @@ -40,14 +39,20 @@ const BUILTIN_GEN: [&str; 6] = [ "__LINE__", ]; +/// Built-in macros that HEMTT supports, special cases +const BUILTIN_SPECIAL: [&str; 1] = ["__EVAL"]; + /// Built-in macros that HEMTT intentionally does not support -const BUILTIN_PROTEST: [&str; 16] = [ +const BUILTIN_PROTEST: [&str; 18] = [ "__DATE_ARR__", "__DATE_STR__", "__DATE_STR_ISO8601__", "__TIME__", "__TIME_UTC__", "__TIMESTAMP_UTC__", + "__DAY__", + "__MONTH__", + "__YEAR__", "__RAND_INT*__", "__RAND_UINT*__", "__GAME_VER__", @@ -57,16 +62,20 @@ const BUILTIN_PROTEST: [&str; 16] = [ "__A3_DIAG__", "__A3_DEBUG__", "__EXEC", - "__EVAL", ]; impl Defines { pub fn is_builtin(key: &str) -> bool { BUILTIN_GEN.contains(&key) + || BUILTIN_SPECIAL.contains(&key) || BUILTIN_PROTEST.contains(&key) || BUILTIN_CONST.iter().any(|(k, _)| *k == key) } + pub fn is_unsupported_builtin(key: &str) -> bool { + BUILTIN_PROTEST.contains(&key) + } + pub fn contains_key(&self, key: &str) -> bool { if BUILTIN_GEN.contains(&key) { return true; diff --git a/libs/preprocessor/src/processor/mod.rs b/libs/preprocessor/src/processor/mod.rs index df8264a8..5ced1802 100644 --- a/libs/preprocessor/src/processor/mod.rs +++ b/libs/preprocessor/src/processor/mod.rs @@ -8,7 +8,7 @@ use hemtt_workspace::{ }; use peekmore::{PeekMore, PeekMoreIterator}; -use crate::codes::pe2_unexpected_eof::UnexpectedEOF; +use crate::codes::{pe26_unsupported_builtin::BuiltInNotSupported, pe2_unexpected_eof::UnexpectedEOF}; use crate::codes::pe3_expected_ident::ExpectedIdent; use crate::codes::pw2_invalid_config_case::InvalidConfigCase; use crate::codes::{pe18_eoi_ifstate::EoiIfState, pe25_exec::ExecNotSupported}; @@ -154,6 +154,9 @@ impl Processor { if w == "__EXEC" { return Err(ExecNotSupported::code((**token).clone())); } + if Defines::is_unsupported_builtin(w) { + return Err(BuiltInNotSupported::code((**token).clone())); + } just_whitespace = false; if Some(w.as_str()) != in_macro && self.defines.contains_key(w) { let token = token.clone(); diff --git a/libs/preprocessor/tests/errors.rs b/libs/preprocessor/tests/errors.rs index 3c6e52a0..80dace4f 100644 --- a/libs/preprocessor/tests/errors.rs +++ b/libs/preprocessor/tests/errors.rs @@ -78,3 +78,4 @@ bootstrap!(pe22_pragma_invalid_flag); bootstrap!(pe23_if_has_include); bootstrap!(pe24_parsing_failed); bootstrap!(pe25_exec); +bootstrap!(pe26_unsupported_builtin); diff --git a/libs/preprocessor/tests/errors/pe26_unsupported_builtin/source.hpp b/libs/preprocessor/tests/errors/pe26_unsupported_builtin/source.hpp new file mode 100644 index 00000000..0c81bdb7 --- /dev/null +++ b/libs/preprocessor/tests/errors/pe26_unsupported_builtin/source.hpp @@ -0,0 +1,3 @@ +class Date { + day = __DAY__; +}; diff --git a/libs/preprocessor/tests/errors/pe26_unsupported_builtin/stderr.ansi b/libs/preprocessor/tests/errors/pe26_unsupported_builtin/stderr.ansi new file mode 100644 index 00000000..f2e6cbff --- /dev/null +++ b/libs/preprocessor/tests/errors/pe26_unsupported_builtin/stderr.ansi @@ -0,0 +1,9 @@ +error[PE26]: built-in macro `__DAY__` is not supported by HEMTT + ┌─ source.hpp:2:11 + │ +2 │ day = __DAY__; + │ ^^^^^^^ built-in macro `__DAY__` is not supported by HEMTT + │ + = note: certain built-in macros can not be rapified at build time + HEMTT does not support them to prevent unexpected behaviour +