Browse Source

make it work with musl (the _nox target does not link the screen module that wouldn't build)

Ondřej Hruška 11 months ago
parent
commit
7efa04054c
Signed by: Ondřej Hruška <ondra@ondrovo.com> GPG key ID: 2C5FD5035250423D

+ 16 - 0
Cargo.lock View File

@@ -366,6 +366,22 @@ dependencies = [
366 366
 ]
367 367
 
368 368
 [[package]]
369
+name = "launcher_nox"
370
+version = "0.1.0"
371
+dependencies = [
372
+ "anyhow",
373
+ "clappconfig",
374
+ "crsn",
375
+ "crsn_arith",
376
+ "crsn_buf",
377
+ "crsn_stdio",
378
+ "log",
379
+ "serde",
380
+ "simple_logger",
381
+ "thiserror",
382
+]
383
+
384
+[[package]]
369 385
 name = "lazy_static"
370 386
 version = "1.4.0"
371 387
 source = "registry+https://github.com/rust-lang/crates.io-index"

+ 1 - 0
Cargo.toml View File

@@ -1,6 +1,7 @@
1 1
 [workspace]
2 2
 members = [
3 3
     "launcher",
4
+    "launcher_nox",
4 5
     "crsn",
5 6
     "crsn_arith",
6 7
     "crsn_screen",

+ 13 - 1
crsn_stdio/src/lib.rs View File

@@ -9,6 +9,7 @@ use crsn::sexp::SourcePosition;
9 9
 use std::convert::TryFrom;
10 10
 use std::io;
11 11
 use crsn::asm::instr::cond::Flag;
12
+use std::fmt;
12 13
 
13 14
 mod console {
14 15
     use std::{io};
@@ -98,7 +99,7 @@ mod console {
98 99
     }
99 100
 }
100 101
 
101
-#[derive(Debug, Clone)]
102
+#[derive(Clone)]
102 103
 pub struct StdioOps {
103 104
     old_tio: Option<libc::termios>,
104 105
     hdl_stdin : Value,
@@ -107,6 +108,17 @@ pub struct StdioOps {
107 108
     hdl_stdout_raw : Value,
108 109
 }
109 110
 
111
+impl fmt::Debug for StdioOps {
112
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113
+        f.debug_struct("StdioOps")
114
+            .field("hdl_stdin", &format_args!("0x{:08x}", self.hdl_stdin))
115
+            .field("hdl_stdin_raw", &format_args!("0x{:08x}", self.hdl_stdin_raw))
116
+            .field("hdl_stdout", &format_args!("0x{:08x}", self.hdl_stdout))
117
+            .field("hdl_stdout_raw", &format_args!("0x{:08x}", self.hdl_stdout_raw))
118
+            .finish()
119
+    }
120
+}
121
+
110 122
 impl StdioOps {
111 123
     pub fn new() -> Box<dyn CrsnExtension> {
112 124
         Box::new(Self {

+ 21 - 0
launcher_nox/Cargo.toml View File

@@ -0,0 +1,21 @@
1
+[package]
2
+name = "launcher_nox"
3
+version = "0.1.0"
4
+authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
5
+edition = "2018"
6
+
7
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
+
9
+[dependencies]
10
+crsn = { path = "../crsn" }
11
+crsn_arith = { path = "../crsn_arith" }
12
+crsn_buf = { path = "../crsn_buf" }
13
+crsn_stdio = { path = "../crsn_stdio" }
14
+
15
+simple_logger = "1.9.0"
16
+log = "0.4.11"
17
+thiserror = "1.0.20"
18
+anyhow = "1.0.32"
19
+clappconfig = "0.4.0"
20
+
21
+serde = { version = "1.0.116", features = ["derive"] }

+ 172 - 0
launcher_nox/src/main.rs View File

@@ -0,0 +1,172 @@
1
+#[macro_use]
2
+extern crate log;
3
+
4
+use std::collections::HashMap;
5
+
6
+use std::time::Duration;
7
+
8
+use clappconfig::{AppConfig, clap};
9
+use clappconfig::clap::ArgMatches;
10
+use serde::{Deserialize, Serialize};
11
+
12
+use crsn::asm::data::literal::Addr;
13
+use crsn::module::{OpTrait, CrsnUniq};
14
+use crsn::runtime::run_thread::{RunThread, ThreadToken, ThreadParams};
15
+use crsn_arith::ArithOps;
16
+use crsn_stdio::StdioOps;
17
+use crsn_buf::BufOps;
18
+
19
+mod read_file;
20
+mod serde_duration_millis;
21
+
22
+#[derive(Debug, Clone, Serialize, Deserialize)]
23
+struct LogConfig {
24
+    level: String,
25
+    modules: HashMap<String, String>,
26
+}
27
+
28
+#[derive(Debug, Clone, Serialize, Deserialize)]
29
+#[serde(default)]
30
+struct Config {
31
+    log: LogConfig,
32
+    #[serde(skip)]
33
+    program_file: String,
34
+    #[serde(skip)]
35
+    assemble_only: bool,
36
+    #[serde(with = "serde_duration_millis")]
37
+    cycle_time: Duration,
38
+}
39
+
40
+impl Default for Config {
41
+    fn default() -> Self {
42
+        Self {
43
+            log: LogConfig {
44
+                level: "warn".to_string(),
45
+                modules: Default::default(),
46
+            },
47
+            program_file: "".to_string(),
48
+            assemble_only: false,
49
+            cycle_time: Duration::default(),
50
+        }
51
+    }
52
+}
53
+
54
+impl AppConfig for Config {
55
+    type Init = Self;
56
+
57
+    fn logging(&self) -> &str {
58
+        &self.log.level
59
+    }
60
+
61
+    fn logging_mod_levels(&self) -> Option<&HashMap<String, String>> {
62
+        Some(&self.log.modules)
63
+    }
64
+
65
+    fn pre_log_println(_message: String) {
66
+        // shut up
67
+    }
68
+
69
+    fn print_banner(_name: &str, _version: &str) {
70
+        // No banner
71
+    }
72
+
73
+    /// Add args to later use in the `configure` method.
74
+    fn add_args<'a: 'b, 'b>(clap: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
75
+        // Default impl
76
+        clap
77
+            .arg(
78
+                clap::Arg::with_name("input")
79
+                    .value_name("FILE")
80
+                    .help("Program to run")
81
+                    .required_unless("default-config")
82
+                    .takes_value(true),
83
+            )
84
+            .arg(
85
+                clap::Arg::with_name("asm-only")
86
+                    .short("P")
87
+                    .long("asm")
88
+                    .help("Only assemble, do not run."),
89
+            )
90
+            .arg(
91
+                clap::Arg::with_name("cycle")
92
+                    .long("cycle")
93
+                    .short("C")
94
+                    .value_name("MICROS")
95
+                    .help("Cycle time (us, append \"s\" or \"ms\" for coarser time)")
96
+                    .takes_value(true),
97
+            )
98
+    }
99
+
100
+    fn configure(mut self, clap: &ArgMatches) -> anyhow::Result<Self> {
101
+        self.program_file = clap.value_of("input").unwrap().to_string();
102
+        self.assemble_only = clap.is_present("asm-only");
103
+        if let Some(t) = clap.value_of("cycle") {
104
+            let (t, mul) = if t.ends_with("us") {
105
+                (&t[..(t.len()-2)], 1)
106
+            } else if t.ends_with("ms") {
107
+                (&t[..(t.len()-2)], 1000)
108
+            } else if t.ends_with("m") {
109
+                (&t[..(t.len()-1)], 1000)
110
+            } else if t.ends_with("u") {
111
+                (&t[..(t.len()-1)], 1)
112
+            } else if t.ends_with("s") {
113
+                (&t[..(t.len()-1)], 1000_000)
114
+            } else {
115
+                (t, 1)
116
+            };
117
+
118
+            self.cycle_time = Duration::from_micros(t.parse::<u64>().expect("parse -C value") * mul);
119
+            println!("ct = {:?}", self.cycle_time);
120
+        }
121
+        Ok(self)
122
+    }
123
+}
124
+
125
+
126
+fn main() -> anyhow::Result<()> {
127
+    let config = Config::init("crsn", "crsn.json5", env!("CARGO_PKG_VERSION"))?;
128
+
129
+    debug!("Loading {}", config.program_file);
130
+
131
+    let source = read_file::read_file(&config.program_file)?;
132
+
133
+    let uniq = CrsnUniq::new();
134
+
135
+    let parsed = crsn::asm::assemble(&source, &uniq, vec![
136
+        ArithOps::new(),
137
+        BufOps::new(),
138
+        StdioOps::new(),
139
+    ])?;
140
+
141
+    if config.assemble_only {
142
+        for (n, op) in parsed.ops.iter().enumerate() {
143
+            println!("{:04} : {}", n, op.to_sexp());
144
+        }
145
+        return Ok(());
146
+    } else {
147
+        trace!("--- Compiled program ---");
148
+        for (n, op) in parsed.ops.iter().enumerate() {
149
+            trace!("{:04} : {}", n, op.to_sexp());
150
+        }
151
+        trace!("------------------------");
152
+    }
153
+
154
+    debug!("Start runtime");
155
+
156
+    let args = &[];
157
+    let thread = RunThread::new(ThreadParams {
158
+        id: ThreadToken(0),
159
+        uniq,
160
+        program: parsed,
161
+        pc: Addr(0),
162
+        cycle_time: config.cycle_time,
163
+        args
164
+    });
165
+
166
+    // run without spawning, so it is on the main thread - required by some extensions
167
+    thread.run();
168
+
169
+    debug!("Runtime shut down.");
170
+
171
+    Ok(())
172
+}

+ 14 - 0
launcher_nox/src/read_file.rs View File

@@ -0,0 +1,14 @@
1
+use std::fs::File;
2
+use std::io;
3
+use std::io::Read;
4
+use std::path::Path;
5
+
6
+/// Read a file to string
7
+pub fn read_file<P: AsRef<Path>>(path: P) -> io::Result<String> {
8
+    let path = path.as_ref();
9
+    let mut file = File::open(path)?;
10
+
11
+    let mut buf = String::new();
12
+    file.read_to_string(&mut buf)?;
13
+    Ok(buf)
14
+}

+ 18 - 0
launcher_nox/src/serde_duration_millis.rs View File

@@ -0,0 +1,18 @@
1
+use std::time::Duration;
2
+
3
+use serde::{self, Deserialize, Deserializer, Serializer};
4
+
5
+pub fn serialize<S>(value: &Duration, se: S) -> Result<S::Ok, S::Error>
6
+    where
7
+        S: Serializer,
8
+{
9
+    se.serialize_u64(value.as_secs() * 1000 + value.subsec_millis() as u64)
10
+}
11
+
12
+pub fn deserialize<'de, D>(de: D) -> Result<Duration, D::Error>
13
+    where
14
+        D: Deserializer<'de>,
15
+{
16
+    let s: u64 = u64::deserialize(de)?;
17
+    Ok(Duration::from_millis(s))
18
+}