cppfilt (empty) → 0.1.0.0
raw patch · 10 files changed
+312/−0 lines, 10 filesdep +basedep +bytestringdep +cppfiltsetup-changed
Dependencies added: base, bytestring, cppfilt, criterion, hspec
Files
- ChangeLog.md +3/−0
- LICENSE +30/−0
- README.md +21/−0
- Setup.hs +2/−0
- bench/Bench.hs +22/−0
- cppfilt.cabal +83/−0
- src/Data/CStringRepresentable.hs +34/−0
- src/System/Demangle.hs +43/−0
- src/System/Demangle/Pure.hs +26/−0
- test/Spec.hs +48/−0
+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for cppfilt++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Georg Rudoy (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,21 @@+# cppfilt++[](https://travis-ci.org/0xd34df00d/cppfilt)++This library provides bindings to the system ABI-exposed C++ name demangling+routines. It provides both `IO`-based API in the `System.Demangle` module+and the pure one in `System.Demangle.Pure`. The latter is deduced as unsafe+due to `unsafePerformIO` (which should be fine, though, since demangling is+hopefully referentially transparent).+++## Supported systems++For now demangling is done using either `libstdc++` or `libc++` (controlled+via the `use-libcpp` build flag). Adding support for other ABIs in a similar+fashion should be easy.++This approach is probably suboptimal, though, since one might want to try+different ABIs that might be available simultaneously (since even clang and+gcc mangle some names slightly differently), but it's not entirely obvious+what the API should be like in this case.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bench/Bench.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++import Criterion.Main+import Data.ByteString(ByteString)+import Data.String++import qualified System.Demangle as D++testData :: IsString a => [(String, a)]+testData = [+ ("simple", "_ZTI5IInfo"),+ ("operator", "_ZrsR11QDataStreamR5QUuid"),+ ("complex", "_ZTSZN10LeechCraft4Util15InstanceFunctorI7QFutureINS0_6EitherIN5boost7variantIN5vmime10exceptions20authentication_errorEJNS7_16connection_errorENS6_8security4cert20certificateExceptionENS_6Snails23GenericExceptionWrapperEEEENSD_19AccountThreadWorker10SyncResultEEEEE5ApplyINS0_7VisitorINS0_4VoidEJZNSD_7Account15SynchronizeImplERK5QListI11QStringListERK10QByteArrayNSD_12TaskPriorityEE3$_1ZNSO_15SynchronizeImplEST_SW_SX_E3$_2EEEEES2_INSt5decayINSt9result_ofIFT_SI_EE4typeEE4typeEERKSJ_RKS13_EUlRKSI_E_"),+ ("rly complex", "_ZN5boost6detail7variant15visitation_implIN4mpl_4int_ILi0EEENS1_20visitation_impl_stepINS_3mpl6l_iterINS7_6l_itemINS3_5long_ILl7EEEN5vmime10exceptions20authentication_errorENS9_INSA_ILl6EEENSD_16connection_errorENS9_INSA_ILl5EEENSC_8security4cert20certificateExceptionENS9_INSA_ILl4EEEN10LeechCraft6Snails23GenericExceptionWrapperENS9_INSA_ILl3EEENSN_15MessageNotFoundENS9_INSA_ILl2EEENSN_13FileOpenErrorENS9_INSA_ILl1EEENSN_18AttachmentNotFoundENS7_5l_endEEEEEEEEEEEEEEEEENS8_ISV_EEEENS1_14invoke_visitorINSM_4Util6detail7VisitorIvJZZNSN_10ThreadPool20PerformScheduledFuncI16QFutureInterfaceINS17_6EitherINS_7variantISE_JSG_SK_SO_SQ_SS_SU_EEENS17_4VoidEEEEMNSN_19AccountThreadWorkerEFNS1D_INS1E_ISQ_JSS_SU_EEES1G_EESt10shared_ptrINSN_7MessageEERK7QStringS1R_EJS1O_S1P_S1P_EEEvPNSN_13AccountThreadET_NSN_12TaskPriorityERKT0_DpRKT1_ENUlS1W_E_clIS1H_EEDaS1W_EUlRKSE_E_ZZNS1B_IS1I_S1T_JS1O_S1P_S1P_EEEvS1V_S1W_S1X_S20_S24_ENS26_IS1H_EEDaS1W_EUlS1W_E_EEEEEPKvNS1F_18has_fallback_type_EEENT1_11result_typeEiiRS2G_T2_NS3_5bool_ILb0EEET3_PS1W_PS1Y_")+ ]++main :: IO ()+main = defaultMain [+ bgroup "demangle string" [ bench name $ nfIO $ D.demangle @String mangled | (name, mangled) <- testData],+ bgroup "demangle bytestring" [ bench name $ nfIO $ D.demangle @ByteString mangled | (name, mangled) <- testData]+ ]
+ cppfilt.cabal view
@@ -0,0 +1,83 @@+-- This file has been generated from package.yaml by hpack version 0.20.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: e0c10543991dcafe3f792b8d89a01a6778270aebbde0275b126c27a106b7366f++name: cppfilt+version: 0.1.0.0+synopsis: Bindings for C++ demangling routines+description: Please see the README on Github at <https://github.com/0xd34df00d/cppfilt#readme>+category: System+homepage: https://github.com/0xd34df00d/cppfilt#readme+bug-reports: https://github.com/0xd34df00d/cppfilt/issues+author: Georg Rudoy+maintainer: 0xd34df00d@gmail.com+copyright: 2018 Georg Rudoy+license: BSD3+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10++extra-source-files:+ ChangeLog.md+ README.md++source-repository head+ type: git+ location: https://github.com/0xd34df00d/cppfilt++flag use-libcpp+ description: Use libc++ for demangling (if you're building your C++ code with clang) instead of libstdc+++ manual: True+ default: False++library+ hs-source-dirs:+ src+ build-depends:+ base >=4.7 && <5+ , bytestring+ if flag(use-libcpp) || os(darwin)+ extra-libraries:+ c+++ else+ extra-libraries:+ stdc+++ exposed-modules:+ Data.CStringRepresentable+ System.Demangle+ System.Demangle.Pure+ other-modules:+ Paths_cppfilt+ default-language: Haskell2010++test-suite cppfilt-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5+ , bytestring+ , cppfilt+ , hspec+ other-modules:+ Paths_cppfilt+ default-language: Haskell2010++benchmark cppfilt-benchmarks+ type: exitcode-stdio-1.0+ main-is: Bench.hs+ hs-source-dirs:+ bench+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base >=4.7 && <5+ , bytestring+ , cppfilt+ , criterion+ other-modules:+ Paths_cppfilt+ default-language: Haskell2010
+ src/Data/CStringRepresentable.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE FlexibleInstances #-}++{-|+ Module : Data.CStringRepresentable+ Description : Type class for string-like objects nicely mapping to 'CString's+ Stability : experimental++ This module provides the type class (and a few implementations) for values that+ can be efficiently converted to/from 'CString'. Instances for 'String' and+ strict 'BS.ByteString' are provided, and the use of 'BS.ByteString' is+ recommended if performance is a concern.+ -}++module Data.CStringRepresentable where++import qualified Data.ByteString.Char8 as BS+import Foreign.C++-- | Represents values that can be efficiently converted to and from 'CString's.+class CStringRepresentable a where+ -- | Perform a function on the 'CString' representation of the value.+ toCString :: a -> (CString -> IO b) -> IO b+ -- | Convert 'CString' to a value of the type. The ownership is not transferred.+ fromCString :: CString -> IO a++-- | 'String's can be represented as 'CString's (albeit conversions are inefficient).+instance CStringRepresentable String where+ toCString = withCString+ fromCString = peekCString++-- | 'BS.ByteString's can be represented as 'CString's.+instance CStringRepresentable BS.ByteString where+ toCString = BS.useAsCString+ fromCString = BS.packCString
+ src/System/Demangle.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+ Module : System.Demangle+ Description : Functions for demangling C++ names+ Stability : experimental+ Portability : wherever gcc lives++ This module provides bindings to the platform C++ ABI demangling routines+ (where the platform is currently limited to gcc). Any string-like type+ implementing 'CStringRepresentable' can be used, though strict bytestrings are+ the most performant.++ This module provides the raw 'IO'-living functions. Thin wrappers pretending+ to be pure live in the "System.Demangle.Pure" module.+ -}++module System.Demangle(demangle) where++import qualified Data.ByteString.Char8 as BS+import Control.Exception++import Foreign.C+import Foreign.Marshal.Alloc+import Foreign.Ptr++import Data.CStringRepresentable++foreign import ccall "__cxa_demangle"+ cxa_demangle :: CString -> CString -> Ptr CSize -> Ptr CInt -> IO CString++-- |Try to demangle a mangled C++ name.+demangle :: CStringRepresentable s => s -> IO (Maybe s)+demangle str = toCString str $ \str' ->+ bracket+ (cxa_demangle str' nullPtr nullPtr nullPtr)+ free+ $ \res ->+ if res == nullPtr+ then pure Nothing+ else do+ res' <- fromCString res+ pure $ Just res'
+ src/System/Demangle/Pure.hs view
@@ -0,0 +1,26 @@+{-|+ Module : System.Demangle.Pure+ Description : Functions for demangling C++ names pretending to be pure+ Stability : experimental+ Portability : wherever gcc lives++ This module provides bindings to the platform C++ ABI demangling routines+ (where the platform is currently limited to gcc). Any string-like type+ implementing 'CStringRepresentable' can be used, though strict bytestrings are+ the most performant.++ This module provides the pure-ish functions which hide the intrinsic 'IO'+ nature of doing FFI calls behind 'unsafePerformIO'. Demangling is+ referentially transparent, though, so that should be fine.+ -}++module System.Demangle.Pure where++import System.IO.Unsafe++import qualified System.Demangle as D+import Data.CStringRepresentable++-- |Try to demangle a mangled C++ name.+demangle :: CStringRepresentable s => s -> Maybe s+demangle = unsafePerformIO . D.demangle
+ test/Spec.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++import Test.Hspec++import qualified Data.ByteString.Char8 as BS+import Data.String+import Control.Monad++import qualified System.Demangle as D+import qualified System.Demangle.Pure as DP++import Data.CStringRepresentable++ioDemangledIs :: (Eq a, Show a, CStringRepresentable a) => a -> Maybe a -> IO ()+ioDemangledIs mangled ref = do+ res <- D.demangle mangled+ res `shouldBe` ref++pureDemangledIs :: (Eq a, Show a, CStringRepresentable a) => a -> Maybe a -> IO ()+pureDemangledIs mangled ref = DP.demangle mangled `shouldBe` ref++testData :: IsString a => [(String, [(a, Maybe a)])]+testData = [+ ("demangles simple class names", [+ ("_ZTS5IInfo", Just "typeinfo name for IInfo")+ ]),+ ("demangles some operators", [+ ("_ZrsR11QDataStreamR5QUuid", Just "operator>>(QDataStream&, QUuid&)")+ ]),+ ("demangle fails", [+ ("_test", Nothing)+ ])+ ]++runTests :: IsString a => (a -> Maybe a -> IO ()) -> SpecWith ()+runTests func =+ forM_ testData $ \(str, pairs) ->+ it str $ forM_ pairs $ uncurry func++main :: IO ()+main = hspec $ do+ describe "Strings" $ do+ describe "IO demangle" $ runTests @String ioDemangledIs+ describe "Pure demangle" $ runTests @String pureDemangledIs+ describe "ByteStrings" $ do+ describe "IO demangle" $ runTests @BS.ByteString ioDemangledIs+ describe "Pure demangle" $ runTests @BS.ByteString pureDemangledIs