From 4806719035de364dd2d49f97112dd8b3a255e3b0 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Tue, 2 Aug 2022 15:47:59 -0700 Subject: [PATCH] Handle variable assignments from `read` in CFG --- src/ShellCheck/CFG.hs | 35 ++++++++++++++++++++++++++++++++++- src/ShellCheck/Data.hs | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/ShellCheck/CFG.hs b/src/ShellCheck/CFG.hs index 771e870..e0c6267 100644 --- a/src/ShellCheck/CFG.hs +++ b/src/ShellCheck/CFG.hs @@ -41,6 +41,7 @@ module ShellCheck.CFG ( import GHC.Generics (Generic) import ShellCheck.AST import ShellCheck.ASTLib +import ShellCheck.Data import ShellCheck.Interface import ShellCheck.Prelude import ShellCheck.Regex @@ -936,6 +937,8 @@ handleCommand cmd vars args literalCmd = do Just "mapfile" -> regularExpansionWithStatus vars args $ handleMapfile args Just "readarray" -> regularExpansionWithStatus vars args $ handleMapfile args + Just "read" -> regularExpansionWithStatus vars args $ handleRead args + Just "DEFINE_boolean" -> regularExpansionWithStatus vars args $ handleDEFINE args Just "DEFINE_float" -> regularExpansionWithStatus vars args $ handleDEFINE args Just "DEFINE_integer" -> regularExpansionWithStatus vars args $ handleDEFINE args @@ -1113,7 +1116,7 @@ handleCommand cmd vars args literalCmd = do in IdTagged id $ CFWriteVariable name CFValueArray getFromArg = do - flags <- getGnuOpts "d:n:O:s:u:C:c:t" args + flags <- getGnuOpts flagsForMapfile args (_, arg) <- lookup "" flags name <- getLiteralString arg return (getId arg, name) @@ -1125,6 +1128,36 @@ handleCommand cmd vars args literalCmd = do guard $ isVariableName name return (getId c, name) + handleRead (cmd:args) = newNodeRange $ CFApplyEffects main + where + main = fromMaybe fallback $ do + flags <- getGnuOpts flagsForRead args + return $ fromMaybe (withFields flags) $ withArray flags + + withArray :: [(String, (Token, Token))] -> Maybe [IdTagged CFEffect] + withArray flags = do + (_, token) <- lookup "a" flags + return $ fromMaybe [] $ do + name <- getLiteralString token + return [ IdTagged (getId token) $ CFWriteVariable name CFValueArray ] + + withFields flags = mapMaybe getAssignment flags + + getAssignment :: (String, (Token, Token)) -> Maybe (IdTagged CFEffect) + getAssignment f = do + ("", (t, _)) <- return f + name <- getLiteralString t + return $ IdTagged (getId t) $ CFWriteVariable name CFValueString + + fallback = + let + names = reverse $ map fromJust $ takeWhile isJust $ map (\c -> sequence (getId c, getLiteralString c)) $ reverse args + namesOrDefault = if null names then [(getId cmd, "REPLY")] else names + hasDashA = any (== "a") $ map fst $ getGenericOpts args + value = if hasDashA then CFValueArray else CFValueString + in + map (\(id, name) -> IdTagged id $ CFWriteVariable name value) namesOrDefault + handleDEFINE (cmd:args) = newNodeRange $ CFApplyEffects $ maybeToList findVar where diff --git a/src/ShellCheck/Data.hs b/src/ShellCheck/Data.hs index fb82ca8..4090922 100644 --- a/src/ShellCheck/Data.hs +++ b/src/ShellCheck/Data.hs @@ -159,5 +159,6 @@ shellForExecutable name = _ -> Nothing flagsForRead = "sreu:n:N:i:p:a:t:" +flagsForMapfile = "d:n:O:s:u:C:c:t" declaringCommands = ["local", "declare", "export", "readonly", "typeset", "let"]