aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-09-12 10:51:13 -0700
committerJoe Wilm <joe@jwilm.com>2016-09-12 10:51:13 -0700
commitdca1c5c633981aa96932e0d50d3e27fe7de7a2b2 (patch)
tree4b160c79627a31cd6e9639d4f3e4dc780a928f19 /src
downloadr-alacritty-vte-dca1c5c633981aa96932e0d50d3e27fe7de7a2b2.tar.gz
r-alacritty-vte-dca1c5c633981aa96932e0d50d3e27fe7de7a2b2.tar.bz2
r-alacritty-vte-dca1c5c633981aa96932e0d50d3e27fe7de7a2b2.zip
WIP
Diffstat (limited to 'src')
-rw-r--r--src/definitions.rs74
-rw-r--r--src/lib.rs53
-rw-r--r--src/table.rs.in214
3 files changed, 341 insertions, 0 deletions
diff --git a/src/definitions.rs b/src/definitions.rs
new file mode 100644
index 0000000..f887559
--- /dev/null
+++ b/src/definitions.rs
@@ -0,0 +1,74 @@
+#[derive(Debug)]
+pub enum State {
+ Anywhere = 0,
+ CsiEntry = 1,
+ CsiIgnore = 2,
+ CsiIntermediate = 3,
+ CsiParam = 4,
+ DcsEntry = 5,
+ DcsIgnore = 6,
+ DcsIntermediate = 7,
+ DcsParam = 8,
+ DcsPassthrough = 9,
+ Escape = 10,
+ EscapeIntermediate = 11,
+ Ground = 12,
+ OscString = 13,
+ SosPmApcString = 14,
+ Unused__ = 15,
+}
+
+#[derive(Debug)]
+pub enum Action {
+ None = 0,
+ Clear = 1,
+ Collect = 2,
+ CsiDispatch = 3,
+ EscDispatch = 4,
+ Execute = 5,
+ Hook = 6,
+ Ignore = 7,
+ OscEnd = 8,
+ OscPut = 9,
+ OscStart = 10,
+ Param = 11,
+ Print = 12,
+ Put = 13,
+ Unhook = 14,
+ Unused__ = 15,
+}
+
+/// Unpack a u8 into a State and Action
+///
+/// The implementation of this assumes that there are *precisely* 16 variants for both Action and
+/// State. Furthermore, it assumes that the enums are tag-only; that is, there is no data in any
+/// variant.
+///
+/// Bad things will happen if those invariants are violated.
+#[inline(always)]
+fn unpack(delta: u8) -> (State, Action) {
+ (
+ // Action is stored in bottom 4 bits
+ unsafe { ::std::mem::transmute(delta & 0x0f) },
+
+ // State is stored in top 4 bits
+ unsafe { ::std::mem::transmute(delta >> 4) },
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{State, Action, unpack};
+ #[test]
+ fn unpack_state_action() {
+ match unpack(0xee) {
+ (State::SosPmApcString, Action::Unhook) => (),
+ _ => panic!("unpack failed"),
+ }
+
+ match unpack(0xff) {
+ (State::Unused__, Action::Unused__) => (),
+ _ => panic!("unpack failed"),
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d7dadad
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,53 @@
+mod table;
+mod definitions;
+
+pub use definitions::{Action, State, unpack};
+
+use table::{EXIT_ACTIONS, ENTRY_ACTIONS, STATE_CHANGE};
+
+impl State {
+ /// Get exit action for this state
+ #[inline(always)]
+ pub fn exit_action(&self) -> Action {
+ unsafe {
+ ::table::EXIT_ACTIONS.get_unchecked(*self as usize)
+ }
+ }
+
+ /// Get entry action for this state
+ #[inline(always)]
+ pub fn entry_action(&self) -> Action {
+ unsafe {
+ ::table::ENTRY_ACTIONS.get_unchecked(*self as usize)
+ }
+ }
+}
+
+
+// struct StateMachine<P: Parser> {
+// state: State,
+// }
+//
+// trait Parser {
+// fn csi_entry(&mut self, c: char);
+// fn csi_param(&mut self, c: char);
+// }
+//
+// struct Foo;
+//
+// impl Parser for Foo {
+// fn csi_entry(&mut self, c: char) {
+// println!("csi_entry char={:?}", c);
+// }
+// fn csi_param(&mut self, c: char) {
+// println!("csi_param char={:?}", c);
+// }
+// }
+//
+// #[test]
+// fn it_works() {
+// let table: u8 = &[Parser::csi_entry, Parser::csi_param];
+// let mut foo = Foo;
+// table[0](&mut foo, 'b');
+// }
+
diff --git a/src/table.rs.in b/src/table.rs.in
new file mode 100644
index 0000000..9c39f5e
--- /dev/null
+++ b/src/table.rs.in
@@ -0,0 +1,214 @@
+/// This is the state change table. It's indexed first by current state and then by the next
+/// character in the pty stream.
+///
+/// TODO implement a syntax extension that runs via syntex in build.rs to actually turn this into a
+/// table.
+static STATE_CHANGE: [[u8; 256]; 16] = state_table! {
+ State::Anywhere => {
+ 0x18 => (Action::Execute, State::Ground),
+ 0x1a => (Action::Execute, State::Ground),
+ 0x80...0x8f => (Action::Execute, State::Ground),
+ 0x91...0x97 => (Action::Execute, State::Ground),
+ 0x99 => (Action::Execute, State::Ground),
+ 0x9a => (Action::Execute, State::Ground),
+ 0x9c => (Action::Execute, State::Ground),
+ 0x1b => State::Escape,
+ 0x98 => State::SosPmApcString,
+ 0x9e => State::SosPmApcString,
+ 0x9f => State::SosPmApcString,
+ 0x90 => State::DcsEntry,
+ 0x9d => State::OscString,
+ 0x9b => State::CsiEntry,
+ },
+
+ State::Ground => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x20...0x7f => Action::Print,
+ 0x80...0x8f => Action::Execute,
+ 0x91...0x9a => Action::Execute,
+ 0x9c => Action::Execute
+ },
+
+ State::Escape => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x7f => Action::Ignore,
+ 0x20...0x2f => (Action::Collect, State::EscapeIntermediate),
+ 0x30...0x4f => (Action::EscDispatch, State::Ground),
+ 0x51...0x57 => (Action::EscDispatch, State::Ground),
+ 0x59 => (Action::EscDispatch, State::Ground),
+ 0x5a => (Action::EscDispatch, State::Ground),
+ 0x5c => (Action::EscDispatch, State::Ground),
+ 0x60...0x7e => (Action::EscDispatch, State::Ground),
+ 0x5b => State::CsiEntry,
+ 0x5d => State::OscString,
+ 0x50 => State::DcsEntry,
+ 0x58 => State::SosPmApcString,
+ 0x5e => State::SosPmApcString,
+ 0x5f => State::SosPmApcString,
+ },
+
+ State::EscapeIntermediate => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x20...0x2f => Action::Collect,
+ 0x7f => Action::Ignore,
+ 0x30...0x7e => (Action::EscDispatch, State::Ground)
+ },
+
+ State::CsiEntry => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x7f => Action::Ignore,
+ 0x20...0x2f => (Action::Collect, State::CsiIntermediate),
+ 0x3a => State::CsiIgnore,
+ 0x30...0x39 => (Action::Param, State::CsiParam),
+ 0x3b => (Action::Param, State::CsiParam),
+ 0x3c...0x3f => (Action::Collect, State::CsiParam),
+ 0x40...0x7e => (Action::CsiDispatch, State::Ground)
+ },
+
+ State::CsiIgnore => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x20...0x3f => Action::Ignore,
+ 0x7f => Action::Ignore,
+ 0x40...0x7e => State::Ground,
+ },
+
+ State::CsiParam => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x30...0x39 => Action::Param,
+ 0x3b => Action::Param,
+ 0x7f => Action::Ignore,
+ 0x3a => State::CsiIgnore,
+ 0x3c...0x3f => State::CsiIgnore,
+ 0x20...0x2f => (Action::Collect, State::CsiIntermediate),
+ 0x40...0x7e => (Action::CsiDispatch, State::Ground)
+ },
+
+ State::CsiIntermediate => {
+ 0x00...0x17 => Action::Execute,
+ 0x19 => Action::Execute,
+ 0x1c...0x1f => Action::Execute,
+ 0x20...0x2f => Action::Collect,
+ 0x7f => Action::Ignore,
+ 0x30...0x3f => State::CsiIgnore,
+ 0x40...0x7e => (Action::CsiDispatch, State::Ground),
+ },
+
+ State::DcsEntry => {
+ 0x00...0x17 => Action::Ignore,
+ 0x19 => Action::Ignore,
+ 0x1c...0x1f => Action::Ignore,
+ 0x7f => Action::Ignore,
+ 0x3a => State::DcsIgnore,
+ 0x20...0x2f => (Action::Collect, State::DcsIntermediate),
+ 0x30...0x39 => (Action::Param, State::DcsParam),
+ 0x3b => (Action::Param, State::DcsParam),
+ 0x3c...0x3f => (Action::Collect, State::DcsParam),
+ 0x40...0x7e => State::DcsPassthrough
+ },
+
+ State::DcsIntermediate => {
+ 0x00...0x17 => Action::Ignore,
+ 0x19 => Action::Ignore,
+ 0x1c...0x1f => Action::Ignore,
+ 0x20...0x2f => Action::Collect,
+ 0x7f => Action::Ignore,
+ 0x30...0x3f => State::DcsIgnore,
+ 0x40...0x7e => State::DcsPassthrough
+ },
+
+ State::DcsIgnore => {
+ 0x00...0x17 => Action::Ignore,
+ 0x19 => Action::Ignore,
+ 0x1c...0x1f => Action::Ignore,
+ 0x20...0x7f => Action::Ignore,
+ 0x9c => State::Ground
+ },
+
+ State::DcsParam => {
+ 0x00...0x17 => Action::Ignore,
+ 0x19 => Action::Ignore,
+ 0x1c...0x1f => Action::Ignore,
+ 0x30...0x39 => Action::Param,
+ 0x3b => Action::Param,
+ 0x7f => Action::Ignore,
+ 0x3a => State::DcsIgnore,
+ 0x3c...0x3f => State::DcsIgnore,
+ 0x20...0x2f => (Action::Collect, State::DcsIntermediate),
+ 0x40...0x7e => State::DcsPassthrough
+ },
+
+ State::DcsPassthrough => {
+ 0x00...0x17 => Action::Put,
+ 0x19 => Action::Put,
+ 0x1c...0x1f => Action::Put,
+ 0x20...0x7e => Action::Put,
+ 0x7f => Action::Ignore,
+ 0x9c => State::Ground,
+ },
+
+ State::SosPmApcString => {
+ 0x00...0x17 => Action::Ignore,
+ 0x19 => Action::Ignore,
+ 0x1c...0x1f => Action::Ignore,
+ 0x20...0x7f => Action::Ignore,
+ 0x9c => State::Ground
+ },
+
+ State::OscString => {
+ 0x00...0x17 => Action::Ignore,
+ 0x19 => Action::Ignore,
+ 0x1c...0x1f => Action::Ignore,
+ 0x20...0x7f => Action::OscPut,
+ 0x9c => State::Ground,
+ }
+};
+
+static ENTRY_ACTIONS: &'static [Action] = &[
+ Action::None, // State::Anywhere
+ Action::Clear, // State::CsiEntry
+ Action::None, // State::CsiIgnore
+ Action::None, // State::CsiIntermediate
+ Action::None, // State::CsiParam
+ Action::Clear, // State::DcsEntry
+ Action::None, // State::DcsIgnore
+ Action::None, // State::DcsIntermediate
+ Action::None, // State::DcsParam
+ Action::Hook, // State::DcsPassthrough
+ Action::Clear, // State::Escape
+ Action::None, // State::EscapeIntermediate
+ Action::None, // State::Ground
+ Action::OscStart, // State::OscString
+ Action::None, // State::SosPmApcString
+ Action::None, // State::Unused__
+];
+
+static EXIT_ACTIONS: &'static [Action] = &[
+ Action::None, // State::Anywhere
+ Action::None, // State::CsiEntry
+ Action::None, // State::CsiIgnore
+ Action::None, // State::CsiIntermediate
+ Action::None, // State::CsiParam
+ Action::None, // State::DcsEntry
+ Action::None, // State::DcsIgnore
+ Action::None, // State::DcsIntermediate
+ Action::None, // State::DcsParam
+ Action::Unhook, // State::DcsPassthrough
+ Action::None, // State::Escape
+ Action::None, // State::EscapeIntermediate
+ Action::None, // State::Ground
+ Action::OscEnd, // State::OscString
+ Action::None, // State::SosPmApcString
+ Action::None, // State::Unused__
+];