From dfc587b61fc6b5783fd0986ad089ef44accc8506 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy <mmstickman@gmail.com> Date: Sun, 29 Oct 2017 10:53:19 -0400 Subject: [PATCH] Statement Splitter Optimization --- Cargo.lock | 134 +++++++++++++++++--------- Cargo.toml | 4 +- src/parser/assignments/actions.rs | 6 +- src/parser/pipelines/collector.rs | 10 +- src/parser/statement/splitter.rs | 151 +++++++++++++++--------------- src/shell/variables/mod.rs | 21 ++--- 6 files changed, 190 insertions(+), 136 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48504811..9b292005 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,34 +1,9 @@ -[root] -name = "ion-shell" -version = "1.0.5" -dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "app_dirs 1.1.1 (git+https://github.com/redox-os/app-dirs-rs.git)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "calculate 0.3.0 (git+https://github.com/redox-os/calc.git)", - "errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "permutate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "users 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -47,6 +22,17 @@ dependencies = [ "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "atty" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.9.1" @@ -64,10 +50,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "calculate" -version = "0.3.0" -source = "git+https://github.com/redox-os/calc.git#9e1ddfe012d488f7a0659e9d77e011f49b184ea8" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)", "decimal 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -77,10 +79,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "ord_subset 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -89,7 +91,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -108,6 +110,31 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ion-shell" +version = "1.0.5" +dependencies = [ + "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.1.1 (git+https://github.com/redox-os/app-dirs-rs.git)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "calculate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "permutate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "users 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -124,7 +151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -149,10 +176,10 @@ dependencies = [ [[package]] name = "memchr" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -193,7 +220,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -211,7 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -241,16 +268,29 @@ name = "smallvec" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strsim" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "textwrap" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread_local" version = "0.3.4" @@ -283,7 +323,7 @@ name = "users" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -291,6 +331,11 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vec_map" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "version_check" version = "0.1.3" @@ -320,10 +365,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum app_dirs 1.1.1 (git+https://github.com/redox-os/app-dirs-rs.git)" = "<none>" +"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989" "checksum bytecount 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4bbeb7c30341fce29f6078b4bdf876ea4779600866e98f5b2d203a534f195050" -"checksum calculate 0.3.0 (git+https://github.com/redox-os/calc.git)" = "<none>" +"checksum calculate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5df70b5da660f26e3bd2c59160178ddd6afbbc58221f8fcbc5f6f88d17afb080" +"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" "checksum decimal 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8e3bfe070d7876527c8f901afc27b4190a715b6e52c8961f72fb35430960e80" "checksum errno 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2c858c42ac0b88532f48fca88b0ed947cad4f1f64d904bcd6c9f138f7b95d70" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" @@ -331,10 +378,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5" -"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148" +"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum libloading 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f92926a9a4ba7aeeb01f5fba3f0d577147243b6e7fa8261c219cd1d6fbe3b1c" "checksum liner 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aff4455f523eb06630ad00ea139701ba51a5425d0a8163935e7bb1841c81e6e8" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum ord_subset 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb8b8c275824bc609c8294f20a55d37d808a1b071cec596da746ce4df0405e8" "checksum permutate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53b7d5b19a715ffab38693a9dd44b067fdfa2b18eef65bd93562dfe507022fae" @@ -343,18 +390,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799" +"checksum serde 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e11a631f964d4e6572712ea12075fb1d65eeef42b0058884195b430ac1e26809" "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d" "checksum smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30950abdb5b38f56a0e181ae56ed64a539b64fa77ea6325147203dc7faeb087f" "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" "checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c" +"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum users 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e7d8fb16f17ce0e6a18a25ce39f08edb5fbe9a25f3f346c9dca5e6ffc0485cdf" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/Cargo.toml b/Cargo.toml index 87c359c4..774fb010 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ version_check = "0.1.3" [dependencies] bitflags = "0.9.1" +calculate = "0.5" fnv = "1.0" glob = "0.2" lazy_static = "0.2" @@ -38,9 +39,6 @@ unicode-segmentation = "1.2" [dependencies.app_dirs] git = "https://github.com/redox-os/app-dirs-rs.git" -[dependencies.calculate] -git = "https://github.com/redox-os/calc.git" - [profile.release] panic = "abort" diff --git a/src/parser/assignments/actions.rs b/src/parser/assignments/actions.rs index 3793ab79..5c0f04c0 100644 --- a/src/parser/assignments/actions.rs +++ b/src/parser/assignments/actions.rs @@ -165,8 +165,7 @@ mod tests { ); let (keys, op, vals) = split("a b[] c:int[] = one [two three] [4 5 6]"); - let actions = AssignmentActions::new(&keys, op, &vals) - .collect::<Vec<_>>(); + let actions = AssignmentActions::new(&keys, op, &vals).collect::<Vec<_>>(); assert_eq!(actions.len(), 3); assert_eq!( actions[0], @@ -203,8 +202,7 @@ mod tests { ); let (keys, op, values) = split("a[] b c[] = [one two] three [four five]"); - let actions = AssignmentActions::new(&keys, op, &values) - .collect::<Vec<_>>(); + let actions = AssignmentActions::new(&keys, op, &values).collect::<Vec<_>>(); assert_eq!(actions.len(), 3); assert_eq!( actions[0], diff --git a/src/parser/pipelines/collector.rs b/src/parser/pipelines/collector.rs index c5a647e7..3df924bd 100644 --- a/src/parser/pipelines/collector.rs +++ b/src/parser/pipelines/collector.rs @@ -345,9 +345,13 @@ impl<'a> Collector<'a> { }; let heredoc = heredoc.lines().collect::<Vec<&str>>(); // Then collect the heredoc from standard input. - inputs.as_mut().map(|x| { - x.push(Input::HereString(heredoc[1..heredoc.len() - 1].join("\n"))) - }); + inputs.as_mut().map( + |x| { + x.push( + Input::HereString(heredoc[1..heredoc.len() - 1].join("\n")), + ) + }, + ); } } else if let Some(file) = self.arg(&mut bytes)? { // Otherwise interpret it as stdin redirection diff --git a/src/parser/statement/splitter.rs b/src/parser/statement/splitter.rs index 6cf29e7a..4baac1ce 100644 --- a/src/parser/statement/splitter.rs +++ b/src/parser/statement/splitter.rs @@ -7,18 +7,16 @@ use std::u16; bitflags! { pub struct Flags : u16 { - const SQUOTE = 1; - const DQUOTE = 2; - const BACKSL = 4; - const COMM_1 = 8; - const COMM_2 = 16; - const VBRACE = 32; - const ARRAY = 64; - const VARIAB = 128; - const METHOD = 256; + const DQUOTE = 1; + const COMM_1 = 2; + const COMM_2 = 4; + const VBRACE = 8; + const ARRAY = 16; + const VARIAB = 32; + const METHOD = 64; /// Set while parsing through an inline arithmetic expression, e.g. $((foo * bar / baz)) - const MATHEXPR = 512; - const POST_MATHEXPR = 1024; + const MATHEXPR = 128; + const POST_MATHEXPR = 256; } } @@ -65,29 +63,49 @@ impl<'a> Display for StatementError<'a> { } } +/// Returns true if the byte matches [^A-Za-z0-9_] +fn is_invalid(byte: u8) -> bool { + byte <= 47 || (byte >= 58 && byte <= 64) || (byte >= 91 && byte <= 94) || byte == 96 + || (byte >= 123 && byte <= 127) +} + pub(crate) struct StatementSplitter<'a> { - data: &'a str, - read: usize, - flags: Flags, - array_level: u8, - array_process_level: u8, - process_level: u8, - brace_level: u8, - math_paren_level: i8, + data: &'a str, + read: usize, + flags: Flags, + a_level: u8, + ap_level: u8, + p_level: u8, + brace_level: u8, + math_paren_level: i8, } impl<'a> StatementSplitter<'a> { pub(crate) fn new(data: &'a str) -> StatementSplitter<'a> { StatementSplitter { - data: data, - read: 0, - flags: Flags::empty(), - array_level: 0, - array_process_level: 0, - process_level: 0, - brace_level: 0, - math_paren_level: 0, + data: data, + read: 0, + flags: Flags::empty(), + a_level: 0, + ap_level: 0, + p_level: 0, + brace_level: 0, + math_paren_level: 0, + } + } + + fn single_quote<B: Iterator<Item = u8>>(&mut self, bytes: &mut B) -> usize { + let mut read = 0; + while let Some(character) = bytes.next() { + read += 1; + if character == b'\\' { + read += 1; + bytes.next(); + } else if character == b'\'' { + break; + } } + read } } @@ -99,9 +117,14 @@ impl<'a> Iterator for StatementSplitter<'a> { let mut else_found = false; let mut else_pos = 0; let mut error = None; - for character in self.data.bytes().skip(self.read) { + let mut bytes = self.data.bytes().skip(self.read); + while let Some(character) = bytes.next() { self.read += 1; match character { + b'\\' => { + self.read += 1; + bytes.next(); + } _ if self.flags.contains(POST_MATHEXPR) => { self.flags -= POST_MATHEXPR; } @@ -114,30 +137,25 @@ impl<'a> Iterator for StatementSplitter<'a> { error = Some(StatementError::InvalidCharacter(character as char, self.read)) } } - _ if self.flags.contains(BACKSL) => self.flags.toggle(BACKSL), - b'\\' => self.flags.toggle(BACKSL), b'\'' if !self.flags.contains(DQUOTE) => { - self.flags.toggle(SQUOTE); - self.flags -= VARIAB | ARRAY; - } - b'"' if !self.flags.contains(SQUOTE) => { - self.flags.toggle(DQUOTE); self.flags -= VARIAB | ARRAY; + self.read += self.single_quote(&mut bytes); } - b'@' if !self.flags.contains(SQUOTE) => { - self.flags -= COMM_1; - self.flags |= COMM_2 | ARRAY; + // Toggle DQUOTE and disable VARIAB + ARRAY. + b'"' => self.flags = (self.flags ^ DQUOTE) - (VARIAB | ARRAY), + // Disable COMM_1 and enable COMM_2 + ARRAY. + b'@' => { + self.flags = (self.flags - COMM_1) | (COMM_2 | ARRAY); continue; } - b'$' if !self.flags.contains(SQUOTE) => { - self.flags -= COMM_2; - self.flags |= COMM_1 | VARIAB; + b'$' => { + self.flags = (self.flags - COMM_2) | (COMM_1 | VARIAB); continue; } b'{' if self.flags.intersects(COMM_1 | COMM_2) => self.flags |= VBRACE, - b'{' if !self.flags.intersects(SQUOTE | DQUOTE) => self.brace_level += 1, + b'{' if !self.flags.contains(DQUOTE) => self.brace_level += 1, b'}' if self.flags.contains(VBRACE) => self.flags.toggle(VBRACE), - b'}' if !self.flags.intersects(SQUOTE | DQUOTE) => if self.brace_level == 0 { + b'}' if !self.flags.contains(DQUOTE) => if self.brace_level == 0 { if error.is_none() { error = Some(StatementError::InvalidCharacter(character as char, self.read)) } @@ -148,27 +166,25 @@ impl<'a> Iterator for StatementSplitter<'a> { self.math_paren_level += 1; } b'(' if !self.flags.intersects(COMM_1 | VARIAB | ARRAY) => { - if error.is_none() && !self.flags.intersects(SQUOTE | DQUOTE) { + if error.is_none() && !self.flags.contains(DQUOTE) { error = Some(StatementError::InvalidCharacter(character as char, self.read)) } } b'(' if self.flags.intersects(COMM_1 | METHOD) => { self.flags -= VARIAB | ARRAY; if self.data.as_bytes()[self.read] == b'(' { - self.flags -= COMM_1; - self.flags |= MATHEXPR; + self.flags = (self.flags - COMM_1) | MATHEXPR; // The next character will always be a left paren in this branch; self.math_paren_level = -1; } else { - self.process_level += 1; + self.p_level += 1; } } b'(' if self.flags.contains(COMM_2) => { - self.array_process_level += 1; + self.ap_level += 1; } b'(' if self.flags.intersects(VARIAB | ARRAY) => { - self.flags -= VARIAB | ARRAY; - self.flags |= METHOD; + self.flags = (self.flags - (VARIAB | ARRAY)) | METHOD; } b')' if self.flags.contains(MATHEXPR) => if self.math_paren_level == 0 { if self.data.as_bytes().len() <= self.read { @@ -178,8 +194,7 @@ impl<'a> Iterator for StatementSplitter<'a> { } else { let next_character = self.data.as_bytes()[self.read] as char; if next_character == ')' { - self.flags -= MATHEXPR; - self.flags |= POST_MATHEXPR; + self.flags = (self.flags - MATHEXPR) | POST_MATHEXPR; } else if error.is_none() { error = Some(StatementError::InvalidCharacter(next_character, self.read)); @@ -188,33 +203,24 @@ impl<'a> Iterator for StatementSplitter<'a> { } else { self.math_paren_level -= 1; }, - b')' if !self.flags.contains(SQUOTE) && self.flags.contains(METHOD) - && self.process_level == 0 => - { + b')' if self.flags.contains(METHOD) && self.p_level == 0 => { self.flags ^= METHOD; } - b')' if self.process_level == 0 && self.array_process_level == 0 - && !self.flags.contains(SQUOTE) => - { - if error.is_none() && !self.flags.intersects(SQUOTE | DQUOTE) { + b')' if self.p_level + self.ap_level == 0 => { + if error.is_none() && !self.flags.contains(DQUOTE) { error = Some(StatementError::InvalidCharacter(character as char, self.read)) } } - b')' if !self.flags.contains(SQUOTE) && self.process_level != 0 => { - self.process_level -= 1 - } - b')' if !self.flags.contains(SQUOTE) => self.array_process_level -= 1, - b';' if !self.flags.intersects(SQUOTE | DQUOTE) && self.process_level == 0 - && self.array_process_level == 0 => - { + b')' if self.p_level != 0 => self.p_level -= 1, + b')' => self.ap_level -= 1, + b';' if !self.flags.contains(DQUOTE) && self.p_level == 0 && self.ap_level == 0 => { return match error { Some(error) => Some(Err(error)), None => Some(Ok(self.data[start..self.read - 1].trim())), } } b'#' if self.read == 1 - || (!self.flags.intersects(SQUOTE | DQUOTE) && self.process_level == 0 - && self.array_process_level == 0 + || (!self.flags.contains(DQUOTE) && self.p_level + self.ap_level == 0 && match self.data.as_bytes()[self.read - 2] { b' ' | b'\t' => true, _ => false, @@ -250,8 +256,9 @@ impl<'a> Iterator for StatementSplitter<'a> { } } // [^A-Za-z0-9_] - 0...47 | 58...64 | 91...94 | 96 | 123...127 => self.flags -= VARIAB | ARRAY, - _ => (), + byte => if self.flags.intersects(VARIAB | ARRAY) { + self.flags -= if is_invalid(byte) { VARIAB | ARRAY } else { Flags::empty() }; + }, } self.flags -= COMM_1 | COMM_2; } @@ -262,9 +269,7 @@ impl<'a> Iterator for StatementSplitter<'a> { self.read = self.data.len(); match error { Some(error) => Some(Err(error)), - None if self.process_level != 0 || self.array_process_level != 0 - || self.array_level != 0 => - { + None if self.p_level != 0 || self.ap_level != 0 || self.a_level != 0 => { Some(Err(StatementError::UnterminatedSubshell)) } None if self.flags.contains(METHOD) => { diff --git a/src/shell/variables/mod.rs b/src/shell/variables/mod.rs index 5cd382db..aca03d0a 100644 --- a/src/shell/variables/mod.rs +++ b/src/shell/variables/mod.rs @@ -112,21 +112,20 @@ impl Variables { } pub fn set_var(&mut self, name: &str, value: &str) { - if name == "NS_PLUGINS" { - match value { - "0" => self.disable_plugins(), - "1" => self.enable_plugins(), - _ => { - eprintln!("ion: unsupported value for NS_PLUGINS. Value must be either 0 or 1.") - } - } - return; - } - if !name.is_empty() { if value.is_empty() { self.variables.remove(name); } else { + if name == "NS_PLUGINS" { + match value { + "0" => self.disable_plugins(), + "1" => self.enable_plugins(), + _ => eprintln!( + "ion: unsupported value for NS_PLUGINS. Value must be either 0 or 1." + ), + } + return; + } self.variables.insert(name.into(), value.into()); } } -- GitLab