-- GENERATED by C->Haskell Compiler, version 0.28.8 Switcheroo, 25 November 2017 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "src/Hapstone/Internal/Capstone.chs" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-|
Module      : Hapstone.Internal.Capstone
Description : capstone's API header ported using C2HS + some boilerplate
Copyright   : (c) Inokentiy Babushkin, 2016
License     : BSD3
Maintainer  : Inokentiy Babushkin <inokentiy.babushkin@googlemail.com>
Stability   : experimental

This module contains capstone's public API, with the necessary datatypes and
functions, and some boilerplate to make it usable. Thus, it exposes an IO-based
interface to capstone, which is a rough 1:1 translation of the capstone C
header to Haskell. Obviously, it isn't very ideomatic to use, so a higher-level
API is present in "Hapstone.Capstone". The approach there is to wrap all
necessary cleanup and initialization and expose an ideomatic (but heavily
abstracted) interface to capstone.

This module, on the other hand, is intended to be used when performance is more
critical or greater versatility is needed. This means that the abstractions
introduced in the C version of the library are still present, but their use has
been restricted to provide more reasonable levels of safety.
-}
module Hapstone.Internal.Capstone 
    ( -- * Datatypes
      Csh
    , CsArch(..)
    , CsSupport(..)
    , CsMode(..)
    , CsOption(..)
    , CsOptionState(..)
    , CsOperand(..)
    , CsGroup(..)
      -- * Skipdata setup
      -- $skipdata
    , CsSkipdataCallback
    , CsSkipdataStruct(..)
    , csSetSkipdata
      -- * Instruction representation
    , ArchInfo(..)
      -- $instructions
    , CsDetail(..)
    , peekDetail
    , CsInsn(..)
    , peekArch
    , peekArrayArch
      -- * Capstone API
    , csInsnOffset
    , CsErr(..)
    , csSupport
    , csOpen
    , csClose
    , csOption
    , csErrno
    , csStrerror
    , csDisasm
    , csDisasmIter
    , csFree
    , csMalloc
    , csRegName
    , csInsnName
    , csGroupName
    , csInsnGroup
    , csRegRead
    , csRegWrite
    , csOpCount
    , csOpIndex
    ) where
import qualified Foreign.C.String as C2HSImp
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Ptr as C2HSImp
import qualified Foreign.Storable as C2HSImp
import qualified System.IO.Unsafe as C2HSImp






{-# LINE 71 "src/Hapstone/Internal/Capstone.chs" #-}


import Control.Monad (join, (>=>))

import Foreign
import Foreign.C.Types
import Foreign.C.String ( CString, peekCString
                        , newCString, castCharToCChar, castCCharToChar)
import Foreign.Marshal.Array (peekArray, pokeArray)
import Foreign.Ptr

import Hapstone.Internal.Util
import qualified Hapstone.Internal.Arm64 as Arm64
import qualified Hapstone.Internal.Arm as Arm
import qualified Hapstone.Internal.Mips as Mips
import qualified Hapstone.Internal.Ppc as Ppc
import qualified Hapstone.Internal.Sparc as Sparc
import qualified Hapstone.Internal.SystemZ as SystemZ
import qualified Hapstone.Internal.X86 as X86
import qualified Hapstone.Internal.XCore as XCore

import System.IO.Unsafe (unsafePerformIO)

-- | capstone's weird^M^M^M^M^Mopaque handle type
type Csh = CSize

{-# LINE 96 "src/Hapstone/Internal/Capstone.chs" #-}


-- | supported architectures
data CsArch = CsArchArm
            | CsArchArm64
            | CsArchMips
            | CsArchX86
            | CsArchPpc
            | CsArchSparc
            | CsArchSysz
            | CsArchXcore
            | CsArchM68k
            | CsArchTms320c64x
            | CsArchM680x
            | CsArchEvm
            | CsArchMax
            | CsArchAll
  deriving (Show,Eq,Bounded)
instance Enum CsArch where
  succ CsArchArm = CsArchArm64
  succ CsArchArm64 = CsArchMips
  succ CsArchMips = CsArchX86
  succ CsArchX86 = CsArchPpc
  succ CsArchPpc = CsArchSparc
  succ CsArchSparc = CsArchSysz
  succ CsArchSysz = CsArchXcore
  succ CsArchXcore = CsArchM68k
  succ CsArchM68k = CsArchTms320c64x
  succ CsArchTms320c64x = CsArchM680x
  succ CsArchM680x = CsArchEvm
  succ CsArchEvm = CsArchMax
  succ CsArch
CsArchMax = CsArch
CsArchAll
  succ CsArch
CsArchAll = String -> CsArch
forall a. HasCallStack => String -> a
error String
"CsArch.succ: CsArchAll has no successor"

  pred CsArchArm64 = CsArchArm
  pred CsArchMips = CsArchArm64
  pred CsArchX86 = CsArchMips
  pred CsArchPpc = CsArchX86
  pred CsArchSparc = CsArchPpc
  pred CsArchSysz = CsArchSparc
  pred CsArchXcore = CsArchSysz
  pred :: CsOptionState -> CsOptionState
pred :: CsOperand -> CsOperand
pred CsArchM68k = CsArchXcore
  pred CsArchTms320c64x = CsArchM68k
  pred CsArchM680x = CsArchTms320c64x
  pred CsArchEvm = CsArchM680x
  pred CsArchMax = CsArchEvm
  pred CsArchAll = CsArchMax
  pred CsArchArm = error "CsArch.pred: CsArchArm has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsArchAll

  fromEnum CsArchArm = 0
  fromEnum CsArchArm64 = 1
  fromEnum CsArchMips = 2
  fromEnum CsArchX86 = 3
  fromEnum CsArchPpc = 4
  fromEnum CsArchSparc = 5
  fromEnum CsArchSysz = 6
  fromEnum CsArchXcore = 7
  fromEnum CsArchM68k = 8
  fromEnum CsArchTms320c64x = 9
  fromEnum CsArchM680x = 10
  fromEnum CsArchEvm = 11
  fromEnum CsArchMax = 12
  fromEnum :: CsGroup -> Int
fromEnum CsArchAll = 65535

  toEnum Int
0 = CsArchArm
  toEnum Int
1 = CsArchArm64
  toEnum Int
2 = CsArchMips
  toEnum Int
3 = CsArchX86
  toEnum Int
4 = CsArchPpc
  toEnum Int
5 = CsArchSparc
  toEnum Int
6 = CsArchSysz
  toEnum 7 = CsArchXcore
  toEnum Int
8 = CsArchM68k
  toEnum Int
9 = CsArchTms320c64x
  toEnum 10 = CsArchM680x
  toEnum 11 = CsArchEvm
  toEnum 12 = CsArchMax
  toEnum 65535 = CsArchAll
  toEnum unmatched = error ("CsArch.toEnum: Cannot match " ++ show unmatched)

{-# LINE 100 "src/Hapstone/Internal/Capstone.chs" #-}


-- | support constants
data CsSupport = CsSupportDiet
               | CsSupportX86Reduce
  deriving (Show,Eq,Bounded)
instance Enum CsSupport where
  succ CsSupportDiet = CsSupportX86Reduce
  succ CsSupportX86Reduce = error "CsSupport.succ: CsSupportX86Reduce has no successor"

  pred CsSupportX86Reduce = CsSupportDiet
  pred CsSupportDiet = error "CsSupport.pred: CsSupportDiet has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsSupportX86Reduce

  fromEnum CsSupportDiet = 65536
  fromEnum CsSupportX86Reduce = 65537

  toEnum 65536 = CsSupportDiet
  toEnum 65537 = CsSupportX86Reduce
  toEnum unmatched = error ("CsSupport.toEnum: Cannot match " ++ show unmatched)

{-# LINE 106 "src/Hapstone/Internal/Capstone.chs" #-}


-- | working modes
data CsMode = CsModeLittleEndian
            | CsModeArm
            | CsMode16
            | CsModeM68k000
            | CsModeM680x6301
            | CsMode32
            | CsModeM68k010
            | CsModeMips32
            | CsModeM680x6309
            | CsMode64
            | CsModeM68k020
            | CsModeMips64
            | CsModeM680x6800
            | CsModeThumb
            | CsModeMicro
            | CsModeV9
            | CsModeQpx
            | CsModeM68k030
            | CsModeM680x6801
            | CsModeMclass
            | CsModeMips3
            | CsModeM68k040
            | CsModeM680x6805
            | CsModeV8
            | CsModeMips32r6
            | CsModeM68k060
            | CsModeM680x6808
            | CsModeMips2
            | CsModeM680x6809
            | CsModeM680x6811
            | CsModeM680xCpu12
            | CsModeM680xHcs08
            | CsModeBigEndian
  deriving (Show,Eq,Bounded)
instance Enum CsMode where
  succ CsModeLittleEndian = CsMode16
  succ CsModeArm = CsMode16
  succ CsMode16 = CsMode32
  succ CsModeM68k000 = CsMode32
  succ CsModeM680x6301 = CsMode32
  succ CsMode32 = CsMode64
  succ CsModeM68k010 = CsMode64
  succ CsModeMips32 = CsMode64
  succ CsModeM680x6309 = CsMode64
  succ CsMode64 = CsModeThumb
  succ CsModeM68k020 = CsModeThumb
  succ CsModeMips64 = CsModeThumb
  succ CsModeM680x6800 = CsModeThumb
  succ CsModeThumb = CsModeMclass
  succ CsModeMicro = CsModeMclass
  succ CsModeV9 = CsModeMclass
  succ CsModeQpx = CsModeMclass
  succ CsModeM68k030 = CsModeMclass
  succ CsModeM680x6801 = CsModeMclass
  succ CsModeMclass = CsModeV8
  succ CsModeMips3 = CsModeV8
  succ CsModeM68k040 = CsModeV8
  succ CsModeM680x6805 = CsModeV8
  succ CsModeV8 = CsModeMips2
  succ CsModeMips32r6 = CsModeMips2
  succ CsModeM68k060 = CsModeMips2
  succ CsModeM680x6808 = CsModeMips2
  succ CsModeMips2 = CsModeM680x6811
  succ CsModeM680x6809 = CsModeM680x6811
  succ CsModeM680x6811 = CsModeM680xCpu12
  succ CsModeM680xCpu12 = CsModeM680xHcs08
  succ CsModeM680xHcs08 = CsModeBigEndian
  succ CsModeBigEndian = error "CsMode.succ: CsModeBigEndian has no successor"

  pred CsMode16 = CsModeLittleEndian
  pred CsModeM68k000 = CsModeLittleEndian
  pred CsModeM680x6301 = CsModeLittleEndian
  pred CsMode32 = CsMode16
  pred CsModeM68k010 = CsMode16
  pred CsModeMips32 = CsMode16
  pred CsModeM680x6309 = CsMode16
  pred CsMode64 = CsMode32
  pred CsModeM68k020 = CsMode32
  pred CsModeMips64 = CsMode32
  pred CsModeM680x6800 = CsMode32
  pred CsModeThumb = CsMode64
  pred CsModeMicro = CsMode64
  pred CsModeV9 = CsMode64
  pred CsModeQpx = CsMode64
  pred CsModeM68k030 = CsMode64
  pred CsModeM680x6801 = CsMode64
  pred CsModeMclass = CsModeThumb
  pred CsModeMips3 = CsModeThumb
  pred CsModeM68k040 = CsModeThumb
  pred CsModeM680x6805 = CsModeThumb
  pred CsModeV8 = CsModeMclass
  pred CsModeMips32r6 = CsModeMclass
  pred CsModeM68k060 = CsModeMclass
  pred CsModeM680x6808 = CsModeMclass
  pred CsModeMips2 = CsModeV8
  pred CsModeM680x6809 = CsModeV8
  pred CsModeM680x6811 = CsModeMips2
  pred CsModeM680xCpu12 = CsModeM680x6811
  pred CsModeM680xHcs08 = CsModeM680xCpu12
  pred CsModeBigEndian = CsModeM680xHcs08
  pred CsModeLittleEndian = error "CsMode.pred: CsModeLittleEndian has no predecessor"
  pred CsModeArm = error "CsMode.pred: CsModeArm has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsModeBigEndian

  fromEnum CsModeLittleEndian = 0
  fromEnum CsModeArm = 0
  fromEnum CsMode16 = 2
  fromEnum CsModeM68k000 = 2
  fromEnum CsModeM680x6301 = 2
  fromEnum CsMode32 = 4
  fromEnum CsModeM68k010 = 4
  fromEnum CsModeMips32 = 4
  fromEnum CsModeM680x6309 = 4
  fromEnum CsMode64 = 8
  fromEnum CsModeM68k020 = 8
  fromEnum CsModeMips64 = 8
  fromEnum CsModeM680x6800 = 8
  fromEnum CsModeThumb = 16
  fromEnum CsModeMicro = 16
  fromEnum CsModeV9 = 16
  fromEnum CsModeQpx = 16
  fromEnum CsModeM68k030 = 16
  fromEnum CsModeM680x6801 = 16
  fromEnum CsModeMclass = 32
  fromEnum CsModeMips3 = 32
  fromEnum CsModeM68k040 = 32
  fromEnum CsModeM680x6805 = 32
  fromEnum CsModeV8 = 64
  fromEnum CsModeMips32r6 = 64
  fromEnum CsModeM68k060 = 64
  fromEnum CsModeM680x6808 = 64
  fromEnum CsModeMips2 = 128
  fromEnum CsModeM680x6809 = 128
  fromEnum CsModeM680x6811 = 256
  fromEnum CsModeM680xCpu12 = 512
  fromEnum CsModeM680xHcs08 = 1024
  fromEnum CsModeBigEndian = 2147483648

  toEnum :: Int -> CsMode
toEnum Int
0 = CsMode
CsModeLittleEndian
  toEnum Int
2 = CsMode
CsMode16
  toEnum Int
4 = CsMode
CsMode32
  toEnum Int
8 = CsMode
CsMode64
  toEnum Int
16 = CsMode
CsModeThumb
  toEnum 32 = CsMode
CsModeMclass
  toEnum Int
64 = CsMode
CsModeV8
  toEnum Int
128 = CsMode
CsModeMips2
  toEnum Int
256 = CsMode
CsModeM680x6811
  toEnum Int
512 = CsMode
CsModeM680xCpu12
  toEnum Int
1024 = CsMode
CsModeM680xHcs08
  toEnum Int
2147483648 = CsMode
CsModeBigEndian
  toEnum Int
unmatched = String -> CsMode
forall a. HasCallStack => String -> a
error (String
"CsMode.toEnum: Cannot match " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
unmatched)

{-# LINE 110 "src/Hapstone/Internal/Capstone.chs" #-}


-- TODO: we will skip user defined dynamic memory routines for now

-- TODO: add cs_opt_mnem struct (yay for naming)

-- | options are, interestingly, represented by different types: an option
data CsOption = CsOptInvalid
              | CsOptSyntax
              | CsOptDetail
              | CsOptMode
              | CsOptMem
              | CsOptSkipdata
              | CsOptSkipdataSetup
              | CsOptMnemonic
              | CsOptUnsigned
  deriving (Show,Eq,Bounded)
instance Enum CsOption where
  succ CsOptInvalid = CsOptSyntax
  succ CsOptSyntax = CsOptDetail
  succ CsOptDetail = CsOptMode
  succ CsOptMode = CsOptMem
  succ CsOptMem = CsOptSkipdata
  succ CsOptSkipdata = CsOptSkipdataSetup
  succ CsOptSkipdataSetup = CsOptMnemonic
  succ CsOptMnemonic = CsOptUnsigned
  succ CsOptUnsigned = error "CsOption.succ: CsOptUnsigned has no successor"

  pred CsOptSyntax = CsOptInvalid
  pred CsOptDetail = CsOptSyntax
  pred CsOptMode = CsOptDetail
  pred CsOptMem = CsOptMode
  pred CsOptSkipdata = CsOptMem
  pred CsOptSkipdataSetup = CsOptSkipdata
  pred CsOptMnemonic = CsOptSkipdataSetup
  pred CsOptUnsigned = CsOptMnemonic
  pred CsOptInvalid = error "CsOption.pred: CsOptInvalid has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsOptUnsigned

  fromEnum CsOptInvalid = 0
  fromEnum CsOptSyntax = 1
  fromEnum CsOptDetail = 2
  fromEnum CsOptMode = 3
  fromEnum CsOptMem = 4
  fromEnum CsOptSkipdata = 5
  fromEnum CsOptSkipdataSetup = 6
  fromEnum CsOptMnemonic = 7
  fromEnum CsOptUnsigned = 8

  toEnum 0 = CsOptInvalid
  toEnum 1 = CsOptSyntax
  toEnum 2 = CsOptDetail
  toEnum 3 = CsOptMode
  toEnum 4 = CsOptMem
  toEnum 5 = CsOptSkipdata
  toEnum 6 = CsOptSkipdataSetup
  toEnum 7 = CsOptMnemonic
  toEnum 8 = CsOptUnsigned
  toEnum unmatched = error ("CsOption.toEnum: Cannot match " ++ show unmatched)

{-# LINE 118 "src/Hapstone/Internal/Capstone.chs" #-}

-- | ... and a state of an option
data CsOptionState = CsOptOff
                   | CsOptSyntaxDefault
                   | CsOptSyntaxIntel
                   | CsOptSyntaxAtt
                   | CsOptOn
                   | CsOptSyntaxNoregname
                   | CsOptSyntaxMasm
  deriving (Show,Eq,Bounded)
instance Enum CsOptionState where
  succ CsOptOff = CsOptSyntaxIntel
  succ CsOptSyntaxDefault = CsOptSyntaxIntel
  succ CsOptSyntaxIntel = CsOptSyntaxAtt
  succ CsOptSyntaxAtt = CsOptOn
  succ CsOptOn = CsOptSyntaxMasm
  succ CsOptSyntaxNoregname = CsOptSyntaxMasm
  succ CsOptSyntaxMasm = error "CsOptionState.succ: CsOptSyntaxMasm has no successor"

  pred CsOptSyntaxIntel = CsOptOff
  pred CsOptSyntaxAtt = CsOptSyntaxIntel
  pred CsOptOn = CsOptSyntaxAtt
  pred CsOptSyntaxNoregname = CsOptSyntaxAtt
  pred CsOptSyntaxMasm = CsOptOn
  pred CsOptOff = error "CsOptionState.pred: CsOptOff has no predecessor"
  pred CsOptSyntaxDefault = error "CsOptionState.pred: CsOptSyntaxDefault has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsOptSyntaxMasm

  fromEnum CsOptOff = 0
  fromEnum CsOptSyntaxDefault = 0
  fromEnum CsOptSyntaxIntel = 1
  fromEnum CsOptSyntaxAtt = 2
  fromEnum CsOptOn = 3
  fromEnum CsOptSyntaxNoregname = 3
  fromEnum CsOptSyntaxMasm = 4

  toEnum 0 = CsOptOff
  toEnum 1 = CsOptSyntaxIntel
  toEnum 2 = CsOptSyntaxAtt
  toEnum 3 = CsOptOn
  toEnum 4 = CsOptSyntaxMasm
  toEnum unmatched = error ("CsOptionState.toEnum: Cannot match " ++ show unmatched)

{-# LINE 121 "src/Hapstone/Internal/Capstone.chs" #-}


-- | arch-uniting operand type
data CsOperand = CsOpInvalid
               | CsOpReg
               | CsOpImm
               | CsOpMem
               | CsOpFp
  deriving (Show,Eq,Bounded)
instance Enum CsOperand where
  succ CsOpInvalid = CsOpReg
  succ CsOpReg = CsOpImm
  succ CsOpImm = CsOpMem
  succ CsOpMem = CsOpFp
  succ CsOpFp = error "CsOperand.succ: CsOpFp has no successor"

  pred CsOpReg = CsOpInvalid
  pred CsOpImm = CsOpReg
  pred CsOpMem = CsOpImm
  pred CsOpFp = CsOpMem
  pred CsOpInvalid = error "CsOperand.pred: CsOpInvalid has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsOpFp

  fromEnum CsOpInvalid = 0
  fromEnum CsOpReg = 1
  fromEnum CsOpImm = 2
  fromEnum CsOpMem = 3
  fromEnum CsOpFp = 4

  toEnum 0 = CsOpInvalid
  toEnum 1 = CsOpReg
  toEnum 2 = CsOpImm
  toEnum 3 = CsOpMem
  toEnum 4 = CsOpFp
  toEnum unmatched = error ("CsOperand.toEnum: Cannot match " ++ show unmatched)

{-# LINE 125 "src/Hapstone/Internal/Capstone.chs" #-}


-- TODO: find a place for cs_ac_type

-- | arch-uniting instruction group type
data CsGroup = CsGrpInvalid
             | CsGrpJump
             | CsGrpCall
             | CsGrpRet
             | CsGrpInt
             | CsGrpIret
             | CsGrpPrivilege
             | CsGrpBranchRelative
  deriving (Show,Eq,Bounded)
instance Enum CsGroup where
  succ CsGrpInvalid = CsGrpJump
  succ CsGrpJump = CsGrpCall
  succ CsGrpCall = CsGrpRet
  succ CsGrpRet = CsGrpInt
  succ CsGrpInt = CsGrpIret
  succ CsGrpIret = CsGrpPrivilege
  succ CsGrpPrivilege = CsGrpBranchRelative
  succ CsGrpBranchRelative = error "CsGroup.succ: CsGrpBranchRelative has no successor"

  pred CsGrpJump = CsGrpInvalid
  pred CsGrpCall = CsGrpJump
  pred CsGrpRet = CsGrpCall
  pred CsGrpInt = CsGrpRet
  pred CsGrpIret = CsGrpInt
  pred CsGrpPrivilege = CsGrpIret
  pred CsGrpBranchRelative = CsGrpPrivilege
  pred CsGrpInvalid = error "CsGroup.pred: CsGrpInvalid has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsGrpBranchRelative

  fromEnum CsGrpInvalid = 0
  fromEnum CsGrpJump = 1
  fromEnum CsGrpCall = 2
  fromEnum CsGrpRet = 3
  fromEnum CsGrpInt = 4
  fromEnum CsGrpIret = 5
  fromEnum CsGrpPrivilege = 6
  fromEnum CsGrpBranchRelative = 7

  toEnum 0 = CsGrpInvalid
  toEnum 1 = CsGrpJump
  toEnum 2 = CsGrpCall
  toEnum 3 = CsGrpRet
  toEnum 4 = CsGrpInt
  toEnum 5 = CsGrpIret
  toEnum 6 = CsGrpPrivilege
  toEnum 7 = CsGrpBranchRelative
  toEnum unmatched = error ("CsGroup.toEnum: Cannot match " ++ show unmatched)

{-# LINE 131 "src/Hapstone/Internal/Capstone.chs" #-}


-- $skipdata
-- SKIPDATA is an option supported by the capstone disassembly engine, that
-- allows to skip data which can't be disassembled and to represent it in form
-- of pseudo-instructions. The types and functions given here attempt to mirror
-- capstone's setup of this option, and a more high-level interface is
-- available in "Hapstone.Capstone".

-- | callback type for user-defined SKIPDATA work
type CsSkipdataCallback =
    FunPtr (Ptr Word8 -> CSize -> CSize -> Ptr () -> IO CSize)

-- | user-defined SKIPDATA setup
data CsSkipdataStruct = CsSkipdataStruct String CsSkipdataCallback (Ptr ())
    deriving (Show, Eq)

instance Storable CsSkipdataStruct where
    sizeOf _ = 24
{-# LINE 149 "src/Hapstone/Internal/Capstone.chs" #-}

    alignment _ = 8
{-# LINE 150 "src/Hapstone/Internal/Capstone.chs" #-}

    peek p = CsSkipdataStruct
        <$> (peekCString =<< (\ptr -> do {C2HSImp.peekByteOff ptr 0 :: IO (C2HSImp.Ptr C2HSImp.CChar)}) p)
        <*> (castFunPtr <$> (\ptr -> do {C2HSImp.peekByteOff ptr 8 :: IO (C2HSImp.FunPtr ((C2HSImp.Ptr C2HSImp.CUChar) -> (C2HSImp.CULong -> (C2HSImp.CULong -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CULong))))))}) p)
        <*> (\ptr -> do {C2HSImp.peekByteOff ptr 16 :: IO (C2HSImp.Ptr ())}) p
    poke p (CsSkipdataStruct s c d) = do
        newCString s >>= (\ptr val -> do {C2HSImp.pokeByteOff ptr 0 (val :: (C2HSImp.Ptr C2HSImp.CChar))}) p
        (\ptr val -> do {C2HSImp.pokeByteOff ptr 8 (val :: (C2HSImp.FunPtr ((C2HSImp.Ptr C2HSImp.CUChar) -> (C2HSImp.CULong -> (C2HSImp.CULong -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CULong)))))))}) p (castFunPtr c)
        (\ptr val -> do {C2HSImp.pokeByteOff ptr 16 (val :: (C2HSImp.Ptr ()))}) p d

-- | safely set SKIPDATA options (reset on Nothing)
csSetSkipdata :: Csh -> Maybe CsSkipdataStruct -> IO CsErr
csSetSkipdata h Nothing = csOption h CsOptSkipdata CsOptOff
csSetSkipdata h (Just s) = do
    csOption h CsOptSkipdata CsOptOn
    with s (csOption h CsOptSkipdataSetup . fromIntegral . ptrToWordPtr)

-- | architecture specific information
data ArchInfo
    = X86 X86.CsX86 -- ^ x86 architecture
    | Arm64 Arm64.CsArm64 -- ^ ARM64 architecture
    | Arm Arm.CsArm -- ^ ARM architecture
    | Mips Mips.CsMips -- ^ MIPS architecture
    | Ppc Ppc.CsPpc -- ^ PPC architecture
    | Sparc Sparc.CsSparc -- ^ SPARC architecture
    | SysZ SystemZ.CsSysZ -- ^ SystemZ architecture
    | XCore XCore.CsXCore -- ^ XCore architecture
    deriving (Show, Eq)

-- | instruction information
data CsDetail = CsDetail
    { regsRead :: [Word8] -- ^ registers read by this instruction
    , regsWrite :: [Word8] -- ^ registers written by this instruction
    , groups :: [Word8] -- ^ instruction groups this instruction belongs to
    , archInfo :: Maybe ArchInfo -- ^ (optional) architecture-specific info
    } deriving (Show, Eq)

-- $instructions
-- The union holding architecture-specific info is not tagged. Thus, we have
-- no way to determine what kind of data is stored in it without resorting to
-- some kind of context lookup, as the corresponding C code would do. Thus, the
-- peek implementation does not get architecture information, use peekDetail
-- for that.

instance Storable CsDetail where
    sizeOf _ = 1560
    alignment _ = 8
    peek p = CsDetail
        <$> do num <- fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 24 :: IO C2HSImp.CUChar}) p
               let ptr = plusPtr p (0)
{-# LINE 199 "src/Hapstone/Internal/Capstone.chs" #-}

               peekArray num ptr
        <*> do num <- fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 66 :: IO C2HSImp.CUChar}) p
               let ptr = plusPtr p (26)
{-# LINE 202 "src/Hapstone/Internal/Capstone.chs" #-}

               peekArray num ptr
        <*> do num <- fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 75 :: IO C2HSImp.CUChar}) p
               let ptr = plusPtr p (67)
{-# LINE 205 "src/Hapstone/Internal/Capstone.chs" #-}

               peekArray num ptr
        <*> pure Nothing
    poke p (CsDetail rR rW g a) = do
        (\ptr val -> do {C2HSImp.pokeByteOff ptr 24 (val :: C2HSImp.CUChar)}) p (fromIntegral $ length rR)
        if length rR > 12
           then error "regs_read overflew 12 bytes"
           else pokeArray (plusPtr p (0)) rR
        (\ptr val -> do {C2HSImp.pokeByteOff ptr 66 (val :: C2HSImp.CUChar)}) p (fromIntegral $ length rW)
        if length rW > 20
           then error "regs_write overflew 20 bytes"
           else pokeArray (plusPtr p (26)) rW
        (\ptr val -> do {C2HSImp.pokeByteOff ptr 75 (val :: C2HSImp.CUChar)}) p (fromIntegral $ length g)
        if length g > 8
           then error "groups overflew 8 bytes"
           else pokeArray (plusPtr p (67)) g
        let bP = plusPtr p ((75) + 1)
        case a of
          Just (X86 x) -> poke bP x
          Just (Arm64 x) -> poke bP x
          Just (Arm x) -> poke bP x
          Just (Mips x) -> poke bP x
          Just (Ppc x) -> poke bP x
          Just (Sparc x) -> poke bP x
          Just (SysZ x) -> poke bP x
          Just (XCore x) -> poke bP x
          Nothing -> return ()

-- | an arch-sensitive peek for cs_detail
peekDetail :: CsArch -> Ptr CsDetail -> IO CsDetail
peekDetail arch p = do
    detail <- peek p
    let bP = plusPtr p 48
    aI <- case arch of
            CsArchX86 -> X86 <$> peek bP
            CsArchArm64 -> Arm64 <$> peek bP
            CsArchArm -> Arm <$> peek bP
            CsArchMips -> Mips <$> peek bP
            CsArchPpc -> Ppc <$> peek bP
            CsArchSparc -> Sparc <$> peek bP
            CsArchSysz -> SysZ <$> peek bP
            CsArchXcore -> XCore <$> peek bP
    return detail { archInfo = Just aI }

-- | instructions
data CsInsn = CsInsn
    { insnId :: Word32 -- ^ instruction ID
    , address :: Word64 -- ^ instruction's address in memory
    , bytes :: [Word8] -- ^ raw byte representation
    , mnemonic :: String -- ^ instruction's mnemonic
    , opStr :: String -- ^ operands
    , detail :: Maybe CsDetail -- ^ (optional) detailed info
    } deriving (Show, Eq)

-- The untagged-union-problem propagates here as well
instance Storable CsInsn where
    sizeOf _ = 240
{-# LINE 261 "src/Hapstone/Internal/Capstone.chs" #-}

    alignment _ = 8
{-# LINE 262 "src/Hapstone/Internal/Capstone.chs" #-}

    peek p = CsInsn
        <$> (fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 0 :: IO C2HSImp.CUInt}) p)
        <*> (fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 8 :: IO C2HSImp.CULong}) p)
        <*> do num <- fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 16 :: IO C2HSImp.CUShort}) p
               let ptr = plusPtr p (18)
{-# LINE 267 "src/Hapstone/Internal/Capstone.chs" #-}

               peekArray num ptr
        <*> ((map castCCharToChar . takeWhile (/=0)) <$>
            peekArray 32 (plusPtr p (34)))
        <*> ((map castCCharToChar . takeWhile (/=0)) <$>
            peekArray 160 (plusPtr p (66)))
        <*> return Nothing
        --(castPtr <$> {#get cs_insn->detail#} p >>= peekMaybe)
    poke :: Ptr CsInsn -> CsInsn -> IO ()
poke Ptr CsInsn
p (CsInsn Word32
i Word64
a [Word8]
b String
m String
o Maybe CsDetail
d) = do
        (\Ptr CsInsn
ptr CUInt
val -> do {Ptr CsInsn -> Int -> CUInt -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
C2HSImp.pokeByteOff Ptr CsInsn
ptr Int
0 (CUInt
val :: C2HSImp.CUInt)}) Ptr CsInsn
p (Word32 -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
i)
        (\Ptr CsInsn
ptr CULong
val -> do {Ptr CsInsn -> Int -> CULong -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
C2HSImp.pokeByteOff Ptr CsInsn
ptr Int
8 (CULong
val :: C2HSImp.CULong)}) Ptr CsInsn
p (Word64 -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a)
        (\Ptr CsInsn
ptr CUShort
val -> do {Ptr CsInsn -> Int -> CUShort -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
C2HSImp.pokeByteOff Ptr CsInsn
ptr Int
16 (CUShort
val :: C2HSImp.CUShort)}) Ptr CsInsn
p (Int -> CUShort
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CUShort) -> Int -> CUShort
forall a b. (a -> b) -> a -> b
$ [Word8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word8]
b)
        if [Word8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word8]
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
16
           then String -> IO ()
forall a. HasCallStack => String -> a
error String
"bytes overflew 16 bytes"
           else Ptr Word8 -> [Word8] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray (Ptr CsInsn -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
p (Int
18)) [Word8]
b
        if String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
m Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
32
           then String -> IO ()
forall a. HasCallStack => String -> a
error String
"mnemonic overflew 32 bytes"
           else do Ptr CChar -> [CChar] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray (Ptr CsInsn -> Int -> Ptr CChar
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
p (Int
34))
                             ((Char -> CChar) -> String -> [CChar]
forall a b. (a -> b) -> [a] -> [b]
map Char -> CChar
castCharToCChar String
m)
                   Ptr Word8 -> Word8 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr CsInsn -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
p ((Int
34) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
m))
                        (Word8
0 :: Word8)
        if String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
160
           then String -> IO ()
forall a. HasCallStack => String -> a
error String
"op_str overflew 160 bytes"
           else do Ptr CChar -> [CChar] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray (Ptr CsInsn -> Int -> Ptr CChar
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
p (Int
66))
                             ((Char -> CChar) -> String -> [CChar]
forall a b. (a -> b) -> [a] -> [b]
map Char -> CChar
castCharToCChar String
o)
                   Ptr Word8 -> Word8 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr CsInsn -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
p ((Int
66) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
o))
                        (Word8
0 :: Word8)
        case Maybe CsDetail
d of
          Maybe CsDetail
Nothing -> (\Ptr CsInsn
ptr Ptr ()
val -> do {Ptr CsInsn -> Int -> Ptr () -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
C2HSImp.pokeByteOff Ptr CsInsn
ptr Int
232 (Ptr ()
val :: (C2HSImp.Ptr ()))}) Ptr CsInsn
p Ptr ()
forall b. Ptr b
nullPtr
          Just CsDetail
d' ->  do Ptr CsDetail
csDetailPtr <- IO (Ptr CsDetail)
forall a. Storable a => IO (Ptr a)
malloc
                         Ptr CsDetail -> CsDetail -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr CsDetail
csDetailPtr CsDetail
d'
                         (\Ptr CsInsn
ptr Ptr ()
val -> do {Ptr CsInsn -> Int -> Ptr () -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
C2HSImp.pokeByteOff Ptr CsInsn
ptr Int
232 (Ptr ()
val :: (C2HSImp.Ptr ()))}) Ptr CsInsn
p (Ptr CsDetail -> Ptr ()
forall a b. Ptr a -> Ptr b
castPtr Ptr CsDetail
csDetailPtr)

-- | an arch-sensitive peek for cs_insn 
peekArch :: CsArch -> Ptr CsInsn -> IO CsInsn
peekArch :: CsArch -> Ptr CsInsn -> IO CsInsn
peekArch CsArch
arch Ptr CsInsn
p = do
    CsInsn
insn <- Ptr CsInsn -> IO CsInsn
forall a. Storable a => Ptr a -> IO a
peek Ptr CsInsn
p
    Ptr CsDetail
bP <- Ptr () -> Ptr CsDetail
forall a b. Ptr a -> Ptr b
castPtr (Ptr () -> Ptr CsDetail) -> IO (Ptr ()) -> IO (Ptr CsDetail)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (\Ptr CsInsn
ptr -> do {Ptr CsInsn -> Int -> IO (Ptr ())
forall a b. Storable a => Ptr b -> Int -> IO a
C2HSImp.peekByteOff Ptr CsInsn
ptr Int
232 :: IO (C2HSImp.Ptr ())}) Ptr CsInsn
p
    if Ptr CsDetail
bP Ptr CsDetail -> Ptr CsDetail -> Bool
forall a. Eq a => a -> a -> Bool
/= Ptr CsDetail
forall b. Ptr b
nullPtr
       then do
           CsDetail
det <- CsArch -> Ptr CsDetail -> IO CsDetail
peekDetail CsArch
arch Ptr CsDetail
bP
           CsInsn -> IO CsInsn
forall (m :: * -> *) a. Monad m => a -> m a
return CsInsn
insn { detail :: Maybe CsDetail
detail = CsDetail -> Maybe CsDetail
forall a. a -> Maybe a
Just CsDetail
det }
       else CsInsn -> IO CsInsn
forall (m :: * -> *) a. Monad m => a -> m a
return CsInsn
insn

-- | an arch-sensitive peekElemOff for cs_insn
peekElemOffArch :: CsArch -> Ptr CsInsn -> Int -> IO CsInsn
peekElemOffArch :: CsArch -> Ptr CsInsn -> Int -> IO CsInsn
peekElemOffArch CsArch
arch Ptr CsInsn
ptr Int
off =
    CsArch -> Ptr CsInsn -> IO CsInsn
peekArch CsArch
arch (Ptr CsInsn -> Int -> Ptr CsInsn
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
ptr (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
* CsInsn -> Int
forall a. Storable a => a -> Int
sizeOf (CsInsn
forall a. HasCallStack => a
undefined :: CsInsn)))

-- | an arch-sensitive peekArray for cs_insn
peekArrayArch :: CsArch -> Int -> Ptr CsInsn -> IO [CsInsn]
peekArrayArch :: CsArch -> Int -> Ptr CsInsn -> IO [CsInsn]
peekArrayArch CsArch
arch Int
num Ptr CsInsn
ptr
    | Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = [CsInsn] -> IO [CsInsn]
forall (m :: * -> *) a. Monad m => a -> m a
return []
    | Bool
otherwise = Int -> [CsInsn] -> IO [CsInsn]
f (Int
numInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) []
  where
    f :: Int -> [CsInsn] -> IO [CsInsn]
f Int
0 [CsInsn]
acc = do CsInsn
e <- CsArch -> Ptr CsInsn -> Int -> IO CsInsn
peekElemOffArch CsArch
arch Ptr CsInsn
ptr Int
0; [CsInsn] -> IO [CsInsn]
forall (m :: * -> *) a. Monad m => a -> m a
return (CsInsn
eCsInsn -> [CsInsn] -> [CsInsn]
forall a. a -> [a] -> [a]
:[CsInsn]
acc)
    f Int
n [CsInsn]
acc = do CsInsn
e <- CsArch -> Ptr CsInsn -> Int -> IO CsInsn
peekElemOffArch CsArch
arch Ptr CsInsn
ptr Int
n; Int -> [CsInsn] -> IO [CsInsn]
f (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (CsInsn
eCsInsn -> [CsInsn] -> [CsInsn]
forall a. a -> [a] -> [a]
:[CsInsn]
acc)

-- | our own port of the CS_INSN_OFFSET macro
csInsnOffset :: Ptr CsInsn -> Int -> Int
csInsnOffset :: Ptr CsInsn -> Int -> Int
csInsnOffset Ptr CsInsn
p Int
n = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
    (-) (Int -> Int -> Int) -> IO Int -> IO (Int -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Any -> IO Int
forall b b. Num b => Ptr b -> IO b
getAddr (Ptr CsInsn -> Int -> Ptr Any
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CsInsn
p (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
240)) IO (Int -> Int) -> IO Int -> IO Int
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Ptr CsInsn -> IO Int
forall b b. Num b => Ptr b -> IO b
getAddr Ptr CsInsn
p
    where getAddr :: Ptr b -> IO b
getAddr Ptr b
p = CULong -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CULong -> b) -> IO CULong -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (\Ptr b
ptr -> do {Ptr b -> Int -> IO CULong
forall a b. Storable a => Ptr b -> Int -> IO a
C2HSImp.peekByteOff Ptr b
ptr Int
8 :: IO C2HSImp.CULong}) Ptr b
p

-- | possible error conditions
data CsErr = CsErrOk
           | CsErrMem
           | CsErrArch
           | CsErrHandle
           | CsErrCsh
           | CsErrMode
           | CsErrOption
           | CsErrDetail
           | CsErrMemsetup
           | CsErrVersion
           | CsErrDiet
           | CsErrSkipdata
           | CsErrX86Att
           | CsErrX86Intel
           | CsErrX86Masm
  deriving (Show,Eq,Bounded)
instance Enum CsErr where
  succ CsErrOk = CsErrMem
  succ CsErrMem = CsErrArch
  succ CsErrArch = CsErrHandle
  succ CsErrHandle = CsErrCsh
  succ CsErrCsh = CsErrMode
  succ CsErrMode = CsErrOption
  succ CsErrOption = CsErrDetail
  succ CsErrDetail = CsErrMemsetup
  succ CsErrMemsetup = CsErrVersion
  succ CsErrVersion = CsErrDiet
  succ CsErrDiet = CsErrSkipdata
  succ CsErrSkipdata = CsErrX86Att
  succ CsErrX86Att = CsErrX86Intel
  succ CsErrX86Intel = CsErrX86Masm
  succ CsErrX86Masm = error "CsErr.succ: CsErrX86Masm has no successor"

  pred :: CsErr -> CsErr
pred CsErr
CsErrMem = CsErr
CsErrOk
  pred CsErr
CsErrArch = CsErr
CsErrMem
  pred CsErr
CsErrHandle = CsErr
CsErrArch
  pred CsErr
CsErrCsh = CsErr
CsErrHandle
  pred CsErr
CsErrMode = CsErr
CsErrCsh
  pred CsErr
CsErrOption = CsErr
CsErrMode
  pred CsErr
CsErrDetail = CsErr
CsErrOption
  pred CsErr
CsErrMemsetup = CsErr
CsErrDetail
  pred CsErrVersion = CsErrMemsetup
  pred CsErr
CsErrDiet = CsErr
CsErrVersion
  pred CsErr
CsErrSkipdata = CsErr
CsErrDiet
  pred CsErr
CsErrX86Att = CsErr
CsErrSkipdata
  pred CsErr
CsErrX86Intel = CsErr
CsErrX86Att
  pred CsErr
CsErrX86Masm = CsErr
CsErrX86Intel
  pred CsErr
CsErrOk = String -> CsErr
forall a. HasCallStack => String -> a
error String
"CsErr.pred: CsErrOk has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from CsErrX86Masm

  fromEnum :: CsErr -> Int
fromEnum CsErr
CsErrOk = Int
0
  fromEnum CsErr
CsErrMem = Int
1
  fromEnum CsErr
CsErrArch = Int
2
  fromEnum CsErr
CsErrHandle = Int
3
  fromEnum CsErr
CsErrCsh = Int
4
  fromEnum CsErr
CsErrMode = Int
5
  fromEnum CsErr
CsErrOption = Int
6
  fromEnum CsErr
CsErrDetail = Int
7
  fromEnum CsErr
CsErrMemsetup = Int
8
  fromEnum CsErrVersion = 9
  fromEnum CsErrDiet = 10
  fromEnum CsErr
CsErrSkipdata = Int
11
  fromEnum CsErr
CsErrX86Att = Int
12
  fromEnum CsErr
CsErrX86Intel = Int
13
  fromEnum CsErr
CsErrX86Masm = Int
14

  toEnum 0 = CsErrOk
  toEnum 1 = CsErrMem
  toEnum 2 = CsErrArch
  toEnum 3 = CsErrHandle
  toEnum 4 = CsErrCsh
  toEnum 5 = CsErrMode
  toEnum 6 = CsErrOption
  toEnum 7 = CsErrDetail
  toEnum 8 = CsErrMemsetup
  toEnum 9 = CsErrVersion
  toEnum 10 = CsErrDiet
  toEnum 11 = CsErrSkipdata
  toEnum 12 = CsErrX86Att
  toEnum 13 = CsErrX86Intel
  toEnum 14 = CsErrX86Masm
  toEnum unmatched = error ("CsErr.toEnum: Cannot match " ++ show unmatched)

{-# LINE 333 "src/Hapstone/Internal/Capstone.chs" #-}


-- | get the library version
csVersion :: ((Int), (Int), (Int))
csVersion =
  C2HSImp.unsafePerformIO $
  alloca $ \a1' -> 
  alloca $ \a2' -> 
  csVersion'_ a1' a2' >>= \res ->
  let {res' = fromIntegral res} in
  peekNum  a1'>>= \a1'' -> 
  peekNum  a2'>>= \a2'' -> 
  return (res', a1'', a2'')

{-# LINE 337 "src/Hapstone/Internal/Capstone.chs" #-}


foreign import ccall "capstone/capstone.h cs_support"
    csSupport' :: CInt -> Bool
-- | get information on supported features
csSupport :: Enum a => a -> Bool
csSupport = csSupport' . fromIntegral . fromEnum

-- | open a new disassembly handle
csOpen :: (CsArch) -> ([CsMode]) -> IO ((CsErr), (Csh))
csOpen a1 a2 =
  let {a1' = (fromIntegral . fromEnum) a1} in 
  let {a2' = combine a2} in 
  alloca $ \a3' -> 
  csOpen'_ a1' a2' a3' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  peek  a3'>>= \a3'' -> 
  return (res', a3'')

{-# LINE 347 "src/Hapstone/Internal/Capstone.chs" #-}


-- | close a handle obtained by cs_open/'csOpen'
csClose' :: (Ptr Csh) -> IO ((CsErr))
csClose' a1 =
  let {a1' = id a1} in 
  csClose''_ a1' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  return (res')

{-# LINE 350 "src/Hapstone/Internal/Capstone.chs" #-}

csClose :: Csh -> IO CsErr
csClose = new >=> csClose'

-- | set an option on a handle
csOption :: Enum a => (Csh) -> (CsOption) -> (a) -> IO ((CsErr))
csOption a1 a2 a3 =
  let {a1' = id a1} in 
  let {a2' = (fromIntegral . fromEnum) a2} in 
  let {a3' = getCULongFromEnum a3} in 
  csOption'_ a1' a2' a3' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  return (res')

{-# LINE 356 "src/Hapstone/Internal/Capstone.chs" #-}


-- | get the last error from a handle
csErrno :: (Csh) -> IO ((CsErr))
csErrno a1 =
  let {a1' = id a1} in 
  csErrno'_ a1' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  return (res')

{-# LINE 359 "src/Hapstone/Internal/Capstone.chs" #-}


-- | get the description of an error
csStrerror :: (CsErr) -> (String)
csStrerror a1 =
  C2HSImp.unsafePerformIO $
  let {a1' = (fromIntegral . fromEnum) a1} in 
  csStrerror'_ a1' >>= \res ->
  C2HSImp.peekCString res >>= \res' ->
  return (res')

{-# LINE 362 "src/Hapstone/Internal/Capstone.chs" #-}


foreign import ccall "capstone/capstone.h cs_disasm"
    csDisasm' :: Csh -- handle
              -> Ptr CUChar -> CSize -- buffer to disassemble
              -> CULong -- address to start at
              -> CSize -- number of instructins to disassemble
              -> Ptr (Ptr CsInsn) -- where to put the instructions
              -> IO CSize -- number of succesfully disassembled instructions

-- | disassemble a buffer
csDisasm :: CsArch -> Csh -> [Word8] -> Word64 -> Int -> IO [CsInsn]
csDisasm arch handle bytes addr num = do
    array <- newArray $ map fromIntegral bytes
    passedPtr <- malloc :: IO (Ptr (Ptr CsInsn))
    resNum <- fromIntegral <$> csDisasm' handle array
        (fromIntegral $ length bytes) (fromIntegral addr)
        (fromIntegral num) passedPtr
    resPtr <- peek passedPtr
    free passedPtr
    res <- peekArrayArch arch resNum resPtr
    csFree resPtr resNum
    return res

-- | free an instruction struct array
csFree :: (Ptr CsInsn) -> (Int) -> IO ()
csFree a1 a2 =
  let {a1' = castPtr a1} in 
  let {a2' = fromIntegral a2} in 
  csFree'_ a1' a2' >>
  return ()

{-# LINE 387 "src/Hapstone/Internal/Capstone.chs" #-}


-- | allocate space for an instruction structure
csMalloc :: (Csh) -> IO ((Ptr CsInsn))
csMalloc a1 =
  let {a1' = id a1} in 
  csMalloc'_ a1' >>= \res ->
  let {res' = castPtr res} in
  return (res')

{-# LINE 390 "src/Hapstone/Internal/Capstone.chs" #-}


foreign import ccall "capstone/capstone.h cs_disasm_iter"
    csDisasmIter' :: Csh -- handle
                  -> Ptr (Ptr CUChar) -> Ptr CSize -- buffer description
                  -> Ptr CULong -- address to start at
                  -> Ptr CsInsn -- output buffer
                  -> IO Bool -- success

-- | disassemble one instruction at a time
csDisasmIter :: Csh -> [Word8] -> Word64
             -> IO ([Word8], Word64, Either CsErr CsInsn)
csDisasmIter handle bytes addr = do
    array <- newArray (map fromIntegral bytes) :: IO (Ptr CUChar)
    arrayPtr <- new array
    sizePtr <- new . fromIntegral $ length bytes
    addrPtr <- new $ fromIntegral addr
    insnPtr <- csMalloc handle
    success <- csDisasmIter' handle arrayPtr sizePtr addrPtr insnPtr
    bytes' <- join $
        peekArray <$> (fromIntegral <$> peek sizePtr) <*> peek arrayPtr
    addr' <- peek addrPtr
    free arrayPtr
    free sizePtr
    free addrPtr
    result <- if success
                 then Right <$> peek insnPtr
                 else Left <$> csErrno handle
    return (map fromIntegral bytes', fromIntegral addr', result)

-- | get a register's name as a String
csRegName' :: (Csh) -> (Int) -> (CString)
csRegName' a1 a2 =
  C2HSImp.unsafePerformIO $
  let {a1' = id a1} in 
  let {a2' = fromIntegral a2} in 
  csRegName''_ a1' a2' >>= \res ->
  return res >>= \res' ->
  return (res')

{-# LINE 421 "src/Hapstone/Internal/Capstone.chs" #-}

csRegName :: Enum e => Csh -> e -> Maybe String
csRegName h = stringLookup . csRegName' h . fromEnum

-- | get a instruction's name as a String
csInsnName' :: (Csh) -> (Int) -> (CString)
csInsnName' a1 a2 =
  C2HSImp.unsafePerformIO $
  let {a1' = id a1} in 
  let {a2' = fromIntegral a2} in 
  csInsnName''_ a1' a2' >>= \res ->
  return res >>= \res' ->
  return (res')

{-# LINE 426 "src/Hapstone/Internal/Capstone.chs" #-}

csInsnName :: Enum e => Csh -> e -> Maybe String
csInsnName h = stringLookup . csInsnName' h . fromEnum

-- | get a instruction group's name as a String
csGroupName' :: (Csh) -> (Int) -> (CString)
csGroupName' a1 a2 =
  C2HSImp.unsafePerformIO $
  let {a1' = id a1} in 
  let {a2' = fromIntegral a2} in 
  csGroupName''_ a1' a2' >>= \res ->
  return res >>= \res' ->
  return (res')

{-# LINE 431 "src/Hapstone/Internal/Capstone.chs" #-}

csGroupName :: Enum e => Csh -> e -> Maybe String
csGroupName h = stringLookup . csGroupName' h . fromEnum

foreign import ccall "capstone/capstone.h cs_insn_group"
    csInsnGroup' :: Csh -> Ptr CsInsn -> IO Bool
-- | check whether an instruction is member of a group
csInsnGroup :: Csh -> CsInsn -> Bool
csInsnGroup h i = unsafePerformIO . withCast i $ csInsnGroup' h

foreign import ccall "capstone/capstone.h cs_reg_read"
    csRegRead' :: Csh -> Ptr CsInsn -> CUInt -> IO Bool
-- | check whether an instruction reads from a register
csRegRead :: Csh -> CsInsn -> Int -> Bool
csRegRead :: Csh -> CsInsn -> Int -> Bool
csRegRead Csh
h CsInsn
i =
    IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> (Int -> IO Bool) -> Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsInsn -> (Ptr CsInsn -> IO Bool) -> IO Bool
forall a b c. Storable a => a -> (Ptr b -> IO c) -> IO c
withCast CsInsn
i ((Ptr CsInsn -> IO Bool) -> IO Bool)
-> (Int -> Ptr CsInsn -> IO Bool) -> Int -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ptr CsInsn -> CUInt -> IO Bool) -> CUInt -> Ptr CsInsn -> IO Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Csh -> Ptr CsInsn -> CUInt -> IO Bool
csRegRead' Csh
h) (CUInt -> Ptr CsInsn -> IO Bool)
-> (Int -> CUInt) -> Int -> Ptr CsInsn -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral

foreign import ccall "capstone/capstone.h cs_reg_write"
    csRegWrite' :: Csh -> Ptr CsInsn -> CUInt -> IO Bool
-- | check whether an instruction writes to a register
csRegWrite :: Csh -> CsInsn -> Int -> Bool
csRegWrite :: Csh -> CsInsn -> Int -> Bool
csRegWrite Csh
h CsInsn
i =
    IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> (Int -> IO Bool) -> Int -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CsInsn -> (Ptr CsInsn -> IO Bool) -> IO Bool
forall a b c. Storable a => a -> (Ptr b -> IO c) -> IO c
withCast CsInsn
i ((Ptr CsInsn -> IO Bool) -> IO Bool)
-> (Int -> Ptr CsInsn -> IO Bool) -> Int -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ptr CsInsn -> CUInt -> IO Bool) -> CUInt -> Ptr CsInsn -> IO Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Csh -> Ptr CsInsn -> CUInt -> IO Bool
csRegWrite' Csh
h) (CUInt -> Ptr CsInsn -> IO Bool)
-> (Int -> CUInt) -> Int -> Ptr CsInsn -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral

-- | return the number of operands of given type an instruction has
csOpCount :: (Csh) -> (CsInsn) -> (Int) -> (Int)
csOpCount :: Csh -> CsInsn -> Int -> Int
csOpCount Csh
a1 CsInsn
a2 Int
a3 =
  IO Int -> Int
forall a. IO a -> a
C2HSImp.unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
  let {a1' :: Csh
a1' = Csh -> Csh
forall a. a -> a
id Csh
a1} in 
  CsInsn -> (Ptr () -> IO Int) -> IO Int
forall a b c. Storable a => a -> (Ptr b -> IO c) -> IO c
withCast CsInsn
a2 ((Ptr () -> IO Int) -> IO Int) -> (Ptr () -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr ()
a2' -> 
  let {a3' :: CUInt
a3' = Int -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a3} in 
  Csh -> Ptr () -> CUInt -> IO CInt
csOpCount'_ Csh
a1' Ptr ()
a2' CUInt
a3' IO CInt -> (CInt -> IO Int) -> IO Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \CInt
res ->
  let {res' :: Int
res' = CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
res} in
  Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
res')

{-# LINE 457 "src/Hapstone/Internal/Capstone.chs" #-}


-- | return the position of the first operand of given type an instruction has,
-- given an inclusive search range
csOpIndex :: (Csh) -> (CsInsn) -> (Int) -> (Int) -> (Int)
csOpIndex a1 a2 a3 a4 =
  C2HSImp.unsafePerformIO $
  let {a1' = id a1} in 
  withCast a2 $ \a2' -> 
  let {a3' = fromIntegral a3} in 
  let {a4' = fromIntegral a4} in 
  csOpIndex'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 462 "src/Hapstone/Internal/Capstone.chs" #-}


-- TODO: bind to cs_regs_access

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_version"
  csVersion'_ :: ((C2HSImp.Ptr C2HSImp.CInt) -> ((C2HSImp.Ptr C2HSImp.CInt) -> (IO C2HSImp.CUInt)))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_open"
  csOpen'_ :: (C2HSImp.CInt -> (C2HSImp.CInt -> ((C2HSImp.Ptr Csh) -> (IO C2HSImp.CInt))))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_close"
  csClose''_ :: ((C2HSImp.Ptr Csh) -> (IO C2HSImp.CInt))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_option"
  csOption'_ :: (Csh -> (C2HSImp.CInt -> (C2HSImp.CULong -> (IO C2HSImp.CInt))))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_errno"
  csErrno'_ :: (Csh -> (IO C2HSImp.CInt))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_strerror"
  csStrerror'_ :: (C2HSImp.CInt -> (IO (C2HSImp.Ptr C2HSImp.CChar)))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_free"
  csFree'_ :: ((C2HSImp.Ptr ()) -> (C2HSImp.CULong -> (IO ())))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_malloc"
  csMalloc'_ :: (Csh -> (IO (C2HSImp.Ptr ())))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_reg_name"
  csRegName''_ :: (Csh -> (C2HSImp.CUInt -> (IO (C2HSImp.Ptr C2HSImp.CChar))))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_insn_name"
  csInsnName''_ :: (Csh -> (C2HSImp.CUInt -> (IO (C2HSImp.Ptr C2HSImp.CChar))))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_group_name"
  csGroupName''_ :: (Csh -> (C2HSImp.CUInt -> (IO (C2HSImp.Ptr C2HSImp.CChar))))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_op_count"
  csOpCount'_ :: (Csh -> ((C2HSImp.Ptr ()) -> (C2HSImp.CUInt -> (IO C2HSImp.CInt))))

foreign import ccall safe "Hapstone/Internal/Capstone.chs.h cs_op_index"
  csOpIndex'_ :: (Csh -> ((C2HSImp.Ptr ()) -> (C2HSImp.CUInt -> (C2HSImp.CUInt -> (IO C2HSImp.CInt)))))