summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-03-21 16:28:07 -0400
committerJoe Crayne <joe@jerkface.net>2019-03-21 16:28:07 -0400
commit9e1579d5074f895cce9ac4a32ea5b94c70e4b269 (patch)
treeb2450529c5a383f43aadc71b4fada0af41465fdb
parent9f4cfc458fbe6140ac2793a29068794bcd23883e (diff)
While parsing coments, use width 8 tabs.
-rw-r--r--Comments.hs31
-rw-r--r--GrepNested.hs93
-rw-r--r--monkeypatch.cabal2
-rw-r--r--monkeypatch.hs50
4 files changed, 137 insertions, 39 deletions
diff --git a/Comments.hs b/Comments.hs
deleted file mode 100644
index 25cd7de..0000000
--- a/Comments.hs
+++ /dev/null
@@ -1,31 +0,0 @@
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE LambdaCase #-}
3module Comments where
4
5import Control.Arrow
6
7parseComments :: (Num col, Num lin) => lin -> col -> [Char] -> [(lin, col, [Char])]
8parseComments !lin !col = \case
9 ('/':'*':cs) -> let (lcnt,col',bcnt) = findCloser 1 (0,col,0) cs
10 (xs,cs') = case drop (bcnt-2) cs of
11 '*':'/':_ -> second (drop 2) $ splitAt (bcnt-2) cs
12 _ -> splitAt bcnt cs
13 in mkComment lin col xs : parseComments (lin + lcnt) col' cs'
14 ('/':'/':cs) -> let (comment,ds) = break (=='\n') cs
15 in mkComment lin col comment : parseComments (lin + 1) 1 cs
16 ('\n' : cs) -> parseComments (lin+1) 1 cs
17 ( x : cs) -> parseComments lin (col+1) cs
18 [] -> []
19
20
21findCloser :: (Num a4, Num a3, Num a2, Num a1, Eq a1) =>
22 a1 -> (a4, a2, a3) -> [Char] -> (a4, a2, a3)
23findCloser !1 (l,c,b) ('*':'/':_) = (l,c+2,b+2)
24findCloser !d (l,c,b) ('*':'/':xs) = findCloser (d - 1) (l,c+2,b+2) xs
25findCloser !d (l,c,b) ('/':'*':xs) = findCloser (d + 1) (l,c+2,b+2) xs
26findCloser !d (l,c,b) ('\n':xs) = findCloser d (l+1,1,b+1) xs
27findCloser !d (l,c,b) (_:xs) = findCloser d (l,c+1,b+1) xs
28findCloser !d (l,c,b) [] = (l,c,b)
29
30mkComment :: a -> b -> c -> (a, b, c)
31mkComment lin no str = (lin,no,str)
diff --git a/GrepNested.hs b/GrepNested.hs
new file mode 100644
index 0000000..c62262f
--- /dev/null
+++ b/GrepNested.hs
@@ -0,0 +1,93 @@
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE OverloadedStrings #-}
4module GrepNested
5 ( grepCComments
6 , grepNested
7 , CommentProtocol(..)
8 , CommentToken(..)
9 ) where
10
11import Control.Arrow
12import Data.List
13import Data.String
14import qualified Data.ByteString.Lazy.Char8 as BL
15
16grepCComments :: Num a => a -> Int -> String -> [(a, Int, String)]
17grepCComments !lin !col = grepNested ccomments lin col
18
19data CommentToken = NullInput -- ^ Empty string.
20 | OpenNested -- ^ Open nested comment.
21 | CloseNested -- ^ Close nested comment.
22 | StartLine -- ^ Open line-comment.
23 | EOL -- ^ Close line-comment.
24 | IgnoredChar Int -- ^ Miscellaneous character. Argument is column width (e.g. 8 for tabs, 1 otherwise).
25
26data CommentProtocol a = CommentProtocol
27 { cmtToken :: a -> (CommentToken,Int,a)
28 , cmtSplitAt :: Int -> a -> (a,a)
29 }
30
31ccomments :: CommentProtocol String
32ccomments = CommentProtocol
33 { cmtToken = \case
34 [] -> (NullInput , 0 , "")
35 '/':'*':s -> (OpenNested , 2 , s)
36 '/':'/':s -> (StartLine , 2 , s)
37 '*':'/':s -> (CloseNested , 2 , s)
38 '\n':s -> (EOL , 1 , s)
39 '\t':s -> (IgnoredChar 8 , 1 , s)
40 _:s -> (IgnoredChar 1 , 1 , s)
41 , cmtSplitAt = splitAt
42 }
43
44ccommentsBL :: CommentProtocol BL.ByteString
45ccommentsBL = CommentProtocol
46 { cmtToken = \s ->
47 if BL.null s then (NullInput,0,s)
48 else if BL.isPrefixOf "/*" s then (OpenNested , 2, BL.drop 2 s)
49 else if BL.isPrefixOf "*/" s then (CloseNested , 2, BL.drop 2 s)
50 else if BL.isPrefixOf "//" s then (StartLine , 2, BL.drop 2 s)
51 else if BL.isPrefixOf "\n" s then (EOL , 1, BL.drop 1 s)
52 else (IgnoredChar (if BL.head s=='\t' then 8 else 1),1,BL.drop 1 s)
53 , cmtSplitAt = BL.splitAt . fromIntegral
54 }
55
56grepNested :: Num a =>
57 CommentProtocol c -> a -> Int -> c -> [(a, Int, c)]
58grepNested p !lin !col s = case cmtToken p s of
59 (OpenNested,tlen,cs)
60 -> let (lcnt,col',bcnt,clserlen) = findCloser p 1 (0,col,0) cs
61 (xs,cs') = case cmtSplitAt p (bcnt-clserlen) cs of
62 (s1,s2) | (CloseNested,l,s3) <- cmtToken p s2
63 -> (s1, snd . cmtSplitAt p clserlen $ s2)
64 _ -> cmtSplitAt p bcnt cs
65 in mkComment lin col xs : grepNested p (lin + lcnt) col' cs'
66 (StartLine,tlen,cs)
67 -> let findEOL !tot xs = case cmtToken p xs of
68 (EOL,tlen,_) -> tot
69 (tok,tlen,ys) -> findEOL (tot + tlen) ys
70 (comment,_) = cmtSplitAt p (findEOL 0 cs) cs
71 in mkComment lin col comment : grepNested p (lin + 1) 1 cs
72 (EOL,tlen,cs) -> grepNested p (lin+1) 1 cs
73 (NullInput,tlen,_) -> []
74 (IgnoredChar clen,_,cs) -> grepNested p lin (col+clen) cs
75
76
77findCloser :: Num lin => CommentProtocol t
78 -> Int -- ^ Nested comment depth, used by recursive calls, pass 1.
79 -> (lin, Int, Int) -- ^ Accumulated result.
80 -> t
81 -> (lin, Int, Int, Int) -- ^ (line,col,bytes,closer length)
82findCloser p !d (l,c,b) s = l `seq` c `seq` b `seq` case cmtToken p s of
83 (NullInput,tlen,_) -> (l,c,b,tlen)
84 (CloseNested,tlen,xs) -> if d==1 then (l,c+tlen,b+tlen,tlen)
85 else findCloser p (d - 1) (l,c+tlen,b+tlen) xs
86 (OpenNested,tlen,xs) -> findCloser p (d + 1) (l,c+tlen,b+tlen) xs
87 (EOL,tlen,xs) -> findCloser p d (l+1,1,b+tlen) xs
88 (IgnoredChar clen,tlen,xs) -> findCloser p d (l,c+clen,b+tlen) xs
89 (StartLine,tlen,xs) -> findCloser p d (l,c+tlen,b+tlen) xs
90
91
92mkComment :: a -> b -> c -> (a, b, c)
93mkComment lin no str = (lin,no,str)
diff --git a/monkeypatch.cabal b/monkeypatch.cabal
index ac31a6d..23bc405 100644
--- a/monkeypatch.cabal
+++ b/monkeypatch.cabal
@@ -52,7 +52,7 @@ extra-source-files: CHANGELOG.md
52 52
53executable monkeypatch 53executable monkeypatch
54 main-is: monkeypatch.hs 54 main-is: monkeypatch.hs
55 other-modules: Comments 55 other-modules: GrepNested
56 -- other-extensions: 56 -- other-extensions:
57 build-depends: base >=4.10.1.0 && <=4.12 57 build-depends: base >=4.10.1.0 && <=4.12
58 , containers ^>=0.5.10.2 58 , containers ^>=0.5.10.2
diff --git a/monkeypatch.hs b/monkeypatch.hs
index 461d3c1..ea97252 100644
--- a/monkeypatch.hs
+++ b/monkeypatch.hs
@@ -24,6 +24,7 @@ import qualified Data.IntMap as IntMap
24import qualified Data.Map as Map 24import qualified Data.Map as Map
25 ;import Data.Map (Map) 25 ;import Data.Map (Map)
26import Data.Maybe 26import Data.Maybe
27import Data.Ord
27import qualified Data.Set as Set 28import qualified Data.Set as Set
28 ;import Data.Set (Set) 29 ;import Data.Set (Set)
29import Language.C.Data.Ident as C 30import Language.C.Data.Ident as C
@@ -47,7 +48,7 @@ import Text.PrettyPrint (Doc, doubleQuotes, empty, text, vcat, ($$),
47 (<+>)) 48 (<+>))
48import Text.Show.Pretty 49import Text.Show.Pretty
49 50
50import Comments 51import GrepNested
51 52
52trace :: p -> a -> a 53trace :: p -> a -> a
53trace _ = id 54trace _ = id
@@ -480,6 +481,31 @@ isFunctionDecl _ = False
480cleanTree :: (Functor f, Data (f b)) => f b -> f Ordering 481cleanTree :: (Functor f, Data (f b)) => f b -> f Ordering
481cleanTree d = fmap (const LT) $ everywhere (mkT eraseNodeInfo) $ d 482cleanTree d = fmap (const LT) $ everywhere (mkT eraseNodeInfo) $ d
482 483
484
485data SymbolExtent = SymbolExtent { startExtent :: Position, stopExtent :: Position }
486
487instance Show SymbolExtent where
488 show (SymbolExtent a b) = "sed -n "++show al++","++show bl++"p "++fn
489 where
490 fn = posFile a
491 al = posRow a
492 bl = posRow b
493
494getSymbolExtent :: (CNode a1, Data a2) =>
495 SymbolInformation a2 -- ^ Symbol database record (symbolSource must have Postion data in it).
496 -> [a1] -- ^ function body (only used for filename)
497 -> SymbolExtent
498getSymbolExtent sym bdy =
499 -- TODO: This could probably be a lot more efficient using NodeInfo's PosLength field.
500 let bdy_poss = map (posOfNode . nodeInfo) bdy
501 -- hpos = map (posOfNode . nodeInfo) (symbolSource sym)
502 cmodule = map posFile (take 1 $ filter isSourcePos $ bdy_poss) -- TODO: What if first statement is provided by macro?
503 allposss = listify (\p -> case cmodule of { [f] | isSourcePos p -> posFile p == f ; _ -> isSourcePos p }) (symbolSource sym) :: [Position]
504 start = minimumBy (comparing posRow) allposss
505 stop = maximumBy (comparing posRow) allposss
506 in SymbolExtent start stop
507
508
483transpile :: C2HaskellOptions -> FilePath -> IncludeStack -> CTranslationUnit NodeInfo -> IO () 509transpile :: C2HaskellOptions -> FilePath -> IncludeStack -> CTranslationUnit NodeInfo -> IO ()
484transpile o fname incs (CTranslUnit edecls _) = do 510transpile o fname incs (CTranslUnit edecls _) = do
485 let db = foldr update initTranspile edecls 511 let db = foldr update initTranspile edecls
@@ -529,6 +555,15 @@ transpile o fname incs (CTranslUnit edecls _) = do
529 555
530 Nothing -> putStrLn $ "??: " ++ ppShow (cleanTree d) 556 Nothing -> putStrLn $ "??: " ++ ppShow (cleanTree d)
531 putStrLn "" 557 putStrLn ""
558 let extent = getSymbolExtent sym bdy
559 cs <- readComments (posFile $ startExtent extent)
560 let (pcs,cs') = seekComment (startExtent extent) cs
561 (cs'',ds) = seekComment (stopExtent extent) cs'
562 -- lineOfComment
563 forM_ cs' $ \(_,col,cmt) -> do
564 putStrLn ""
565 putStrLn $ replicate col ' ' ++ cmt
566 print extent
532 return () 567 return ()
533 568
534isHeaderDecl :: CNode a => a -> Bool 569isHeaderDecl :: CNode a => a -> Bool
@@ -895,8 +930,9 @@ enumCases (CDeclExt (CDecl xs _ ni)) = do
895lineOfComment :: (Int, b, String) -> Int 930lineOfComment :: (Int, b, String) -> Int
896lineOfComment (l,_,s) = l + length (lines s) 931lineOfComment (l,_,s) = l + length (lines s)
897 932
898seekComment :: NodeInfo -> [(Int,Int,String)] -> ([(Int,Int,String)],[(Int,Int,String)]) 933-- Break a comment list into comments preceding the given node and comments that come after it.
899seekComment ni cs = break (\c -> lineOfComment c>=posRow (posOfNode ni)) cs 934seekComment :: Position -> [(Int,Int,String)] -> ([(Int,Int,String)],[(Int,Int,String)])
935seekComment pos cs = break (\c -> lineOfComment c>=posRow pos) cs
900 936
901strip :: [Char] -> [Char] 937strip :: [Char] -> [Char]
902strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace 938strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace
@@ -955,13 +991,13 @@ c2haskell opts cs cmodname missings incs (CTranslUnit edecls _) = do
955 cs <- maybe (return []) readComments symfile 991 cs <- maybe (return []) readComments symfile
956 -- mapM_ (hPutStrLn haskmod . commented . ppShow) $ cs 992 -- mapM_ (hPutStrLn haskmod . commented . ppShow) $ cs
957 -- mapM_ (hPutStrLn haskmod . commented . ppShow) $ symbolSource si 993 -- mapM_ (hPutStrLn haskmod . commented . ppShow) $ symbolSource si
958 let (_,cs') = seekComment eni cs 994 let (_,cs') = seekComment (posOfNode eni) cs
959 forM_ (take 1 cs') $ \(_,c,s) -> 995 forM_ (take 1 cs') $ \(_,c,s) ->
960 when (c==1) $ hPutStr haskmod $ commented $ "| " ++ strip s 996 when (c==1) $ hPutStr haskmod $ commented $ "| " ++ strip s
961 hPutStrLn haskmod $ unwords ["newtype",t,"=",t,"CInt"] 997 hPutStrLn haskmod $ unwords ["newtype",t,"=",t,"CInt"]
962 forM_ (zip es [0..]) $ \((e,_),n) -> do 998 forM_ (zip es [0..]) $ \((e,_),n) -> do
963 let r = posRow . posOfNode . nodeInfo $ e 999 let r = posRow . posOfNode . nodeInfo $ e
964 case seekComment (nodeInfo e) cs' of 1000 case seekComment (posOfNode $ nodeInfo e) cs' of
965 (_,(lno,cno,s):_) | lno==r-1 && cno==1 1001 (_,(lno,cno,s):_) | lno==r-1 && cno==1
966 || cno>1 && lno == r 1002 || cno>1 && lno == r
967 -> hPutStr haskmod $ commented $ "| " ++ strip s 1003 -> hPutStr haskmod $ commented $ "| " ++ strip s
@@ -1356,8 +1392,8 @@ goMissing haskmod db cfun = do
1356 htyp -> hPutStr haskmod $ commented $ "Unsupported haskell type: " ++ HS.prettyPrint htyp 1392 htyp -> hPutStr haskmod $ commented $ "Unsupported haskell type: " ++ HS.prettyPrint htyp
1357 1393
1358 1394
1359readComments :: (Num lin, Num col) => FilePath -> IO [(lin, col, [Char])] 1395readComments :: Num lin => FilePath -> IO [(lin, Int, [Char])]
1360readComments fname = parseComments 1 1 <$> readFile fname 1396readComments fname = grepCComments 1 1 <$> readFile fname
1361 1397
1362sanitizeArgs :: [String] -> [String] 1398sanitizeArgs :: [String] -> [String]
1363sanitizeArgs (('-':'M':_):args) = sanitizeArgs args 1399sanitizeArgs (('-':'M':_):args) = sanitizeArgs args