Skip to content

Commit bc5c32c

Browse files
committed
env
1 parent a8460c8 commit bc5c32c

File tree

4 files changed

+315
-178
lines changed

4 files changed

+315
-178
lines changed

src/patch/device.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{fs::File, io::Read, path::Path};
99
use super::iterators::{MatchIter, Matched};
1010
use super::peripheral::{PeripheralExt, RegisterBlockExt};
1111
use super::yaml_ext::{AsType, GetVal};
12-
use super::{abspath, matchname, Config, PatchResult, Spec, VAL_LVL};
12+
use super::{abspath, matchname, update_env, Config, Env, PatchResult, Spec, VAL_LVL};
1313
use super::{make_address_block, make_address_blocks, make_cpu, make_interrupt, make_peripheral};
1414
use super::{make_dim_element, modify_dim_element, modify_register_properties};
1515

@@ -33,14 +33,14 @@ pub trait DeviceExt {
3333
fn modify_cpu(&mut self, cmod: &Hash) -> PatchResult;
3434

3535
/// Modify pspec inside device according to pmod
36-
fn modify_peripheral(&mut self, pspec: &str, pmod: &Hash) -> PatchResult;
36+
fn modify_peripheral(&mut self, pspec: &str, pmod: &Hash, env: &Env) -> PatchResult;
3737

3838
/// Add pname given by padd to device
39-
fn add_peripheral(&mut self, pname: &str, padd: &Hash) -> PatchResult;
39+
fn add_peripheral(&mut self, pname: &str, padd: &Hash, env: &Env) -> PatchResult;
4040

4141
/// Remove registers from pname and mark it as derivedFrom pderive.
4242
/// Update all derivedFrom referencing pname
43-
fn derive_peripheral(&mut self, pname: &str, pderive: &Yaml) -> PatchResult;
43+
fn derive_peripheral(&mut self, pname: &str, pderive: &Yaml, env: &Env) -> PatchResult;
4444

4545
/// Move registers from pold to pnew.
4646
/// Update all derivedFrom referencing pold
@@ -55,6 +55,7 @@ pub trait DeviceExt {
5555
pspec: &str,
5656
peripheral: &Hash,
5757
config: &Config,
58+
env: &Env,
5859
) -> PatchResult;
5960
}
6061

@@ -64,6 +65,9 @@ impl DeviceExt for Device {
6465
}
6566

6667
fn process(&mut self, device: &Hash, config: &Config) -> PatchResult {
68+
let mut env = Env::new();
69+
update_env(&mut env, device)?;
70+
6771
// Handle any deletions
6872
for pspec in device.str_vec_iter("_delete")? {
6973
self.delete_peripheral(pspec)
@@ -91,7 +95,7 @@ impl DeviceExt for Device {
9195
"_peripherals" => {
9296
for (pspec, pmod) in val.hash()? {
9397
let pspec = pspec.str()?;
94-
self.modify_peripheral(pspec, pmod.hash()?)
98+
self.modify_peripheral(pspec, pmod.hash()?, &env)
9599
.with_context(|| {
96100
format!("Modifying peripherals matched to `{pspec}`")
97101
})?;
@@ -115,7 +119,7 @@ impl DeviceExt for Device {
115119
}
116120

117121
_ => self
118-
.modify_peripheral(key, val.hash()?)
122+
.modify_peripheral(key, val.hash()?, &env)
119123
.with_context(|| format!("Modifying peripherals matched to `{key}`"))?,
120124
}
121125
}
@@ -130,14 +134,14 @@ impl DeviceExt for Device {
130134
// Handle any new peripherals (!)
131135
for (pname, padd) in device.hash_iter("_add") {
132136
let pname = pname.str()?;
133-
self.add_peripheral(pname, padd.hash()?)
137+
self.add_peripheral(pname, padd.hash()?, &env)
134138
.with_context(|| format!("Adding peripheral `{pname}`"))?;
135139
}
136140

137141
// Handle any derived peripherals
138142
for (pname, pderive) in device.hash_iter("_derive") {
139143
let pname = pname.str()?;
140-
self.derive_peripheral(pname, pderive)
144+
self.derive_peripheral(pname, pderive, &env)
141145
.with_context(|| format!("Deriving peripheral `{pname}` from `{pderive:?}`"))?;
142146
}
143147

@@ -154,7 +158,7 @@ impl DeviceExt for Device {
154158
let periphspec = periphspec.str()?;
155159
if !periphspec.starts_with('_') {
156160
//val["_path"] = device["_path"]; // TODO: check
157-
self.process_peripheral(periphspec, val.hash()?, config)
161+
self.process_peripheral(periphspec, val.hash()?, config, &env)
158162
.with_context(|| format!("According to `{periphspec}`"))?;
159163
}
160164
}
@@ -218,11 +222,11 @@ impl DeviceExt for Device {
218222
Ok(())
219223
}
220224

221-
fn modify_peripheral(&mut self, pspec: &str, pmod: &Hash) -> PatchResult {
225+
fn modify_peripheral(&mut self, pspec: &str, pmod: &Hash, env: &Env) -> PatchResult {
222226
let mut modified = HashSet::new();
223227
let ptags = self.iter_peripherals(pspec).collect::<Vec<_>>();
224228
if !ptags.is_empty() {
225-
let peripheral_builder = make_peripheral(pmod, true)?;
229+
let peripheral_builder = make_peripheral(pmod, true, env)?;
226230
let dim = make_dim_element(pmod)?;
227231
for ptag in ptags {
228232
modified.insert(ptag.name.clone());
@@ -267,12 +271,12 @@ impl DeviceExt for Device {
267271
Ok(())
268272
}
269273

270-
fn add_peripheral(&mut self, pname: &str, padd: &Hash) -> PatchResult {
274+
fn add_peripheral(&mut self, pname: &str, padd: &Hash, env: &Env) -> PatchResult {
271275
if self.get_peripheral(pname).is_some() {
272276
return Err(anyhow!("device already has a peripheral {pname}"));
273277
}
274278

275-
let pnew = make_peripheral(padd, false)?
279+
let pnew = make_peripheral(padd, false, env)?
276280
.name(pname.to_string())
277281
.build(VAL_LVL)?;
278282
let pnew = if let Some(dim) = make_dim_element(padd)? {
@@ -285,7 +289,7 @@ impl DeviceExt for Device {
285289
Ok(())
286290
}
287291

288-
fn derive_peripheral(&mut self, pname: &str, pderive: &Yaml) -> PatchResult {
292+
fn derive_peripheral(&mut self, pname: &str, pderive: &Yaml, env: &Env) -> PatchResult {
289293
let (pderive, info) = if let Some(pderive) = pderive.as_str() {
290294
(
291295
pderive,
@@ -300,7 +304,7 @@ impl DeviceExt for Device {
300304
})?;
301305
(
302306
pderive,
303-
make_peripheral(hash, true)?.derived_from(Some(pderive.into())),
307+
make_peripheral(hash, true, env)?.derived_from(Some(pderive.into())),
304308
)
305309
} else {
306310
return Err(anyhow!("derive: incorrect syntax for {pname}"));
@@ -415,13 +419,14 @@ impl DeviceExt for Device {
415419
pspec: &str,
416420
peripheral: &Hash,
417421
config: &Config,
422+
env: &Env,
418423
) -> PatchResult {
419424
// Find all peripherals that match the spec
420425
let mut pcount = 0;
421426
let (pspec, ignore) = pspec.spec();
422427
for ptag in self.iter_peripherals(pspec) {
423428
pcount += 1;
424-
ptag.process(peripheral, config)
429+
ptag.process(peripheral, config, env.clone())
425430
.with_context(|| format!("Processing peripheral `{}`", ptag.name))?;
426431
}
427432
if !ignore && pcount == 0 {

src/patch/mod.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
pub mod patch_cli;
22

3+
use std::borrow::Cow;
4+
use std::collections::HashMap;
35
use std::fs::File;
46
use std::io::{Read, Write};
57
use std::path::{Path, PathBuf};
@@ -30,6 +32,31 @@ use crate::get_encoder_config;
3032

3133
const VAL_LVL: ValidateLevel = ValidateLevel::Weak;
3234

35+
pub type Env = HashMap<Cow<'static, str>, String>;
36+
37+
fn update_env(env: &mut Env, dict: &Hash) -> PatchResult {
38+
for (key, val) in dict.hash_iter("_env") {
39+
let key = key.str()?;
40+
let val = val.str()?;
41+
env.insert(key.to_string().into(), val.to_string());
42+
}
43+
Ok(())
44+
}
45+
46+
fn insert_env<'a>(s: &'a str, env: &Env) -> Cow<'a, str> {
47+
let mut s = Cow::Borrowed(s);
48+
for (k, v) in env {
49+
let k = format!("`{k}`");
50+
if s.contains(&k) {
51+
s = s.replace(&k, v).into();
52+
}
53+
}
54+
s
55+
}
56+
fn insert_env_opt(s: Option<&str>, env: &Env) -> Option<String> {
57+
s.map(|s| insert_env(s, env).into_owned())
58+
}
59+
3360
#[non_exhaustive]
3461
#[derive(Clone, Debug)]
3562
pub struct Config {
@@ -429,10 +456,10 @@ fn modify_dim_element<T: Clone>(
429456
Ok(())
430457
}
431458

432-
fn make_field(fadd: &Hash) -> Result<FieldInfoBuilder> {
459+
fn make_field(fadd: &Hash, env: &Env) -> Result<FieldInfoBuilder> {
433460
let mut fnew = FieldInfo::builder()
434-
.description(fadd.get_string("description")?)
435-
.derived_from(fadd.get_string("derivedFrom")?)
461+
.description(insert_env_opt(fadd.get_str("description")?, env))
462+
.derived_from(insert_env_opt(fadd.get_str("derivedFrom")?, env))
436463
.access(fadd.get_str("access")?.and_then(Access::parse_str))
437464
.modified_write_values(
438465
fadd.get_str("modifiedWriteValues")?
@@ -460,11 +487,11 @@ fn make_field(fadd: &Hash) -> Result<FieldInfoBuilder> {
460487
Ok(fnew)
461488
}
462489

463-
fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
490+
fn make_register(radd: &Hash, env: &Env) -> Result<RegisterInfoBuilder> {
464491
let mut rnew = RegisterInfo::builder()
465492
.display_name(radd.get_string("displayName")?)
466-
.description(radd.get_string("description")?)
467-
.derived_from(radd.get_string("derivedFrom")?)
493+
.description(insert_env_opt(radd.get_str("description")?, env))
494+
.derived_from(insert_env_opt(radd.get_str("derivedFrom")?, env))
468495
.alternate_group(radd.get_string("alternateGroup")?)
469496
.alternate_register(radd.get_string("alternateRegister")?)
470497
.properties(get_register_properties(radd)?)
@@ -473,7 +500,7 @@ fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
473500
let mut fields = Vec::new();
474501
for (fname, val) in h {
475502
fields.push(
476-
make_field(val.hash()?)?
503+
make_field(val.hash()?, env)?
477504
.name(fname.str()?.into())
478505
.build(VAL_LVL)?
479506
.single(),
@@ -519,18 +546,18 @@ fn make_register(radd: &Hash) -> Result<RegisterInfoBuilder> {
519546
Ok(rnew)
520547
}
521548

522-
fn make_cluster(cadd: &Hash) -> Result<ClusterInfoBuilder> {
549+
fn make_cluster(cadd: &Hash, env: &Env) -> Result<ClusterInfoBuilder> {
523550
let mut cnew = ClusterInfo::builder()
524-
.description(cadd.get_string("description")?)
525-
.derived_from(cadd.get_string("derivedFrom")?)
551+
.description(insert_env_opt(cadd.get_str("description")?, env))
552+
.derived_from(insert_env_opt(cadd.get_str("derivedFrom")?, env))
526553
.default_register_properties(get_register_properties(cadd)?)
527554
.children(match cadd.get_hash("registers")? {
528555
Some(h) => {
529556
let mut ch = Vec::new();
530557
for (rname, val) in h {
531558
ch.push(RegisterCluster::Register({
532559
let radd = val.hash()?;
533-
let reg = make_register(radd)?
560+
let reg = make_register(radd, env)?
534561
.name(rname.str()?.into())
535562
.build(VAL_LVL)?;
536563
if let Some(dim) = make_dim_element(radd)? {
@@ -565,12 +592,12 @@ fn make_interrupt(iadd: &Hash) -> Result<InterruptBuilder> {
565592
Ok(int)
566593
}
567594

568-
fn make_peripheral(padd: &Hash, modify: bool) -> Result<PeripheralInfoBuilder> {
595+
fn make_peripheral(padd: &Hash, modify: bool, env: &Env) -> Result<PeripheralInfoBuilder> {
569596
let mut pnew = PeripheralInfo::builder()
570597
.display_name(padd.get_string("displayName")?)
571598
.version(padd.get_string("version")?)
572-
.description(padd.get_string("description")?)
573-
.derived_from(padd.get_string("derivedFrom")?)
599+
.description(insert_env_opt(padd.get_str("description")?, env))
600+
.derived_from(insert_env_opt(padd.get_str("derivedFrom")?, env))
574601
.group_name(padd.get_string("groupName")?)
575602
.interrupt(if !modify {
576603
match padd.get_hash("interrupts")? {
@@ -619,7 +646,7 @@ fn make_peripheral(padd: &Hash, modify: bool) -> Result<PeripheralInfoBuilder> {
619646
for (rname, val) in h.iter() {
620647
regs.push(RegisterCluster::Register({
621648
let radd = val.hash()?;
622-
let reg = make_register(radd)?
649+
let reg = make_register(radd, env)?
623650
.name(rname.str()?.into())
624651
.build(VAL_LVL)?;
625652
if let Some(dim) = make_dim_element(radd)? {

0 commit comments

Comments
 (0)