Parse JSON into linker script

This commit is contained in:
Jaby 2022-12-03 02:55:12 +01:00
parent 268642fb6b
commit 897969467f
6 changed files with 120 additions and 7 deletions

View File

@ -0,0 +1,16 @@
{
"slot_0": {
"main_area": {
"pattern": ["bin/PSX-release/src/*.o"]
},
"main_area2": {
"pattern": ["Wuffi/*", "Knuffi/*"]
}
},
"slot_1": {
"following": "slot_0",
"blubb": {
"pattern": ["cody/*"]
}
}
}

View File

@ -7,3 +7,4 @@ edition = "2021"
[dependencies]
tool_helper = {path = "../tool_helper"}
serde_json = "*"

View File

@ -38,7 +38,7 @@ pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(),
writeln!(output, "\t\t.{} {{", section.name)?;
writeln!(output, "\t\t\t__{}_start = .;", section.name)?;
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header)", patr))?;
writeln!(output, "\t\t\t__main_area_ctor = .;")?;
writeln!(output, "\t\t\t__{}_ctor = .;", section.name)?;
for section_type in [".text.startup._GLOBAL__*", ".ctors", ".text.*", ".rodata*", ".sdata*", ".data*", ".sbss*", ".bss*"] {
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\t{}({})", patr, section_type))?;
@ -46,7 +46,7 @@ pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(),
writeln!(output, "\t\t}}")?;
}
writeln!(output, "\t}}")?;
writeln!(output, "\t{}_end = .;", slot.name)?;
writeln!(output, "\t__{}_end = .;", slot.name)?;
writeln!(output, "")?;
}
writeln!(output, "\t/DISCARD/ : {{ *(.comment*) *(.gnu.*) *(.mdebug*) *(.debug_*) *(.pdr)}}")?;

View File

@ -1,7 +1,8 @@
use mkoverlay::types::{OverlaySection, OverlaySlot};
use tool_helper::{Error, open_output};
use tool_helper::{Error, open_input, open_output};
use std::path::PathBuf;
fn generate_file() -> Vec<OverlaySlot> {
fn _generate_file() -> Vec<OverlaySlot> {
let mut slots = Vec::new();
let mut slot = OverlaySlot::new("slot_0".to_owned(), None);
let mut section = OverlaySection::new("main_area".to_owned());
@ -15,7 +16,7 @@ fn generate_file() -> Vec<OverlaySlot> {
}
fn run_main() -> Result<(), Error> {
let input = generate_file();
let input = mkoverlay::types::json_reader::read_config(open_input(Some(PathBuf::from("../Tests/Overlay.json")))?)?;
let mut output = open_output(None)?;
mkoverlay::creator::ldscript::write(&mut output, &input)

View File

@ -0,0 +1,84 @@
use super::{OverlaySection, OverlaySlot};
use tool_helper::{Error, format_if_error, Input};
pub fn read_config(input: Input) -> Result<Vec<OverlaySlot>, Error> {
let json_reader:serde_json::Value = format_if_error!(serde_json::from_reader(input), "Parsing JSON failed with: {error_text}")?;
let mut overlay_slots = Vec::new();
if let Some(objects) = json_reader.as_object() {
for object in objects {
overlay_slots.push(read_as_slot(object)?);
}
Ok(overlay_slots)
}
else {
Err(Error::from_str("JSON must start with an object"))
}
}
fn read_as_slot(json_value: (&String, &serde_json::Value)) -> Result<OverlaySlot, Error> {
let (slot_name, json_value) = json_value;
let mut slot = OverlaySlot::new(slot_name.clone(), None);
if let Some(json_value) = json_value.as_object() {
for (name, json_value) in json_value {
if name == "following" {
if let Some(start_adr) = json_value.as_str() {
slot.start_adr = Some(format!("__{}_end", start_adr));
}
else {
return Err(Error::from_text(format!("\"following\" option of {} must be a string", slot_name)));
}
}
else {
slot.add_section(read_as_section(name.clone(), json_value)?);
}
}
}
Ok(slot)
}
fn read_as_section(section_name: String, json_value: &serde_json::Value) -> Result<OverlaySection, Error> {
fn create_pattern_error<T>(section_name: &String) -> Result<T, Error> {
Err(Error::from_text(format!("Pattern element of section declaration \"{}\" must contain only strings", section_name)))
}
fn read_pattern(section_name: &String, json_value: &serde_json::Value) -> Result<String, Error> {
if let Some(pattern) = json_value.as_str() {
Ok(pattern.to_owned())
}
else {
create_pattern_error(section_name)
}
}
let mut section = OverlaySection::new(section_name);
if let Some(pattern_json) = json_value.get("pattern") {
if let Some(pattern) = pattern_json.as_array() {
for cur_pattern in pattern {
section.add_file_pattern(read_pattern(&section.name, cur_pattern)?);
}
Ok(section)
}
else if let Some(pattern) = pattern_json.as_str() {
section.add_file_pattern(pattern.to_owned());
Ok(section)
}
else {
create_pattern_error(&section.name)
}
}
else {
Err(Error::from_text(format!("Section declaration \"{}\" does not contain any pattern!", section.name)))
}
}

View File

@ -1,3 +1,5 @@
pub mod json_reader;
#[derive(Debug)]
pub struct OverlaySection {
pub(super) name: String,
@ -22,7 +24,16 @@ pub struct OverlaySlot {
}
impl OverlaySlot {
pub fn new(name: String, start_adr: Option<String>) -> OverlaySlot {
pub fn new(name: String, start_adr: Option<&str>) -> OverlaySlot {
let start_adr = {
if let Some(str) = start_adr {
Some(str.to_owned())
}
else {
None
}
};
OverlaySlot{name, start_adr, sections: Vec::new()}
}