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


{-# LINE 1 "src/Heystone/Internal/Keystone.chs" #-}
{-# LANGUAGE ForeignFunctionInterface #-}

{-|
Module      : Heystone.Internal.Keystone
Description : The Keystone assembler engine.
Copyright   : (c) Adrian Herrera, 2016
License     : GPL-2

Low-level bindings for the Keystone assembler engine.

This module should not be directly imported; it is only exposed because of the
way cabal handles ordering of chs files.
-}
module Heystone.Internal.Keystone
    ( -- * Types
      Architecture(..)
    , Mode(..)
    , OptionType(..)
    , OptionValue(..)

      -- * Function bindings
    , ksOpen
    , ksOption
    , ksFree
    , ksAsm
    , ksVersion
    , ksErrno
    , ksStrerror
    ) where
import qualified Foreign.C.String as C2HSImp
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Ptr as C2HSImp
import qualified System.IO.Unsafe as C2HSImp



import Foreign
import Foreign.C

import Heystone.Internal.Util

import Heystone.Internal.Core
{-# LINE 36 "src/Heystone/Internal/Keystone.chs" #-}



{-# LINE 38 "src/Heystone/Internal/Keystone.chs" #-}




-------------------------------------------------------------------------------
-- Types
-------------------------------------------------------------------------------

-- | CPU architecture.
data Architecture = ArchArm
                  | ArchArm64
                  | ArchMips
                  | ArchX86
                  | ArchPpc
                  | ArchSparc
                  | ArchSystemz
                  | ArchHexagon
                  | ArchEvm
                  | ArchMax
  deriving (Int -> Architecture -> ShowS
[Architecture] -> ShowS
Architecture -> String
(Int -> Architecture -> ShowS)
-> (Architecture -> String)
-> ([Architecture] -> ShowS)
-> Show Architecture
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Architecture] -> ShowS
$cshowList :: [Architecture] -> ShowS
show :: Architecture -> String
$cshow :: Architecture -> String
showsPrec :: Int -> Architecture -> ShowS
$cshowsPrec :: Int -> Architecture -> ShowS
Show,Architecture -> Architecture -> Bool
(Architecture -> Architecture -> Bool)
-> (Architecture -> Architecture -> Bool) -> Eq Architecture
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Architecture -> Architecture -> Bool
$c/= :: Architecture -> Architecture -> Bool
== :: Architecture -> Architecture -> Bool
$c== :: Architecture -> Architecture -> Bool
Eq,Architecture
Architecture -> Architecture -> Bounded Architecture
forall a. a -> a -> Bounded a
maxBound :: Architecture
$cmaxBound :: Architecture
minBound :: Architecture
$cminBound :: Architecture
Bounded)
instance Enum Architecture where
  succ :: Architecture -> Architecture
succ Architecture
ArchArm = Architecture
ArchArm64
  succ Architecture
ArchArm64 = Architecture
ArchMips
  succ ArchMips = ArchX86
  succ ArchX86 = ArchPpc
  succ ArchPpc = ArchSparc
  succ Architecture
ArchSparc = Architecture
ArchSystemz
  succ :: OptionType -> OptionType
succ Architecture
ArchSystemz = Architecture
ArchHexagon
  succ Architecture
ArchHexagon = Architecture
ArchEvm
  succ Architecture
ArchEvm = Architecture
ArchMax
  succ Architecture
ArchMax = String -> Architecture
forall a. HasCallStack => String -> a
error String
"Architecture.succ: ArchMax has no successor"

  pred :: Architecture -> Architecture
pred Architecture
ArchArm64 = Architecture
ArchArm
  pred Architecture
ArchMips = Architecture
ArchArm64
  pred Architecture
ArchX86 = Architecture
ArchMips
  pred Architecture
ArchPpc = Architecture
ArchX86
  pred Architecture
ArchSparc = Architecture
ArchPpc
  pred Architecture
ArchSystemz = Architecture
ArchSparc
  pred Architecture
ArchHexagon = Architecture
ArchSystemz
  pred ArchEvm = ArchHexagon
  pred ArchMax = ArchEvm
  pred ArchArm = error String
"Architecture.pred: ArchArm has no predecessor"

  enumFromTo :: Architecture -> Architecture -> [Architecture]
enumFromTo Architecture
from Architecture
to = go from
    where
      end :: Int
end = Architecture -> Int
forall a. Enum a => a -> Int
fromEnum Architecture
to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom :: Architecture -> [Architecture]
enumFrom Architecture
from = Architecture -> Architecture -> [Architecture]
forall a. Enum a => a -> a -> [a]
enumFromTo Architecture
from Architecture
ArchMax

  fromEnum ArchArm = 1
  fromEnum ArchArm64 = 2
  fromEnum ArchMips = 3
  fromEnum ArchX86 = 4
  fromEnum ArchPpc = 5
  fromEnum ArchSparc = 6
  fromEnum ArchSystemz = 7
  fromEnum ArchHexagon = 8
  fromEnum ArchEvm = 9
  fromEnum ArchMax = 10

  toEnum 1 = ArchArm
  toEnum 2 = ArchArm64
  toEnum 3 = ArchMips
  toEnum 4 = ArchX86
  toEnum 5 = ArchPpc
  toEnum 6 = ArchSparc
  toEnum 7 = ArchSystemz
  toEnum 8 = ArchHexagon
  toEnum 9 = ArchEvm
  toEnum 10 = ArchMax
  toEnum unmatched = error ("Architecture.toEnum: Cannot match " ++ show unmatched)

{-# LINE 51 "src/Heystone/Internal/Keystone.chs" #-}


-- | CPU hardware mode.
data Mode = ModeLittleEndian
          | ModeArm
          | Mode16
          | ModeMips32
          | Mode32
          | ModePpc32
          | ModeSparc32
          | ModeMips64
          | Mode64
          | ModePpc64
          | ModeSparc64
          | ModeThumb
          | ModeMicro
          | ModeQpx
          | ModeV9
          | ModeMips3
          | ModeV8
          | ModeMips32r6
          | ModeBigEndian
  deriving (Show,Eq,Bounded)
instance Enum Mode where
  succ ModeLittleEndian = ModeArm
  succ ModeArm = Mode16
  succ Mode16 = ModeMips32
  succ ModeMips32 = ModeMips64
  succ Mode32 = ModeMips64
  succ ModePpc32 = ModeMips64
  succ ModeSparc32 = ModeMips64
  succ ModeMips64 = ModeThumb
  succ Mode64 = ModeThumb
  succ ModePpc64 = ModeThumb
  succ ModeSparc64 = ModeThumb
  succ ModeThumb = ModeMips3
  succ ModeMicro = ModeMips3
  succ ModeQpx = ModeMips3
  succ ModeV9 = ModeMips3
  succ ModeMips3 = ModeV8
  succ ModeV8 = ModeBigEndian
  succ ModeMips32r6 = ModeBigEndian
  succ ModeBigEndian = error "Mode.succ: ModeBigEndian has no successor"

  pred ModeArm = ModeLittleEndian
  pred Mode16 = ModeArm
  pred ModeMips32 = Mode16
  pred Mode32 = Mode16
  pred ModePpc32 = Mode16
  pred ModeSparc32 = Mode16
  pred ModeMips64 = ModeMips32
  pred Mode64 = ModeMips32
  pred ModePpc64 = ModeMips32
  pred ModeSparc64 = ModeMips32
  pred ModeThumb = ModeMips64
  pred ModeMicro = ModeMips64
  pred ModeQpx = ModeMips64
  pred ModeV9 = ModeMips64
  pred ModeMips3 = ModeThumb
  pred ModeV8 = ModeMips3
  pred ModeMips32r6 = ModeMips3
  pred ModeBigEndian = ModeV8
  pred ModeLittleEndian = error "Mode.pred: ModeLittleEndian 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 ModeBigEndian

  fromEnum ModeLittleEndian = 0
  fromEnum ModeArm = 1
  fromEnum Mode16 = 2
  fromEnum ModeMips32 = 4
  fromEnum Mode32 = 4
  fromEnum ModePpc32 = 4
  fromEnum ModeSparc32 = 4
  fromEnum ModeMips64 = 8
  fromEnum Mode64 = 8
  fromEnum ModePpc64 = 8
  fromEnum ModeSparc64 = 8
  fromEnum ModeThumb = 16
  fromEnum ModeMicro = 16
  fromEnum ModeQpx = 16
  fromEnum ModeV9 = 16
  fromEnum ModeMips3 = 32
  fromEnum ModeV8 = 64
  fromEnum ModeMips32r6 = 64
  fromEnum ModeBigEndian = 1073741824

  toEnum :: Int -> Mode
toEnum Int
0 = Mode
ModeLittleEndian
  toEnum 1 = ModeArm
  toEnum 2 = Mode16
  toEnum Int
4 = Mode
ModeMips32
  toEnum 8 = ModeMips64
  toEnum 16 = ModeThumb
  toEnum Int
32 = Mode
ModeMips3
  toEnum 64 = ModeV8
  toEnum 1073741824 = ModeBigEndian
  toEnum Int
unmatched = String -> Mode
forall a. HasCallStack => String -> a
error (String
"Mode.toEnum: Cannot match " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
unmatched)

{-# LINE 58 "src/Heystone/Internal/Keystone.chs" #-}


-- | Runtime option types.
data OptionType = OptSyntax
                | OptSymResolver
  deriving (Show,Eq,Bounded)
instance Enum OptionType where
  succ OptSyntax = OptSymResolver
  succ OptSymResolver = error "OptionType.succ: OptSymResolver has no successor"

  pred OptSymResolver = OptSyntax
  pred OptSyntax = error "OptionType.pred: OptSyntax 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 OptSymResolver

  fromEnum OptSyntax = 1
  fromEnum OptSymResolver = 2

  toEnum 1 = OptSyntax
  toEnum 2 = OptSymResolver
  toEnum unmatched = error ("OptionType.toEnum: Cannot match " ++ show unmatched)

{-# LINE 65 "src/Heystone/Internal/Keystone.chs" #-}


-- | Runtime option values.
data OptionValue = SyntaxIntel
                 | SyntaxAtt
                 | SyntaxNasm
                 | SyntaxMasm
                 | SyntaxGas
                 | SyntaxRadix16
  deriving (Show,Eq,Bounded)
instance Enum OptionValue where
  succ SyntaxIntel = SyntaxAtt
  succ SyntaxAtt = SyntaxNasm
  succ SyntaxNasm = SyntaxMasm
  succ SyntaxMasm = SyntaxGas
  succ SyntaxGas = SyntaxRadix16
  succ SyntaxRadix16 = error "OptionValue.succ: SyntaxRadix16 has no successor"

  pred SyntaxAtt = SyntaxIntel
  pred SyntaxNasm = SyntaxAtt
  pred SyntaxMasm = SyntaxNasm
  pred SyntaxGas = SyntaxMasm
  pred SyntaxRadix16 = SyntaxGas
  pred SyntaxIntel = error "OptionValue.pred: SyntaxIntel 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 SyntaxRadix16

  fromEnum SyntaxIntel = 1
  fromEnum SyntaxAtt = 2
  fromEnum SyntaxNasm = 4
  fromEnum SyntaxMasm = 8
  fromEnum SyntaxGas = 16
  fromEnum SyntaxRadix16 = 32

  toEnum 1 = SyntaxIntel
  toEnum 2 = SyntaxAtt
  toEnum 4 = SyntaxNasm
  toEnum 8 = SyntaxMasm
  toEnum 16 = SyntaxGas
  toEnum 32 = SyntaxRadix16
  toEnum unmatched = error ("OptionValue.toEnum: Cannot match " ++ show unmatched)

{-# LINE 72 "src/Heystone/Internal/Keystone.chs" #-}


-------------------------------------------------------------------------------
-- Assembler control
-------------------------------------------------------------------------------

ksOpen :: (Architecture) -> ([Mode]) -> IO ((Error), (EnginePtr))
ksOpen a1 a2 =
  let {a1' = (fromIntegral . fromEnum) a1} in 
  let {a2' = combineEnums a2} in 
  alloca $ \a3' -> 
  ksOpen'_ a1' a2' a3' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  peek  a3'>>= \a3'' -> 
  return (res', a3'')

{-# LINE 83 "src/Heystone/Internal/Keystone.chs" #-}


ksOption :: (Engine) -> (OptionType) -> (OptionValue) -> IO ((Error))
ksOption a1 a2 a3 =
  (withEngine) a1 $ \a1' -> 
  let {a2' = (fromIntegral . fromEnum) a2} in 
  let {a3' = (fromIntegral . fromEnum) a3} in 
  ksOption'_ a1' a2' a3' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  return (res')

{-# LINE 90 "src/Heystone/Internal/Keystone.chs" #-}


ksAsm :: (Engine) -> (String) -> (Word64) -> IO ((Int), (Ptr CUChar), (Int), (Int))
ksAsm a1 a2 a3 =
  (withEngine) a1 $ \a1' -> 
  C2HSImp.withCString a2 $ \a2' -> 
  let {a3' = fromIntegral a3} in 
  alloca $ \a4' -> 
  alloca $ \a5' -> 
  alloca $ \a6' -> 
  ksAsm'_ a1' a2' a3' a4' a5' a6' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a4'>>= \a4'' -> 
  peekToInt  a5'>>= \a5'' -> 
  peekToInt  a6'>>= \a6'' -> 
  return (res', a4'', a5'', a6'')

{-# LINE 100 "src/Heystone/Internal/Keystone.chs" #-}


ksFree :: (Ptr CUChar) -> IO ()
ksFree a1 =
  let {a1' = castPtr a1} in 
  ksFree'_ a1' >>
  return ()

{-# LINE 105 "src/Heystone/Internal/Keystone.chs" #-}


-------------------------------------------------------------------------------
-- Misc.
-------------------------------------------------------------------------------

ksVersion :: (Ptr CUInt) -> (Ptr CUInt) -> (Int)
ksVersion a1 a2 =
  C2HSImp.unsafePerformIO $
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  ksVersion'_ a1' a2' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 115 "src/Heystone/Internal/Keystone.chs" #-}


ksErrno :: (Engine) -> IO ((Error))
ksErrno a1 =
  (withEngine) a1 $ \a1' -> 
  ksErrno'_ a1' >>= \res ->
  let {res' = (toEnum . fromIntegral) res} in
  return (res')

{-# LINE 120 "src/Heystone/Internal/Keystone.chs" #-}


ksStrerror :: (Error) -> (String)
ksStrerror a1 =
  C2HSImp.unsafePerformIO $
  let {a1' = (fromIntegral . fromEnum) a1} in 
  ksStrerror'_ a1' >>= \res ->
  C2HSImp.peekCString res >>= \res' ->
  return (res')

{-# LINE 125 "src/Heystone/Internal/Keystone.chs" #-}


-------------------------------------------------------------------------------
-- Helper functions
-------------------------------------------------------------------------------

peekToInt :: (Storable a, Integral a, Num b)
          => Ptr a
          -> IO b
peekToInt ptr =
    peek ptr >>= (return . fromIntegral)

foreign import ccall safe "Heystone/Internal/Keystone.chs.h ks_open"
  ksOpen'_ :: (C2HSImp.CInt -> (C2HSImp.CInt -> ((C2HSImp.Ptr (EnginePtr)) -> (IO C2HSImp.CInt))))

foreign import ccall safe "Heystone/Internal/Keystone.chs.h ks_option"
  ksOption'_ :: ((EnginePtr) -> (C2HSImp.CInt -> (C2HSImp.CULong -> (IO C2HSImp.CInt))))

foreign import ccall safe "Heystone/Internal/Keystone.chs.h ks_asm"
  ksAsm'_ :: ((EnginePtr) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (C2HSImp.CULong -> ((C2HSImp.Ptr (C2HSImp.Ptr C2HSImp.CUChar)) -> ((C2HSImp.Ptr C2HSImp.CULong) -> ((C2HSImp.Ptr C2HSImp.CULong) -> (IO C2HSImp.CInt)))))))

foreign import ccall safe "Heystone/Internal/Keystone.chs.h ks_free"
  ksFree'_ :: ((C2HSImp.Ptr C2HSImp.CUChar) -> (IO ()))

foreign import ccall unsafe "Heystone/Internal/Keystone.chs.h ks_version"
  ksVersion'_ :: ((C2HSImp.Ptr C2HSImp.CUInt) -> ((C2HSImp.Ptr C2HSImp.CUInt) -> (IO C2HSImp.CUInt)))

foreign import ccall unsafe "Heystone/Internal/Keystone.chs.h ks_errno"
  ksErrno'_ :: ((EnginePtr) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Heystone/Internal/Keystone.chs.h ks_strerror"
  ksStrerror'_ :: (C2HSImp.CInt -> (IO (C2HSImp.Ptr C2HSImp.CChar)))