Permalink
Browse files

pure tests pass

  • Loading branch information...
1 parent 3c1806a commit bd4a62f3f97f9d528f7983a5f69415898cc662e2 Alexander Bernauer committed Dec 29, 2012
Showing with 1,835 additions and 208 deletions.
  1. +0 −198 GDBMI.hs
  2. +15 −10 hgdbmi.cabal
  3. +6 −0 src/Gdbmi.hs
  4. +630 −0 src/Gdbmi/Commands.hs
  5. +187 −0 src/Gdbmi/IO.hs
  6. +442 −0 src/Gdbmi/Representation.hs
  7. +195 −0 src/Gdbmi/Responses.hs
  8. +20 −0 tests/Lib.hs
  9. +340 −0 tests/pure.hs
View
198 GDBMI.hs
@@ -1,198 +0,0 @@
--- hgdbmi: a Haskell interface to GDB/MI.
--- Copyright (C) 2008 Evan Martin <martine@danga.com>
-
--- |GDB\/MI lets programs drive GDB. It can be used, for example, by GDB
--- frontends. This module wraps attaching GDB to a process and parsing the
--- (surprisingly complicated) GDB\/MI output.
-
-module GDBMI (
- GDB,
- attach,
- detach,
-
- runCommand,
- GDBCommand(..),
- MIOutput(..),
- MIOOB(..),
- MIResult(..),
- MIKeyVal,
- MIValue(..),
-
- parse
-) where
-
-import System.IO
-import System.Posix.IO (createPipe, fdToHandle)
-import System.Posix.Types (ProcessID)
-import System.Process (runProcess, ProcessHandle)
-import Text.ParserCombinators.Parsec hiding (parse)
-import qualified Text.ParserCombinators.Parsec as Parsec (parse)
-
--- |A connection to a GDB process.
-data GDB = GDB {
- gdbPid :: ProcessHandle,
- gdbCommand :: Handle,
- gdbResponse :: Handle
-}
-
--- |A GDB command. CLICommand is any command you'd normally type at the GDB
--- prompt. MICommand are more machine-parsing friendly commands; see the
--- GDB\/MI docs for details.
-data GDBCommand = CLICommand String
- | MICommand String -- ^TODO: expand this to support arguments.
-
--- |The output of running a GDB command. Output is a collection of Out-Of-Band
--- messages (such as logging information) and an optional final result.
-data MIOutput = MIOutput [MIOOB] (Maybe MIResult) deriving Show
-
--- |The type of OOB mesages. (TODO: many of these aren't properly parsed yet.)
-data MIOOB =
- MIStatus String -- ^Contains on-going status information about the progress
- -- of a slow operation.
- | MIExec String -- ^Contains asynchronous state change on the target
- -- (stopped, started, disappeared).
- | MINotify String -- ^Contains supplementary information that the client
- -- should handle (e.g., a new breakpoint information).
- | MIConsole String -- ^Output that should be displayed as is in the console.
- -- It is the textual response to a CLI command.
- | MITarget String -- ^The output produced by the target program.
- | MILog String -- ^Output text coming from GDB's internals, for instance
- -- messages that should be displayed as part of an error
- -- log.
- deriving (Eq, Show)
-
--- |The type of the GDB result. (TODO: many result types aren't implemented
--- yet.)
-data MIResult =
- MIDone [MIKeyVal] -- ^The synchronous operation was successful,
- -- along with potential key-value return data.
- | MIError String -- ^The operation failed. The string contains the
- -- corresponding error message.
- deriving (Eq, Show)
-
--- |A key-value pair output from GDB.
-type MIKeyVal = (String, MIValue)
-
--- |The type of a GDB "value", used in the output of structured data.
-data MIValue =
- MIString String
- | MITuple [MIKeyVal]
- deriving (Eq, Show)
-
--- |Attach to a process, returning an error or the 'GDB' connection and its
--- initial output.
-attach :: Maybe FilePath -- ^Working directory for GDB. (Important if the
- -- process has loaded libraries from relative paths.)
- -> ProcessID
- -> IO (Either String (GDB, MIOutput))
-attach workdir pid = do
- (commandR, commandW) <- createPipe >>= asHandles
- (responseR, responseW) <- createPipe >>= asHandles
- phandle <- runProcess "gdb" ["--interpreter", "mi", "-p", show pid]
- workdir Nothing{-env-}
- (Just commandR) -- stdin
- (Just responseW) -- stdout
- Nothing -- stderr
- mapM_ (`hSetBuffering` LineBuffering) [commandW, responseR]
- let gdb = GDB phandle commandW responseR
- resp <- readResponse gdb
- case resp of
- Left err -> return $ Left err
- Right ok -> return $ Right (gdb, ok)
- where
- asHandles (f1, f2) = do
- h1 <- fdToHandle f1; h2 <- fdToHandle f2; return (h1, h2)
-
--- |Close a 'GDB' connection.
-detach :: GDB -> IO ()
--- TODO: we don't examine the result code, because our parser wants each
--- response to be terminated by the "(gdb) " prompt, which this lacks.
-detach gdb = hPutStrLn (gdbCommand gdb) "-gdb-exit"
-
--- |Run a GDB command.
-runCommand :: GDBCommand -> GDB -> IO (Either String MIOutput)
-runCommand cmd gdb = do
- hPutStrLn (gdbCommand gdb) (cmdStr cmd)
- readResponse gdb
- where
- cmdStr (CLICommand str) = str
- cmdStr (MICommand str) = '-' : str
-
-readResponse :: GDB -> IO (Either String MIOutput)
-readResponse gdb = do
- resp <- readResponseLines
- case parse "output" (unlines resp) of
- Left err -> return $ Left (show err)
- Right out -> return $ Right out
- where
- readResponseLines :: IO [String]
- readResponseLines = do
- line <- hGetLine (gdbResponse gdb)
- if line == "(gdb) "
- then return []
- else do rest <- readResponseLines
- return (line:rest)
-
--- Our Parsec parsers all start with p_.
-
--- Parse the main ouptut from GDB.
-p_output = do
- oob <- p_oob `sepEndBy` newline
- res <- optionMaybe p_result
- eof
- return $ MIOutput oob res
--- Parse an "OOB" message from GDB.
-p_oob = p_console <|> p_log
--- Parse a console OOB message from GDB.
-p_console = do char '~'; str <- p_cstring; return $ MIConsole str
--- Parse a log OOB message from GDB.
-p_log = do char '&'; str <- p_cstring; return $ MILog str
-
--- Parse a result message from GDB.
-p_result = do
- char '^'
- res <- p_done <|> p_error
- newline; return res
- where
- -- Parse a done result message from GDB.
- p_done = do
- string "done"
- res <- (do char ','; p_keyval `sepBy` char ',') <|> return []
- return $ MIDone res
- -- Parse a error result message from GDB.
- p_error = do
- string "error"
- char ','
- -- XXX: The GDB/MI docs say this should be just a cstring, but my GDB
- -- doesn't agree.
- string "msg=" -- Hack here; perhaps it's really like the "done" output?
- err <- p_cstring
- return $ MIError err
-
--- Parse a key=val output ("result") from GDB.
-p_keyval = do var <- p_var; char '='; val <- p_val; return $ (var, val) where
- p_var = many1 (letter <|> char '-') -- XXX: this is underspecified.
- p_val = p_const <|> p_tuple
- p_const = do str <- p_cstring; return $ MIString str
- p_tuple = do
- vals <- tuplewrap $ p_keyval `sepBy` char ','
- return $ MITuple vals
- -- It's unclear why they have []-style tuples and {}-style tuples...
- tuplewrap p = between (char '{') (char '}') p
- <|> between (char '[') (char ']') p
-
--- Parse a C-style string (underspecified by the GDB manual).
-p_cstring = between (char '"') (char '"') (many p_cchar) where
- p_cchar = p_cbackslash
- <|> noneOf "\""
- p_cbackslash = do
- char '\\'
- c <- anyChar
- case c of
- '\\' -> return '\\'
- 'n' -> return '\n'
- '"' -> return '"'
- _ -> fail $ "unknown backslash escape: " ++ show c
-
--- |An interface to the output parser. Just used for testing.
-parse = Parsec.parse p_output
View
@@ -2,25 +2,27 @@ name: hgdbmi
category: Development
version: 0.2
license: BSD3
-cabal-version: >= 1.14
+cabal-version: >= 1.14
license-file: LICENSE
author: Alexander Bernauer, Evan Martin
maintainer: Alexander Bernauer <acopton@gmail.com>
stability: provisional
homepage: https://github.com/copton/hgdbmi
bug-reports: https://github.com/copton/hgdbmi/issues
-copyright: (c) 2012 Alexander Bernauer <acopton@gmail.com>, (c) 2008 Evan Martin <martine@danga.com>
+copyright: (c) 2012 Alexander Bernauer <acopton@gmail.com>, 2008 Evan Martin <martine@danga.com>
Synopsis: GDB Machine Interface: program-driven control of GDB
Description:
GDB\/MI lets programs drive GDB. It can be used, for example, by GDB
- frontends. This module encapsualtes a GDB subprocess and provides an
- API to send commands as well as receive both responses and notifications.
+ frontends. See section 27 of the GDB manual
+ .
+ This module encapsualtes a GDB subprocess and provides an API to send
+ commands as well as receive both responses and notifications.
.
The actual GDB behavior diverges from the GDB manual in many points, so the
implementation of the Machine Interface highly depends on the GDB version.
- This module supports GDB version 7.4.
+ This module is tested with GDB version 7.4.
-build-type: custom
+build-type: Simple
tested-with: GHC == 7.4.2
extra-source-files:
gdb-manual.pdf
@@ -39,7 +41,8 @@ library
base >= 4 && < 5,
parsec == 3.1.*,
process == 1.1.*,
- unix == 2.6.*
+ unix == 2.6.*,
+ stm == 2.3.*
exposed-modules:
Gdbmi.IO
@@ -49,17 +52,19 @@ library
ghc-options: -Wall
hs-source-dirs: src
+ default-language: Haskell2010
test-suite pure
type: exitcode-stdio-1.0
main-is: pure.hs
- other-modules: Lib.hs
build-depends:
+ hgdbmi,
base >= 4 && < 5,
HUnit == 1.2.*,
test-framework == 0.6.*,
test-framework-hunit == 0.2.*,
template-haskell
- ghc-options: -Wall
- hs-source-dirs: tests
+ ghc-options: -Wall
+ hs-source-dirs: tests
+ default-language: Haskell2010
View
@@ -0,0 +1,6 @@
+module Gdbmi
+
+import Gdbmi.IO
+import Gdbmi.Representation
+import Gdbmi.Commands
+import Gdbmi.Responses
Oops, something went wrong.

0 comments on commit bd4a62f

Please sign in to comment.