packages feed

hgdbmi 0.1 → 0.2

raw patch · 11 files changed

+2368/−306 lines, 11 filesdep +HUnitdep +directorydep +hgdbmidep ~basedep ~parsecdep ~processnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: HUnit, directory, hgdbmi, stm, template-haskell, temporary, test-framework, test-framework-hunit

Dependency ranges changed: base, parsec, process, unix

API changes (from Hackage documentation)

- GDBMI: CLICommand :: String -> GDBCommand
- GDBMI: MICommand :: String -> GDBCommand
- GDBMI: MIConsole :: String -> MIOOB
- GDBMI: MIDone :: [MIKeyVal] -> MIResult
- GDBMI: MIError :: String -> MIResult
- GDBMI: MIExec :: String -> MIOOB
- GDBMI: MILog :: String -> MIOOB
- GDBMI: MINotify :: String -> MIOOB
- GDBMI: MIOutput :: [MIOOB] -> (Maybe MIResult) -> MIOutput
- GDBMI: MIStatus :: String -> MIOOB
- GDBMI: MIString :: String -> MIValue
- GDBMI: MITarget :: String -> MIOOB
- GDBMI: MITuple :: [MIKeyVal] -> MIValue
- GDBMI: attach :: Maybe FilePath -> ProcessID -> IO (Either String (GDB, MIOutput))
- GDBMI: data GDB
- GDBMI: data GDBCommand
- GDBMI: data MIOOB
- GDBMI: data MIOutput
- GDBMI: data MIResult
- GDBMI: data MIValue
- GDBMI: detach :: GDB -> IO ()
- GDBMI: instance Eq MIOOB
- GDBMI: instance Eq MIResult
- GDBMI: instance Eq MIValue
- GDBMI: instance Show MIOOB
- GDBMI: instance Show MIOutput
- GDBMI: instance Show MIResult
- GDBMI: instance Show MIValue
- GDBMI: parse :: SourceName -> [Char] -> Either ParseError MIOutput
- GDBMI: runCommand :: GDBCommand -> GDB -> IO (Either String MIOutput)
- GDBMI: type MIKeyVal = (String, MIValue)
+ Gdbmi.Commands: Address :: OutputFormat
+ Gdbmi.Commands: AllValues :: PrintValues
+ Gdbmi.Commands: Binary :: FormatSpec
+ Gdbmi.Commands: BinaryInteger :: OutputFormat
+ Gdbmi.Commands: CharacterConstantInteger :: OutputFormat
+ Gdbmi.Commands: Console :: Interpreter
+ Gdbmi.Commands: Core :: FilePath -> Target
+ Gdbmi.Commands: CurrentFrame :: FrameSelect
+ Gdbmi.Commands: DBinary :: DataFormat
+ Gdbmi.Commands: DDecimal :: DataFormat
+ Gdbmi.Commands: DHexadecimal :: DataFormat
+ Gdbmi.Commands: DNatural :: DataFormat
+ Gdbmi.Commands: DOctal :: DataFormat
+ Gdbmi.Commands: DRaw :: DataFormat
+ Gdbmi.Commands: Decimal :: FormatSpec
+ Gdbmi.Commands: DisassemblyMode :: Bool -> Bool -> DisassemblyMode
+ Gdbmi.Commands: Exec :: FilePath -> Target
+ Gdbmi.Commands: Floating :: FrameSelect
+ Gdbmi.Commands: FloatingPointNumber :: OutputFormat
+ Gdbmi.Commands: FrameAddr :: String -> FrameSelect
+ Gdbmi.Commands: FrameNumber :: Int -> TraceMode
+ Gdbmi.Commands: Frozen :: FrozenFlag
+ Gdbmi.Commands: Hexadecimal :: FormatSpec
+ Gdbmi.Commands: HexadecimalInteger :: OutputFormat
+ Gdbmi.Commands: Line :: Location -> TraceMode
+ Gdbmi.Commands: MI :: Interpreter
+ Gdbmi.Commands: MI1 :: Interpreter
+ Gdbmi.Commands: MI2 :: Interpreter
+ Gdbmi.Commands: Natural :: FormatSpec
+ Gdbmi.Commands: NoValues :: PrintValues
+ Gdbmi.Commands: None :: TraceMode
+ Gdbmi.Commands: Nrom :: Target
+ Gdbmi.Commands: OString :: OutputFormat
+ Gdbmi.Commands: Octal :: FormatSpec
+ Gdbmi.Commands: OctalInteger :: OutputFormat
+ Gdbmi.Commands: PC :: String -> TraceMode
+ Gdbmi.Commands: PCInsideRange :: String -> String -> TraceMode
+ Gdbmi.Commands: PCOutsideRange :: String -> String -> TraceMode
+ Gdbmi.Commands: Pipe :: String -> Medium
+ Gdbmi.Commands: Raw :: OutputFormat
+ Gdbmi.Commands: Remote :: Medium -> Target
+ Gdbmi.Commands: SerialDevice :: String -> Medium
+ Gdbmi.Commands: SignedDecimalInteger :: OutputFormat
+ Gdbmi.Commands: Sim :: [String] -> Target
+ Gdbmi.Commands: SimpleValues :: PrintValues
+ Gdbmi.Commands: TcpHost :: String -> Int -> Medium
+ Gdbmi.Commands: TracepointNumber :: Int -> TraceMode
+ Gdbmi.Commands: UdpHost :: String -> Int -> Medium
+ Gdbmi.Commands: Unfrozen :: FrozenFlag
+ Gdbmi.Commands: UnsignedDecimalInteger :: OutputFormat
+ Gdbmi.Commands: ada_task_info :: Maybe Int -> Command
+ Gdbmi.Commands: add_inferior :: Command
+ Gdbmi.Commands: break_after :: Int -> Int -> Command
+ Gdbmi.Commands: break_commands :: Int -> [String] -> Command
+ Gdbmi.Commands: break_condition :: Int -> String -> Command
+ Gdbmi.Commands: break_delete :: [Int] -> Command
+ Gdbmi.Commands: break_disable :: [Int] -> Command
+ Gdbmi.Commands: break_enable :: [Int] -> Command
+ Gdbmi.Commands: break_info :: Int -> Command
+ Gdbmi.Commands: break_insert :: Bool -> Bool -> Bool -> Bool -> Bool -> Maybe String -> Maybe Int -> Maybe Int -> Location -> Command
+ Gdbmi.Commands: break_list :: Command
+ Gdbmi.Commands: break_passcount :: Int -> Int -> Command
+ Gdbmi.Commands: break_watch :: Bool -> Command
+ Gdbmi.Commands: cli_command :: String -> Command
+ Gdbmi.Commands: data DataFormat
+ Gdbmi.Commands: data DisassemblyMode
+ Gdbmi.Commands: data FormatSpec
+ Gdbmi.Commands: data FrameSelect
+ Gdbmi.Commands: data FrozenFlag
+ Gdbmi.Commands: data Interpreter
+ Gdbmi.Commands: data Location
+ Gdbmi.Commands: data Medium
+ Gdbmi.Commands: data OutputFormat
+ Gdbmi.Commands: data PrintValues
+ Gdbmi.Commands: data Target
+ Gdbmi.Commands: data TraceMode
+ Gdbmi.Commands: data_disassemble :: Either (String, String) (String, Int, Maybe Int) -> DisassemblyMode -> Command
+ Gdbmi.Commands: data_evaluate_expression :: String -> Command
+ Gdbmi.Commands: data_list_changed_registers :: Command
+ Gdbmi.Commands: data_list_register_names :: [Int] -> Command
+ Gdbmi.Commands: data_list_register_values :: DataFormat -> [Int] -> Command
+ Gdbmi.Commands: data_read_memory :: Maybe Int -> String -> OutputFormat -> Int -> Int -> Int -> Maybe Char -> Command
+ Gdbmi.Commands: data_read_memory_bytes :: Maybe Int -> String -> Int -> Command
+ Gdbmi.Commands: data_write_memory_bytes :: String -> String -> Command
+ Gdbmi.Commands: enable_pretty_printing :: Command
+ Gdbmi.Commands: enable_timings :: Bool -> Command
+ Gdbmi.Commands: environment_cd :: String -> Command
+ Gdbmi.Commands: environment_directory :: Bool -> [String] -> Command
+ Gdbmi.Commands: environment_path :: Bool -> [String] -> Command
+ Gdbmi.Commands: environment_pwd :: Command
+ Gdbmi.Commands: exec_arguments :: [String] -> Command
+ Gdbmi.Commands: exec_continue :: Bool -> Either Bool Int -> Command
+ Gdbmi.Commands: exec_finish :: Bool -> Command
+ Gdbmi.Commands: exec_interrupt :: Either Bool Int -> Command
+ Gdbmi.Commands: exec_jump :: Location -> Command
+ Gdbmi.Commands: exec_next :: Command
+ Gdbmi.Commands: exec_next_instruction :: Bool -> Command
+ Gdbmi.Commands: exec_return :: Command
+ Gdbmi.Commands: exec_run :: Either Bool Int -> Command
+ Gdbmi.Commands: exec_step :: Command
+ Gdbmi.Commands: exec_step_instruction :: Bool -> Command
+ Gdbmi.Commands: exec_until :: Location -> Command
+ Gdbmi.Commands: expr_address_location :: String -> Location
+ Gdbmi.Commands: file_exec_and_symbols :: Maybe FilePath -> Command
+ Gdbmi.Commands: file_exec_file :: Maybe FilePath -> Command
+ Gdbmi.Commands: file_func_address_location :: String -> String -> Location
+ Gdbmi.Commands: file_function_location :: String -> String -> Location
+ Gdbmi.Commands: file_line_location :: String -> Int -> Location
+ Gdbmi.Commands: file_list_exec_source_file :: Command
+ Gdbmi.Commands: file_list_exec_source_files :: Command
+ Gdbmi.Commands: file_symbol_file :: Maybe FilePath -> Command
+ Gdbmi.Commands: func_address_location :: String -> Location
+ Gdbmi.Commands: function_label_location :: String -> String -> Location
+ Gdbmi.Commands: function_location :: String -> Location
+ Gdbmi.Commands: gdb_exit :: Command
+ Gdbmi.Commands: gdb_gdbShow :: String -> Command
+ Gdbmi.Commands: gdb_set :: String -> Command
+ Gdbmi.Commands: gdb_version :: Command
+ Gdbmi.Commands: inferior_tty_gdbShow :: Command
+ Gdbmi.Commands: inferior_tty_set :: String -> Command
+ Gdbmi.Commands: info_os :: Maybe String -> Command
+ Gdbmi.Commands: instance GdbShow Char
+ Gdbmi.Commands: instance GdbShow DataFormat
+ Gdbmi.Commands: instance GdbShow DisassemblyMode
+ Gdbmi.Commands: instance GdbShow FormatSpec
+ Gdbmi.Commands: instance GdbShow FrameSelect
+ Gdbmi.Commands: instance GdbShow FrozenFlag
+ Gdbmi.Commands: instance GdbShow Int
+ Gdbmi.Commands: instance GdbShow Interpreter
+ Gdbmi.Commands: instance GdbShow Location
+ Gdbmi.Commands: instance GdbShow Medium
+ Gdbmi.Commands: instance GdbShow OutputFormat
+ Gdbmi.Commands: instance GdbShow PrintValues
+ Gdbmi.Commands: instance GdbShow Target
+ Gdbmi.Commands: instance GdbShow TraceMode
+ Gdbmi.Commands: instance GdbShow a => GdbShow [a]
+ Gdbmi.Commands: interpreter_exec :: Interpreter -> Command -> Command
+ Gdbmi.Commands: label_location :: String -> Location
+ Gdbmi.Commands: list_features :: Command
+ Gdbmi.Commands: list_target_features :: Command
+ Gdbmi.Commands: list_thread_groups :: Bool -> Maybe Int -> [Int] -> Command
+ Gdbmi.Commands: negative_offset_location :: Int -> Location
+ Gdbmi.Commands: plain_address_location :: String -> Location
+ Gdbmi.Commands: positive_offset_location :: Int -> Location
+ Gdbmi.Commands: set_token :: Token -> Command -> Command
+ Gdbmi.Commands: stack_info_depth :: Maybe Int -> Command
+ Gdbmi.Commands: stack_info_frame :: Command
+ Gdbmi.Commands: stack_list_arguments :: PrintValues -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: stack_list_arguments' :: Int -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: stack_list_frames :: Maybe (Int, Int) -> Command
+ Gdbmi.Commands: stack_list_locals :: PrintValues -> Command
+ Gdbmi.Commands: stack_list_locals' :: Int -> Command
+ Gdbmi.Commands: stack_list_variables :: PrintValues -> Command
+ Gdbmi.Commands: stack_list_variables' :: Int -> Command
+ Gdbmi.Commands: stack_select_frame :: Int -> Command
+ Gdbmi.Commands: symbol_list_lines :: String -> Command
+ Gdbmi.Commands: target_attach :: Either Int FilePath -> Command
+ Gdbmi.Commands: target_detach :: Maybe Int -> Command
+ Gdbmi.Commands: target_disconnect :: Command
+ Gdbmi.Commands: target_download :: Command
+ Gdbmi.Commands: target_file_delete :: FilePath -> Command
+ Gdbmi.Commands: target_file_get :: FilePath -> FilePath -> Command
+ Gdbmi.Commands: target_file_put :: FilePath -> FilePath -> Command
+ Gdbmi.Commands: target_select :: Target -> Command
+ Gdbmi.Commands: thread_info :: Maybe Int -> Command
+ Gdbmi.Commands: thread_list_ids :: Command
+ Gdbmi.Commands: thread_select :: Int -> Command
+ Gdbmi.Commands: trace_define_variable :: String -> Maybe String -> Command
+ Gdbmi.Commands: trace_find :: TraceMode -> Command
+ Gdbmi.Commands: trace_list_variables :: Command
+ Gdbmi.Commands: trace_save :: Bool -> String -> Command
+ Gdbmi.Commands: trace_start :: Command
+ Gdbmi.Commands: trace_status :: Command
+ Gdbmi.Commands: trace_stop :: Command
+ Gdbmi.Commands: var_assign :: String -> String -> Command
+ Gdbmi.Commands: var_create :: Maybe String -> FrameSelect -> String -> Command
+ Gdbmi.Commands: var_delete :: Bool -> String -> Command
+ Gdbmi.Commands: var_evaluate_expression :: Maybe FormatSpec -> String -> Command
+ Gdbmi.Commands: var_gdbShow_attributes :: String -> Command
+ Gdbmi.Commands: var_gdbShow_format :: String -> Command
+ Gdbmi.Commands: var_info_expression :: String -> Command
+ Gdbmi.Commands: var_info_num_children :: String -> Command
+ Gdbmi.Commands: var_info_path_expressoin :: String -> Command
+ Gdbmi.Commands: var_info_type :: Command
+ Gdbmi.Commands: var_list_children :: Maybe PrintValues -> String -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: var_list_children' :: Int -> String -> Maybe (Int, Int) -> Command
+ Gdbmi.Commands: var_set_format :: String -> FormatSpec -> Command
+ Gdbmi.Commands: var_set_frozen :: String -> FrozenFlag -> Command
+ Gdbmi.Commands: var_set_update_range :: String -> Int -> Int -> Command
+ Gdbmi.Commands: var_set_visualizer :: String -> String -> Command
+ Gdbmi.Commands: var_update :: Maybe PrintValues -> Maybe String -> Command
+ Gdbmi.IO: Callback :: ([Stream] -> IO ()) -> ([Notification] -> IO ()) -> Maybe ([Stopped] -> IO ()) -> Callback
+ Gdbmi.IO: Config :: [String] -> Maybe FilePath -> Config
+ Gdbmi.IO: cbNotify :: Callback -> [Notification] -> IO ()
+ Gdbmi.IO: cbStopped :: Callback -> Maybe ([Stopped] -> IO ())
+ Gdbmi.IO: cbStream :: Callback -> [Stream] -> IO ()
+ Gdbmi.IO: confCommandLine :: Config -> [String]
+ Gdbmi.IO: confLogfile :: Config -> Maybe FilePath
+ Gdbmi.IO: data Callback
+ Gdbmi.IO: data Config
+ Gdbmi.IO: data Context
+ Gdbmi.IO: default_config :: Config
+ Gdbmi.IO: send_command :: Context -> Command -> IO Response
+ Gdbmi.IO: setup :: Config -> Callback -> IO Context
+ Gdbmi.IO: shutdown :: Context -> IO ()
+ Gdbmi.Representation: ACBreakpointModified :: AsyncClass
+ Gdbmi.Representation: ACLibraryLoaded :: AsyncClass
+ Gdbmi.Representation: ACRunning :: AsyncClass
+ Gdbmi.Representation: ACStop :: AsyncClass
+ Gdbmi.Representation: ACThreadCreated :: AsyncClass
+ Gdbmi.Representation: ACThreadExited :: AsyncClass
+ Gdbmi.Representation: ACThreadGroupAdded :: AsyncClass
+ Gdbmi.Representation: ACThreadGroupExited :: AsyncClass
+ Gdbmi.Representation: ACThreadGroupStarted :: AsyncClass
+ Gdbmi.Representation: ARExecAsyncOutput :: ExecAsyncOutput -> AsyncRecord
+ Gdbmi.Representation: ARNotifyAsyncOutput :: NotifyAsyncOutput -> AsyncRecord
+ Gdbmi.Representation: ARStatusAsyncOutput :: StatusAsyncOutput -> AsyncRecord
+ Gdbmi.Representation: AsyncOutput :: AsyncClass -> [Result] -> AsyncOutput
+ Gdbmi.Representation: CLICommand :: (Maybe Token) -> String -> Command
+ Gdbmi.Representation: Console :: StreamClass
+ Gdbmi.Representation: ConsoleStreamOutput :: CString -> ConsoleStreamOutput
+ Gdbmi.Representation: EmptyList :: List
+ Gdbmi.Representation: Exec :: NotificationClass
+ Gdbmi.Representation: ExecAsyncOutput :: (Maybe Token) -> AsyncOutput -> ExecAsyncOutput
+ Gdbmi.Representation: Log :: StreamClass
+ Gdbmi.Representation: LogStreamOutput :: CString -> LogStreamOutput
+ Gdbmi.Representation: MICommand :: (Maybe Token) -> Operation -> [Option] -> [Parameter] -> Command
+ Gdbmi.Representation: Notification :: NotificationClass -> AsyncClass -> [Result] -> Notification
+ Gdbmi.Representation: Notify :: NotificationClass
+ Gdbmi.Representation: NotifyAsyncOutput :: (Maybe Token) -> AsyncOutput -> NotifyAsyncOutput
+ Gdbmi.Representation: OOBAsyncRecord :: AsyncRecord -> OutOfBandRecord
+ Gdbmi.Representation: OOBStreamRecord :: StreamRecord -> OutOfBandRecord
+ Gdbmi.Representation: Option :: Parameter -> (Maybe Parameter) -> Option
+ Gdbmi.Representation: Output :: [OutOfBandRecord] -> (Maybe ResultRecord) -> Output
+ Gdbmi.Representation: QuotedString :: String -> Parameter
+ Gdbmi.Representation: RCConnected :: ResultClass
+ Gdbmi.Representation: RCDone :: ResultClass
+ Gdbmi.Representation: RCError :: ResultClass
+ Gdbmi.Representation: RCExit :: ResultClass
+ Gdbmi.Representation: RCRunning :: ResultClass
+ Gdbmi.Representation: RawString :: String -> Parameter
+ Gdbmi.Representation: Response :: ResultClass -> [Result] -> Response
+ Gdbmi.Representation: Result :: Variable -> Value -> Result
+ Gdbmi.Representation: ResultList :: [Result] -> List
+ Gdbmi.Representation: ResultRecord :: (Maybe Token) -> ResultClass -> [Result] -> ResultRecord
+ Gdbmi.Representation: SRConsoleStreamOutput :: ConsoleStreamOutput -> StreamRecord
+ Gdbmi.Representation: SRLogStreamOutput :: LogStreamOutput -> StreamRecord
+ Gdbmi.Representation: SRTargetStreamOutput :: TargetStreamOutput -> StreamRecord
+ Gdbmi.Representation: Status :: NotificationClass
+ Gdbmi.Representation: StatusAsyncOutput :: (Maybe Token) -> AsyncOutput -> StatusAsyncOutput
+ Gdbmi.Representation: Stream :: StreamClass -> String -> Stream
+ Gdbmi.Representation: Target :: StreamClass
+ Gdbmi.Representation: TargetStreamOutput :: CString -> TargetStreamOutput
+ Gdbmi.Representation: Tuple :: [Result] -> Tuple
+ Gdbmi.Representation: VConst :: Const -> Value
+ Gdbmi.Representation: VList :: List -> Value
+ Gdbmi.Representation: VTuple :: Tuple -> Value
+ Gdbmi.Representation: ValueList :: [Value] -> List
+ Gdbmi.Representation: asConst :: Value -> Maybe Const
+ Gdbmi.Representation: asList :: Value -> Maybe List
+ Gdbmi.Representation: asTuple :: Value -> Maybe Tuple
+ Gdbmi.Representation: class GetToken a
+ Gdbmi.Representation: data AsyncClass
+ Gdbmi.Representation: data AsyncOutput
+ Gdbmi.Representation: data AsyncRecord
+ Gdbmi.Representation: data Command
+ Gdbmi.Representation: data ConsoleStreamOutput
+ Gdbmi.Representation: data ExecAsyncOutput
+ Gdbmi.Representation: data List
+ Gdbmi.Representation: data LogStreamOutput
+ Gdbmi.Representation: data Notification
+ Gdbmi.Representation: data NotificationClass
+ Gdbmi.Representation: data NotifyAsyncOutput
+ Gdbmi.Representation: data Option
+ Gdbmi.Representation: data OutOfBandRecord
+ Gdbmi.Representation: data Output
+ Gdbmi.Representation: data Parameter
+ Gdbmi.Representation: data Response
+ Gdbmi.Representation: data Result
+ Gdbmi.Representation: data ResultClass
+ Gdbmi.Representation: data ResultRecord
+ Gdbmi.Representation: data StatusAsyncOutput
+ Gdbmi.Representation: data Stream
+ Gdbmi.Representation: data StreamClass
+ Gdbmi.Representation: data StreamRecord
+ Gdbmi.Representation: data TargetStreamOutput
+ Gdbmi.Representation: data Tuple
+ Gdbmi.Representation: data Value
+ Gdbmi.Representation: get_token :: GetToken a => a -> Maybe Token
+ Gdbmi.Representation: instance Eq AsyncClass
+ Gdbmi.Representation: instance Eq NotificationClass
+ Gdbmi.Representation: instance Eq ResultClass
+ Gdbmi.Representation: instance GetToken AsyncRecord
+ Gdbmi.Representation: instance GetToken Command
+ Gdbmi.Representation: instance GetToken ExecAsyncOutput
+ Gdbmi.Representation: instance GetToken NotifyAsyncOutput
+ Gdbmi.Representation: instance GetToken OutOfBandRecord
+ Gdbmi.Representation: instance GetToken Output
+ Gdbmi.Representation: instance GetToken ResultRecord
+ Gdbmi.Representation: instance GetToken StatusAsyncOutput
+ Gdbmi.Representation: instance Show AsyncClass
+ Gdbmi.Representation: instance Show AsyncOutput
+ Gdbmi.Representation: instance Show AsyncRecord
+ Gdbmi.Representation: instance Show ConsoleStreamOutput
+ Gdbmi.Representation: instance Show ExecAsyncOutput
+ Gdbmi.Representation: instance Show List
+ Gdbmi.Representation: instance Show LogStreamOutput
+ Gdbmi.Representation: instance Show Notification
+ Gdbmi.Representation: instance Show NotificationClass
+ Gdbmi.Representation: instance Show NotifyAsyncOutput
+ Gdbmi.Representation: instance Show OutOfBandRecord
+ Gdbmi.Representation: instance Show Output
+ Gdbmi.Representation: instance Show Response
+ Gdbmi.Representation: instance Show Result
+ Gdbmi.Representation: instance Show ResultClass
+ Gdbmi.Representation: instance Show ResultRecord
+ Gdbmi.Representation: instance Show StatusAsyncOutput
+ Gdbmi.Representation: instance Show Stream
+ Gdbmi.Representation: instance Show StreamClass
+ Gdbmi.Representation: instance Show StreamRecord
+ Gdbmi.Representation: instance Show TargetStreamOutput
+ Gdbmi.Representation: instance Show Tuple
+ Gdbmi.Representation: instance Show Value
+ Gdbmi.Representation: notiAsyncClass :: Notification -> AsyncClass
+ Gdbmi.Representation: notiClass :: Notification -> NotificationClass
+ Gdbmi.Representation: notiResults :: Notification -> [Result]
+ Gdbmi.Representation: output_notification :: Output -> [Notification]
+ Gdbmi.Representation: output_response :: Output -> Maybe Response
+ Gdbmi.Representation: output_stream :: Output -> [Stream]
+ Gdbmi.Representation: parameter_valid :: Parameter -> Bool
+ Gdbmi.Representation: parse_output :: String -> Output
+ Gdbmi.Representation: render_command :: Command -> String
+ Gdbmi.Representation: resValue :: Result -> Value
+ Gdbmi.Representation: resVariable :: Result -> Variable
+ Gdbmi.Representation: respClass :: Response -> ResultClass
+ Gdbmi.Representation: respResults :: Response -> [Result]
+ Gdbmi.Representation: tupleResults :: Tuple -> [Result]
+ Gdbmi.Representation: type CString = String
+ Gdbmi.Representation: type Const = CString
+ Gdbmi.Representation: type Operation = String
+ Gdbmi.Representation: type Token = Int
+ Gdbmi.Representation: type Variable = String
+ Gdbmi.Semantics: Arg :: String -> String -> Arg
+ Gdbmi.Semantics: Breakpoint :: BkptNumber -> BreakpointType -> BreakpointDisp -> Bool -> String -> String -> String -> String -> Int -> Int -> String -> Breakpoint
+ Gdbmi.Semantics: BreakpointDel :: BreakpointDisp
+ Gdbmi.Semantics: BreakpointHit :: BreakpointDisp -> BkptNumber -> StopReason
+ Gdbmi.Semantics: BreakpointKeep :: BreakpointDisp
+ Gdbmi.Semantics: EndSteppingRange :: StopReason
+ Gdbmi.Semantics: Frame :: Maybe Int -> String -> String -> Maybe [Arg] -> String -> Maybe String -> Int -> Frame
+ Gdbmi.Semantics: FunctionFinished :: StopReason
+ Gdbmi.Semantics: Stack :: [Frame] -> Stack
+ Gdbmi.Semantics: Stopped :: StopReason -> Frame -> Int -> String -> Int -> Stopped
+ Gdbmi.Semantics: argName :: Arg -> String
+ Gdbmi.Semantics: argValue :: Arg -> String
+ Gdbmi.Semantics: bkptAddress :: Breakpoint -> String
+ Gdbmi.Semantics: bkptDisp :: Breakpoint -> BreakpointDisp
+ Gdbmi.Semantics: bkptEnabled :: Breakpoint -> Bool
+ Gdbmi.Semantics: bkptFile :: Breakpoint -> String
+ Gdbmi.Semantics: bkptFullname :: Breakpoint -> String
+ Gdbmi.Semantics: bkptFunc :: Breakpoint -> String
+ Gdbmi.Semantics: bkptHitDisp :: StopReason -> BreakpointDisp
+ Gdbmi.Semantics: bkptHitNumber :: StopReason -> BkptNumber
+ Gdbmi.Semantics: bkptLine :: Breakpoint -> Int
+ Gdbmi.Semantics: bkptNumber :: Breakpoint -> BkptNumber
+ Gdbmi.Semantics: bkptOriginalLocation :: Breakpoint -> String
+ Gdbmi.Semantics: bkptTimes :: Breakpoint -> Int
+ Gdbmi.Semantics: bkptType :: Breakpoint -> BreakpointType
+ Gdbmi.Semantics: data Arg
+ Gdbmi.Semantics: data Breakpoint
+ Gdbmi.Semantics: data BreakpointDisp
+ Gdbmi.Semantics: data Frame
+ Gdbmi.Semantics: data StopReason
+ Gdbmi.Semantics: data Stopped
+ Gdbmi.Semantics: frameAddr :: Frame -> String
+ Gdbmi.Semantics: frameArgs :: Frame -> Maybe [Arg]
+ Gdbmi.Semantics: frameFile :: Frame -> String
+ Gdbmi.Semantics: frameFullname :: Frame -> Maybe String
+ Gdbmi.Semantics: frameFunc :: Frame -> String
+ Gdbmi.Semantics: frameLevel :: Frame -> Maybe Int
+ Gdbmi.Semantics: frameLine :: Frame -> Int
+ Gdbmi.Semantics: instance Read BreakpointDisp
+ Gdbmi.Semantics: instance Show Arg
+ Gdbmi.Semantics: instance Show Breakpoint
+ Gdbmi.Semantics: instance Show BreakpointDisp
+ Gdbmi.Semantics: instance Show Frame
+ Gdbmi.Semantics: instance Show Stack
+ Gdbmi.Semantics: instance Show StopReason
+ Gdbmi.Semantics: instance Show Stopped
+ Gdbmi.Semantics: newtype Stack
+ Gdbmi.Semantics: notification_stopped :: [Result] -> Maybe Stopped
+ Gdbmi.Semantics: response_break_insert :: [Result] -> Maybe Breakpoint
+ Gdbmi.Semantics: response_data_evaluate_expression :: [Result] -> Maybe String
+ Gdbmi.Semantics: response_error :: [Result] -> Maybe String
+ Gdbmi.Semantics: response_exec_return :: [Result] -> Maybe Frame
+ Gdbmi.Semantics: response_stack_list_frames :: [Result] -> Maybe Stack
+ Gdbmi.Semantics: stackFrames :: Stack -> [Frame]
+ Gdbmi.Semantics: stoppedCore :: Stopped -> Int
+ Gdbmi.Semantics: stoppedFrame :: Stopped -> Frame
+ Gdbmi.Semantics: stoppedReason :: Stopped -> StopReason
+ Gdbmi.Semantics: stoppedThreadId :: Stopped -> Int
+ Gdbmi.Semantics: stoppedThreads :: Stopped -> String
+ Gdbmi.Semantics: type BkptNumber = Int
+ Gdbmi.Semantics: type BreakpointType = String

Files

− 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
LICENSE view
@@ -1,4 +1,5 @@ Copyright (c) 2008 Evan Martin <martine@danga.com>+Copyright (c) 2012 Alexander Bernauer <acopton@gmail.com> All rights reserved.  Redistribution and use in source and binary forms, with or without
− Test.hs
@@ -1,89 +0,0 @@--- hgdbmi: a Haskell interface to GDB/MI.--- Copyright (C) 2008 Evan Martin <martine@danga.com>--import GDBMI-import Test.HUnit--startupText =-  "~\"GNU gdb 6.7.1-debian\\n\"\n" ++-  "~\"Copyright (C) 2007 Free Software Foundation, Inc.\\n\"\n" ++-  "~\"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\\n\"\n" ++-  "~\"This is free software: you are free to change and redistribute it.\\n\"\n" ++-  "~\"There is NO WARRANTY, to the extent permitted by law.  Type \\\"show copying\\\"\\n\"\n" ++-  "~\"and \\\"show warranty\\\" for details.\\n\"\n" ++-  "~\"This GDB was configured as \\\"i486-linux-gnu\\\".\\n\"\n" ++-  "~\"Attaching to process 8902\\n\"\n" ++-  "~\"Reading symbols from /home/martine/projects/c-repl/dist/build/child...\"\n" ++-  "~\"done.\\n\"\n" ++-  "~\"Using host libthread_db library \\\"/lib/tls/i686/cmov/libthread_db.so.1\\\".\\n\"\n" ++-  "~\"Reading symbols from /lib/tls/i686/cmov/libdl.so.2...\"\n" ++-  "~\"done.\\n\"\n" ++-  "~\"Loaded symbols for /lib/tls/i686/cmov/libdl.so.2\\n\"\n" ++-  "~\"Reading symbols from /lib/tls/i686/cmov/libc.so.6...\"\n" ++-  "~\"done.\\n\"\n" ++-  "~\"Loaded symbols for /lib/tls/i686/cmov/libc.so.6\\n\"\n" ++-  "~\"Reading symbols from /lib/ld-linux.so.2...\"\n" ++-  "~\"done.\\n\"\n" ++-  "~\"Loaded symbols for /lib/ld-linux.so.2\\n\"\n" ++-  "~\"Reading symbols from /home/martine/projects/c-repl/.c-repl/dl1.so...\"\n" ++-  "~\"done.\\n\"\n" ++-  "~\"Loaded symbols for ./.c-repl/dl1.so\\n\"\n"--testStartup = test $-  case GDBMI.parse "startup" startupText of-    Left err -> assertFailure $ show err-    Right (MIOutput info result) -> do-      assertEqual "oob line count" 23 (length info)-      assertEqual "oob first line"-        (MIConsole "GNU gdb 6.7.1-debian\n") (head info)--printText =-  "&\"p x\\n\"\n" ++-  "~\"$1 = 3\"\n" ++-  "~\"\n\"\n" ++-  "^done,thread-id=\"0\",frame={addr=\"0xb7f0a410\",func=\"__kernel_vsyscall\",args=[]}\n"--testPrint = test $-  case GDBMI.parse "parse 'p x' output" printText of-    Left err -> assertFailure $ show err-    Right (MIOutput info result) -> do-      assertEqual "oob line count" 3 (length info)-      assertEqual "oob first line" (MILog "p x\n") (head info)-      case result of-        Just (MIDone tuples) -> do-          assertEqual "done tuple #1" ("thread-id", MIString "0") (head tuples)-          case lookup "frame" tuples of-            Just (MITuple frame) -> -              assertEqual "done tuple #4" ("args", MITuple []) (last frame)-            _ -> assertFailure $ "couldn't find 'frame'"-        _ ->-          assertFailure $ "expected done result, got " ++ show result--errorPrintText =-  "&\"p y\\n\"\n" ++-  "&\"No symbol \\\"y\\\" in current context.\\n\"\n" ++-  "^error,msg=\"No symbol \\\"y\\\" in current context.\"\n"--testErrorPrint = test $-  case GDBMI.parse "parse 'p y' error output" errorPrintText of-    Left err -> assertFailure $ show err-    Right (MIOutput info result) -> do-      assertEqual "oob line count" 2 (length info)-      assertEqual "oob first line" (MILog "p y\n") (head info)-      assertEqual "result"-          (Just (MIError "No symbol \"y\" in current context.")) result--varCreateText = "^done,name=\"vx\",numchild=\"0\",value=\"4\",type=\"int\"\n"--testVarCreate = test $-  case GDBMI.parse "parse 'var-create' output" varCreateText of-    Left err -> assertFailure $ show err-    Right (MIOutput info result) -> do-      assertEqual "no oob info" 0 (length info)-      assertEqual "result"-          (Just (MIDone [("name", MIString "vx"), ("numchild", MIString "0"),-                         ("value", MIString "4"), ("type", MIString "int")]))-          result--main =-  runTestTT $ TestList [testStartup, testPrint, testErrorPrint, testVarCreate]
hgdbmi.cabal view
@@ -1,21 +1,84 @@-Cabal-Version: >= 1.2-Build-Type: Simple-Name: hgdbmi-Version: 0.1-Synopsis: GDBMI interface (program-driven control of GDB)+name:           hgdbmi+category:       Development+version:        0.2+license:        BSD3+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>, 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 wraps attaching GDB to a process and parsing the-  (surprisingly complicated) GDB\/MI output.-Category: Development-License: BSD3-License-File: LICENSE-Author: Evan Martin-Maintainer: martine@danga.com-Copyright: (c) 2008 Evan Martin <martine@danga.com>-Homepage: http://neugierig.org/software/darcs/browse/?r=hgdbmi;a=summary-Extra-Source-Files: Test.hs+  GDB\/MI lets programs drive GDB. It can be used, for example, by GDB+  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 is tested with GDB version 7.4. -Library-  Build-Depends: base, parsec, process, unix-  Exposed-Modules: GDBMI+build-type:     Simple+tested-with:    GHC == 7.4.2++source-repository head+  type: git+  location: git://github.com/copton/hgdbmi.git++source-repository this+  type: git+  location: git://github.com/copton/hgdbmi.git+  tag: v0.2++library+  build-depends:+    base        >= 4 && < 5,+    parsec      == 3.1.*,+    process     == 1.1.*,+    unix        == 2.6.*,+    stm         == 2.3.*++  exposed-modules:+    Gdbmi.IO+    Gdbmi.Commands+    Gdbmi.Representation+    Gdbmi.Semantics++  hs-source-dirs:     src+  ghc-options:        -Wall+  default-language:   Haskell2010+ +test-suite pure+  type:             exitcode-stdio-1.0+  main-is:          pure.hs+  other-modules:    Paste+  hs-source-dirs:   tests+  ghc-options:      -Wall+  default-language: Haskell2010+  build-depends:+    hgdbmi,+    base                 >= 4 && < 5,+    HUnit                == 1.2.*,+    test-framework       == 0.6.*,+    test-framework-hunit == 0.2.*,+    template-haskell +++test-suite io+  type:             exitcode-stdio-1.0+  main-is:          io.hs+  other-modules:    Paste+  hs-source-dirs:   tests+  ghc-options:      -Wall+  default-language: Haskell2010+  build-depends:+    hgdbmi,+    base                 >= 4 && < 5,+    directory            == 1.2.*,+    process              == 1.1.*,+    temporary            == 1.1.*,+    template-haskell 
+ src/Gdbmi/Commands.hs view
@@ -0,0 +1,828 @@+-- | Constructor functions for 'Gdmi.Representation.Command' values.+-- +-- Please consult the cited GDB documentation for the semantics of the individual commands.+module Gdbmi.Commands+-- {{{1 exports+(+  -- * Commands+  -- ** Breakpoint Commands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Breakpoint-Commands.html>+  break_after,+  break_commands,+  break_condition,+  break_delete,+  break_disable,+  break_enable,+  break_info,+  break_insert,+  break_list,+  break_passcount,+  break_watch,++  -- ** Program Context+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Program-Context.html>+  exec_arguments,+  environment_cd,+  environment_directory,+  environment_path,+  environment_pwd,++  -- ** Thread Commands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html>+  thread_info,+  thread_list_ids,+  thread_select,++  -- ** Ada Tasking Commands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Ada-Tasking-Commands.html>+  ada_task_info,++  -- ** Program Execution+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Program-Execution.html>+  exec_continue,+  exec_finish,+  exec_interrupt,+  exec_jump,+  exec_next,+  exec_next_instruction,+  exec_return,+  exec_run,+  exec_step,+  exec_step_instruction,+  exec_until,++  -- ** Stack Manipulation+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html>+  stack_info_frame,+  stack_info_depth,+  stack_list_arguments,+  stack_list_arguments',+  stack_list_frames,+  stack_list_locals,+  stack_list_locals',+  stack_list_variables,+  stack_list_variables',+  stack_select_frame,++  -- ** Variable Objects+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html>+  enable_pretty_printing,+  var_create,+  var_delete,+  var_set_format,+  var_gdbShow_format,+  var_info_num_children,+  var_list_children,+  var_list_children',+  var_info_type,+  var_info_expression,+  var_info_path_expressoin,+  var_gdbShow_attributes,+  var_evaluate_expression,+  var_assign,+  var_update,+  var_set_frozen,+  var_set_update_range,+  var_set_visualizer,++  -- ** Data Manipulation+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html>+  data_disassemble,+  data_evaluate_expression,+  data_list_changed_registers,+  data_list_register_names,+  data_list_register_values,+  data_read_memory,+  data_read_memory_bytes,+  data_write_memory_bytes,++  -- ** Tracepoint Commands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Tracepoint-Commands.html>+  trace_find,+  trace_define_variable,+  trace_list_variables,+  trace_save,+  trace_start,+  trace_status,+  trace_stop,++  -- ** Symbol Query+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html>+  symbol_list_lines,++  -- ** File Commands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-File-Commands.html>+  file_exec_and_symbols,+  file_exec_file,+  file_list_exec_source_file,+  file_list_exec_source_files,+  file_symbol_file,++  -- ** Target Manipulation+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html>+  target_attach,+  target_detach,+  target_disconnect,+  target_download,+  target_select,++  -- ** File Transfer Commands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-File-Transfer-Commands.html>+  target_file_put,+  target_file_get,+  target_file_delete,++  -- ** Miscellaneous Commmands+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html>+  gdb_exit,+  gdb_set,+  gdb_gdbShow,+  gdb_version,+  list_features,+  list_target_features,+  list_thread_groups,+  info_os,+  add_inferior,+  interpreter_exec,+  inferior_tty_set,+  inferior_tty_gdbShow,+  enable_timings,++  -- * Auxiliary Types+  -- ** Location+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/Specify-Location.html>.+  Location,+  positive_offset_location,+  negative_offset_location,+  file_line_location,+  function_location,+  function_label_location,+  file_function_location,+  label_location,+  plain_address_location,+  expr_address_location,+  func_address_location,+  file_func_address_location,++  -- ** Other Types+  -- | See the documentation of the commands that use these types for their semantics.+  PrintValues(..),+  FrameSelect(..),+  FormatSpec(..),+  FrozenFlag(..),+  DisassemblyMode(..),+  DataFormat(..),+  OutputFormat(..),+  TraceMode(..),+  Target(..),+  Medium(..),+  Interpreter(..),+   +  -- * Helper Functions+  cli_command,+  set_token+) where++-- imports {{{1+import Data.List (intersperse)+import Data.Maybe (fromMaybe)+import Prelude hiding (reverse, all, lines)++import Gdbmi.Representation (Command(..), Option(..), Token, Parameter(..), render_command)++-- types {{{1+class GdbShow a where -- {{{2+  gdbShow :: a -> String++instance GdbShow Char where+  gdbShow = (:[])++instance GdbShow a => GdbShow [a] where+  gdbShow = concatMap gdbShow++instance GdbShow Int where+  gdbShow = show++newtype Location = Location String -- {{{2++instance GdbShow Location where -- {{{3+  gdbShow (Location location) = location ++positive_offset_location :: Int -> Location -- {{{3+positive_offset_location offset = Location $ "+" ++ gdbShow offset++negative_offset_location :: Int -> Location -- {{{3+negative_offset_location offset = Location $ "-" ++ gdbShow offset++file_line_location :: String -> Int -> Location -- {{{3+file_line_location filename linenum = Location $ filename ++ ":" ++ gdbShow linenum++function_location :: String -> Location -- {{{3+function_location = Location++function_label_location :: String -> String -> Location -- {{{3+function_label_location function label = Location $ function ++ ":" ++ label++file_function_location :: String -> String -> Location -- {{{3+file_function_location filename function = Location $ filename ++ ":" ++ function++label_location :: String -> Location -- {{{3+label_location = Location++plain_address_location :: String -> Location -- {{{3+plain_address_location addr = Location $ "*" ++ addr++expr_address_location :: String -> Location -- {{{3+expr_address_location = plain_address_location++func_address_location :: String -> Location -- {{{3+func_address_location = plain_address_location++file_func_address_location :: String -> String -> Location -- {{{3+file_func_address_location filename funcaddr = Location $ "'" ++ filename ++ "'::" ++ funcaddr++data PrintValues -- {{{2+  = NoValues     -- ^ \"--no-values\"     or \"0\"+  | AllValues    -- ^ \"--all-values\"    or \"1\"+  | SimpleValues -- ^ \"--simple-values\" or \"2\"++instance GdbShow PrintValues where+  gdbShow NoValues     = "--no-values"+  gdbShow AllValues    = "--all-values"+  gdbShow SimpleValues = "--simple-values"++mapPrintValues :: (PrintValues -> a) -> Int -> a+mapPrintValues f 0 = f NoValues+mapPrintValues f 1 = f AllValues+mapPrintValues f 2 = f SimpleValues+mapPrintValues _ _ = error "valid integers for the print-value parameter range from 0 to 2 only"++data FrameSelect -- {{{2+  = FrameAddr String -- ^ just the given address+  | CurrentFrame     -- ^ \"*\"+  | Floating         -- ^ \"\@\"++instance GdbShow FrameSelect where+  gdbShow (FrameAddr addr) = addr+  gdbShow CurrentFrame = "*"+  gdbShow Floating = "@"++data FormatSpec -- {{{2+  = Binary      -- ^ \"binary\"+  | Decimal     -- ^ \"decimal\"+  | Hexadecimal -- ^ \"hexadecimal\"+  | Octal       -- ^ \"octal\"+  | Natural     -- ^ \"natural\"++instance GdbShow FormatSpec where+  gdbShow Binary = "binary"+  gdbShow Decimal = "decimal"+  gdbShow Hexadecimal = "hexadecimal"+  gdbShow Octal = "octal"+  gdbShow Natural = "natural"++data FrozenFlag -- {{{2+  = Frozen   -- ^ \"1\"+  | Unfrozen -- ^ \"0\"++instance GdbShow FrozenFlag where+  gdbShow Frozen = "1"+  gdbShow Unfrozen = "0"++data DisassemblyMode -- {{{2+  = DisassemblyMode Bool Bool -- ^ with mixed source?, with raw opcodes?++instance GdbShow DisassemblyMode where+  gdbShow (DisassemblyMode False False) = "0"+  gdbShow (DisassemblyMode True False) = "1"+  gdbShow (DisassemblyMode False True) = "2"+  gdbShow (DisassemblyMode True True) = "3"++data DataFormat -- {{{2+  = DHexadecimal -- ^ \"x\"+  | DOctal       -- ^ \"o\"+  | DBinary      -- ^ \"t\"+  | DDecimal     -- ^ \"d\"+  | DRaw         -- ^ \"r\"+  | DNatural     -- ^ \"N\"++instance GdbShow DataFormat where+  gdbShow DHexadecimal = "x"+  gdbShow DOctal = "o"+  gdbShow DBinary = "t"+  gdbShow DDecimal = "d"+  gdbShow DRaw = "r"+  gdbShow DNatural = "N"++data OutputFormat -- {{{2+  = HexadecimalInteger        -- ^ \"x\"+  | SignedDecimalInteger      -- ^ \"d\"+  | UnsignedDecimalInteger    -- ^ \"u\"+  | OctalInteger              -- ^ \"o\"+  | BinaryInteger             -- ^ \"t\"+  | Address                   -- ^ \"a\"+  | CharacterConstantInteger  -- ^ \"c\"+  | FloatingPointNumber       -- ^ \"f\"+  | OString                   -- ^ \"s\"+  | Raw                       -- ^ \"r\"++instance GdbShow OutputFormat where+  gdbShow HexadecimalInteger = "x"+  gdbShow SignedDecimalInteger = "d"+  gdbShow UnsignedDecimalInteger = "u"+  gdbShow OctalInteger = "o"+  gdbShow BinaryInteger = "t"+  gdbShow Address = "a"+  gdbShow CharacterConstantInteger = "c"+  gdbShow FloatingPointNumber = "f"+  gdbShow OString = "s"+  gdbShow Raw = "r"++data TraceMode -- {{{2+  = None                          -- ^ \"none\"+  | FrameNumber Int               -- ^ \"frame-number\"+  | TracepointNumber Int          -- ^ \"tracepoint-number\"+  | PC String                     -- ^ \"pc\"+  | PCInsideRange String String   -- ^ \"pc-inside-range\"+  | PCOutsideRange String String  -- ^ \"pc-outside-range\"+  | Line Location                 -- ^ \"line\"++instance GdbShow TraceMode where+  gdbShow None = "none"+  gdbShow (FrameNumber _) = "frame-number"+  gdbShow (TracepointNumber _) = "tracepoint-number"+  gdbShow (PC _) = "pc"+  gdbShow (PCInsideRange _ _) = "pc-inside-range"+  gdbShow (PCOutsideRange _ _) = "pc-outside-range"+  gdbShow (Line _) = "line"++traceModeOptions :: TraceMode -> [Option]+traceModeOptions None = []+traceModeOptions (FrameNumber x) = [opt x]+traceModeOptions (TracepointNumber x) = [opt x]+traceModeOptions (PC x) = [opt x]+traceModeOptions (PCInsideRange x y) = [opt x, opt y]+traceModeOptions (PCOutsideRange x y) = [opt x, opt y]+traceModeOptions (Line x) = [opt x]++data Target -- {{{2+  = Exec FilePath  -- ^ \"exec\"+  | Core FilePath  -- ^ \"core\"+  | Remote Medium  -- ^ \"remote\"+  | Sim [String]   -- ^ \"sim\"+  | Nrom           -- ^ \"nrom\"++instance GdbShow Target where+  gdbShow (Exec _) = "exec" +  gdbShow (Core _) = "core"+  gdbShow (Remote _) = "remote" +  gdbShow (Sim _) = "sim"+  gdbShow Nrom = "nrom"++targetOptions :: Target -> [Option]+targetOptions (Exec x) = [opt x] +targetOptions (Core x) = [opt x] +targetOptions (Remote x) = [opt x]+targetOptions (Sim xs) = map opt xs+targetOptions Nrom = []+  +data Medium -- {{{2+  = SerialDevice String  -- ^ just the given device+  | TcpHost String Int   -- ^ \"tcp:%s:%d\" host port+  | UdpHost String Int   -- ^ \"udp:%s:%d\" host port+  | Pipe String          -- ^ \"|%s\" command++instance GdbShow Medium where+  gdbShow (SerialDevice device) = device+  gdbShow (TcpHost host port) = "tcp:" ++ host ++ ":" ++ gdbShow port+  gdbShow (UdpHost host port) = "udp:" ++ host ++ ":" ++ gdbShow port+  gdbShow (Pipe command) = "| " ++ command++data Interpreter -- {{{2+  = Console -- ^ \"console\"+  | MI      -- ^ \"mi\"+  | MI2     -- ^ \"mi2\"+  | MI1     -- ^ \"mi1\"++instance GdbShow Interpreter where+  gdbShow Console = "console"+  gdbShow MI = "mi"+  gdbShow MI2 = "mi2"+  gdbShow MI1 = "mi1"+   +-- helper {{{1+set_token :: Token -> Command -> Command -- {{{2+-- | Set the token of a command.+-- <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Input-Syntax.html>+--+-- Newly created commands have no token, but setting a token manually is usually not necessary.+-- 'Gdbmi.IO.send_command' will assign a unique token to a given command in any case.+set_token token (MICommand _ x y z) = MICommand (Just token) x y z+set_token token (CLICommand _ x)    = CLICommand (Just token) x++cli_command :: String -> Command+-- | Create a CLI command, i.e., use the provided string literaly.+-- +-- Some GDB commands are not reflected in the Machine Interface. In those+-- cases one has to resort to Command Line Interface commands, which the MI+-- accepts as well.+cli_command = CLICommand Nothing++-- commands {{{1+-- breakpoint commands {{{2+break_after :: Int -> Int -> Command -- {{{3+break_after number count = cmd "break-after" $ map opt [number, count]++break_commands :: Int -> [String] -> Command -- {{{3+break_commands number commands = cmd "break-commands" $ opt number : map opt commands++break_condition :: Int -> String -> Command -- {{{3+break_condition number expr = cmd "break-condition" $ opt number : opt expr : []++break_delete :: [Int] -> Command -- {{{3+break_delete numbers = cmd "break-delete" $ map optr numbers++break_disable :: [Int] -> Command -- {{{3+break_disable numbers = cmd "break-disable" $ map opt numbers++break_enable :: [Int] -> Command -- {{{3+break_enable numbers = cmd "break-enable" $ map opt numbers++break_info :: Int -> Command -- {{{3+break_info number = cmd "break-info" [opt number]++break_insert :: Bool -> Bool -> Bool -> Bool -> Bool -> Maybe String -> Maybe Int -> Maybe Int -> Location -> Command -- {{{3+break_insert temporary hardware pending disabled tracepoint condition ignoreCount threadId location =+  cmd "break-insert" $ temporary' ?: hardware' ?: pending' ?: disabled' ?: tracepoint' ?: condition' ?: ignoreCount' ?: threadId' ?: opt location : []+  where+    temporary'   = flagOpt "-t" temporary+    hardware'    = flagOpt "-h" hardware+    pending'     = flagOpt "-p" pending+    disabled'    = flagOpt "-d" disabled+    tracepoint'  = flagOpt "-a" tracepoint+    condition'   = valueOpt "-c" condition+    ignoreCount' = valueOpt "-i" ignoreCount+    threadId'    = valueOpt "-p" threadId+    +break_list :: Command -- {{{3+break_list = cmd "break-list" []++break_passcount :: Int -> Int -> Command -- {{{3+break_passcount tracepointNumber passcount = cmd "break-passcount" $ map opt [tracepointNumber, passcount]++break_watch :: Bool -> Command -- {{{3+break_watch access =  cmd "break-watch" [opt (if access then "-a" else "-r")]++-- program context {{{2+exec_arguments :: [String] -> Command -- {{{3+exec_arguments args = cmd "exec-arguments" $ map opt args++environment_cd :: String -> Command -- {{{3+environment_cd pathdir = cmd "environment-cd" [opt pathdir]++environment_directory :: Bool -> [String] -> Command -- {{{3+environment_directory reset pathdirs = cmd "environment-directory" $ flagOpt "-r" reset ?: map opt pathdirs++environment_path :: Bool -> [String] -> Command -- {{{3+environment_path reset pathdirs = cmd "environment-path" $ flagOpt "-r" reset ?: map opt pathdirs++environment_pwd :: Command -- {{{3+environment_pwd = cmd "environment-pwd" []++-- thread commands {{{2+thread_info :: Maybe Int -> Command -- {{{3+thread_info threadId = cmd "thread-info" $ fmap opt threadId ?: []++thread_list_ids :: Command -- {{{3+thread_list_ids = cmd "thread-list-ids" []++thread_select :: Int -> Command -- {{{3+thread_select threadnum = cmd "thread-select" [opt threadnum]++-- ada tasking commands {{{2+ada_task_info :: Maybe Int -> Command -- {{{3+ada_task_info taskId = cmd "ada-task-info" $ fmap opt taskId ?: []++-- program execution {{{2+exec_continue :: Bool -> Either Bool Int -> Command -- {{{3+exec_continue reverse x = cmd "exec-continue" $ reverse' ?: x' ?: []+  where+    reverse'     = flagOpt "--reverse" reverse+    x' = case x of+      Left all -> flagOpt "--all" all+      Right threadGroup -> Just $ opt' "--threadGroup" threadGroup++exec_finish :: Bool -> Command -- {{{3+exec_finish reverse = cmd "exec-finish" $ flagOpt "--reverse" reverse ?: []++exec_interrupt :: Either Bool Int -> Command -- {{{3+exec_interrupt x = cmd "exec-interrupt" $ x' ?: [] +  where+    x' = case x of+      Left all -> flagOpt "-all" all+      Right threadGroup -> Just $ opt' "--threadGroup" threadGroup++exec_jump :: Location -> Command -- {{{3+exec_jump location = cmd "exec-jump" [opt location]++exec_next :: Command -- {{{3+exec_next = cmd "exec-next" []++exec_next_instruction :: Bool -> Command -- {{{3+exec_next_instruction reverse = cmd "exec-next-instruction" $ flagOpt "--reverse" reverse ?: []++exec_return :: Command -- {{{3+exec_return = cmd "exec-return" []++exec_run :: Either Bool Int -> Command -- {{{3+exec_run x = cmd "exec-run" $ x' ?: []+  where+    x' = case x of+      Left all -> flagOpt "-all" all+      Right threadGroup -> Just $ opt' "--threadGroup" threadGroup++exec_step :: Command -- {{{3+exec_step = cmd "exec-step" []++exec_step_instruction :: Bool -> Command -- {{{3+exec_step_instruction reverse = cmd "exec-step-instruction" $ flagOpt "--reverse" reverse ?: []+  +exec_until :: Location -> Command -- {{{3+exec_until location = cmd "exec-until" [opt location]++-- stack manipulation {{{2+stack_info_frame :: Command -- {{{3+stack_info_frame = cmd "stack-info-frame" []++stack_info_depth :: Maybe Int -> Command  -- {{{3+stack_info_depth maxDepth = cmd "stack-info-depth" $ fmap opt maxDepth ?: []++stack_list_arguments :: PrintValues -> Maybe (Int, Int) -> Command -- {{{3+stack_list_arguments printValues frames = cmd "stack-list-arguments" $ opt printValues : maybTupleOpt frames++stack_list_arguments' :: Int -> Maybe (Int, Int) -> Command+stack_list_arguments' = mapPrintValues stack_list_arguments++stack_list_frames :: Maybe (Int, Int) -> Command -- {{{3+stack_list_frames frames = cmd "stack-list-frames" $ maybTupleOpt frames++stack_list_locals :: PrintValues -> Command -- {{{3+stack_list_locals printValues = cmd "stack-list-locals" [opt printValues]++stack_list_locals' :: Int -> Command -- {{{3+stack_list_locals' = mapPrintValues stack_list_locals++stack_list_variables :: PrintValues -> Command -- {{{3+stack_list_variables printValues = cmd "stack-list-variable" [opt printValues]++stack_list_variables' :: Int -> Command -- {{{3+stack_list_variables' = mapPrintValues stack_list_variables++stack_select_frame :: Int -> Command -- {{{3+stack_select_frame framenum = cmd "stack-select-frame" [opt framenum]++-- variable objects {{{2+enable_pretty_printing :: Command -- {{{3+enable_pretty_printing = cmd "enable-pretty-printing" []++var_create :: Maybe String -> FrameSelect -> String -> Command -- {{{3+var_create name frameSelect expression = cmd "var-create" $ [name', opt frameSelect, opt expression]+  where+    name' = opt (fromMaybe "-" name)++var_delete :: Bool -> String -> Command -- {{{3+var_delete children name = cmd "var-delete" $ flagOpt "-c" children ?: opt name : []++var_set_format :: String -> FormatSpec -> Command -- {{{3+var_set_format name formatSpec = cmd "var-set-format" [opt name, opt formatSpec]++var_gdbShow_format :: String -> Command -- {{{3+var_gdbShow_format name = cmd "var-gdbShow-format" [opt name]++var_info_num_children :: String -> Command -- {{{3+var_info_num_children name = cmd "var-info-num-children" [opt name]++var_list_children :: Maybe PrintValues -> String -> Maybe (Int, Int) -> Command -- {{{3+var_list_children Nothing name range = var_list_children (Just NoValues) name range+var_list_children (Just printValues) name range = cmd "var-list-children" $ opt printValues : opt name : maybTupleOpt range++var_list_children' :: Int -> String -> Maybe (Int, Int) -> Command+var_list_children' = mapPrintValues (var_list_children . Just)++var_info_type :: Command -- {{{3+var_info_type = cmd "var-info-type" []++var_info_expression :: String -> Command -- {{{3+var_info_expression name = cmd "var-info-expression" [opt name]++var_info_path_expressoin :: String -> Command -- {{{3+var_info_path_expressoin name = cmd "var-info-path-expression" [opt name]++var_gdbShow_attributes :: String -> Command -- {{{3+var_gdbShow_attributes name = cmd "var-gdbShow-attributes" [opt name]++var_evaluate_expression :: Maybe FormatSpec -> String -> Command -- {{{3+var_evaluate_expression formatSpec name = cmd "var-evaluate-expression" $ valueOpt "-f" formatSpec ?: opt name : []++var_assign :: String -> String -> Command -- {{{3+var_assign name expression = cmd "var-assign" [opt name, opt expression]++var_update :: Maybe PrintValues -> Maybe String -> Command -- {{{3+var_update Nothing name = var_update (Just NoValues) name+var_update (Just printValues) name = cmd "var-update" $ opt printValues : fmap opt name ?: []++var_set_frozen :: String -> FrozenFlag -> Command -- {{{3+var_set_frozen name flag = cmd "var-set-frozen" [opt name, opt flag]++var_set_update_range :: String -> Int -> Int -> Command -- {{{3+var_set_update_range name from to = cmd "var-set-update-range" [opt name, opt from, opt to]++var_set_visualizer :: String -> String -> Command -- {{{3+var_set_visualizer name visualizer = cmd "ver-set-visualizer" [opt name, opt visualizer]++-- data manipulation {{{2+data_disassemble :: Either (String, String) (String, Int, Maybe Int) -> DisassemblyMode -> Command -- {{{3+data_disassemble x mode = MICommand Nothing "data-disassemble" options [QuotedString . gdbShow $ mode]+  where+    options = case x of+      Left (start, end) -> opt' "-s" start : opt' "-e" end : []+      Right (filename, linenum, lines) -> opt' "-f" filename : opt' "-l" linenum : valueOpt "-n" lines ?: []++data_evaluate_expression :: String -> Command -- {{{3+data_evaluate_expression expr = cmd "data-evaluate-expression" [opt expr]++data_list_changed_registers :: Command -- {{{3+data_list_changed_registers = cmd "data-list-changed-registers" []++data_list_register_names :: [Int] -> Command -- {{{3+data_list_register_names regnos = cmd "data-list-register-names" $ map opt regnos++data_list_register_values :: DataFormat -> [Int] -> Command -- {{{3+data_list_register_values fmt regnos = cmd "data-list-register-values" $ opt fmt : map opt regnos++data_read_memory :: Maybe Int -> String -> OutputFormat -> Int -> Int -> Int -> Maybe Char -> Command -- {{{3+data_read_memory byteOffset address wordFormat wordSize nrRows nrCols asChar =+  cmd "data-read-memory" $ valueOpt "-o" byteOffset ?: opt address : opt wordFormat : opt wordSize : opt nrRows : opt nrCols : fmap opt asChar ?: []++data_read_memory_bytes :: Maybe Int -> String -> Int -> Command -- {{{3+data_read_memory_bytes byteOffset address count = cmd "data-read-memory-bytes" $ valueOpt "-o" byteOffset ?: opt address : opt count : []++data_write_memory_bytes :: String -> String -> Command -- {{{3+data_write_memory_bytes address contents = cmd "data-write-memory-bytes" [opt address, opt contents]++-- tracepoint commands {{{2+trace_find :: TraceMode -> Command -- {{{3+trace_find traceMode = cmd "trace-find" $ opt traceMode : traceModeOptions traceMode++trace_define_variable :: String -> Maybe String -> Command -- {{{3+trace_define_variable name value = cmd "trace-define-variable" $ opt name : fmap opt value ?: []++trace_list_variables :: Command -- {{{3+trace_list_variables = cmd "trace-list-variables" []++trace_save :: Bool -> String -> Command  -- {{{3+trace_save remote filename = cmd "trace-save" $ flagOpt "-r" remote ?: opt filename : []++trace_start :: Command -- {{{3+trace_start = cmd "trace-start" []++trace_status :: Command -- {{{3+trace_status = cmd "trace-status" []++trace_stop :: Command -- {{{3+trace_stop = cmd "trace-stop" []++-- symbol query {{{2++symbol_list_lines :: String -> Command -- {{{3+symbol_list_lines filename = cmd "symbol-list-lines" [opt filename]++-- file commands {{{2+file_exec_and_symbols :: Maybe FilePath -> Command -- {{{3+file_exec_and_symbols file = cmd "file-exec-and-symbols" $ fmap opt file ?: []++file_exec_file :: Maybe FilePath -> Command -- {{{3+file_exec_file file = cmd "file-exec-file" $ fmap opt file ?: []++file_list_exec_source_file :: Command -- {{{3+file_list_exec_source_file = cmd "file-list-exec-source-file" []++file_list_exec_source_files :: Command -- {{{3+file_list_exec_source_files = cmd "file-list-exec-source-files" []++file_symbol_file :: Maybe FilePath -> Command -- {{{3+file_symbol_file file = cmd "file-symbol-file" $ fmap opt file ?: []++-- target manipulation {{{2+target_attach :: Either Int FilePath -> Command -- {{{3+target_attach x = cmd "target-attach" $ x' : []+  where+    x' = case x of+      Left pidOrGid -> opt pidOrGid+      Right file -> opt file++target_detach :: Maybe Int -> Command -- {{{3+target_detach pidOrGid = cmd "target-detach" $ fmap opt pidOrGid ?: []++target_disconnect :: Command -- {{{3+target_disconnect = cmd "target-disconnect" []++target_download :: Command -- {{{3+target_download = cmd "target-download" []++target_select :: Target -> Command -- {{{3+target_select target = cmd "target-select" $ opt target : targetOptions target++-- file transfer commands {{{2+target_file_put :: FilePath -> FilePath -> Command -- {{{3+target_file_put hostfile targetfile = cmd "target-file-put" $ opt hostfile : opt targetfile : []++target_file_get :: FilePath -> FilePath -> Command -- {{{3+target_file_get targetfile hostfile = cmd "target-file-get" $ opt targetfile : opt hostfile : []++target_file_delete :: FilePath -> Command -- {{{3+target_file_delete targetfile = cmd "target-file-delete" $ opt targetfile : []++-- miscellaneous commmands {{{2+gdb_exit :: Command -- {{{3+gdb_exit = cmd "gdb-exit" []++gdb_set :: String -> Command -- {{{3+gdb_set expr = cmd "gdb-set" $ opt expr : []++gdb_gdbShow :: String -> Command -- {{{3+gdb_gdbShow name = cmd "gdb-gdbShow" $ opt name : []++gdb_version :: Command -- {{{3+gdb_version = cmd "gdb-version" []++list_features :: Command -- {{{3+list_features = cmd "list-features" []++list_target_features :: Command -- {{{3+list_target_features = cmd "list-target-features" []++list_thread_groups :: Bool -> Maybe Int -> [Int] -> Command -- {{{3+list_thread_groups available recurse groups = cmd "list-thread-groups" $ flagOpt "--available" available ?: valueOpt "--recurse" recurse ?: map opt groups++info_os :: Maybe String -> Command -- {{{3+info_os type_ = cmd "info-os" $ fmap opt type_ ?: []++add_inferior :: Command -- {{{3+add_inferior = cmd "add-inferior" []++interpreter_exec :: Interpreter -> Command -> Command -- {{{3+interpreter_exec interpreter command = cmd "interpreter-exec" $ opt interpreter : opt ((escapeQuotes . render_command) command) : []++inferior_tty_set :: String -> Command -- {{{3+inferior_tty_set tty = cmd "inferior-tty-set" $ opt tty : []++inferior_tty_gdbShow :: Command -- {{{3+inferior_tty_gdbShow = cmd "inferior-tty-gdbShow" []++enable_timings :: Bool -> Command -- {{{3+enable_timings flag = cmd "enable-timings" $ opt (if flag then "yes" else "no") : []++-- utils {{{1+cmd :: String -> [Option] -> Command -- {{{2+cmd operation options = MICommand Nothing operation options []++opt :: GdbShow a => a -> Option -- {{{2+opt parameter = Option (QuotedString . gdbShow $ parameter) Nothing++optr :: Show a => a -> Option -- {{{2+optr parameter = Option (RawString . show $ parameter) Nothing++opt' :: (GdbShow a, GdbShow b) => a -> b -> Option -- {{{2+opt' name value = Option (QuotedString . gdbShow $ name) (Just (QuotedString . gdbShow $ value))++flagOpt :: String -> Bool -> Maybe Option -- {{{2+flagOpt _ False = Nothing+flagOpt flag True = Just (opt flag)++valueOpt :: GdbShow a => String -> Maybe a -> Maybe Option -- {{{2+valueOpt _ Nothing = Nothing+valueOpt flag param = Just (Option (QuotedString flag) (fmap (QuotedString . gdbShow) param))++maybTupleOpt :: GdbShow a => Maybe (a, a) -> [Option] -- {{{2+maybTupleOpt Nothing = []+maybTupleOpt (Just (lowFrame, highFrame)) = map opt [lowFrame, highFrame]++(?:) :: Maybe a -> [a] -> [a] -- {{{1+(Just x) ?: xs = x : xs+Nothing ?:  xs = xs+infixr 5 ?:++escapeQuotes :: String -> String -- {{{2+escapeQuotes = replace '"' "\\\""++replace :: Char -> String -> String -> String -- {{{2+replace old new = join new . split old+  where+    join delim l = concat (intersperse delim l)+    split _ [] = []+    split c str =+      let (str', rest) = break (==c) str in+      if null rest+        then [str']+        else str' : split c (tail rest)
+ src/Gdbmi/IO.hs view
@@ -0,0 +1,239 @@+-- | Control execution of a GDB instance, send commands and receive results, notifications and stream information.+--+-- Due to <http://sourceware.org/bugzilla/show_bug.cgi?id=8759> the first command issued should be to set the output terminal for GDB to \/dev\/null. Unfortunatelly, there is no MI command for this, so we have to resort to the CLI command \"tty\". For example:+--+-- >>> ctx  <- setup config callback+-- >>> resp <- send_command ctx (cli_command "tty /dev/null")+-- >>> when (respClass resp /= RCDone) (error ("unexpected response: " ++ show resp))+--+module Gdbmi.IO+-- exports {{{1+(+    Context, Config(..), Callback(..)+  , default_config+  , setup, shutdown, send_command+) where++-- imports {{{1+import Control.Applicative ((<*>), (<$>))+import Control.Concurrent (forkIO, killThread, ThreadId, MVar, newEmptyMVar, tryTakeMVar, putMVar, takeMVar)+import Control.Concurrent.STM (TVar, TChan, TMVar, newEmptyTMVar, newTVarIO, newTChanIO, atomically, takeTMVar, readTVar, writeTVar, writeTChan, readTChan, putTMVar)+import Control.Exception (catchJust)+import Control.Exception.Base (AsyncException(ThreadKilled))+import Control.Monad (replicateM_, when)+import Control.Monad.Fix (mfix)+import Data.List (partition)+import Prelude hiding (catch, interact)+import System.IO (Handle, hSetBuffering, BufferMode(LineBuffering), hPutStr, hWaitForInput, hGetLine, IOMode(WriteMode), stdout, openFile, hFlush, hClose)+import System.Posix.IO (fdToHandle, createPipe)+import System.Process (ProcessHandle, runProcess, waitForProcess)++import qualified Gdbmi.Commands       as C+import qualified Gdbmi.Representation as R+import qualified Gdbmi.Semantics      as S++data Context = Context { -- {{{1+-- gdb process {{{2+    ctxProcess       :: ProcessHandle+  , ctxCommandPipe   :: Handle+  , ctxOutputPipe    :: Handle+  , ctxLog           :: Maybe Handle+-- callback+  , ctxCallback      :: Callback+-- threads+  , ctxCommandThread :: ThreadId+  , ctxOutputThread  :: ThreadId+  , ctxCurrentJob    :: MVar Job+  , ctxFinished      :: MVar ()+-- jobs+  , ctxNextToken     :: TVar R.Token+  , ctxJobs          :: TChan Job+}++data Job = Job {+    jobCommand  :: R.Command+  , jobResponse :: TMVar R.Response+  , jobToken    :: R.Token+  }++-- | Call-back functions for asynchronous GDB output.+-- +-- The call-backs are called in a separate thread per GDB output, so they may block.+--+-- Stop events are 'Gdbmi.Representation.Notification' events with 'R.NotificationClass' 'R.Exec' and 'R.AsyncClass' 'R.ACStop'.+-- If 'cbStopped' is given stop events are delivered to that call-back instead of 'cbNotify'.+data Callback  -- {{{1+  = Callback {+      cbStream  :: [R.Stream] -> IO ()          -- ^ call-back for 'Gdbmi.Representation.Stream' events+    , cbNotify  :: [R.Notification] -> IO ()    -- ^ call-back for 'Gdbmi.Representation.Notification' events+    , cbStopped :: Maybe ([S.Stopped] -> IO ()) -- ^ optionally a special call-back for 'Gdbmi.Semantics.Stopped' events+  }++-- | Configuration+data Config -- {{{1+  = Config {+      confCommandLine :: [String]        -- ^ command line to execute. The library will add \"--interpreter mi\".+    , confLogfile     :: Maybe FilePath  -- ^ optinonally a file path to a log file for GDB\/MI input and output. \'-\' means stdout.+  }++default_config :: Config -- {{{2+-- | Default configuration: "gdb" command line, no log file+default_config = Config ["gdb"] Nothing++setup :: Config -> Callback -> IO Context -- {{{1+-- | Launch a GDB instance in Machine Interface mode.+--+-- The child process is run in a new session to avoid receiving SIGINTs when issuing -exec-interrupt.+setup config callback = do+  (commandR,  commandW)  <- createPipe >>= asHandles+  (outputR,   outputW)   <- createPipe >>= asHandles+  phandle <- runProcess "setsid" (confCommandLine config ++ ["--interpreter", "mi"])+                 Nothing Nothing+                 (Just commandR)+                 (Just outputW)+                 Nothing+  mapM_ (`hSetBuffering` LineBuffering) [commandW, outputR]+  logH <- case (confLogfile config) of+    Nothing  -> return    $ Nothing+    Just "-" -> return    $ Just stdout+    Just f   -> fmap Just $ openFile f WriteMode++  currentJob <- newEmptyMVar+  finished   <- newEmptyMVar+  nextToken  <- newTVarIO 0+  jobs       <- newTChanIO+  ctx        <- mfix (\ctx -> do+      itid <- forkIO (handleCommands ctx)+      otid <- forkIO (handleOutput ctx)+      return $ Context phandle commandW outputR logH callback itid otid currentJob finished nextToken jobs+    )+  return ctx+  where+  asHandles (f1, f2) = do+    h1 <- fdToHandle f1+    h2 <- fdToHandle f2+    return (h1, h2)++shutdown :: Context -> IO () -- {{{1+-- | Shut down the GDB instance and all resources associated with the 'Context'.+shutdown ctx = do+  mapM_ (killThread . ($ctx)) [ctxCommandThread, ctxOutputThread]+  replicateM_ 2 (takeMVar (ctxFinished ctx))+  writeCommand ctx C.gdb_exit 0+  _ <- waitForProcess (ctxProcess ctx)+  putMVar (ctxFinished ctx) ()+  case ctxLog ctx of+    Nothing -> return ()+    Just handle -> +      if handle /= stdout+        then hClose handle+        else return ()++send_command :: Context -> R.Command -> IO R.Response -- {{{1+-- | Send a GDB command and wait for the response.+--+-- This function is thread safe, i.e., it can be called by multiple threads in an interleaved fashion.+send_command ctx command = checkShutdown >> sendCommand >>= receiveResponse+  where+    checkShutdown = do+      finished <- tryTakeMVar (ctxFinished ctx)+      case finished of+        Nothing -> return ()+        Just () -> error "context has already been shut down"++    sendCommand = atomically $ do+      token <- readTVar (ctxNextToken ctx)+      writeTVar (ctxNextToken ctx) (if token == maxBound then 0 else token + 1)+      response <- newEmptyTMVar+      writeTChan (ctxJobs ctx) $ Job command response token+      return response+    +    receiveResponse = atomically . takeTMVar++-- implementation {{{1+handleCommands :: Context -> IO () -- {{{2+handleCommands ctx = handleKill ctx $ do+  job <- atomically $ readTChan (ctxJobs ctx)+  putMVar (ctxCurrentJob ctx) job+  writeCommand ctx (jobCommand job) (jobToken job)+  handleCommands ctx++handleOutput :: Context -> IO () -- {{{2+handleOutput ctx = handleKill ctx $ do+  output  <- readOutput ctx+  _ <- callBack ctx output+  case R.output_response output of+    Nothing -> return ()+    Just response -> do+      maybJob <- tryTakeMVar (ctxCurrentJob ctx)+      case maybJob of+        Nothing -> error "result record lost!"+        Just job -> +          if (R.get_token output /= Just (jobToken job))+            then error $ "token missmatch! " ++ show (R.get_token output) ++ " vs. " ++ show (jobToken job)+            else atomically $ putTMVar (jobResponse job) response+  handleOutput ctx  ++callBack :: Context -> R.Output -> IO ()+callBack ctx output = forkIO go >> return ()+  where+    go =+      let+        callbacks       = ctxCallback ctx+        streamsCb       = cbStream callbacks+        notifyCb        = cbNotify callbacks+        stoppedCbMb     = cbStopped callbacks++        streams         = R.output_stream output+        notifications   = R.output_notification output+        (stops, others) = partition ((&&) <$> (R.Exec==) . R.notiClass <*> (R.ACStop==) . R.notiAsyncClass) notifications+        Just stops'     = sequence $ map (S.notification_stopped . R.notiResults) stops+      in case stoppedCbMb of+        Nothing -> do+          when (not (null streams))       (streamsCb streams)+          when (not (null notifications)) (notifyCb notifications)+        Just stoppedCb -> do+          when (not (null streams))       (streamsCb streams)+          when (not (null others))        (notifyCb others)+          when (not (null stops'))        (stoppedCb stops')++handleKill :: Context -> IO () -> IO ()+handleKill ctx action = catchJust select action handler+  where+    select :: AsyncException -> Maybe ()+    select ThreadKilled = Just ()+    select _ = Nothing++    handler :: () -> IO ()+    handler _ = putMVar (ctxFinished ctx) ()++writeCommand :: Context -> R.Command -> R.Token -> IO () -- {{{2+writeCommand ctx cmd token = +  let cmdstr = (R.render_command . C.set_token token) cmd in+  do+    debugLog ctx True cmdstr+    hPutStr (ctxCommandPipe ctx) cmdstr++readOutput :: Context -> IO R.Output -- {{{2+readOutput ctx = do+  _ <- hWaitForInput (ctxOutputPipe ctx) (-1)+  str <- outputString (ctxOutputPipe ctx)+  debugLog ctx False str+  return (R.parse_output str)+  where+    outputString handle = outputLines handle >>= return . unlines+    outputLines handle = do+      line <- hGetLine handle+      if line == "(gdb) "+        then return [line]+        else outputLines handle >>= return . (line:)++debugLog :: Context -> Bool -> String -> IO () -- {{{2+debugLog ctx io text = +  let+    prefix = if io then "/i " else "/o "+    line = ((unlines . map (prefix++) . lines) text)+  in+  case (ctxLog ctx) of+    Nothing -> return ()+    Just h -> hPutStr h line >> hFlush h
+ src/Gdbmi/Representation.hs view
@@ -0,0 +1,506 @@+-- | Data structures, parsers and printers for GDB/MI communication.+--+-- This is a low-level module not intended to be used by clients of this library.+-- Use 'Gdbmi.Commands' to create commands and receive responses as well as notifications via 'Gdbmi.IO'.+--+-- On-the-wire types reflect the GDB/MI grammar. Please consult the cited GDB documentation for details.+-- The simplified types provide a simple abstraction over the on-the-wire types.+module Gdbmi.Representation+-- exports {{{1+(+  -- * On-the-Wire Types+  -- ** Input+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Input-Syntax.html>+  Command(..),+  Token,+  Operation,+  Option(..),+  Parameter(..),+  -- ** Output+  -- | <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Output-Syntax.html>+  Output(..),+  ResultRecord(..),+  OutOfBandRecord(..),+  AsyncRecord(..), +  ExecAsyncOutput(..),+  StatusAsyncOutput(..),+  NotifyAsyncOutput(..),+  AsyncOutput(..),+  ResultClass(..),+  AsyncClass(..),+  Result(..),+  Variable,+  Value(..), Const, Tuple(..), List(..),+  StreamRecord(..),+  ConsoleStreamOutput(..),+  TargetStreamOutput(..),+  LogStreamOutput(..),+  CString,+  -- * Simplified+  Response(..),+  Notification(..), NotificationClass(..),+  Stream(..), StreamClass(..),+  -- * Functions+  render_command,+  parse_output,+  output_response,+  output_notification,+  output_stream,+  GetToken(..),+  asConst, asTuple, asList,+  parameter_valid+) where++-- imports {{{1+import Control.Applicative ((<$>), (<*>), (<*))+import Data.Char (isAscii)+import Data.List (find)+import Data.Maybe (isNothing)+import Text.ParserCombinators.Parsec hiding (token)++-- input {{{1+-- types {{{2+data Command -- {{{3+  = CLICommand (Maybe Token) String+  | MICommand (Maybe Token) Operation [Option] [Parameter]++type Operation = String -- {{{3++data Option = Option Parameter (Maybe Parameter) -- {{{3++data Parameter -- {{{3+  -- the documentation does not specify this, but de-facto some parameters have+  -- to be quoted and other must not+  = RawString String+  | QuotedString String++-- rendering {{{2+render_command :: Command -> String -- {{{3+-- | Generate the on-the-wire string suitable to be sent to GDB.+render_command cmd = r_command cmd ""++r_command :: Command -> ShowS -- {{{3+r_command (CLICommand tok str) = maybe id r_token tok . showString str . showString "\n"+r_command (MICommand tok operation options parameters) =+    maybe id shows tok+  . showString "-" . r_operation operation+  . foldl (\f o -> f . showString " " . r_option o) id options+  . (if null parameters+    then id+    else showString " --" . foldl (\f p -> f . showString " " . r_parameter p) id parameters)+  . showString "\n"++r_operation :: Operation -> ShowS -- {{{3+r_operation op = (op++)++r_option :: Option -> ShowS -- {{{3+ -- the documentation specifies a "-" before each option but some operations+ -- such as file-exec-and-symbols are not happy with this :-/+r_option (Option p p') =+    r_parameter p+  . maybe id (\x -> showString " " . r_parameter x) p'++r_parameter :: Parameter -> ShowS -- {{{3+r_parameter (RawString s)    = showString s+r_parameter (QuotedString s) = shows s++r_token :: Token -> ShowS -- {{{3+r_token = shows++-- output {{{1+-- types {{{2+data Output -- {{{3+  = Output [OutOfBandRecord] (Maybe ResultRecord)+  deriving Show++data ResultRecord -- {{{3+  = ResultRecord (Maybe Token) ResultClass [Result]+  deriving Show++data OutOfBandRecord -- {{{3+  = OOBAsyncRecord AsyncRecord+  | OOBStreamRecord StreamRecord+  deriving Show++data AsyncRecord -- {{{3+  = ARExecAsyncOutput ExecAsyncOutput+  | ARStatusAsyncOutput StatusAsyncOutput+  | ARNotifyAsyncOutput NotifyAsyncOutput+  deriving Show++data ExecAsyncOutput -- {{{3+  = ExecAsyncOutput (Maybe Token) AsyncOutput+  deriving Show++data StatusAsyncOutput -- {{{3+  = StatusAsyncOutput (Maybe Token) AsyncOutput+  deriving Show++data NotifyAsyncOutput -- {{{3+  = NotifyAsyncOutput (Maybe Token) AsyncOutput+  deriving Show++data AsyncOutput -- {{{3+  = AsyncOutput AsyncClass [Result]+  deriving Show++data ResultClass -- {{{3+  = RCDone+  | RCRunning+  | RCConnected+  | RCError+  | RCExit+  deriving (Show, Eq)+ +data AsyncClass -- {{{3+  = ACStop+  | ACThreadGroupAdded+  | ACThreadGroupStarted+  | ACThreadCreated+  | ACRunning+  | ACLibraryLoaded+  | ACThreadExited+  | ACThreadGroupExited+  | ACBreakpointModified+  deriving (Show, Eq)++data Result -- {{{3+  = Result {+      resVariable :: Variable+    , resValue    :: Value+  }+  deriving Show++type Variable = String -- {{{3++data Value -- {{{3+  = VConst Const+  | VTuple Tuple+  | VList  List+  deriving Show++type Const = CString -- {{{3++data Tuple -- {{{3+  = Tuple {+      tupleResults :: [Result]+  }+  deriving Show++data List -- {{{3+  = EmptyList+  | ValueList [Value]+  | ResultList [Result]+  deriving Show++data StreamRecord  -- {{{3+  = SRConsoleStreamOutput ConsoleStreamOutput+  | SRTargetStreamOutput TargetStreamOutput+  | SRLogStreamOutput LogStreamOutput+  deriving Show++data ConsoleStreamOutput -- {{{3+  = ConsoleStreamOutput CString+  deriving Show++data TargetStreamOutput -- {{{3+  = TargetStreamOutput CString+  deriving Show++data LogStreamOutput -- {{{3+  = LogStreamOutput CString+  deriving Show++type CString = String -- {{{3++-- parsing {{{2+parse_output :: String -> Output -- {{{3+-- | Turn an GDB output string to an 'Output' value.+parse_output str = case parse p_output "gdb" str of+  Left pe -> error $ "parse failed: " ++ show pe+  Right o -> o++p_output :: Parser Output -- {{{3+-- http://sourceware.org/bugzilla/show_bug.cgi?id=7708+-- p_output = Output <$> many p_outOfBandRecord <*> optionMaybe p_resultRecord <* string "(gdb) " <* newline <* eof+p_output = do+  oob  <- many        p_outOfBandRecord+  rr   <- optionMaybe p_resultRecord+  oob' <- many        p_outOfBandRecord+  string "(gdb) " >> newline >> eof+  return $ Output (oob ++ oob') rr++p_resultRecord :: Parser ResultRecord -- {{{3+p_resultRecord =+  ResultRecord <$> optionMaybe p_token <* char '^' <*> p_resultClass <*> many (char ',' >> p_result) <* newline++p_outOfBandRecord :: Parser OutOfBandRecord -- {{{3+p_outOfBandRecord =+       try (p_asyncRecord  >>= return . OOBAsyncRecord)+  <|>      (p_streamRecord >>= return . OOBStreamRecord)++p_asyncRecord :: Parser AsyncRecord -- {{{3+p_asyncRecord =+      (p_execAsyncOutput   >>= return . ARExecAsyncOutput)+  <|> (p_statusAsyncOutput >>= return . ARStatusAsyncOutput)+  <|> (p_notifyAsyncOutput >>= return . ARNotifyAsyncOutput)++p_execAsyncOutput :: Parser ExecAsyncOutput -- {{{3+p_execAsyncOutput =+  ExecAsyncOutput <$> optionMaybe p_token <* char '*' <*> p_asyncOutput++p_statusAsyncOutput :: Parser StatusAsyncOutput -- {{{3+p_statusAsyncOutput =+  StatusAsyncOutput <$> optionMaybe p_token <* char '+' <*> p_asyncOutput++p_notifyAsyncOutput :: Parser NotifyAsyncOutput -- {{{3+p_notifyAsyncOutput =+  NotifyAsyncOutput <$> optionMaybe p_token <* char '=' <*> p_asyncOutput++p_asyncOutput :: Parser AsyncOutput -- {{{3+p_asyncOutput =+  AsyncOutput <$> p_asyncClass <*> many (char ',' >> p_result) <* newline++p_resultClass :: Parser ResultClass -- {{{3+p_resultClass =+      try (string "done"      >> return RCDone)+  <|> try (string "running"   >> return RCRunning)+  <|> try (string "connected" >> return RCConnected)+  <|> try (string "error"     >> return RCError)+  <|>     (string "exit"      >> return RCExit)++p_asyncClass :: Parser AsyncClass -- {{{3+p_asyncClass =+      try (string "stopped"              >> return ACStop)+  <|> try (string "thread-group-added"   >> return ACThreadGroupAdded)+  <|> try (string "thread-group-started" >> return ACThreadGroupStarted)+  <|> try (string "thread-created"       >> return ACThreadCreated)+  <|> try (string "running"              >> return ACRunning)+  <|> try (string "thread-exited"        >> return ACThreadExited)+  <|> try (string "thread-group-exited"  >> return ACThreadGroupExited)+  <|> try (string "breakpoint-modified"  >> return ACBreakpointModified)+  <|>     (string "library-loaded"       >> return ACLibraryLoaded)++p_result :: Parser Result -- {{{3+p_result =+  Result <$> p_variable <* char '=' <*> p_value++p_variable :: Parser Variable -- {{{3+p_variable = many1 (letter <|> digit <|> oneOf "_-")++p_value :: Parser Value -- {{{3+p_value =+      (p_const >>= return . VConst)+  <|> (p_tuple >>= return . VTuple)+  <|> (p_list  >>= return . VList)++p_const :: Parser Const -- {{{3+p_const = p_cString++p_tuple :: Parser Tuple -- {{{3+p_tuple = try p_emptyTuple <|> p_filledTuple+  where+    p_emptyTuple = string "{}" >> return (Tuple [])+    p_filledTuple = do+      _ <- char '{'+      first <- p_result+      rest <- many (char ',' >> p_result)+      _ <- char '}'+      return $ Tuple (first:rest)++p_list :: Parser List -- {{{3+p_list = try p_emptyList <|> try p_valueList <|> p_resultList+  where+    p_emptyList = string "[]" >> return EmptyList+    p_valueList = do+      _ <- char '['+      first <- p_value+      rest <- many (char ',' >> p_value)+      _ <- char ']'+      return $ ValueList (first:rest)+  +    p_resultList = do+      _ <- char '['+      first <- p_result+      rest <- many (char ',' >> p_result)+      _ <- char ']'+      return $ ResultList (first:rest)++p_streamRecord :: Parser StreamRecord -- {{{3+p_streamRecord = do+  sr <- anyStreamRecord+  _ <- newline -- the documentation does not specifiy this newline, but this is what GDB is doing+  return sr+  where+    anyStreamRecord =+          (p_consoleStreamOutput >>= return . SRConsoleStreamOutput)+      <|> (p_targetStreamOutput  >>= return . SRTargetStreamOutput)+      <|> (p_logStreamOutput     >>= return . SRLogStreamOutput)++p_consoleStreamOutput :: Parser ConsoleStreamOutput -- {{{3+p_consoleStreamOutput = char '~' >> p_cString >>= return . ConsoleStreamOutput++p_targetStreamOutput :: Parser TargetStreamOutput -- {{{3+p_targetStreamOutput = char '@' >> p_cString >>= return . TargetStreamOutput++p_logStreamOutput :: Parser LogStreamOutput -- {{{3+p_logStreamOutput = char '&' >> p_cString >>= return . LogStreamOutput++p_cString :: Parser CString -- {{{3+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++p_token :: Parser Token -- {{{3+p_token = many1 digit >>= return . read++-- simplification {{{1+data Response -- {{{2+  -- | The 'ResultRecord' of an 'Output'+  = Response {+      respClass   :: ResultClass+    , respResults :: [Result]   +    }+    deriving (Show)++data Notification -- {{{2+  -- | Simplification of the 'AsyncRecord' type hierarchie, a possible 'OutOfBandRecord' value of an 'Output'.+  = Notification {+      notiClass      :: NotificationClass+    , notiAsyncClass :: AsyncClass+    , notiResults    :: [Result]+    }+    deriving Show++data NotificationClass -- {{{3+  = Exec    -- ^ 'ARExecAsyncOutput'+  | Status  -- ^ 'ARStatusAsyncOutput'+  | Notify  -- ^ 'ARNotifyAsyncOutput'+  deriving (Show, Eq)++data Stream -- {{{2+  -- | Simplifcation of the 'StreamRecord' type hierarchie, a possible 'OutOfBandRecord' value of an 'Output'.+  = Stream StreamClass String+  deriving Show++data StreamClass -- {{{3+  = Console  -- ^ 'SRConsoleStreamOutput'+  | Target   -- ^ 'SRTargetStreamOutpu'+  | Log      -- ^ 'SRLogStreamOutput'+  deriving Show++output_response :: Output -> Maybe Response -- {{{2+-- | Extract the response from an output, if existent. +output_response (Output _ Nothing) = Nothing+output_response (Output _ (Just (ResultRecord _ rc rs))) = Just $ Response rc rs++output_notification :: Output -> [Notification] -- {{{2+-- | Extract the (possible empty) list of notifications of an output.+output_notification (Output oobs _) = map (notification . unp) $ filter isNotification oobs+  where+    isNotification (OOBAsyncRecord _) = True+    isNotification _ = False++    unp (OOBAsyncRecord x) = x+    unp x = error $ "unexpected parameter: " ++ show x++    notification (ARExecAsyncOutput (ExecAsyncOutput _ (AsyncOutput ac rs))) = Notification Exec ac rs+    notification (ARStatusAsyncOutput (StatusAsyncOutput _ (AsyncOutput ac rs))) = Notification Status ac rs +    notification (ARNotifyAsyncOutput (NotifyAsyncOutput _ (AsyncOutput ac rs))) = Notification Notify ac rs++output_stream :: Output -> [Stream] -- {{{2+-- | Extract the (possibly) empty list of notifications of an output.+output_stream (Output oobs _) = map (stream . unp) $ filter isStream oobs+  where+    isStream (OOBStreamRecord _) = True+    isStream _ = False++    unp (OOBStreamRecord x) = x+    unp x = error $ "unexpected parameter: " ++ show x++    stream (SRConsoleStreamOutput (ConsoleStreamOutput s)) = Stream Console s+    stream (SRTargetStreamOutput (TargetStreamOutput s)) = Stream Target s+    stream (SRLogStreamOutput (LogStreamOutput s)) = Stream Log s++-- utils {{{2+asConst :: Value -> Maybe Const -- {{{2+-- | Coerce a value to a const.+asConst (VConst x) = Just x+asConst _          = Nothing++asTuple :: Value -> Maybe Tuple -- {{{2+-- | Coerce a value to a tuple.+asTuple (VTuple x) = Just x+asTuple _          = Nothing++asList  :: Value -> Maybe List -- {{{2+-- | Coerce a value to a list.+asList (VList x) = Just x+asList _         = Nothing++-- token {{{1+type Token = Int+ +-- | Return the token of the given object, if existent.+class GetToken a where+  get_token :: a -> Maybe Token ++instance GetToken ResultRecord where+  get_token (ResultRecord token _ _) = token++instance GetToken Command where+  get_token (CLICommand token _) = token+  get_token (MICommand token _ _ _) = token++instance GetToken Output where+  get_token (Output _ (Just r)) = get_token r+  get_token _ = Nothing++instance GetToken OutOfBandRecord where+  get_token (OOBAsyncRecord r) = get_token r+  get_token (OOBStreamRecord _) = Nothing++instance GetToken AsyncRecord where+  get_token (ARExecAsyncOutput x) = get_token x+  get_token (ARStatusAsyncOutput x) = get_token x+  get_token (ARNotifyAsyncOutput x) = get_token x++instance GetToken ExecAsyncOutput where+  get_token (ExecAsyncOutput token _) = token++instance GetToken StatusAsyncOutput where+  get_token (StatusAsyncOutput token _) = token++instance GetToken NotifyAsyncOutput where+  get_token (NotifyAsyncOutput token _) = token++-- utils {{{1+parameter_valid :: Parameter -> Bool -- {{{2+-- | Verify that the given parameter is either a c-string or a \"non-blank-sequence\".+-- See <http://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Input-Syntax.html>+parameter_valid (RawString s) = validParam s+parameter_valid (QuotedString s) = validParam s++validParam :: String -> Bool -- {{{2+validParam param +  | null param = False+  | isCString param = isNothing $ find (not . isAscii) param+  | otherwise = isNothing $ find isSpecial param+  where+    isCString ('"':rest) = last rest == '"'+    isCString _          = False++    isSpecial ' '  = True+    isSpecial '-'  = True+    isSpecial '\n' = True+    isSpecial '"'  = True+    isSpecial _    = False
+ src/Gdbmi/Semantics.hs view
@@ -0,0 +1,222 @@+-- | Semantical data structures and conversion functions for GDB\/MI output.+--  +-- While working with 'Gdbmi.Representation.Response' and 'Gdbmi.Representation.Notification' is always possible in general, handling the generic 'Gdbmi.Representation.Result' lists is cumbersome. This module provides convenient data types instead to facilitate pattern matching etc..+--  +-- This module is incomplete, as we only implemented what we needed up to now.+module Gdbmi.Semantics+-- export {{{1+(+  -- * Conversion Functions  +  -- | A conversion fails if the result list does not contain the expected values.+  response_break_insert,+  response_data_evaluate_expression,+  response_exec_return,+  response_stack_list_frames,+  response_error,+  notification_stopped,+  -- * Types+  -- | Please consult the GDB manual for details on the returned responses.+  Breakpoint(..), BreakpointType, BreakpointDisp(..), BkptNumber,+  Stack(..), Frame(..), Arg(..),+  Stopped(..), StopReason(..)+) where++-- import {{{1+import Control.Applicative ((<$>), (<*>))+import Control.Monad (guard, msum, (<=<))+import Data.List (find)++import Gdbmi.Representation++-- types {{{1+type BkptNumber = Int+data Breakpoint = Breakpoint { -- {{{2+    bkptNumber           :: BkptNumber+  , bkptType             :: BreakpointType+  , bkptDisp             :: BreakpointDisp+  , bkptEnabled          :: Bool+  , bkptAddress          :: String+  , bkptFunc             :: String+  , bkptFile             :: String+  , bkptFullname         :: String+  , bkptLine             :: Int+  , bkptTimes            :: Int+  , bkptOriginalLocation :: String+  }+  deriving Show++type BreakpointType = String -- {{{2++data BreakpointDisp -- {{{2+  = BreakpointKeep+  | BreakpointDel+  deriving Show++instance Read BreakpointDisp where+  readsPrec _ "del" = [(BreakpointDel, "")]+  readsPrec _ "keep" = [(BreakpointKeep, "")]+  readsPrec _ _ = []++newtype Stack -- {{{2+  = Stack {stackFrames :: [Frame] }+  deriving Show++data Frame = Frame { -- {{{2+    frameLevel    :: Maybe Int+  , frameAddr     :: String+  , frameFunc     :: String+  , frameArgs     :: Maybe [Arg]+  , frameFile     :: String+  , frameFullname :: Maybe String+  , frameLine     :: Int+  } deriving Show++data Stopped = Stopped { -- {{{2+      stoppedReason   :: StopReason+    , stoppedFrame    :: Frame+    , stoppedThreadId :: Int+    , stoppedThreads  :: String+    , stoppedCore     :: Int+  }+  deriving Show++data StopReason -- {{{2+  = BreakpointHit {+      bkptHitDisp   :: BreakpointDisp+    , bkptHitNumber :: BkptNumber+    }+  | EndSteppingRange+  | FunctionFinished++  deriving Show++data Arg = Arg { -- {{{2+    argName  :: String+  , argValue :: String+  } deriving Show++-- composition {{{1+responseBreakpoint :: Result -> Maybe Breakpoint -- {{{2+responseBreakpoint (Result variable value) = do+  guard (variable == "bkpt")+  (Tuple rs) <- asTuple value+  Breakpoint+    <$> get rs tryRead "number"+    <*> get rs Just    "type" +    <*> get rs tryRead "disp"+    <*> get rs gdbBool "enabled"+    <*> get rs Just    "addr"+    <*> get rs Just    "func"+    <*> get rs Just    "file"+    <*> get rs Just    "fullname"+    <*> get rs tryRead "line"+    <*> get rs tryRead "times"+    <*> get rs Just    "original-location"++responseStack :: Result -> Maybe Stack -- {{{2+responseStack (Result variable value) = do+  guard (variable == "stack")+  list <- asList value+  case list of+    EmptyList -> Just $ Stack []+    ResultList is ->+      Stack <$> mapM responseFrame is+    _ -> Nothing++responseFrame :: Result -> Maybe Frame -- {{{2+responseFrame (Result variable value) = do+  guard (variable == "frame")+  (Tuple rs) <- asTuple value+  Frame+    <$> Just (get rs tryRead "level")+    <*>       get rs Just    "addr"+    <*>       get rs Just    "func"+    <*> Just (msum (map responseArgs rs))+    <*>       get rs Just   "file"+    <*> Just (get rs Just   "fullname")+    <*>       get rs tryRead "line"++responseStopped :: [Result] -> Maybe Stopped -- {{{2+responseStopped rs = do+  Stopped+    <$> responseStopReason rs+    <*> msum (map responseFrame rs)+    <*> get rs tryRead "thread-id"+    <*> get rs Just    "stopped-threads"+    <*> get rs tryRead "core"++responseStopReason :: [Result] -> Maybe StopReason  -- {{{2+responseStopReason rs = do+  reason <- find (("reason"==) . resVariable) rs >>= asConst . resValue+  case reason of +    "breakpoint-hit" ->+      BreakpointHit+        <$> get rs tryRead "disp"+        <*> get rs tryRead "bkptno"+    "end-stepping-range" -> Just EndSteppingRange+    "function-finished"  -> Just FunctionFinished+    _ -> Nothing ++responseArgs :: Result -> Maybe [Arg] -- {{{2+responseArgs (Result variable value) = do+  guard (variable == "args")+  list <- asList value+  case list of+    EmptyList -> Just []+    ValueList is -> do+      mapM ((responseArg . tupleResults) <=< asTuple) is+    _ -> Nothing ++responseArg :: [Result] -> Maybe Arg -- {{{2+responseArg rs = do+  Arg+    <$> get rs Just "name"+    <*> get rs Just "value"++-- functions {{{1+response_stack_list_frames :: [Result] -> Maybe Stack -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.stack_list_frames' command response.+response_stack_list_frames [item] = responseStack item+response_stack_list_frames _      = Nothing++response_break_insert :: [Result] -> Maybe Breakpoint -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.break_insert' command response.+response_break_insert [item] = responseBreakpoint item+response_break_insert _      = Nothing++response_data_evaluate_expression :: [Result] -> Maybe String -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.data_evaluate_expression' command response.+response_data_evaluate_expression [(Result variable value)] = do+  guard  (variable == "value")+  asConst value+response_data_evaluate_expression _ = Nothing++response_exec_return :: [Result] -> Maybe Frame -- {{{2+-- | Convert the result list of a 'Gdbmi.Commands.exec_return' command response.+response_exec_return [item] = responseFrame item+response_exec_return _      = Nothing++response_error :: [Result] -> Maybe String -- {{{2+-- | Convert the result list of a 'Gdbmi.Representation.Response' with 'Gdbmi.Representation.ResultClass' 'Gdbmi.Representation.RCError'.+response_error [(Result variable value)] = do+  guard (variable == "msg")+  asConst value+response_error _ = Nothing++notification_stopped :: [Result] -> Maybe Stopped -- {{{2+-- | Convert the result list of a 'Gdbmi.Representation.Notification' with 'Gdbmi.Representation.NotificationClass' 'Gdbmi.Representation.Exec' and 'Gdbmi.Representation.AsyncClass' 'Gdbmi.Representation.ACStop'.+notification_stopped items = responseStopped items++-- utils {{{1+get :: [Result] -> (String -> Maybe a) -> (String -> Maybe a) -- {{{2+get rs parse key = find ((key==) . resVariable) rs >>= asConst . resValue >>= parse++tryRead :: Read a => String -> Maybe a -- {{{2+tryRead str = case readsPrec 0 str of+  [(x, "")] -> Just x+  _ -> Nothing++gdbBool :: String -> Maybe Bool -- {{{2+gdbBool "y" = Just True+gdbBool "n" = Just False+gdbBool _ = Nothing
+ tests/Paste.hs view
@@ -0,0 +1,12 @@+module Paste where++import Language.Haskell.TH.Quote (QuasiQuoter(..))+import Language.Haskell.TH (stringE)++paste :: QuasiQuoter+paste = QuasiQuoter {+  quoteExp = stringE,+  quotePat = undefined,+  quoteType = undefined,+  quoteDec = undefined+  }
+ tests/io.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE QuasiQuotes #-}+{-+ - Test the IO interface of hgdbmi.+ -+ - Requirements:+ -    - gdb (see config)+ -    - gcc (see setup)+ -+ - Steps:+ -    - create temporary directory+ -    - write test program (example)+ -    - compile test program with debugging+ -    - start debugger+ -    - set breakpoint+ -    - run debugger+ -    - wait for stop event, evaluate variable and continue (10 times)+ -    - quit+ -    - dump log file+ -+ - Output:+ -    - stream and notification events (excluding stop events)+ -    - log file with GDB/MI communication+-}+module Main (main) where++import Control.Concurrent     (newEmptyMVar, putMVar, takeMVar, MVar)+import Control.Exception.Base (bracket)+import Control.Monad          (forM_, when)+import System.Directory       (removeDirectoryRecursive, getCurrentDirectory, setCurrentDirectory)+import System.Exit            (ExitCode(..))+import System.IO.Temp         (createTempDirectory)+import System.Process         (readProcessWithExitCode)+import Text.Printf            (printf)++import Paste (paste)++import qualified Gdbmi.IO             as G+import qualified Gdbmi.Commands       as C+import qualified Gdbmi.Semantics      as S+import qualified Gdbmi.Representation as R++config :: G.Config+config = G.Config ["gdb"] (Just "gdb.log")++example :: String+example = [paste|+#include <stdio.h>++void print(int i) {+    printf("hello world %d\n", i);+}++int main() {+    int i;+    for (i=0; ; i++) {+        print(i);+    }+    return 0;+}+|]++callback :: MVar [S.Stopped] -> G.Callback+callback mv = G.Callback print print (Just (putMVar mv))++setup :: IO ()+setup = do+  writeFile "example.c" example+  (ec, sout, serr) <- readProcessWithExitCode "gcc" (words "-o example -g example.c") "" +  case ec of+    ExitFailure ec' -> do+      putStrLn sout+      putStrLn serr+      error $ printf "failed to execute gcc: %s" (show ec')+    ExitSuccess -> return ()++command :: G.Context -> R.ResultClass -> R.Command -> IO [R.Result]+command ctx rc cmd = do+  resp <- G.send_command ctx cmd+  let msg = printf "command '%s' failed (%s): %s"+              (R.render_command cmd)+              (show (R.respClass resp))+              ((show . S.response_error . R.respResults) resp)+  when (R.respClass resp /= rc) (error msg)+  return (R.respResults resp)++assert :: (Eq a, Show a) => String -> a -> a -> IO ()+assert what x y = if (x == y)+  then return ()+  else error $ printf "assertion failed: %s: %s vs. %s" what (show x) (show y)++test ::  IO ()+test = do +  _            <- setup+  mv           <- newEmptyMVar+  ctx          <- G.setup config (callback mv)+  let cmd       = command ctx+  _            <- cmd R.RCDone $ C.cli_command "tty /dev/null"+  _            <- cmd R.RCDone $ C.file_exec_and_symbols (Just "example")+  let loc       = C.file_function_location "example.c" "print"+  bp'          <- cmd R.RCDone $ C.break_insert False False False False False Nothing Nothing Nothing loc+  let (Just bp) = S.response_break_insert bp'+  _            <- cmd R.RCRunning $ C.exec_run (Left True)+  forM_ [(0::Int)..10] (\counter -> do+      [stopped]      <- takeMVar mv +      assert "breakpoint number" ((S.bkptHitNumber . S.stoppedReason) stopped) (S.bkptNumber bp)+      value'          <- cmd R.RCDone $ C.data_evaluate_expression "i"+      let (Just value) = S.response_data_evaluate_expression value'+      assert "value of i" value (show counter)+      _               <- cmd R.RCRunning $ C.exec_continue False (Left True)+      return ()+    )+  G.shutdown ctx+  readFile "gdb.log" >>= putStr++withTemporaryDirectory :: IO a -> IO a+withTemporaryDirectory f = bracket acquire release inbetween+  where+    acquire = do+      tmpdir <- createTempDirectory "/tmp" "hgdbmi-test"+      curdir <- getCurrentDirectory+      setCurrentDirectory tmpdir+      return (curdir, tmpdir)++    release (curdir, tmpdir) = do+      setCurrentDirectory curdir+      removeDirectoryRecursive tmpdir++    inbetween (_, _) = f++main :: IO ()+main = withTemporaryDirectory test
+ tests/pure.hs view
@@ -0,0 +1,347 @@+{-# LANGUAGE QuasiQuotes #-}+module Main (main) where++-- imports {{{1+import Gdbmi.Representation+import Gdbmi.Semantics+import Test.Framework                 (Test, defaultMain, testGroup)+import Test.Framework.Providers.HUnit (testCase)+import Test.HUnit                     ((@=?), Assertion)+import Text.Printf                    (printf)++import Paste                          (paste)++main :: IO () -- {{{1+main = defaultMain [+          test_render_command+        , test_parse_output+        , test_response_break_insert+        , test_response_stopped+        , test_response_stack_list_frames+        , test_response_exec_return+        , test_response_data_evaluate_expression+        , test_response_error+        ]++test_render_command:: Test -- {{{2+test_render_command = enumTestGroup "render_command" $ map runTest [+    (+      MICommand Nothing "break-info" [] []+    , "-break-info\n"+    ), (+      MICommand (Just 23) "exec-arguments" [Option (qp "-v") (Just (qp "word"))] []+    , "23-exec-arguments \"-v\" \"word\"\n"+    ), (+      MICommand (Just 42) "break-commands" [Option (qp "1") Nothing, Option (qp "print v") Nothing] []+      , "42-break-commands \"1\" \"print v\"\n"+    )+  ]+  where+    runTest :: (Command, String) -> Assertion+    runTest (cmd, expected) = expected @=? render_command cmd++test_parse_output :: Test -- {{{2+test_parse_output = enumTestGroup "parse_output" $ map runTest [+    -- welcome text {{{3+    ([paste|+=thread-group-added,id="i1"+~"GNU gdb (GDB) 7.2-ubuntu\n"+~"Copyright (C) 2010 Free Software Foundation, Inc.\n"+~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\n"+~"This GDB was configured as \"x86_64-linux-gnu\".\nFor bug reporting instructions, please see:\n"+~"<http://www.gnu.org/software/gdb/bugs/>...\n"+~"Reading symbols from /tmp/tc.elf..."+~"done.\n"+(gdb) +|], Output ([+        OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACThreadGroupAdded [Result "id" (VConst "i1")]+    ] ++ map (OOBStreamRecord . SRConsoleStreamOutput . ConsoleStreamOutput) [+        "GNU gdb (GDB) 7.2-ubuntu\n"+      , "Copyright (C) 2010 Free Software Foundation, Inc.\n"+      , "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\n"+      , "This GDB was configured as \"x86_64-linux-gnu\".\nFor bug reporting instructions, please see:\n"+      , "<http://www.gnu.org/software/gdb/bugs/>...\n"+      , "Reading symbols from /tmp/tc.elf..."+      , "done.\n"+    ])+    Nothing)+  , -- command result -break-info {{{3+    ([paste|+^done,BreakpointTable={nr_rows="0",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="10",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[]}+(gdb) +|], Output [] $ Just $ ResultRecord Nothing RCDone [+        Result "BreakpointTable" $ VTuple $ Tuple [+            Result "nr_rows" $ VConst "0"+          , Result "nr_cols" $ VConst "6"+          , Result "hdr" $ VList $ ValueList [+                VTuple $ Tuple [+                    Result "width" $ VConst "7"+                  , Result "alignment" $ VConst "-1"+                  , Result "col_name" $ VConst "number"+                  , Result "colhdr" $ VConst "Num"+                  ]+              , VTuple $ Tuple [+                    Result "width" $ VConst "14"+                  , Result "alignment" $ VConst "-1"+                  , Result "col_name" $ VConst "type"+                  , Result "colhdr" $ VConst "Type"+                  ]+              , VTuple $ Tuple [+                    Result "width" $ VConst "4"+                  , Result "alignment" $ VConst "-1"+                  , Result "col_name" $ VConst "disp"+                  , Result "colhdr" $ VConst "Disp"+                  ]+              , VTuple $ Tuple [+                    Result "width" $ VConst "3"+                  , Result "alignment" $ VConst "-1"+                  , Result "col_name" $ VConst "enabled"+                  , Result "colhdr" $ VConst "Enb"+                  ]+              , VTuple $ Tuple [+                    Result "width" $ VConst "10"+                  , Result "alignment" $ VConst "-1"+                  , Result "col_name" $ VConst "addr"+                  , Result "colhdr" $ VConst "Address"+                  ]+              , VTuple $ Tuple [+                    Result "width" $ VConst "40"+                  , Result "alignment" $ VConst "2"+                  , Result "col_name" $ VConst "what"+                  , Result "colhdr" $ VConst "What"+                  ]+              ]+          , Result "body" $ VList $ EmptyList+          ]+      ]+    )+  , -- command result break-insert {{{3+  ([paste|+^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x000000000040154e",func="cond_wait",file="tc.c",fullname="/tmp/tc.c",line="23",times="0",original-location="tc.c:23"}+(gdb) +|], Output [] $ Just $ ResultRecord Nothing RCDone [+        Result "bkpt" $ VTuple $ Tuple [+            Result "number" $ VConst "1"+          , Result "type" $ VConst "breakpoint"+          , Result "disp" $ VConst "keep"+          , Result "enabled" $ VConst "y"+          , Result "addr" $ VConst "0x000000000040154e"+          , Result "func" $ VConst "cond_wait"+          , Result "file" $ VConst "tc.c"+          , Result "fullname" $ VConst "/tmp/tc.c"+          , Result "line" $ VConst "23"+          , Result "times" $ VConst "0"+          , Result "original-location" $ VConst "tc.c:23"+          ]+      ]+    )+  , -- command result gdb-version {{{3+  ([paste|+~"GNU gdb (GDB) 7.2-ubuntu\n"+0^done+(gdb) +|], Output [OOBStreamRecord $ SRConsoleStreamOutput $ ConsoleStreamOutput "GNU gdb (GDB) 7.2-ubuntu\n"] (Just $ ResultRecord (Just 0) RCDone [])+  )+  , -- command result exec-run {{{3+  ([paste|+=thread-group-started,id="i1",pid="18510"+=thread-created,id="1",group-id="i1"+2^running+*running,thread-id="all"+(gdb) +|], Output [+        OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACThreadGroupStarted [Result "id" (VConst "i1"), Result "pid" (VConst "18510")]+      , OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACThreadCreated [Result "id" (VConst "1"), Result "group-id" (VConst "i1")]+      , OOBAsyncRecord $ ARExecAsyncOutput $ ExecAsyncOutput Nothing $ AsyncOutput ACRunning [Result "thread-id" (VConst "all")]+    ] $ Just $ ResultRecord (Just 2) RCRunning []+  )+  , -- breakpoint hit {{{3+  ([paste|+=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"+=library-loaded,id="/lib/libc.so.6",target-name="/lib/libc.so.6",host-name="/lib/libc.so.6",symbols-loaded="0",thread-group="i1"+*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x0000000000400ba9",func="ec_thread_0",args=[{name="ec_cont",value="0x0"}],file="ec.c",fullname="/tmp/ec.c",line="303"},thread-id="1",stopped-threads="all",core="0"+(gdb) +|], Output+      [+        OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACLibraryLoaded +          [+            Result "id" (VConst "/lib64/ld-linux-x86-64.so.2")+          , Result "target-name" (VConst "/lib64/ld-linux-x86-64.so.2")+          , Result "host-name" (VConst "/lib64/ld-linux-x86-64.so.2")+          , Result "symbols-loaded" (VConst "0")+          , Result "thread-group" (VConst "i1")+          ]+      , OOBAsyncRecord $ ARNotifyAsyncOutput $ NotifyAsyncOutput Nothing $ AsyncOutput ACLibraryLoaded +          [+            Result "id" (VConst "/lib/libc.so.6")+          , Result "target-name" (VConst "/lib/libc.so.6")+          , Result "host-name" (VConst "/lib/libc.so.6")+          , Result "symbols-loaded" (VConst "0")+          , Result "thread-group" (VConst "i1")+          ]+      , OOBAsyncRecord $ ARExecAsyncOutput $ ExecAsyncOutput Nothing $ AsyncOutput ACStop+          [+            Result "reason" (VConst "breakpoint-hit")+          , Result "disp" (VConst "keep")+          , Result "bkptno" (VConst "1")+          , Result "frame" (VTuple $ Tuple+            [+              Result "addr" (VConst "0x0000000000400ba9")+            , Result "func" (VConst "ec_thread_0")+            , Result "args" (VList $ ValueList [VTuple $ Tuple+              [+                Result "name" (VConst "ec_cont")+              , Result "value" (VConst "0x0")+              ]])+            , Result "file" (VConst "ec.c")+            , Result "fullname" (VConst "/tmp/ec.c")+            , Result "line" (VConst "303")+            ])+          , Result "thread-id" (VConst "1")+          , Result "stopped-threads" (VConst "all")+          , Result "core" (VConst "0")+          ]+      ] Nothing)+  ]+  where+    runTest :: (String, Output) -> Assertion -- {{{3+    runTest (str, output) =+      show output @=? show (parse_output (tail str))++test_response_break_insert :: Test -- {{{2+test_response_break_insert = enumTestGroup "response_break_insert" $ map runTest [+  -- example {{{3+  ([paste|+^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000000400ba9",func="ec_thread_0",file="ec.c",fullname="/tmp/ec.c",line="303",times="0",original-location="ec.c:ec_thread_0"}+(gdb) +|], Breakpoint 1 "breakpoint" BreakpointKeep True "0x0000000000400ba9" "ec_thread_0" "ec.c" "/tmp/ec.c" 303 0 "ec.c:ec_thread_0")+  ]+  where +    runTest :: (String, Breakpoint) -> Assertion -- {{{3+    runTest (str, bp) =+      let+        output = parse_output (tail str)+        bp' = do +          response <- output_response output+          response_break_insert (respResults response)+      in +        show (Just bp) @=? show bp'++test_response_stopped :: Test -- {{{2+test_response_stopped = enumTestGroup "response_stopped" $ map runTest [+  -- breakpoint hit {{{3+  ([paste|+*stopped,reason="breakpoint-hit",disp="keep",bkptno="7",frame={addr="0x0000000000400e24",func="ec_thread_1",args=[{name="ec_cont",value="0x400ed5"}],file="ec.c",fullname="/tmp/ec.c",line="433"},thread-id="1",stopped-threads="all",core="1"+(gdb) +|], Stopped (BreakpointHit BreakpointKeep 7) (Frame Nothing "0x0000000000400e24" "ec_thread_1" (Just [Arg "ec_cont" "0x400ed5"]) "ec.c" (Just "/tmp/ec.c") 433) 1 "all" 1)+  , -- end stepping range {{{3+  ([paste|+*stopped,reason="end-stepping-range",frame={addr="0x00000000004017fa",func="main",args=[],file="pal.c",fullname="/tmp/pal.c",line="196"},thread-id="1",stopped-threads="all",core="1"+(gdb) +|], Stopped EndSteppingRange (Frame Nothing "0x00000000004017fa" "main" (Just []) "pal.c" (Just "/tmp/pal.c") 196) 1 "all" 1)+  ]+    where+    runTest :: (String, Stopped) -> Assertion -- {{{3+    runTest (str, stp) =+      let+        output = parse_output (tail str)+        [notification] = output_notification output+        stp' = notification_stopped (notiResults notification)+      in+        show (Just stp) @=? show stp'++test_response_stack_list_frames :: Test -- {{{2+test_response_stack_list_frames = enumTestGroup "response_stack_list_frames" $ map runTest [+    -- example {{{3 +    ([paste|+^done,stack=[frame={level="0",addr="0x00007ffff7a9dcc7",func="_IO_vfprintf_internal",file="vfprintf.c",line="1647"},frame={level="1",addr="0x00007ffff7ac2c79",func="__IO_vsprintf",file="iovsprintf.c",line="43"},frame={level="2",addr="0x0000000000402520",func="logger_syscall",file="logger.c",fullname="/tmp/logger.c",line="57"},frame={level="3",addr="0x0000000000401c13",func="os_receive",file="core.c",fullname="/tmp/core.c",line="145"},frame={level="4",addr="0x0000000000401489",func="tc_receive",file="pal.c",fullname="/tmp/pal.c",line="116"},frame={level="5",addr="0x0000000000400e2e",func="ec_thread_1",file="ec.c",fullname="/tmp/ec.c",line="433"},frame={level="6",addr="0x00000000004016b2",func="flash_write_cb",file="pal.c",fullname="/tmp/pal.c",line="156"},frame={level="7",addr="0x00000000004019ff",func="cb_default",file="core.c",fullname="/tmp/core.c",line="90"},frame={level="8",addr="0x0000000000402f05",func="dispatcher_run",file="dispatcher.c",fullname="/tmp/dispatcher.c",line="93"},frame={level="9",addr="0x000000000040188e",func="os_run",file="core.c",fullname="/tmp/core.c",line="37"},frame={level="10",addr="0x00000000004012f0",func="pal_run",file="pal.c",fullname="/tmp/pal.c",line="70"},frame={level="11",addr="0x0000000000401818",func="main",file="pal.c",fullname="/tmp/pal.c",line="200"}]+(gdb) +|], Stack [+        Frame  (Just 0) "0x00007ffff7a9dcc7" "_IO_vfprintf_internal" Nothing "vfprintf.c"   Nothing 1647+      , Frame  (Just 1) "0x00007ffff7ac2c79" "__IO_vsprintf"         Nothing "iovsprintf.c" Nothing 43+      , Frame  (Just 2) "0x0000000000402520" "logger_syscall"        Nothing "logger.c"     (Just "/tmp/logger.c") 57+      , Frame  (Just 3) "0x0000000000401c13" "os_receive"            Nothing "core.c"       (Just "/tmp/core.c") 145+      , Frame  (Just 4) "0x0000000000401489" "tc_receive"            Nothing "pal.c"        (Just "/tmp/pal.c") 116+      , Frame  (Just 5) "0x0000000000400e2e" "ec_thread_1"           Nothing "ec.c"         (Just "/tmp/ec.c") 433+      , Frame  (Just 6) "0x00000000004016b2" "flash_write_cb"        Nothing "pal.c"        (Just "/tmp/pal.c") 156+      , Frame  (Just 7) "0x00000000004019ff" "cb_default"            Nothing "core.c"       (Just "/tmp/core.c") 90+      , Frame  (Just 8) "0x0000000000402f05" "dispatcher_run"        Nothing "dispatcher.c" (Just "/tmp/dispatcher.c") 93+      , Frame  (Just 9) "0x000000000040188e" "os_run"                Nothing "core.c"       (Just "/tmp/core.c") 37+      , Frame (Just 10) "0x00000000004012f0" "pal_run"               Nothing "pal.c"        (Just "/tmp/pal.c") 70+      , Frame (Just 11) "0x0000000000401818" "main"                  Nothing "pal.c"        (Just "/tmp/pal.c") 200+      ])+  ]+  where+    runTest :: (String, Stack) -> Assertion -- {{{3+    runTest (str, stack) =+      let+        output = parse_output (tail str)+        stack' = do +          response <- output_response output+          response_stack_list_frames (respResults response)+      in +        show (Just stack) @=? show stack'++test_response_exec_return :: Test -- {{{2+test_response_exec_return = enumTestGroup "response_exec_return" $ map runTest [+  -- example {{{3+  ([paste|+^done,frame={level="0",addr="0x080483cc",func="f",args=[],file="foo.c",fullname="/tmp/foo.c",line="9"}+(gdb) +|], Frame (Just 0) "0x080483cc" "f" (Just []) "foo.c" (Just "/tmp/foo.c") 9+  )+  ]+  where+    runTest :: (String, Frame) -> Assertion -- {{{3+    runTest (str, frame) = +      let+        output = parse_output (tail str)+        frame' = do+          response <- output_response output+          response_exec_return (respResults response)+      in+        show (Just frame) @=? show frame'++test_response_data_evaluate_expression :: Test -- {{{2+test_response_data_evaluate_expression = enumTestGroup "response_data_evaluate_expression" $ map runTest [+    -- example {{{3+    ([paste|+^done,value="24"+(gdb) +|], "24")+  ]+  where+    runTest :: (String, String) -> Assertion -- {{{3+    runTest (str, expr) =+      let+        output = parse_output (tail str)+        (Just response) = output_response output+      in do+        RCDone @=? respClass response+        Just expr @=? (response_data_evaluate_expression . respResults) response++test_response_error :: Test -- {{{2+test_response_error = enumTestGroup "response_error" $ map runTest [+    -- example {{{3+    ([paste|+^error,msg="No symbol \"j\" in current context."+(gdb) +|], "No symbol \"j\" in current context.")+  ]+  where+    runTest :: (String, String) -> Assertion -- {{{3+    runTest (str, err) =+      let+        output = parse_output (tail str)+        (Just response) = output_response output+      in do+        RCError @=? respClass response+        Just err @=? (response_error . respResults) response++-- utils {{{1+qp :: String -> Parameter+qp = QuotedString++enumTestGroup :: String -> [Assertion] -> Test+enumTestGroup name =+  testGroup name . zipWith (testCase . printf "%.2d") [(1 :: Int)..]