summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQrius <[email protected]>2024-12-19 14:35:56 +0100
committerQrius <[email protected]>2024-12-19 14:36:07 +0100
commitb84765abc10598c3c808ea207ba89be40211189b (patch)
treee5e13ac52367904b30c0dbea8782ff03b8665d32
parent861779e4c6b82f9f4bf09fd7e714ac5106b4455d (diff)
downloadskaldpress-b84765abc10598c3c808ea207ba89be40211189b.tar.gz
skaldpress-b84765abc10598c3c808ea207ba89be40211189b.zip
Try to make a macro to get guile things instead
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml5
-rwxr-xr-xpackaging/package_debian.sh1
-rw-r--r--src/guile/guile.rs75
-rw-r--r--src/guile/guiledefs.c1
-rw-r--r--src/macro_processor/macro_processor.rs32
-rw-r--r--src/macro_processor/main.rs44
7 files changed, 133 insertions, 27 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3e57970..874d526 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -236,7 +236,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "skaldpress"
-version = "2.1.0"
+version = "2.2.0"
dependencies = [
"chrono",
"markdown",
diff --git a/Cargo.toml b/Cargo.toml
index 8e35973..1ec0d03 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,16 +1,17 @@
[package]
name = "skaldpress"
-version = "2.1.0"
+version = "2.2.0"
edition = "2021"
default-run = "skaldpress"
[features]
-default = ["time", "markdown", "deadlinks", "guile"]
+default = ["time", "markdown", "deadlinks", "guile", "readline"]
time = ["dep:chrono"]
markdown = ["dep:markdown"]
deadlinks = ["dep:minreq"]
webring = []
guile = []
+readline = []
[dependencies]
markdown = { version = "1.0.0-alpha.20", optional = true }
diff --git a/packaging/package_debian.sh b/packaging/package_debian.sh
index 2c147e6..6549717 100755
--- a/packaging/package_debian.sh
+++ b/packaging/package_debian.sh
@@ -1,5 +1,6 @@
#!/bin/bash
set -x
+set -o pipefail
tmpdir=$(mktemp -d)
diff --git a/src/guile/guile.rs b/src/guile/guile.rs
index 36df62a..a459a64 100644
--- a/src/guile/guile.rs
+++ b/src/guile/guile.rs
@@ -1,13 +1,41 @@
+use crate::macro_processor::macro_processor::MacroProcessor;
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int, c_void};
+use std::sync::mpsc;
+use std::thread;
+
+macro_rules! dprint {
+ ($($x:tt)*) => {
+ #[cfg(debug_assertions)]
+ print!($($x)*)
+ }
+}
+
#[link(name = "guile-3.0")]
extern "C" {
fn scm_init_guile();
fn scm_c_eval_string(expr: *const c_char) -> *mut c_void;
+ fn scm_from_utf8_string(expr: *const c_char) -> *mut c_void;
fn scm_to_locale_string(scm_obj: *mut c_void) -> *const c_char;
fn scm_is_string(scm_obj: *mut c_void) -> c_int;
fn scm_object_to_string(scm_obj: *mut c_void, printer: *mut c_void) -> *mut c_void;
+ fn scm_to_pointer(scm_obj: *mut c_void) -> *mut c_void;
+ fn scm_c_define_gsubr(
+ name: *const c_char,
+ req: c_int,
+ opt: c_int,
+ rst: c_int,
+ func: extern "C" fn(scm_obj: *mut c_void) -> *mut c_void,
+ );
+ fn scm_c_define(name: *const c_char, value: *mut c_void);
+ fn scm_from_pointer(value: *mut c_void) -> *mut c_void;
+ //fn scm_with_guile(func: extern "C" fn(data: *mut c_void) -> *mut c_void, data: *mut c_void) -> *mut c_void;
+ //fn scm_is_number(scm_obj: *mut c_void) -> c_int;
+ //fn scm_without_guile(func: extern "C" fn(data: *mut c_void) -> *mut c_void, data: *mut c_void) -> *mut c_void;
+ //fn scm_c_write(scm_obj: *mut c_void, port: *mut c_void);
+ //fn scm_get_output_string(port: *mut c_void) -> *mut c_void;
+ //fn scm_open_output_string() -> *mut c_void;
}
#[link(name = "guiledefs")]
@@ -44,7 +72,30 @@ fn string_from_scm(scm_obj: *mut c_void) -> Result<String, ()> {
}
}
-#[derive(Clone)]
+extern "C" fn scm_smp_macro(arg: *mut c_void) -> *mut c_void {
+ let arg_str;
+ unsafe {
+ arg_str = CStr::from_ptr(scm_to_locale_string(arg))
+ .to_string_lossy()
+ .into_owned();
+ }
+ dprint!("ARG {:#?}\n", arg_str);
+ let c_smp_state_ptr = CString::new("smp_state_ptr").expect("CString::new() failed");
+ unsafe {
+ let smp_state_scm = scm_c_eval_string(c_smp_state_ptr.as_ptr());
+ let smp_state_ptr = scm_to_pointer(smp_state_scm);
+ let smp: &mut MacroProcessor = &mut *(smp_state_ptr as *mut MacroProcessor);
+ if let Some(macro_value) = smp.macros.get(&arg_str) {
+ let r = CString::new(macro_value.to_string()).expect("CString::new() failed");
+ scm_from_utf8_string(r.as_ptr())
+ } else {
+ let r = CString::new("Macro not found").expect("CString::new() failed");
+ scm_from_utf8_string(r.as_ptr())
+ }
+ }
+}
+
+#[derive(Debug)]
pub struct Guile {}
impl Guile {
@@ -52,10 +103,16 @@ impl Guile {
unsafe {
scm_init_guile();
}
- Guile {}
+ let guile = Guile {};
+ let func_name = CString::new("smp_get").unwrap();
+ unsafe {
+ scm_c_define_gsubr(func_name.as_ptr(), 1, 0, 0, scm_smp_macro);
+ }
+ guile
}
pub fn evaluate_expression(&self, expr: &str) -> Result<String, ()> {
+ dprint!("(eval \"{}\")\n", expr);
unsafe {
let c_expr = CString::new(expr).map_err(|_| ())?;
let result = scm_c_eval_string(c_expr.as_ptr());
@@ -70,13 +127,19 @@ impl Guile {
defs_scm_define_string(c_name.as_ptr(), c_value.as_ptr());
}
}
+
+ pub fn define(&self, name: &str, value: *mut c_void) {
+ let c_name = CString::new(name).expect("CString::new failed");
+ unsafe {
+ scm_c_define(c_name.as_ptr(), scm_from_pointer(value));
+ }
+ }
}
impl Drop for Guile {
fn drop(&mut self) {
- if let Err(e) = self.evaluate_expression("(exit)") {
- panic!("Error while exiting {:#?}", e);
- }
+ //if let Err(e) = self.evaluate_expression("(variable-unset! \"smp_state_ptr\")") {
+ // panic!("Error while exiting {:#?}", e);
+ //}
}
}
-
diff --git a/src/guile/guiledefs.c b/src/guile/guiledefs.c
index a0e9bd2..bf050af 100644
--- a/src/guile/guiledefs.c
+++ b/src/guile/guiledefs.c
@@ -10,3 +10,4 @@ int defs_scm_is_eq(SCM x, SCM y) {
void defs_scm_define_string(const char* name, const char* value) {
scm_c_define(name, scm_from_utf8_string(value));
}
+
diff --git a/src/macro_processor/macro_processor.rs b/src/macro_processor/macro_processor.rs
index 306c8da..52fc581 100644
--- a/src/macro_processor/macro_processor.rs
+++ b/src/macro_processor/macro_processor.rs
@@ -1,10 +1,12 @@
#[cfg(feature = "guile")]
-use crate::guile::guile::Guile;
+use crate::guile::guile::{scm_undefined, Guile};
#[cfg(feature = "deadlinks")]
use crate::macro_processor::deadlinks::smp_builtin_wodl;
use crate::macro_processor::error::SMPError;
use std::collections::HashMap;
use std::fs;
+#[cfg(feature = "guile")]
+use std::os::raw::c_void;
use std::process::Command;
// print only with debug_assertions
@@ -537,6 +539,9 @@ fn smp_builtin_html_from_markdown(
}
fn macro_is_whitespace_deleting(s: &str) -> bool {
+ if s.len() == 0 {
+ return false;
+ }
s.chars().nth(s.len() - 1) == Some('_')
}
@@ -623,7 +628,7 @@ impl MacroProcessorWarning {
/// Defines a MacroProcessor object, with it's associated state
/// the state mostly includes the defined macros
-#[derive(Clone)]
+#[derive(Debug, Clone)]
pub struct MacroProcessor {
/// All currently defined macros in this MacroProcessor
pub macros: HashMap<String, MacroType>,
@@ -632,9 +637,11 @@ pub struct MacroProcessor {
/// Emitted warnings
pub warnings: Vec<MacroProcessorWarning>,
#[cfg(feature = "guile")]
- pub guile: Guile,
+ pub guile: std::rc::Rc<Guile>,
}
+pub static mut GLOBS: Option<&MacroProcessor> = None;
+
impl MacroProcessor {
pub fn new() -> Self {
let mut smp = Self {
@@ -642,12 +649,21 @@ impl MacroProcessor {
macro_invocations: Vec::new(),
warnings: Vec::new(),
#[cfg(feature = "guile")]
- guile: Guile::new(),
+ guile: std::rc::Rc::new(Guile::new()),
};
smp.define_builtins();
smp
}
+ pub fn defself(&mut self) {
+ // Find a better way to do this Rc-stuff
+ let guile = std::rc::Rc::as_ptr(&self.guile);
+ unsafe {
+ let data_ptr: *mut c_void = self as *mut _ as *mut c_void;
+ (*guile).define("smp_state_ptr", data_ptr);
+ }
+ }
+
/// Bootstrapping-function for defining all builtins,
/// the same way all other macros might be defined
fn define_builtins(&mut self) {
@@ -747,13 +763,6 @@ impl MacroProcessor {
/// * `name` - The name of the new macro
/// * `macro_expansion` - The MacroType struct to use.
pub fn define_macro(&mut self, name: String, macro_expansion: MacroType) {
- #[cfg(feature = "guile")]
- {
- match &macro_expansion {
- MacroType::String(s) => self.guile.define_string(&(name.clone()), s),
- _ => (),
- }
- }
self.macros.insert(name, macro_expansion);
}
@@ -916,6 +925,7 @@ impl MacroProcessor {
#[cfg(feature = "guile")]
ParserState::InGuile => match c {
')' if peek == Some(&'%') => {
+ self.defself();
let r = self
.guile
.evaluate_expression(&guile_expr)
diff --git a/src/macro_processor/main.rs b/src/macro_processor/main.rs
index d8247d6..2435cf3 100644
--- a/src/macro_processor/main.rs
+++ b/src/macro_processor/main.rs
@@ -1,9 +1,31 @@
use skaldpress::macro_processor::MacroProcessor;
use std::env;
use std::fs;
+#[cfg(not(feature = "readline"))]
use std::io;
+#[cfg(not(feature = "readline"))]
use std::io::Write;
+#[cfg(feature = "readline")]
+use std::ffi::{CStr, CString};
+#[cfg(feature = "readline")]
+use std::os::raw::c_char;
+
+#[cfg(feature = "readline")]
+#[link(name = "readline")]
+extern "C" {
+ fn readline(p: *const c_char) -> *const c_char;
+}
+
+#[cfg(feature = "readline")]
+fn readline_r(prompt: &str) -> String {
+ let c_prompt = CString::new(prompt).expect("Could not convert to c_string");
+ unsafe {
+ let ret = readline(c_prompt.as_ptr());
+ CStr::from_ptr(ret).to_string_lossy().into_owned()
+ }
+}
+
fn repl() {
println!("=Skaldpress Macro Processor (REPL)");
println!(" type \"quit\" to exit");
@@ -11,14 +33,22 @@ fn repl() {
loop {
let mut input = String::new();
loop {
- print!("> ");
- let _ = io::stdout().flush();
let mut _input = String::new();
- io::stdin()
- .read_line(&mut _input)
- .expect("error: unable to read user input");
- if _input == "\n" {
- input.pop();
+
+ #[cfg(feature = "readline")]
+ {
+ _input = readline_r("> ")
+ }
+ #[cfg(not(feature = "readline"))]
+ {
+ print!("> ");
+ let _ = io::stdout().flush();
+ io::stdin()
+ .read_line(&mut _input)
+ .expect("error: unable to read user input");
+ }
+
+ if _input == "" {
break;
}
if _input == "quit\n" {