diff --git a/CHANGELOG-rust.md b/CHANGELOG-rust.md index fef93507..70cfb5a7 100644 --- a/CHANGELOG-rust.md +++ b/CHANGELOG-rust.md @@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See ## [Unreleased] +* `regex` replacements for descriptions during `_modify` + ## [v0.3.19] 2024-10-18 * Fix deletion childrens on cluster modify diff --git a/src/patch/device.rs b/src/patch/device.rs index 2ed3ed89..27dfb5f1 100644 --- a/src/patch/device.rs +++ b/src/patch/device.rs @@ -9,7 +9,7 @@ use std::{fs::File, io::Read, path::Path}; use super::iterators::{MatchIter, Matched}; use super::peripheral::{PeripheralExt, RegisterBlockExt}; use super::yaml_ext::{AsType, GetVal}; -use super::{abspath, matchname, Config, PatchResult, Spec, VAL_LVL}; +use super::{abspath, do_replacements, matchname, Config, PatchResult, Spec, VAL_LVL}; use super::{make_address_block, make_address_blocks, make_cpu, make_interrupt, make_peripheral}; use super::{make_dim_element, modify_dim_element, modify_register_properties}; @@ -255,6 +255,10 @@ impl DeviceExt for Device { modify_dim_element(ptag, &dim)?; ptag.modify_from(peripheral_builder.clone(), VAL_LVL)?; + if let Ok(Some(h)) = pmod.get_hash("description") { + ptag.description = + Some(do_replacements(ptag.description.as_deref().unwrap_or(""), h)?.into()); + } if let Some(ints) = pmod.get_hash("interrupts")? { for (iname, val) in ints { let iname = iname.str()?; diff --git a/src/patch/mod.rs b/src/patch/mod.rs index 36eae12c..c1b2b231 100644 --- a/src/patch/mod.rs +++ b/src/patch/mod.rs @@ -1,5 +1,6 @@ pub mod patch_cli; +use regex::Regex; use std::borrow::Cow; use std::fs::File; use std::io::{Read, Write}; @@ -476,7 +477,10 @@ fn modify_dim_element( fn make_field(fadd: &Hash, rpath: Option<&RegisterPath>) -> Result { let mut fnew = FieldInfo::builder() - .description(opt_interpolate(&rpath, fadd.get_str("description")?)) + .description(opt_interpolate( + &rpath, + fadd.get_str("description").unwrap_or(None), + )) .derived_from(opt_interpolate(&rpath, fadd.get_str("derivedFrom")?)) .access(fadd.get_str("access")?.and_then(Access::parse_str)) .modified_write_values( @@ -509,7 +513,10 @@ fn make_field(fadd: &Hash, rpath: Option<&RegisterPath>) -> Result) -> Result { let mut rnew = RegisterInfo::builder() .display_name(radd.get_string("displayName")?) - .description(opt_interpolate(&path, radd.get_str("description")?)) + .description(opt_interpolate( + &path, + radd.get_str("description").unwrap_or(None), + )) .derived_from(opt_interpolate(&path, radd.get_str("derivedFrom")?)) .alternate_group(radd.get_string("alternateGroup")?) .alternate_register(radd.get_string("alternateRegister")?) @@ -576,7 +583,10 @@ fn get_write_constraint(h: &Hash) -> Result> { fn make_cluster(cadd: &Hash, path: Option<&BlockPath>) -> Result { let mut cnew = ClusterInfo::builder() - .description(opt_interpolate(&path, cadd.get_str("description")?)) + .description(opt_interpolate( + &path, + cadd.get_str("description").unwrap_or(None), + )) .derived_from(opt_interpolate(&path, cadd.get_str("derivedFrom")?)) .default_register_properties(get_register_properties(cadd)?); @@ -622,7 +632,7 @@ fn make_peripheral(padd: &Hash, modify: bool) -> Result { let mut pnew = PeripheralInfo::builder() .display_name(padd.get_string("displayName")?) .version(padd.get_string("version")?) - .description(padd.get_string("description")?) + .description(padd.get_string("description").unwrap_or(None)) .derived_from(padd.get_string("derivedFrom")?) .group_name(padd.get_string("groupName")?) .interrupt(if !modify { @@ -767,6 +777,30 @@ fn check_offsets(offsets: &[u32], dim_increment: u32) -> bool { true } +fn do_replacements<'a>(s: &'a str, h: &Hash) -> Result> { + let mut curr = Cow::Borrowed(s); + for (pat, rep) in h { + let pat = pat.str()?; + let re = Regex::new(pat).unwrap(); + match rep { + Yaml::String(rep) => { + curr = re.replace_all(curr.as_ref(), rep).to_string().into(); + } + Yaml::Array(v) if v.len() == 2 => { + let n = v[0].i64()?; + let rep = v[1].str()?; + curr = re.replacen(curr.as_ref(), n as _, rep).to_string().into(); + } + _ => { + return Err(anyhow!( + "Replacer should be string or number of replacements and string" + )) + } + } + } + Ok(curr) +} + /// Tries to get common description (or displayNames) for register/field array with "%s" in index position. /// Returns `None` if incoming descriptions have more then 1 difference fn common_description(descs: &[Option<&str>], dim_index: &[String]) -> Option> { diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index a5f8cd4a..3761095e 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Context, Ok}; +use anyhow::{anyhow, Context}; use itertools::Itertools; use svd::Name; use svd_parser::expand::BlockPath; @@ -12,7 +12,7 @@ use super::iterators::{MatchIter, Matched}; use super::register::{RegisterExt, RegisterInfoExt}; use super::yaml_ext::{AsType, GetVal, ToYaml}; use super::{ - check_offsets, common_description, make_dim_element, matchname, matchsubspec, + check_offsets, common_description, do_replacements, make_dim_element, matchname, matchsubspec, modify_dim_element, spec_ind, Config, PatchResult, Spec, VAL_LVL, }; use super::{make_cluster, make_interrupt, make_register}; @@ -843,6 +843,10 @@ fn modify_register(rtags: Vec<&mut Register>, rmod: &Hash, bpath: &BlockPath) -> for rtag in rtags { modify_dim_element(rtag, &dim)?; rtag.modify_from(register_builder.clone(), VAL_LVL)?; + if let Ok(Some(h)) = rmod.get_hash("description") { + rtag.description = + Some(do_replacements(rtag.description.as_deref().unwrap_or(""), h)?.into()); + } if let Some("") = rmod.get_str("access")? { rtag.properties.access = None; } @@ -856,6 +860,10 @@ fn modify_cluster(ctags: Vec<&mut Cluster>, cmod: &Hash, bpath: &BlockPath) -> P for ctag in ctags { modify_dim_element(ctag, &dim)?; ctag.modify_from(cluster_builder.clone(), VAL_LVL)?; + if let Ok(Some(h)) = cmod.get_hash("description") { + ctag.description = + Some(do_replacements(ctag.description.as_deref().unwrap_or(""), h)?.into()); + } } Ok(()) } diff --git a/src/patch/register.rs b/src/patch/register.rs index a2883484..f4f88071 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -14,8 +14,8 @@ use crate::patch::EnumAutoDerive; use super::iterators::{MatchIter, Matched}; use super::yaml_ext::{AsType, GetVal, ToYaml}; use super::{ - check_offsets, common_description, make_dim_element, matchname, modify_dim_element, spec_ind, - Config, PatchResult, Spec, VAL_LVL, + check_offsets, common_description, do_replacements, make_dim_element, matchname, + modify_dim_element, spec_ind, Config, PatchResult, Spec, VAL_LVL, }; use super::{make_derived_enumerated_values, make_ev_array, make_ev_name, make_field}; @@ -311,6 +311,10 @@ impl RegisterExt for Register { } // For all other tags, just set the value ftag.modify_from(field_builder.clone(), VAL_LVL)?; + if let Ok(Some(h)) = fmod.get_hash("description") { + ftag.description = + Some(do_replacements(ftag.description.as_deref().unwrap_or(""), h)?.into()); + } if let Some("") = fmod.get_str("access")? { ftag.access = None; }