summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-11-22 21:14:09 -0500
committerJoe Crayne <joe@jerkface.net>2018-11-22 21:14:09 -0500
commitdf1bd7353b41f4c4214b77934085889b84be8839 (patch)
tree754af1fa973def4535c3947b7523ed193d0e49ea
parentac87e9c2b4d5526ceb3a952998cc784dc9e47496 (diff)
Use parsed include stack for for pretty-printed C.
-rw-r--r--c2haskell.hs58
1 files changed, 40 insertions, 18 deletions
diff --git a/c2haskell.hs b/c2haskell.hs
index cc590c3..48b30e3 100644
--- a/c2haskell.hs
+++ b/c2haskell.hs
@@ -7,6 +7,7 @@
7{-# LANGUAGE QuasiQuotes #-} 7{-# LANGUAGE QuasiQuotes #-}
8{-# LANGUAGE TemplateHaskell #-} 8{-# LANGUAGE TemplateHaskell #-}
9 9
10import Control.Arrow (left)
10import Data.Generics.Aliases 11import Data.Generics.Aliases
11import Data.Generics.Schemes 12import Data.Generics.Schemes
12-- import Debug.Trace 13-- import Debug.Trace
@@ -48,23 +49,38 @@ trace _ = id
48-- 49--
49-- The resulting file may not compile (because of missing @#define@ directives and similar things), but is very useful 50-- The resulting file may not compile (because of missing @#define@ directives and similar things), but is very useful
50-- for testing, as otherwise the pretty printed file will be cluttered with declarations from system headers. 51-- for testing, as otherwise the pretty printed file will be cluttered with declarations from system headers.
51prettyUsingInclude :: CTranslUnit -> Doc 52prettyUsingInclude :: IncludeStack -> CTranslUnit -> Doc
52prettyUsingInclude (CTranslUnit edecls _) = 53prettyUsingInclude incs (CTranslUnit edecls _) =
53 includeWarning headerFiles 54 vcat (map (either includeHeader pretty) $ sortBy sysfst mappedDecls)
54 $$
55 vcat (map (either includeHeader pretty) mappedDecls)
56 where 55 where
57 (headerFiles,mappedDecls) = foldr (addDecl . tagIncludedDecls) (Set.empty,[]) edecls 56 (headerFiles,mappedDecls) = foldr (addDecl . tagIncludedDecls) (Set.empty,[]) edecls
58 tagIncludedDecls edecl | maybe False isHeaderFile (fileOfNode edecl) = Left ((posFile . posOf) edecl) 57 tagIncludedDecls edecl | maybe False isHeaderFile (fileOfNode edecl) = Left ((includeTopLevel incs . posFile . posOf) edecl)
59 | otherwise = Right edecl 58 | otherwise = Right edecl
60 addDecl decl@(Left headerRef) (headerSet, ds) 59 addDecl decl@(Left headerRef) (headerSet, ds)
61 | Set.member headerRef headerSet = (headerSet, ds) 60 | null headerRef || Set.member headerRef headerSet
62 | otherwise = (Set.insert headerRef headerSet, decl : ds) 61 = (headerSet, ds)
62 | otherwise = (Set.insert headerRef headerSet, decl : ds)
63 addDecl decl (headerSet,ds) = (headerSet, decl : ds) 63 addDecl decl (headerSet,ds) = (headerSet, decl : ds)
64 includeHeader hFile = text "#include" <+> doubleQuotes (text hFile) 64
65 includeHeader hFile = text "#include" <+> text hFile
65 isHeaderFile = (".h" `isSuffixOf`) 66 isHeaderFile = (".h" `isSuffixOf`)
66 includeWarning hs | Set.null hs = empty 67
67 | otherwise = text "/* Warning: The #include directives in this file aren't necessarily correct. */" 68 sysfst (Left ('"':a)) (Left ('<':b)) = Prelude.GT
69 sysfst (Left a) (Left b) = trace (show (a,b)) $ Prelude.GT
70 sysfst _ _ = Prelude.LT
71
72
73includeTopLevel (IncludeStack incs) f = do
74 stacks <- maybeToList $ Map.lookup f incs
75 stack <- take 1 stacks
76 top <- take 1 $ drop 4 $ reverse stack
77 if take 1 top == "/"
78 then let ws = groupBy (\_ c -> c /='/') top
79 (xs,ys) = break (=="/include") ws
80 ys' = drop 1 ys
81 in if not (null ys') then '<': drop 1 (concat ys') ++ ">"
82 else '"':top++"\""
83 else '"':top ++"\""
68 84
69specs :: CExternalDeclaration a -> [CDeclarationSpecifier a] 85specs :: CExternalDeclaration a -> [CDeclarationSpecifier a]
70specs (CFDefExt (CFunDef ss _ _ _ _)) = ss 86specs (CFDefExt (CFunDef ss _ _ _ _)) = ss
@@ -397,7 +413,10 @@ makeAcceptableImport (HS.TyFun a (TyCon c (UnQual d (HS.Ident e x))) xs)
397makeAcceptableImport t = t 413makeAcceptableImport t = t
398 414
399-- c2haskell :: Foldable t => C2HaskellOptions -> p -> t String -> CTranslationUnit NodeInfo -> IO () 415-- c2haskell :: Foldable t => C2HaskellOptions -> p -> t String -> CTranslationUnit NodeInfo -> IO ()
400c2haskell opts cs missings (CTranslUnit edecls _) = do 416c2haskell :: Foldable t =>
417 C2HaskellOptions
418 -> p1 -> t String -> IncludeStack -> CTranslationUnit NodeInfo -> IO ()
419c2haskell opts cs missings incs (CTranslUnit edecls _) = do
401 let db = foldr update initTranspile edecls 420 let db = foldr update initTranspile edecls
402 es = Map.filter (\d -> symbolLocal d && not (symbolStatic d)) (syms db) 421 es = Map.filter (\d -> symbolLocal d && not (symbolStatic d)) (syms db)
403 case selectFunction opts of 422 case selectFunction opts of
@@ -824,21 +843,24 @@ main = do
824 let usageString = self ++ " [-v] [-p] [-f <sym>] -- [gcc options] <cfile>" 843 let usageString = self ++ " [-v] [-p] [-f <sym>] -- [gcc options] <cfile>"
825 let m = usage args 844 let m = usage args
826 fromMaybe (putStrLn usageString) $ m <&> \(hopts,cargs,fname) -> do 845 fromMaybe (putStrLn usageString) $ m <&> \(hopts,cargs,fname) -> do
827 r <- parseCFile (newGCC "gcc") Nothing cargs fname 846 prer <- runPreprocessor (newGCC "gcc") (rawCppArgs cargs fname)
847 let r = do
848 pre <- left Left $ prer
849 c <- left Right $ parseC pre (initPos fname)
850 return (includeStack pre,c)
828 cs <- readComments fname 851 cs <- readComments fname
829 case () of 852 case () of
830 _ | preprocess hopts -- --cpp 853 _ | preprocess hopts -- --cpp
831 -> do 854 -> do
832 r2 <- runPreprocessor (newGCC "gcc") (rawCppArgs cargs fname) 855 case prer of
833 case r2 of
834 Left e -> print e 856 Left e -> print e
835 Right bs -> putStrLn $ ppShow $ includeStack $ bs 857 Right bs -> putStrLn $ ppShow $ includeStack $ bs
836 _ | prettyC hopts -- -p 858 _ | prettyC hopts -- -p
837 -> do 859 -> do
838 print (fmap prettyUsingInclude r) 860 print (fmap (\(incs,decls) -> prettyUsingInclude incs decls) r)
839 _ | prettyTree hopts -- -t 861 _ | prettyTree hopts -- -t
840 -> do 862 -> do
841 putStrLn $ ppShow $ everywhere (mkT eraseNodeInfo) <$> r 863 putStrLn $ ppShow $ everywhere (mkT eraseNodeInfo) . snd <$> r
842 _ -> do 864 _ -> do
843 syms <- linker cargs fname 865 syms <- linker cargs fname
844 either print (c2haskell hopts cs syms) r 866 either print (uncurry $ c2haskell hopts cs syms) r