Skip to content

Commit a29973c

Browse files
committed
Interpolate path and name
1 parent b6fb516 commit a29973c

File tree

4 files changed

+88
-29
lines changed

4 files changed

+88
-29
lines changed

CHANGELOG-rust.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This changelog tracks the Rust `svdtools` project. See
1010
* Refactor `RegisterBlockExt`, use `BlockPath` for better errors
1111
* Allow specs started with `_`
1212
* Allow process, `_delete` and `_modify` cluster without `_clusters` specifier
13+
* Interpolate path and name in `description` and `derivedFrom`
1314

1415
## [v0.3.11] 2024-03-06
1516

src/patch/mod.rs

Lines changed: 64 additions & 12 deletions
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,
@@ -429,10 +431,10 @@ fn modify_dim_element<T: Clone>(
429431
Ok(())
430432
}
431433

432-
fn make_field(fadd: &Hash) -> Result<FieldInfoBuilder> {
434+
fn make_field(fadd: &Hash, rpath: Option<&RegisterPath>) -> Result<FieldInfoBuilder> {
433435
let mut fnew = FieldInfo::builder()
434-
.description(fadd.get_string("description")?)
435-
.derived_from(fadd.get_string("derivedFrom")?)
436+
.description(opt_interpolate(&rpath, fadd.get_str("description")?))
437+
.derived_from(opt_interpolate(&rpath, fadd.get_str("derivedFrom")?))
436438
.access(fadd.get_str("access")?.and_then(Access::parse_str))
437439
.modified_write_values(
438440
fadd.get_str("modifiedWriteValues")?
@@ -460,11 +462,11 @@ fn make_field(fadd: &Hash) -> Result<FieldInfoBuilder> {
460462
Ok(fnew)
461463
}
462464

463-
fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
465+
fn make_register(radd: &Hash, path: Option<&BlockPath>) -> Result<RegisterInfoBuilder> {
464466
let mut rnew = RegisterInfo::builder()
465467
.display_name(radd.get_string("displayName")?)
466-
.description(radd.get_string("description")?)
467-
.derived_from(radd.get_string("derivedFrom")?)
468+
.description(opt_interpolate(&path, radd.get_str("description")?))
469+
.derived_from(opt_interpolate(&path, radd.get_str("derivedFrom")?))
468470
.alternate_group(radd.get_string("alternateGroup")?)
469471
.alternate_register(radd.get_string("alternateRegister")?)
470472
.properties(get_register_properties(radd)?)
@@ -473,7 +475,7 @@ fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
473475
let mut fields = Vec::new();
474476
for (fname, val) in h {
475477
fields.push(
476-
make_field(val.hash()?)?
478+
make_field(val.hash()?, None)?
477479
.name(fname.str()?.into())
478480
.build(VAL_LVL)?
479481
.single(),
@@ -519,18 +521,18 @@ fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
519521
Ok(rnew)
520522
}
521523

522-
fn make_cluster(cadd: &Hash) -> Result<ClusterInfoBuilder> {
524+
fn make_cluster(cadd: &Hash, path: Option<&BlockPath>) -> Result<ClusterInfoBuilder> {
523525
let mut cnew = ClusterInfo::builder()
524-
.description(cadd.get_string("description")?)
525-
.derived_from(cadd.get_string("derivedFrom")?)
526+
.description(opt_interpolate(&path, cadd.get_str("description")?))
527+
.derived_from(opt_interpolate(&path, cadd.get_str("derivedFrom")?))
526528
.default_register_properties(get_register_properties(cadd)?)
527529
.children(match cadd.get_hash("registers")? {
528530
Some(h) => {
529531
let mut ch = Vec::new();
530532
for (rname, val) in h {
531533
ch.push(RegisterCluster::Register({
532534
let radd = val.hash()?;
533-
let reg = make_register(radd)?
535+
let reg = make_register(radd, None)?
534536
.name(rname.str()?.into())
535537
.build(VAL_LVL)?;
536538
if let Some(dim) = make_dim_element(radd)? {
@@ -619,7 +621,7 @@ fn make_peripheral(padd: &Hash, modify: bool) -> Result<PeripheralInfoBuilder> {
619621
for (rname, val) in h.iter() {
620622
regs.push(RegisterCluster::Register({
621623
let radd = val.hash()?;
622-
let reg = make_register(radd)?
624+
let reg = make_register(radd, None)?
623625
.name(rname.str()?.into())
624626
.build(VAL_LVL)?;
625627
if let Some(dim) = make_dim_element(radd)? {
@@ -769,3 +771,53 @@ impl Spec for str {
769771
}
770772
}
771773
}
774+
775+
fn opt_interpolate<T: Interpolate>(path: &Option<&T>, s: Option<&str>) -> Option<String> {
776+
path.and_then(|path| path.interpolate_opt(s))
777+
}
778+
779+
trait Interpolate {
780+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str>;
781+
fn interpolate_opt(&self, s: Option<&str>) -> Option<String> {
782+
s.map(|s| self.interpolate(s).into_owned())
783+
}
784+
}
785+
786+
impl Interpolate for BlockPath {
787+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str> {
788+
let mut cow = Cow::Borrowed(s);
789+
if cow.contains("`peripheral`") {
790+
cow = cow.replace("`peripheral`", &self.peripheral).into()
791+
}
792+
if cow.contains("`block_path`") {
793+
cow = cow.replace("`block_path`", &self.to_string()).into()
794+
}
795+
cow
796+
}
797+
}
798+
799+
impl Interpolate for RegisterPath {
800+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str> {
801+
let mut cow = self.block.interpolate(s);
802+
if cow.contains("`register`") {
803+
cow = cow.replace("`register`", &self.name).into()
804+
}
805+
if cow.contains("`register_path`") {
806+
cow = cow.replace("`register_path`", &self.to_string()).into()
807+
}
808+
cow
809+
}
810+
}
811+
812+
impl Interpolate for FieldPath {
813+
fn interpolate<'a>(&self, s: &'a str) -> Cow<'a, str> {
814+
let mut cow = self.register().interpolate(s);
815+
if cow.contains("`field`") {
816+
cow = cow.replace("`field`", &self.name).into()
817+
}
818+
if cow.contains("`field_path`") {
819+
cow = cow.replace("`field_path`", &self.to_string()).into()
820+
}
821+
cow
822+
}
823+
}

src/patch/peripheral.rs

Lines changed: 16 additions & 12 deletions
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

Lines changed: 7 additions & 5 deletions
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)