module ShellCheck.ASTLib where
import ShellCheck.AST
import Control.Monad.Writer
import Control.Monad
import Data.Char
import Data.Functor
import Data.List
import Data.Maybe
isLoop :: Token -> Bool
isLoop t :: Token
t = case Token
t of
T_WhileExpression {} -> Bool
True
T_UntilExpression {} -> Bool
True
T_ForIn {} -> Bool
True
T_ForArithmetic {} -> Bool
True
T_SelectIn {} -> Bool
True
_ -> Bool
False
willSplit :: Token -> Bool
willSplit x :: Token
x =
case Token
x of
T_DollarBraced {} -> Bool
True
T_DollarExpansion {} -> Bool
True
T_Backticked {} -> Bool
True
T_BraceExpansion {} -> Bool
True
T_Glob {} -> Bool
True
T_Extglob {} -> Bool
True
T_NormalWord _ l :: [Token]
l -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
willSplit [Token]
l
_ -> Bool
False
isGlob :: Token -> Bool
isGlob T_Extglob {} = Bool
True
isGlob T_Glob {} = Bool
True
isGlob (T_NormalWord _ l :: [Token]
l) = (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
isGlob [Token]
l
isGlob _ = Bool
False
isConstant :: Token -> Bool
isConstant token :: Token
token =
case Token
token of
T_NormalWord _ (T_Literal _ ('~':_) : _) -> Bool
False
T_NormalWord _ l :: [Token]
l -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Token -> Bool
isConstant [Token]
l
T_DoubleQuoted _ l :: [Token]
l -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Token -> Bool
isConstant [Token]
l
T_SingleQuoted _ _ -> Bool
True
T_Literal _ _ -> Bool
True
_ -> Bool
False
isEmpty :: Token -> Bool
isEmpty token :: Token
token =
case Token
token of
T_NormalWord _ l :: [Token]
l -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Token -> Bool
isEmpty [Token]
l
T_DoubleQuoted _ l :: [Token]
l -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Token -> Bool
isEmpty [Token]
l
T_SingleQuoted _ "" -> Bool
True
T_Literal _ "" -> Bool
True
_ -> Bool
False
oversimplify :: Token -> [[Char]]
oversimplify token :: Token
token =
case Token
token of
(T_NormalWord _ l :: [Token]
l) -> [[[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ((Token -> [[Char]]) -> [Token] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [[Char]]
oversimplify [Token]
l)]
(T_DoubleQuoted _ l :: [Token]
l) -> [[[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ((Token -> [[Char]]) -> [Token] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [[Char]]
oversimplify [Token]
l)]
(T_SingleQuoted _ s :: [Char]
s) -> [[Char]
s]
(T_DollarBraced _ _ _) -> ["${VAR}"]
(T_DollarArithmetic _ _) -> ["${VAR}"]
(T_DollarExpansion _ _) -> ["${VAR}"]
(T_Backticked _ _) -> ["${VAR}"]
(T_Glob _ s :: [Char]
s) -> [[Char]
s]
(T_Pipeline _ _ [x :: Token
x]) -> Token -> [[Char]]
oversimplify Token
x
(T_Literal _ x :: [Char]
x) -> [[Char]
x]
(T_ParamSubSpecialChar _ x :: [Char]
x) -> [[Char]
x]
(T_SimpleCommand _ vars :: [Token]
vars words :: [Token]
words) -> (Token -> [[Char]]) -> [Token] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [[Char]]
oversimplify [Token]
words
(T_Redirecting _ _ foo :: Token
foo) -> Token -> [[Char]]
oversimplify Token
foo
(T_DollarSingleQuoted _ s :: [Char]
s) -> [[Char]
s]
(T_Annotation _ _ s :: Token
s) -> Token -> [[Char]]
oversimplify Token
s
(TA_Sequence _ [TA_Expansion _ v :: [Token]
v]) -> (Token -> [[Char]]) -> [Token] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [[Char]]
oversimplify [Token]
v
_ -> []
getFlagsUntil :: ([Char] -> Bool) -> Token -> [(Token, [Char])]
getFlagsUntil stopCondition :: [Char] -> Bool
stopCondition (T_SimpleCommand _ _ (_:args :: [Token]
args)) =
let tokenAndText :: [(Token, [Char])]
tokenAndText = (Token -> (Token, [Char])) -> [Token] -> [(Token, [Char])]
forall a b. (a -> b) -> [a] -> [b]
map (\x :: Token
x -> (Token
x, [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ Token -> [[Char]]
oversimplify Token
x)) [Token]
args
(flagArgs :: [(Token, [Char])]
flagArgs, rest :: [(Token, [Char])]
rest) = ((Token, [Char]) -> Bool)
-> [(Token, [Char])] -> ([(Token, [Char])], [(Token, [Char])])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break ([Char] -> Bool
stopCondition ([Char] -> Bool)
-> ((Token, [Char]) -> [Char]) -> (Token, [Char]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token, [Char]) -> [Char]
forall a b. (a, b) -> b
snd) [(Token, [Char])]
tokenAndText
in
((Token, [Char]) -> [(Token, [Char])])
-> [(Token, [Char])] -> [(Token, [Char])]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Token, [Char]) -> [(Token, [Char])]
forall a. (a, [Char]) -> [(a, [Char])]
flag [(Token, [Char])]
flagArgs [(Token, [Char])] -> [(Token, [Char])] -> [(Token, [Char])]
forall a. [a] -> [a] -> [a]
++ ((Token, [Char]) -> (Token, [Char]))
-> [(Token, [Char])] -> [(Token, [Char])]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: Token
t, _) -> (Token
t, "")) [(Token, [Char])]
rest
where
flag :: (a, [Char]) -> [(a, [Char])]
flag (x :: a
x, '-':'-':arg :: [Char]
arg) = [ (a
x, (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '=') [Char]
arg) ]
flag (x :: a
x, '-':args :: [Char]
args) = (Char -> (a, [Char])) -> [Char] -> [(a, [Char])]
forall a b. (a -> b) -> [a] -> [b]
map (\v :: Char
v -> (a
x, [Char
v])) [Char]
args
flag (x :: a
x, _) = [ (a
x, "") ]
getFlagsUntil _ _ = [Char] -> [(Token, [Char])]
forall a. HasCallStack => [Char] -> a
error "Internal shellcheck error, please report! (getFlags on non-command)"
getAllFlags :: Token -> [(Token, String)]
getAllFlags :: Token -> [(Token, [Char])]
getAllFlags = ([Char] -> Bool) -> Token -> [(Token, [Char])]
getFlagsUntil ([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== "--")
getLeadingFlags :: Token -> [(Token, [Char])]
getLeadingFlags = ([Char] -> Bool) -> Token -> [(Token, [Char])]
getFlagsUntil (\x :: [Char]
x -> [Char]
x [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== "--" Bool -> Bool -> Bool
|| (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ "-" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
x))
hasFlag :: Token -> [Char] -> Bool
hasFlag cmd :: Token
cmd str :: [Char]
str = [Char]
str [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (((Token, [Char]) -> [Char]) -> [(Token, [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (Token, [Char]) -> [Char]
forall a b. (a, b) -> b
snd ([(Token, [Char])] -> [[Char]]) -> [(Token, [Char])] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ Token -> [(Token, [Char])]
getAllFlags Token
cmd)
isFlag :: Token -> Bool
isFlag token :: Token
token =
case Token -> [Token]
getWordParts Token
token of
T_Literal _ ('-':_) : _ -> Bool
True
_ -> Bool
False
isUnquotedFlag :: Token -> Bool
isUnquotedFlag token :: Token
token = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
[Char]
str <- Token -> Maybe [Char]
getLeadingUnquotedString Token
token
Bool -> Maybe Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Maybe Bool) -> Bool -> Maybe Bool
forall a b. (a -> b) -> a -> b
$ "-" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
str
bracedString :: Token -> [Char]
bracedString (T_DollarBraced _ _ l :: Token
l) = [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ Token -> [[Char]]
oversimplify Token
l
bracedString _ = [Char] -> [Char]
forall a. HasCallStack => [Char] -> a
error "Internal shellcheck error, please report! (bracedString on non-variable)"
isArrayExpansion :: Token -> Bool
isArrayExpansion t :: Token
t@(T_DollarBraced _ _ _) =
let string :: [Char]
string = Token -> [Char]
bracedString Token
t in
"@" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
string Bool -> Bool -> Bool
||
Bool -> Bool
not ("#" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
string) Bool -> Bool -> Bool
&& "[@]" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` [Char]
string
isArrayExpansion _ = Bool
False
mayBecomeMultipleArgs :: Token -> Bool
mayBecomeMultipleArgs t :: Token
t = Token -> Bool
willBecomeMultipleArgs Token
t Bool -> Bool -> Bool
|| Token -> Bool
f Token
t
where
f :: Token -> Bool
f t :: Token
t@(T_DollarBraced _ _ _) =
let string :: [Char]
string = Token -> [Char]
bracedString Token
t in
"!" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
string
f (T_DoubleQuoted _ parts :: [Token]
parts) = (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
f [Token]
parts
f (T_NormalWord _ parts :: [Token]
parts) = (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
f [Token]
parts
f _ = Bool
False
willBecomeMultipleArgs :: Token -> Bool
willBecomeMultipleArgs t :: Token
t = Token -> Bool
willConcatInAssignment Token
t Bool -> Bool -> Bool
|| Token -> Bool
f Token
t
where
f :: Token -> Bool
f T_Extglob {} = Bool
True
f T_Glob {} = Bool
True
f T_BraceExpansion {} = Bool
True
f (T_DoubleQuoted _ parts :: [Token]
parts) = (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
f [Token]
parts
f (T_NormalWord _ parts :: [Token]
parts) = (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
f [Token]
parts
f _ = Bool
False
willConcatInAssignment :: Token -> Bool
willConcatInAssignment token :: Token
token =
case Token
token of
t :: Token
t@T_DollarBraced {} -> Token -> Bool
isArrayExpansion Token
t
(T_DoubleQuoted _ parts :: [Token]
parts) -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
willConcatInAssignment [Token]
parts
(T_NormalWord _ parts :: [Token]
parts) -> (Token -> Bool) -> [Token] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Token -> Bool
willConcatInAssignment [Token]
parts
_ -> Bool
False
getLiteralString :: Token -> Maybe String
getLiteralString :: Token -> Maybe [Char]
getLiteralString = (Token -> Maybe [Char]) -> Token -> Maybe [Char]
getLiteralStringExt (Maybe [Char] -> Token -> Maybe [Char]
forall a b. a -> b -> a
const Maybe [Char]
forall a. Maybe a
Nothing)
onlyLiteralString :: Token -> String
onlyLiteralString :: Token -> [Char]
onlyLiteralString = Maybe [Char] -> [Char]
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe [Char] -> [Char])
-> (Token -> Maybe [Char]) -> Token -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token -> Maybe [Char]) -> Token -> Maybe [Char]
getLiteralStringExt (Maybe [Char] -> Token -> Maybe [Char]
forall a b. a -> b -> a
const (Maybe [Char] -> Token -> Maybe [Char])
-> Maybe [Char] -> Token -> Maybe [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return "")
getUnquotedLiteral :: Token -> Maybe [Char]
getUnquotedLiteral (T_NormalWord _ list :: [Token]
list) =
[[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Char]] -> [Char]) -> Maybe [[Char]] -> Maybe [Char]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Token -> Maybe [Char]) -> [Token] -> Maybe [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Token -> Maybe [Char]
str [Token]
list
where
str :: Token -> Maybe [Char]
str (T_Literal _ s :: [Char]
s) = [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
s
str _ = Maybe [Char]
forall a. Maybe a
Nothing
getUnquotedLiteral _ = Maybe [Char]
forall a. Maybe a
Nothing
getTrailingUnquotedLiteral :: Token -> Maybe Token
getTrailingUnquotedLiteral :: Token -> Maybe Token
getTrailingUnquotedLiteral t :: Token
t =
case Token
t of
(T_NormalWord _ list :: [Token]
list@(_:_)) ->
Token -> Maybe Token
from ([Token] -> Token
forall a. [a] -> a
last [Token]
list)
_ -> Maybe Token
forall a. Maybe a
Nothing
where
from :: Token -> Maybe Token
from t :: Token
t =
case Token
t of
T_Literal {} -> Token -> Maybe Token
forall (m :: * -> *) a. Monad m => a -> m a
return Token
t
_ -> Maybe Token
forall a. Maybe a
Nothing
getLeadingUnquotedString :: Token -> Maybe String
getLeadingUnquotedString :: Token -> Maybe [Char]
getLeadingUnquotedString t :: Token
t =
case Token
t of
T_NormalWord _ ((T_Literal _ s :: [Char]
s) : _) -> [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
s
_ -> Maybe [Char]
forall a. Maybe a
Nothing
getGlobOrLiteralString :: Token -> Maybe [Char]
getGlobOrLiteralString = (Token -> Maybe [Char]) -> Token -> Maybe [Char]
getLiteralStringExt Token -> Maybe [Char]
f
where
f :: Token -> Maybe [Char]
f (T_Glob _ str :: [Char]
str) = [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
str
f _ = Maybe [Char]
forall a. Maybe a
Nothing
getLiteralStringExt :: (Token -> Maybe String) -> Token -> Maybe String
getLiteralStringExt :: (Token -> Maybe [Char]) -> Token -> Maybe [Char]
getLiteralStringExt more :: Token -> Maybe [Char]
more = Token -> Maybe [Char]
g
where
allInList :: [Token] -> Maybe [Char]
allInList = ([[Char]] -> [Char]) -> Maybe [[Char]] -> Maybe [Char]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Maybe [[Char]] -> Maybe [Char])
-> ([Token] -> Maybe [[Char]]) -> [Token] -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token -> Maybe [Char]) -> [Token] -> Maybe [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Token -> Maybe [Char]
g
g :: Token -> Maybe [Char]
g (T_DoubleQuoted _ l :: [Token]
l) = [Token] -> Maybe [Char]
allInList [Token]
l
g (T_DollarDoubleQuoted _ l :: [Token]
l) = [Token] -> Maybe [Char]
allInList [Token]
l
g (T_NormalWord _ l :: [Token]
l) = [Token] -> Maybe [Char]
allInList [Token]
l
g (TA_Expansion _ l :: [Token]
l) = [Token] -> Maybe [Char]
allInList [Token]
l
g (T_SingleQuoted _ s :: [Char]
s) = [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
s
g (T_Literal _ s :: [Char]
s) = [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
s
g (T_ParamSubSpecialChar _ s :: [Char]
s) = [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
s
g (T_DollarSingleQuoted _ s :: [Char]
s) = [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> Maybe [Char]) -> [Char] -> Maybe [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
decodeEscapes [Char]
s
g x :: Token
x = Token -> Maybe [Char]
more Token
x
decodeEscapes :: [Char] -> [Char]
decodeEscapes ('\\':c :: Char
c:cs :: [Char]
cs) =
case Char
c of
'a' -> '\a' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'b' -> '\b' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'e' -> '\x1B' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'f' -> '\f' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'n' -> '\n' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'r' -> '\r' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
't' -> '\t' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'v' -> '\v' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'\'' -> '\'' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'"' -> '"' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'\\' -> '\\' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
'x' ->
case [Char]
cs of
(x :: Char
x:y :: Char
y:more :: [Char]
more) ->
if Char -> Bool
isHexDigit Char
x Bool -> Bool -> Bool
&& Char -> Bool
isHexDigit Char
y
then Int -> Char
chr (16Int -> Int -> Int
forall a. Num a => a -> a -> a
*(Char -> Int
digitToInt Char
x) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Char -> Int
digitToInt Char
y)) Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
else '\\'Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
rest
_ | Char -> Bool
isOctDigit Char
c ->
let digits :: [Char]
digits = Int -> [Char] -> [Char]
forall a. Int -> [a] -> [a]
take 3 ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
isOctDigit (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
cs)
num :: Int
num = [Char] -> Int
parseOct [Char]
digits
in (if Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< 256 then Int -> Char
chr Int
num else '?') Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
_ -> '\\' Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: Char
c Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
rest
where
rest :: [Char]
rest = [Char] -> [Char]
decodeEscapes [Char]
cs
parseOct :: [Char] -> Int
parseOct = Int -> [Char] -> Int
f 0
where
f :: Int -> [Char] -> Int
f n :: Int
n "" = Int
n
f n :: Int
n (c :: Char
c:rest :: [Char]
rest) = Int -> [Char] -> Int
f (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* 8 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
digitToInt Char
c) [Char]
rest
decodeEscapes (c :: Char
c:cs :: [Char]
cs) = Char
c Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char] -> [Char]
decodeEscapes [Char]
cs
decodeEscapes [] = []
isLiteral :: Token -> Bool
isLiteral t :: Token
t = Maybe [Char] -> Bool
forall a. Maybe a -> Bool
isJust (Maybe [Char] -> Bool) -> Maybe [Char] -> Bool
forall a b. (a -> b) -> a -> b
$ Token -> Maybe [Char]
getLiteralString Token
t
getWordParts :: Token -> [Token]
getWordParts (T_NormalWord _ l :: [Token]
l) = (Token -> [Token]) -> [Token] -> [Token]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [Token]
getWordParts [Token]
l
getWordParts (T_DoubleQuoted _ l :: [Token]
l) = [Token]
l
getWordParts (TA_Expansion _ l :: [Token]
l) = (Token -> [Token]) -> [Token] -> [Token]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Token -> [Token]
getWordParts [Token]
l
getWordParts other :: Token
other = [Token
other]
braceExpand :: Token -> [Token]
braceExpand (T_NormalWord id :: Id
id list :: [Token]
list) = Int -> [Token] -> [Token]
forall a. Int -> [a] -> [a]
take 1000 ([Token] -> [Token]) -> [Token] -> [Token]
forall a b. (a -> b) -> a -> b
$ do
[Token]
items <- (Token -> [Token]) -> [Token] -> [[Token]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Token -> [Token]
part [Token]
list
Token -> [Token]
forall (m :: * -> *) a. Monad m => a -> m a
return (Token -> [Token]) -> Token -> [Token]
forall a b. (a -> b) -> a -> b
$ Id -> [Token] -> Token
T_NormalWord Id
id [Token]
items
where
part :: Token -> [Token]
part (T_BraceExpansion id :: Id
id items :: [Token]
items) = do
Token
item <- [Token]
items
Token -> [Token]
braceExpand Token
item
part x :: Token
x = Token -> [Token]
forall (m :: * -> *) a. Monad m => a -> m a
return Token
x
getCommand :: Token -> Maybe Token
getCommand t :: Token
t =
case Token
t of
T_Redirecting _ _ w :: Token
w -> Token -> Maybe Token
getCommand Token
w
T_SimpleCommand _ _ (w :: Token
w:_) -> Token -> Maybe Token
forall (m :: * -> *) a. Monad m => a -> m a
return Token
t
T_Annotation _ _ t :: Token
t -> Token -> Maybe Token
getCommand Token
t
_ -> Maybe Token
forall a. Maybe a
Nothing
getCommandName :: Token -> Maybe String
getCommandName :: Token -> Maybe [Char]
getCommandName = (Maybe [Char], Token) -> Maybe [Char]
forall a b. (a, b) -> a
fst ((Maybe [Char], Token) -> Maybe [Char])
-> (Token -> (Maybe [Char], Token)) -> Token -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Token -> (Maybe [Char], Token)
getCommandNameAndToken
getCommandTokenOrThis :: Token -> Token
getCommandTokenOrThis = (Maybe [Char], Token) -> Token
forall a b. (a, b) -> b
snd ((Maybe [Char], Token) -> Token)
-> (Token -> (Maybe [Char], Token)) -> Token -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Token -> (Maybe [Char], Token)
getCommandNameAndToken
getCommandNameAndToken :: Token -> (Maybe String, Token)
getCommandNameAndToken :: Token -> (Maybe [Char], Token)
getCommandNameAndToken t :: Token
t = (Maybe [Char], Token)
-> Maybe (Maybe [Char], Token) -> (Maybe [Char], Token)
forall a. a -> Maybe a -> a
fromMaybe (Maybe [Char]
forall a. Maybe a
Nothing, Token
t) (Maybe (Maybe [Char], Token) -> (Maybe [Char], Token))
-> Maybe (Maybe [Char], Token) -> (Maybe [Char], Token)
forall a b. (a -> b) -> a -> b
$ do
(T_SimpleCommand _ _ (w :: Token
w:rest :: [Token]
rest)) <- Token -> Maybe Token
getCommand Token
t
[Char]
s <- Token -> Maybe [Char]
getLiteralString Token
w
if "busybox" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` [Char]
s Bool -> Bool -> Bool
|| "builtin" [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
s
then
case [Token]
rest of
(applet :: Token
applet:_) -> (Maybe [Char], Token) -> Maybe (Maybe [Char], Token)
forall (m :: * -> *) a. Monad m => a -> m a
return (Token -> Maybe [Char]
getLiteralString Token
applet, Token
applet)
_ -> (Maybe [Char], Token) -> Maybe (Maybe [Char], Token)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
s, Token
w)
else
(Maybe [Char], Token) -> Maybe (Maybe [Char], Token)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
s, Token
w)
getCommandNameFromExpansion :: Token -> Maybe String
getCommandNameFromExpansion :: Token -> Maybe [Char]
getCommandNameFromExpansion t :: Token
t =
case Token
t of
T_DollarExpansion _ [c :: Token
c] -> Token -> Maybe [Char]
extract Token
c
T_Backticked _ [c :: Token
c] -> Token -> Maybe [Char]
extract Token
c
T_DollarBraceCommandExpansion _ [c :: Token
c] -> Token -> Maybe [Char]
extract Token
c
_ -> Maybe [Char]
forall a. Maybe a
Nothing
where
extract :: Token -> Maybe [Char]
extract (T_Pipeline _ _ [cmd :: Token
cmd]) = Token -> Maybe [Char]
getCommandName Token
cmd
extract _ = Maybe [Char]
forall a. Maybe a
Nothing
getCommandBasename :: Token -> Maybe [Char]
getCommandBasename = ([Char] -> [Char]) -> Maybe [Char] -> Maybe [Char]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Char] -> [Char]
basename (Maybe [Char] -> Maybe [Char])
-> (Token -> Maybe [Char]) -> Token -> Maybe [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Token -> Maybe [Char]
getCommandName
where
basename :: [Char] -> [Char]
basename = [Char] -> [Char]
forall a. [a] -> [a]
reverse ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '/') ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char]
forall a. [a] -> [a]
reverse
isAssignment :: Token -> Bool
isAssignment t :: Token
t =
case Token
t of
T_Redirecting _ _ w :: Token
w -> Token -> Bool
isAssignment Token
w
T_SimpleCommand _ (w :: Token
w:_) [] -> Bool
True
T_Assignment {} -> Bool
True
T_Annotation _ _ w :: Token
w -> Token -> Bool
isAssignment Token
w
_ -> Bool
False
isOnlyRedirection :: Token -> Bool
isOnlyRedirection t :: Token
t =
case Token
t of
T_Pipeline _ _ [x :: Token
x] -> Token -> Bool
isOnlyRedirection Token
x
T_Annotation _ _ w :: Token
w -> Token -> Bool
isOnlyRedirection Token
w
T_Redirecting _ (_:_) c :: Token
c -> Token -> Bool
isOnlyRedirection Token
c
T_SimpleCommand _ [] [] -> Bool
True
_ -> Bool
False
isFunction :: Token -> Bool
isFunction t :: Token
t = case Token
t of T_Function {} -> Bool
True; _ -> Bool
False
isFunctionLike :: Token -> Bool
isFunctionLike t :: Token
t =
case Token
t of
T_Function {} -> Bool
True
T_BatsTest {} -> Bool
True
_ -> Bool
False
isBraceExpansion :: Token -> Bool
isBraceExpansion t :: Token
t = case Token
t of T_BraceExpansion {} -> Bool
True; _ -> Bool
False
getCommandSequences :: Token -> [[Token]]
getCommandSequences :: Token -> [[Token]]
getCommandSequences t :: Token
t =
case Token
t of
T_Script _ _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_BraceGroup _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_Subshell _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_WhileExpression _ _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_UntilExpression _ _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_ForIn _ _ _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_ForArithmetic _ _ _ _ cmds :: [Token]
cmds -> [[Token]
cmds]
T_IfExpression _ thens :: [([Token], [Token])]
thens elses :: [Token]
elses -> (([Token], [Token]) -> [Token])
-> [([Token], [Token])] -> [[Token]]
forall a b. (a -> b) -> [a] -> [b]
map ([Token], [Token]) -> [Token]
forall a b. (a, b) -> b
snd [([Token], [Token])]
thens [[Token]] -> [[Token]] -> [[Token]]
forall a. [a] -> [a] -> [a]
++ [[Token]
elses]
T_Annotation _ _ t :: Token
t -> Token -> [[Token]]
getCommandSequences Token
t
_ -> []
getAssociativeArrays :: Token -> [[Char]]
getAssociativeArrays t :: Token
t =
[[Char]] -> [[Char]]
forall a. Eq a => [a] -> [a]
nub ([[Char]] -> [[Char]])
-> (Writer [[Char]] Token -> [[Char]])
-> Writer [[Char]] Token
-> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Writer [[Char]] Token -> [[Char]]
forall w a. Writer w a -> w
execWriter (Writer [[Char]] Token -> [[Char]])
-> Writer [[Char]] Token -> [[Char]]
forall a b. (a -> b) -> a -> b
$ (Token -> WriterT [[Char]] Identity ())
-> Token -> Writer [[Char]] Token
forall (m :: * -> *).
Monad m =>
(Token -> m ()) -> Token -> m Token
doAnalysis Token -> WriterT [[Char]] Identity ()
f Token
t
where
f :: Token -> Writer [String] ()
f :: Token -> WriterT [[Char]] Identity ()
f t :: Token
t@T_SimpleCommand {} = WriterT [[Char]] Identity ()
-> Maybe (WriterT [[Char]] Identity ())
-> WriterT [[Char]] Identity ()
forall a. a -> Maybe a -> a
fromMaybe (() -> WriterT [[Char]] Identity ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (Maybe (WriterT [[Char]] Identity ())
-> WriterT [[Char]] Identity ())
-> Maybe (WriterT [[Char]] Identity ())
-> WriterT [[Char]] Identity ()
forall a b. (a -> b) -> a -> b
$ do
[Char]
name <- Token -> Maybe [Char]
getCommandName Token
t
let assocNames :: [[Char]]
assocNames = ["declare","local","typeset"]
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem [Char]
name [[Char]]
assocNames
let flags :: [(Token, [Char])]
flags = Token -> [(Token, [Char])]
getAllFlags Token
t
Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem "A" ([[Char]] -> Bool) -> [[Char]] -> Bool
forall a b. (a -> b) -> a -> b
$ ((Token, [Char]) -> [Char]) -> [(Token, [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (Token, [Char]) -> [Char]
forall a b. (a, b) -> b
snd [(Token, [Char])]
flags
let args :: [Token]
args = ((Token, [Char]) -> Token) -> [(Token, [Char])] -> [Token]
forall a b. (a -> b) -> [a] -> [b]
map (Token, [Char]) -> Token
forall a b. (a, b) -> a
fst ([(Token, [Char])] -> [Token])
-> ([(Token, [Char])] -> [(Token, [Char])])
-> [(Token, [Char])]
-> [Token]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Token, [Char]) -> Bool) -> [(Token, [Char])] -> [(Token, [Char])]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
(==) "" ([Char] -> Bool)
-> ((Token, [Char]) -> [Char]) -> (Token, [Char]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token, [Char]) -> [Char]
forall a b. (a, b) -> b
snd) ([(Token, [Char])] -> [Token]) -> [(Token, [Char])] -> [Token]
forall a b. (a -> b) -> a -> b
$ [(Token, [Char])]
flags
let names :: [[Char]]
names = (Token -> Maybe [Char]) -> [Token] -> [[Char]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ((Token -> Maybe [Char]) -> Token -> Maybe [Char]
getLiteralStringExt Token -> Maybe [Char]
nameAssignments) [Token]
args
WriterT [[Char]] Identity ()
-> Maybe (WriterT [[Char]] Identity ())
forall (m :: * -> *) a. Monad m => a -> m a
return (WriterT [[Char]] Identity ()
-> Maybe (WriterT [[Char]] Identity ()))
-> WriterT [[Char]] Identity ()
-> Maybe (WriterT [[Char]] Identity ())
forall a b. (a -> b) -> a -> b
$ [[Char]] -> WriterT [[Char]] Identity ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell [[Char]]
names
f _ = () -> WriterT [[Char]] Identity ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
nameAssignments :: Token -> Maybe [Char]
nameAssignments t :: Token
t =
case Token
t of
T_Assignment _ _ name :: [Char]
name _ _ -> [Char] -> Maybe [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
name
_ -> Maybe [Char]
forall a. Maybe a
Nothing
data PseudoGlob = PGAny | PGMany | PGChar Char
deriving (PseudoGlob -> PseudoGlob -> Bool
(PseudoGlob -> PseudoGlob -> Bool)
-> (PseudoGlob -> PseudoGlob -> Bool) -> Eq PseudoGlob
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PseudoGlob -> PseudoGlob -> Bool
$c/= :: PseudoGlob -> PseudoGlob -> Bool
== :: PseudoGlob -> PseudoGlob -> Bool
$c== :: PseudoGlob -> PseudoGlob -> Bool
Eq, Int -> PseudoGlob -> [Char] -> [Char]
[PseudoGlob] -> [Char] -> [Char]
PseudoGlob -> [Char]
(Int -> PseudoGlob -> [Char] -> [Char])
-> (PseudoGlob -> [Char])
-> ([PseudoGlob] -> [Char] -> [Char])
-> Show PseudoGlob
forall a.
(Int -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [PseudoGlob] -> [Char] -> [Char]
$cshowList :: [PseudoGlob] -> [Char] -> [Char]
show :: PseudoGlob -> [Char]
$cshow :: PseudoGlob -> [Char]
showsPrec :: Int -> PseudoGlob -> [Char] -> [Char]
$cshowsPrec :: Int -> PseudoGlob -> [Char] -> [Char]
Show)
wordToPseudoGlob :: Token -> Maybe [PseudoGlob]
wordToPseudoGlob :: Token -> Maybe [PseudoGlob]
wordToPseudoGlob word :: Token
word =
[PseudoGlob] -> [PseudoGlob]
simplifyPseudoGlob ([PseudoGlob] -> [PseudoGlob])
-> ([[PseudoGlob]] -> [PseudoGlob])
-> [[PseudoGlob]]
-> [PseudoGlob]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[PseudoGlob]] -> [PseudoGlob]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[PseudoGlob]] -> [PseudoGlob])
-> Maybe [[PseudoGlob]] -> Maybe [PseudoGlob]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Token -> Maybe [PseudoGlob]) -> [Token] -> Maybe [[PseudoGlob]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Token -> Maybe [PseudoGlob]
forall (m :: * -> *). Monad m => Token -> m [PseudoGlob]
f (Token -> [Token]
getWordParts Token
word)
where
f :: Token -> m [PseudoGlob]
f x :: Token
x = case Token
x of
T_Literal _ s :: [Char]
s -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return ([PseudoGlob] -> m [PseudoGlob]) -> [PseudoGlob] -> m [PseudoGlob]
forall a b. (a -> b) -> a -> b
$ (Char -> PseudoGlob) -> [Char] -> [PseudoGlob]
forall a b. (a -> b) -> [a] -> [b]
map Char -> PseudoGlob
PGChar [Char]
s
T_SingleQuoted _ s :: [Char]
s -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return ([PseudoGlob] -> m [PseudoGlob]) -> [PseudoGlob] -> m [PseudoGlob]
forall a b. (a -> b) -> a -> b
$ (Char -> PseudoGlob) -> [Char] -> [PseudoGlob]
forall a b. (a -> b) -> [a] -> [b]
map Char -> PseudoGlob
PGChar [Char]
s
T_DollarBraced {} -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
T_DollarExpansion {} -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
T_Backticked {} -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
T_Glob _ "?" -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGAny]
T_Glob _ ('[':_) -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGAny]
T_Glob {} -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
T_Extglob {} -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
_ -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
wordToExactPseudoGlob :: Token -> Maybe [PseudoGlob]
wordToExactPseudoGlob :: Token -> Maybe [PseudoGlob]
wordToExactPseudoGlob word :: Token
word =
[PseudoGlob] -> [PseudoGlob]
simplifyPseudoGlob ([PseudoGlob] -> [PseudoGlob])
-> ([[PseudoGlob]] -> [PseudoGlob])
-> [[PseudoGlob]]
-> [PseudoGlob]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[PseudoGlob]] -> [PseudoGlob]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[PseudoGlob]] -> [PseudoGlob])
-> Maybe [[PseudoGlob]] -> Maybe [PseudoGlob]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Token -> Maybe [PseudoGlob]) -> [Token] -> Maybe [[PseudoGlob]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Token -> Maybe [PseudoGlob]
forall (m :: * -> *). MonadFail m => Token -> m [PseudoGlob]
f (Token -> [Token]
getWordParts Token
word)
where
f :: Token -> m [PseudoGlob]
f x :: Token
x = case Token
x of
T_Literal _ s :: [Char]
s -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return ([PseudoGlob] -> m [PseudoGlob]) -> [PseudoGlob] -> m [PseudoGlob]
forall a b. (a -> b) -> a -> b
$ (Char -> PseudoGlob) -> [Char] -> [PseudoGlob]
forall a b. (a -> b) -> [a] -> [b]
map Char -> PseudoGlob
PGChar [Char]
s
T_SingleQuoted _ s :: [Char]
s -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return ([PseudoGlob] -> m [PseudoGlob]) -> [PseudoGlob] -> m [PseudoGlob]
forall a b. (a -> b) -> a -> b
$ (Char -> PseudoGlob) -> [Char] -> [PseudoGlob]
forall a b. (a -> b) -> [a] -> [b]
map Char -> PseudoGlob
PGChar [Char]
s
T_Glob _ "?" -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGAny]
T_Glob _ "*" -> [PseudoGlob] -> m [PseudoGlob]
forall (m :: * -> *) a. Monad m => a -> m a
return [PseudoGlob
PGMany]
_ -> [Char] -> m [PseudoGlob]
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail "Unknown token type"
simplifyPseudoGlob :: [PseudoGlob] -> [PseudoGlob]
simplifyPseudoGlob :: [PseudoGlob] -> [PseudoGlob]
simplifyPseudoGlob = [PseudoGlob] -> [PseudoGlob]
f
where
f :: [PseudoGlob] -> [PseudoGlob]
f [] = []
f (x :: PseudoGlob
x@(PGChar _) : rest :: [PseudoGlob]
rest ) = PseudoGlob
x PseudoGlob -> [PseudoGlob] -> [PseudoGlob]
forall a. a -> [a] -> [a]
: [PseudoGlob] -> [PseudoGlob]
f [PseudoGlob]
rest
f list :: [PseudoGlob]
list =
let (anys :: [PseudoGlob]
anys, rest :: [PseudoGlob]
rest) = (PseudoGlob -> Bool)
-> [PseudoGlob] -> ([PseudoGlob], [PseudoGlob])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span (\x :: PseudoGlob
x -> PseudoGlob
x PseudoGlob -> PseudoGlob -> Bool
forall a. Eq a => a -> a -> Bool
== PseudoGlob
PGMany Bool -> Bool -> Bool
|| PseudoGlob
x PseudoGlob -> PseudoGlob -> Bool
forall a. Eq a => a -> a -> Bool
== PseudoGlob
PGAny) [PseudoGlob]
list in
[PseudoGlob] -> [PseudoGlob]
order [PseudoGlob]
anys [PseudoGlob] -> [PseudoGlob] -> [PseudoGlob]
forall a. [a] -> [a] -> [a]
++ [PseudoGlob] -> [PseudoGlob]
f [PseudoGlob]
rest
order :: [PseudoGlob] -> [PseudoGlob]
order s :: [PseudoGlob]
s = let (any :: [PseudoGlob]
any, many :: [PseudoGlob]
many) = (PseudoGlob -> Bool)
-> [PseudoGlob] -> ([PseudoGlob], [PseudoGlob])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (PseudoGlob -> PseudoGlob -> Bool
forall a. Eq a => a -> a -> Bool
== PseudoGlob
PGAny) [PseudoGlob]
s in
[PseudoGlob]
any [PseudoGlob] -> [PseudoGlob] -> [PseudoGlob]
forall a. [a] -> [a] -> [a]
++ Int -> [PseudoGlob] -> [PseudoGlob]
forall a. Int -> [a] -> [a]
take 1 [PseudoGlob]
many
pseudoGlobsCanOverlap :: [PseudoGlob] -> [PseudoGlob] -> Bool
pseudoGlobsCanOverlap :: [PseudoGlob] -> [PseudoGlob] -> Bool
pseudoGlobsCanOverlap = [PseudoGlob] -> [PseudoGlob] -> Bool
matchable
where
matchable :: [PseudoGlob] -> [PseudoGlob] -> Bool
matchable x :: [PseudoGlob]
x@(xf :: PseudoGlob
xf:xs :: [PseudoGlob]
xs) y :: [PseudoGlob]
y@(yf :: PseudoGlob
yf:ys :: [PseudoGlob]
ys) =
case (PseudoGlob
xf, PseudoGlob
yf) of
(PGMany, _) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
x [PseudoGlob]
ys Bool -> Bool -> Bool
|| [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
y
(_, PGMany) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
x [PseudoGlob]
ys Bool -> Bool -> Bool
|| [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
y
(PGAny, _) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
ys
(_, PGAny) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
ys
(_, _) -> PseudoGlob
xf PseudoGlob -> PseudoGlob -> Bool
forall a. Eq a => a -> a -> Bool
== PseudoGlob
yf Bool -> Bool -> Bool
&& [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
ys
matchable [] [] = Bool
True
matchable (PGMany : rest :: [PseudoGlob]
rest) [] = [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
rest []
matchable (_:_) [] = Bool
False
matchable [] r :: [PseudoGlob]
r = [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
r []
pseudoGlobIsSuperSetof :: [PseudoGlob] -> [PseudoGlob] -> Bool
pseudoGlobIsSuperSetof :: [PseudoGlob] -> [PseudoGlob] -> Bool
pseudoGlobIsSuperSetof = [PseudoGlob] -> [PseudoGlob] -> Bool
matchable
where
matchable :: [PseudoGlob] -> [PseudoGlob] -> Bool
matchable x :: [PseudoGlob]
x@(xf :: PseudoGlob
xf:xs :: [PseudoGlob]
xs) y :: [PseudoGlob]
y@(yf :: PseudoGlob
yf:ys :: [PseudoGlob]
ys) =
case (PseudoGlob
xf, PseudoGlob
yf) of
(PGMany, PGMany) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
x [PseudoGlob]
ys
(PGMany, _) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
x [PseudoGlob]
ys Bool -> Bool -> Bool
|| [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
y
(_, PGMany) -> Bool
False
(PGAny, _) -> [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
ys
(_, PGAny) -> Bool
False
(_, _) -> PseudoGlob
xf PseudoGlob -> PseudoGlob -> Bool
forall a. Eq a => a -> a -> Bool
== PseudoGlob
yf Bool -> Bool -> Bool
&& [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
xs [PseudoGlob]
ys
matchable [] [] = Bool
True
matchable (PGMany : rest :: [PseudoGlob]
rest) [] = [PseudoGlob] -> [PseudoGlob] -> Bool
matchable [PseudoGlob]
rest []
matchable _ _ = Bool
False
wordsCanBeEqual :: Token -> Token -> Bool
wordsCanBeEqual x :: Token
x y :: Token
y = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
True (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$
([PseudoGlob] -> [PseudoGlob] -> Bool)
-> Maybe [PseudoGlob] -> Maybe [PseudoGlob] -> Maybe Bool
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 [PseudoGlob] -> [PseudoGlob] -> Bool
pseudoGlobsCanOverlap (Token -> Maybe [PseudoGlob]
wordToPseudoGlob Token
x) (Token -> Maybe [PseudoGlob]
wordToPseudoGlob Token
y)
isQuoteableExpansion :: Token -> Bool
isQuoteableExpansion t :: Token
t = case Token
t of
T_DollarBraced {} -> Bool
True
_ -> Token -> Bool
isCommandSubstitution Token
t
isCommandSubstitution :: Token -> Bool
isCommandSubstitution t :: Token
t = case Token
t of
T_DollarExpansion {} -> Bool
True
T_DollarBraceCommandExpansion {} -> Bool
True
T_Backticked {} -> Bool
True
_ -> Bool
False
isAnnotationIgnoringCode :: Integer -> Token -> Bool
isAnnotationIgnoringCode code :: Integer
code t :: Token
t =
case Token
t of
T_Annotation _ anns :: [Annotation]
anns _ -> (Annotation -> Bool) -> [Annotation] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Annotation -> Bool
hasNum [Annotation]
anns
_ -> Bool
False
where
hasNum :: Annotation -> Bool
hasNum (DisableComment ts :: Integer
ts) = Integer
code Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
ts
hasNum _ = Bool
False