Skip to content

Commit 38028cc

Browse files
committed
Interpolate path and name
1 parent d6a30c4 commit 38028cc

File tree

4 files changed

+89
-29
lines changed

4 files changed

+89
-29
lines changed

CHANGELOG-rust.md

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See
55

66
## [Unreleased]
77

8+
* Interpolate path and name in `description` and `derivedFrom`
9+
810
## [v0.3.12] 2024-03-23
911

1012
* `dimArrayIndex` support

src/patch/mod.rs

+64-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
pub mod patch_cli;
22

3+
use std::borrow::Cow;
34
use std::fs::File;
45
use std::io::{Read, Write};
56
use std::path::{Path, PathBuf};
7+
use svd_parser::expand::{BlockPath, FieldPath, RegisterPath};
68
use svd_parser::svd::{
79
addressblock::AddressBlockBuilder, interrupt::InterruptBuilder, Access, AddressBlock,
810
AddressBlockUsage, ClusterInfo, ClusterInfoBuilder, Cpu, CpuBuilder, Endian, EnumeratedValue,
@@ -462,10 +464,10 @@ fn modify_dim_element<T: Clone>(
462464
Ok(())
463465
}
464466

465-
fn make_field(fadd: &Hash) -> Result<FieldInfoBuilder> {
467+
fn make_field(fadd: &Hash, rpath: Option<&RegisterPath>) -> Result<FieldInfoBuilder> {
466468
let mut fnew = FieldInfo::builder()
467-
.description(fadd.get_string("description")?)
468-
.derived_from(fadd.get_string("derivedFrom")?)
469+
.description(opt_interpolate(&rpath, fadd.get_str("description")?))
470+
.derived_from(opt_interpolate(&rpath, fadd.get_str("derivedFrom")?))
469471
.access(fadd.get_str("access")?.and_then(Access::parse_str))
470472
.modified_write_values(
471473
fadd.get_str("modifiedWriteValues")?
@@ -493,11 +495,11 @@ fn make_field(fadd: &Hash) -> Result<FieldInfoBuilder> {
493495
Ok(fnew)
494496
}
495497

496-
fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
498+
fn make_register(radd: &Hash, path: Option<&BlockPath>) -> Result<RegisterInfoBuilder> {
497499
let mut rnew = RegisterInfo::builder()
498500
.display_name(radd.get_string("displayName")?)
499-
.description(radd.get_string("description")?)
500-
.derived_from(radd.get_string("derivedFrom")?)
501+
.description(opt_interpolate(&path, radd.get_str("description")?))
502+
.derived_from(opt_interpolate(&path, radd.get_str("derivedFrom")?))
501503
.alternate_group(radd.get_string("alternateGroup")?)
502504
.alternate_register(radd.get_string("alternateRegister")?)
503505
.properties(get_register_properties(radd)?)
@@ -506,7 +508,7 @@ fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
506508
let mut fields = Vec::new();
507509
for (fname, val) in h {
508510
fields.push(
509-
make_field(val.hash()?)?
511+
make_field(val.hash()?, None)?
510512
.name(fname.str()?.into())
511513
.build(VAL_LVL)?
512514
.single(),
@@ -552,18 +554,18 @@ fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
552554
Ok(rnew)
553555
}
554556

555-
fn make_cluster(cadd: &Hash) -> Result<ClusterInfoBuilder> {
557+
fn make_cluster(cadd: &Hash, path: Option<&BlockPath>) -> Result<ClusterInfoBuilder> {
556558
let mut cnew = ClusterInfo::builder()
557-
.description(cadd.get_string("description")?)
558-
.derived_from(cadd.get_string("derivedFrom")?)
559+
.description(opt_interpolate(&path, cadd.get_str("description")?))
560+
.derived_from(opt_interpolate(&path, cadd.get_str("derivedFrom")?))
559561
.default_register_properties(get_register_properties(cadd)?)
560562
.children(match cadd.get_hash("registers")? {
561563
Some(h) => {
562564
let mut ch = Vec::new();
563565
for (rname, val) in h {
564566
ch.push(RegisterCluster::Register({
565567
let radd = val.hash()?;
566-
let reg = make_register(radd)?
568+
let reg = make_register(radd, None)?
567569
.name(rname.str()?.into())
568570
.build(VAL_LVL)?;
569571
if let Some(dim) = make_dim_element(radd)? {
@@ -652,7 +654,7 @@ fn make_peripheral(padd: &Hash, modify: bool) -> Result<PeripheralInfoBuilder> {
652654
for (rname, val) in h.iter() {
653655
regs.push(RegisterCluster::Register({
654656
let radd = val.hash()?;
655-
let reg = make_register(radd)?
657+
let reg = make_register(radd, None)?
656658
.name(rname.str()?.into())
657659
.build(VAL_LVL)?;
658660
if let Some(dim) = make_dim_element(radd)? {
@@ -802,3 +804,53 @@ impl Spec for str {
802804
}
803805
}
804806
}
807+
808+
fn opt_interpolate<T: Interpolate>(path: &Option<&T>, s: Option<&str>) -> Option<String> {
809+
path.and_then(|path| path.interpolate_opt(s))
810+
}
811+
812+
trait Interpolate {
813+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str>;
814+
fn interpolate_opt(&self, s: Option<&str>) -> Option<String> {
815+
s.map(|s| self.interpolate(s).into_owned())
816+
}
817+
}
818+
819+
impl Interpolate for BlockPath {
820+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str> {
821+
let mut cow = Cow::Borrowed(s);
822+
if cow.contains("`peripheral`") {
823+
cow = cow.replace("`peripheral`", &self.peripheral).into()
824+
}
825+
if cow.contains("`block_path`") {
826+
cow = cow.replace("`block_path`", &self.to_string()).into()
827+
}
828+
cow
829+
}
830+
}
831+
832+
impl Interpolate for RegisterPath {
833+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str> {
834+
let mut cow = self.block.interpolate(s);
835+
if cow.contains("`register`") {
836+
cow = cow.replace("`register`", &self.name).into()
837+
}
838+
if cow.contains("`register_path`") {
839+
cow = cow.replace("`register_path`", &self.to_string()).into()
840+
}
841+
cow
842+
}
843+
}
844+
845+
impl Interpolate for FieldPath {
846+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str> {
847+
let mut cow = self.register().interpolate(s);
848+
if cow.contains("`field`") {
849+
cow = cow.replace("`field`", &self.name).into()
850+
}
851+
if cow.contains("`field_path`") {
852+
cow = cow.replace("`field_path`", &self.to_string()).into()
853+
}
854+
cow
855+
}
856+
}

src/patch/peripheral.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,9 @@ pub(crate) trait RegisterBlockExt: Name {
202202
));
203203
}
204204
self.add_child(RegisterCluster::Register({
205-
let reg = make_register(radd)?.name(rname.into()).build(VAL_LVL)?;
205+
let reg = make_register(radd, Some(bpath))?
206+
.name(rname.into())
207+
.build(VAL_LVL)?;
206208
if let Some(dim) = make_dim_element(radd)? {
207209
reg.array(dim.build(VAL_LVL)?)
208210
} else {
@@ -221,7 +223,9 @@ pub(crate) trait RegisterBlockExt: Name {
221223
));
222224
}
223225
self.add_child(RegisterCluster::Cluster({
224-
let cl = make_cluster(cadd)?.name(cname.into()).build(VAL_LVL)?;
226+
let cl = make_cluster(cadd, Some(bpath))?
227+
.name(cname.into())
228+
.build(VAL_LVL)?;
225229
if let Some(dim) = make_dim_element(cadd)? {
226230
cl.array(dim.build(VAL_LVL)?)
227231
} else {
@@ -245,7 +249,7 @@ pub(crate) trait RegisterBlockExt: Name {
245249
})?;
246250
(
247251
rderive,
248-
make_register(hash)?.derived_from(Some(rderive.into())),
252+
make_register(hash, Some(bpath))?.derived_from(Some(rderive.into())),
249253
)
250254
} else {
251255
return Err(anyhow!("derive: incorrect syntax for {rname}"));
@@ -295,7 +299,7 @@ pub(crate) trait RegisterBlockExt: Name {
295299
)
296300
})?
297301
.clone();
298-
let fixes = make_register(rcopy)?
302+
let fixes = make_register(rcopy, Some(bpath))?
299303
.name(rname.into())
300304
.display_name(Some("".into()));
301305
// Modifying fields in derived register not implemented
@@ -325,10 +329,10 @@ pub(crate) trait RegisterBlockExt: Name {
325329
"Could not find `{bpath}:{rcspec}. Present registers: {present}.`"
326330
))
327331
} else {
328-
modify_cluster(ctags, rcmod)
332+
modify_cluster(ctags, rcmod, bpath)
329333
}
330334
} else {
331-
modify_register(rtags, rcmod)
335+
modify_register(rtags, rcmod, bpath)
332336
}
333337
}
334338

@@ -342,7 +346,7 @@ pub(crate) trait RegisterBlockExt: Name {
342346
"Could not find `{bpath}:{rspec}. Present registers: {present}.`"
343347
));
344348
}
345-
modify_register(rtags, rmod)
349+
modify_register(rtags, rmod, bpath)
346350
}
347351

348352
/// Modify cspec inside ptag according to cmod
@@ -355,7 +359,7 @@ pub(crate) trait RegisterBlockExt: Name {
355359
"Could not find cluster `{bpath}:{cspec}. Present clusters: {present}.`"
356360
));
357361
}
358-
modify_cluster(ctags, cmod)
362+
modify_cluster(ctags, cmod, bpath)
359363
}
360364
/// Work through a register or cluster
361365
fn process_child(
@@ -553,8 +557,8 @@ pub(crate) trait RegisterBlockExt: Name {
553557
}
554558
}
555559

556-
fn modify_register(rtags: Vec<&mut Register>, rmod: &Hash) -> PatchResult {
557-
let register_builder = make_register(rmod)?;
560+
fn modify_register(rtags: Vec<&mut Register>, rmod: &Hash, bpath: &BlockPath) -> PatchResult {
561+
let register_builder = make_register(rmod, Some(bpath))?;
558562
let dim = make_dim_element(rmod)?;
559563
for rtag in rtags {
560564
modify_dim_element(rtag, &dim)?;
@@ -566,8 +570,8 @@ fn modify_register(rtags: Vec<&mut Register>, rmod: &Hash) -> PatchResult {
566570
Ok(())
567571
}
568572

569-
fn modify_cluster(ctags: Vec<&mut Cluster>, cmod: &Hash) -> PatchResult {
570-
let cluster_builder = make_cluster(cmod)?;
573+
fn modify_cluster(ctags: Vec<&mut Cluster>, cmod: &Hash, bpath: &BlockPath) -> PatchResult {
574+
let cluster_builder = make_cluster(cmod, Some(bpath))?;
571575
let dim = make_dim_element(cmod)?;
572576
for ctag in ctags {
573577
modify_dim_element(ctag, &dim)?;

src/patch/register.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub trait RegisterExt {
110110
fn strip_end(&mut self, substr: &str) -> PatchResult;
111111

112112
/// Modify fspec inside rtag according to fmod
113-
fn modify_field(&mut self, fspec: &str, fmod: &Hash) -> PatchResult;
113+
fn modify_field(&mut self, fspec: &str, fmod: &Hash, rpath: &RegisterPath) -> PatchResult;
114114

115115
/// Merge all fspec in rtag.
116116
/// Support list of field to auto-merge, and dict with fspec or list of fspec
@@ -175,7 +175,7 @@ impl RegisterExt for Register {
175175
// Handle modifications
176176
for (fspec, fmod) in rmod.hash_iter("_modify") {
177177
let fspec = fspec.str()?;
178-
self.modify_field(fspec, fmod.hash()?)
178+
self.modify_field(fspec, fmod.hash()?, &rpath)
179179
.with_context(|| format!("Modifying fields matched to `{fspec}`"))?;
180180
}
181181
// Handle additions
@@ -268,9 +268,9 @@ impl RegisterExt for Register {
268268
Ok(())
269269
}
270270

271-
fn modify_field(&mut self, fspec: &str, fmod: &Hash) -> PatchResult {
271+
fn modify_field(&mut self, fspec: &str, fmod: &Hash, rpath: &RegisterPath) -> PatchResult {
272272
let ftags = self.iter_fields(fspec).collect::<Vec<_>>();
273-
let field_builder = make_field(fmod)?;
273+
let field_builder = make_field(fmod, Some(rpath))?;
274274
let dim = make_dim_element(fmod)?;
275275
if !ftags.is_empty() {
276276
for ftag in ftags {
@@ -313,7 +313,9 @@ impl RegisterExt for Register {
313313
if self.get_field(fname).is_some() {
314314
return Err(anyhow!("register {rpath} already has a field {fname}"));
315315
}
316-
let fnew = make_field(fadd)?.name(fname.into()).build(VAL_LVL)?;
316+
let fnew = make_field(fadd, Some(rpath))?
317+
.name(fname.into())
318+
.build(VAL_LVL)?;
317319
let fnew = if let Some(dim) = make_dim_element(fadd)? {
318320
fnew.array(dim.build(VAL_LVL)?)
319321
} else {

0 commit comments

Comments
 (0)