diff options
author | joe <joe@jerkface.net> | 2018-03-13 16:33:54 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2018-03-13 16:33:54 -0400 |
commit | 0f917b68b3a81bb4d79bc2954a01588558f12f63 (patch) | |
tree | 4c1d151aed360972988614217d1bd99955dc7812 | |
parent | 3d3327ffa257b7b58e6d5c4b83a13d55071720a4 (diff) |
NetSurf efforts
-rw-r--r-- | c2haskell.hs | 453 |
1 files changed, 294 insertions, 159 deletions
diff --git a/c2haskell.hs b/c2haskell.hs index 8397f98..03ba9cd 100644 --- a/c2haskell.hs +++ b/c2haskell.hs | |||
@@ -1,169 +1,304 @@ | |||
1 | {-# LANGUAGE BangPatterns #-} | ||
2 | {-# LANGUAGE FlexibleContexts #-} | ||
3 | {-# LANGUAGE LambdaCase #-} | ||
4 | {-# LANGUAGE NondecreasingIndentation #-} | ||
5 | {-# LANGUAGE QuasiQuotes #-} | ||
6 | {-# LANGUAGE TemplateHaskell #-} | ||
1 | 7 | ||
2 | import Language.C | 8 | import Data.Generics.Aliases |
9 | import Data.Generics.Schemes | ||
10 | import Debug.Trace | ||
11 | import Control.Monad | ||
12 | import Data.Char | ||
13 | import Data.Data | ||
14 | import Data.List | ||
15 | import qualified Data.Map as Map | ||
16 | ;import Data.Map (Map) | ||
17 | import Data.Maybe | ||
18 | import qualified Data.Set as Set | ||
19 | ;import Data.Set (Set) | ||
20 | import Language.C.Data.Ident as C | ||
21 | import Language.C as C hiding (prettyUsingInclude) | ||
3 | import Language.C.System.GCC | 22 | import Language.C.System.GCC |
23 | import Language.Haskell.Exts.Pretty as HS | ||
24 | import Language.Haskell.Exts.Syntax as HS | ||
25 | import Language.Haskell.TH | ||
26 | import Language.Haskell.TH.Ppr | ||
27 | import Language.Haskell.TH.Syntax as TH | ||
4 | import System.Environment | 28 | import System.Environment |
5 | import System.IO | 29 | import System.IO |
30 | import Text.PrettyPrint (Doc, doubleQuotes, empty, text, vcat, ($$), | ||
31 | (<+>)) | ||
32 | import Text.Show.Pretty | ||
6 | 33 | ||
7 | hack_incs = [ "-I." ] | 34 | -- | Pretty print the given tranlation unit, but replace declarations from header files with @#include@ directives. |
8 | 35 | -- | |
9 | -- pkg-config --cflags clutter-1.0 | 36 | -- The resulting file may not compile (because of missing @#define@ directives and similar things), but is very useful |
10 | clutter_incs = | 37 | -- for testing, as otherwise the pretty printed file will be cluttered with declarations from system headers. |
11 | [ "-pthread" | 38 | prettyUsingInclude :: CTranslUnit -> Doc |
12 | , "-I/usr/include/clutter-1.0" | 39 | prettyUsingInclude (CTranslUnit edecls _) = |
13 | , "-I/usr/include/cogl" | 40 | includeWarning headerFiles |
14 | , "-I/usr/include/atk-1.0" | 41 | $$ |
15 | , "-I/usr/include/cogl" | 42 | vcat (map (either includeHeader pretty) mappedDecls) |
16 | , "-I/usr/include/libdrm" | 43 | where |
17 | , "-I/usr/include/json-glib-1.0" | 44 | (headerFiles,mappedDecls) = foldr (addDecl . tagIncludedDecls) (Set.empty,[]) edecls |
18 | , "-I/usr/include/gtk-3.0" | 45 | tagIncludedDecls edecl | maybe False isHeaderFile (fileOfNode edecl) = Left ((posFile . posOf) edecl) |
19 | , "-I/usr/include/gio-unix-2.0/" | 46 | | otherwise = Right edecl |
20 | , "-I/usr/include/cairo" | 47 | addDecl decl@(Left headerRef) (headerSet, ds) |
21 | , "-I/usr/include/pango-1.0" | 48 | | Set.member headerRef headerSet = (headerSet, ds) |
22 | , "-I/usr/include/harfbuzz" | 49 | | otherwise = (Set.insert headerRef headerSet, decl : ds) |
23 | , "-I/usr/include/pango-1.0" | 50 | addDecl decl (headerSet,ds) = (headerSet, decl : ds) |
24 | , "-I/usr/include/gdk-pixbuf-2.0" | 51 | includeHeader hFile = text "#include" <+> doubleQuotes (text hFile) |
25 | , "-I/usr/include/libpng16" | 52 | isHeaderFile = (".h" `isSuffixOf`) |
26 | , "-I/usr/include/cairo" | 53 | includeWarning hs | Set.null hs = empty |
27 | , "-I/usr/include/pixman-1" | 54 | | otherwise = text "/* Warning: The #include directives in this file aren't necessarily correct. */" |
28 | , "-I/usr/include/freetype2" | ||
29 | , "-I/usr/include/libpng16" | ||
30 | , "-I/usr/include/glib-2.0" | ||
31 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
32 | ] | ||
33 | |||
34 | |||
35 | -- pkg-config --cflags cogl-pango-2.0-experimental | ||
36 | cogl_pango2_incs = | ||
37 | [ "-D COGL_ENABLE_EXPERIMENTAL_2_0_API" | ||
38 | , "-pthread" | ||
39 | , "-I/usr/include/cogl" | ||
40 | , "-I/usr/include/cairo" | ||
41 | , "-I/usr/include/pixman-1" | ||
42 | , "-I/usr/include/freetype2" | ||
43 | , "-I/usr/include/libpng16" | ||
44 | , "-I/usr/include/gdk-pixbuf-2.0" | ||
45 | , "-I/usr/include/libpng16" | ||
46 | , "-I/usr/include/glib-2.0" | ||
47 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
48 | , "-I/usr/include/libdrm" | ||
49 | ] | ||
50 | |||
51 | |||
52 | -- pkg-config cogl-pango-1.0 --cflags | ||
53 | cogl_pango_incs = | ||
54 | [ "-pthread" | ||
55 | , "-I/usr/include/cogl" | ||
56 | , "-I/usr/include/cairo" | ||
57 | , "-I/usr/include/pixman-1" | ||
58 | , "-I/usr/include/freetype2" | ||
59 | , "-I/usr/include/libpng16" | ||
60 | , "-I/usr/include/gdk-pixbuf-2.0" | ||
61 | , "-I/usr/include/libpng16" | ||
62 | , "-I/usr/include/glib-2.0" | ||
63 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
64 | , "-I/usr/include/libdrm" ] | ||
65 | |||
66 | -- pkg-config gtk+-3.0 --cflags | ||
67 | gtk_incs = | ||
68 | [ "-pthread" | ||
69 | , "-I/usr/include/gtk-3.0" | ||
70 | , "-I/usr/include/at-spi2-atk/2.0" | ||
71 | , "-I/usr/include/at-spi-2.0" | ||
72 | , "-I/usr/include/dbus-1.0" | ||
73 | , "-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include" | ||
74 | , "-I/usr/include/gtk-3.0" | ||
75 | , "-I/usr/include/gio-unix-2.0/" | ||
76 | , "-I/usr/include/cairo" | ||
77 | , "-I/usr/include/pango-1.0" | ||
78 | , "-I/usr/include/harfbuzz" | ||
79 | , "-I/usr/include/pango-1.0" | ||
80 | , "-I/usr/include/atk-1.0" | ||
81 | , "-I/usr/include/cairo" | ||
82 | , "-I/usr/include/pixman-1" | ||
83 | , "-I/usr/include/freetype2" | ||
84 | , "-I/usr/include/libpng16" | ||
85 | , "-I/usr/include/gdk-pixbuf-2.0" | ||
86 | , "-I/usr/include/libpng16" | ||
87 | , "-I/usr/include/glib-2.0" | ||
88 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
89 | ] | ||
90 | |||
91 | -- pkg-config --cflags gobject-introspection-1.0 | ||
92 | gobj_incs = | ||
93 | [ "-pthread" | ||
94 | , "-I/usr/include/gobject-introspection-1.0" | ||
95 | , "-I/usr/include/glib-2.0" | ||
96 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
97 | ] | ||
98 | |||
99 | -- pkg-config --cflags libmutter-1 | ||
100 | mutter_incs = | ||
101 | [ "-pthread" | ||
102 | , "-I/usr/include/mutter" | ||
103 | , "-I/usr/include/gtk-3.0" | ||
104 | , "-I/usr/include/at-spi2-atk/2.0" | ||
105 | , "-I/usr/include/at-spi-2.0" | ||
106 | , "-I/usr/include/dbus-1.0" | ||
107 | , "-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include" | ||
108 | , "-I/usr/include/gtk-3.0" | ||
109 | , "-I/usr/include/gio-unix-2.0/" | ||
110 | , "-I/usr/include/cairo" | ||
111 | , "-I/usr/include/mutter/clutter-1" | ||
112 | , "-I/usr/include/cairo" | ||
113 | , "-I/usr/include/atk-1.0" | ||
114 | , "-I/usr/include/pango-1.0" | ||
115 | , "-I/usr/include/harfbuzz" | ||
116 | , "-I/usr/include/pango-1.0" | ||
117 | , "-I/usr/include/json-glib-1.0" | ||
118 | , "-I/usr/include/mutter/cogl" | ||
119 | , "-I/usr/include/cairo" | ||
120 | , "-I/usr/include/pixman-1" | ||
121 | , "-I/usr/include/freetype2" | ||
122 | , "-I/usr/include/libpng16" | ||
123 | , "-I/usr/include/gdk-pixbuf-2.0" | ||
124 | , "-I/usr/include/libpng16" | ||
125 | , "-I/usr/include/glib-2.0" | ||
126 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
127 | , "-I/usr/include/libdrm" | ||
128 | , "-I/usr/include/gsettings-desktop-schemas" | ||
129 | ] | ||
130 | |||
131 | -- pkg-config --cflags gjs-1.0 | ||
132 | gjs_incs = | ||
133 | [ "-pthread" | ||
134 | , "-include" | ||
135 | , "/usr/include/mozjs-52/js/RequiredDefines.h" | ||
136 | , "-pthread" | ||
137 | , "-I/usr/include/gobject-introspection-1.0" | ||
138 | , "-I/usr/include/mozjs-52" | ||
139 | , "-I/usr/include/gtk-3.0" | ||
140 | , "-I/usr/include/at-spi2-atk/2.0" | ||
141 | , "-I/usr/include/at-spi-2.0" | ||
142 | , "-I/usr/include/dbus-1.0" | ||
143 | , "-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include" | ||
144 | , "-I/usr/include/gtk-3.0" | ||
145 | , "-I/usr/include/gio-unix-2.0/" | ||
146 | , "-I/usr/include/cairo" | ||
147 | , "-I/usr/include/pango-1.0" | ||
148 | , "-I/usr/include/harfbuzz" | ||
149 | , "-I/usr/include/pango-1.0" | ||
150 | , "-I/usr/include/atk-1.0" | ||
151 | , "-I/usr/include/cairo" | ||
152 | , "-I/usr/include/pixman-1" | ||
153 | , "-I/usr/include/freetype2" | ||
154 | , "-I/usr/include/libpng16" | ||
155 | , "-I/usr/include/gdk-pixbuf-2.0" | ||
156 | , "-I/usr/include/libpng16" | ||
157 | , "-I/usr/include/glib-2.0" | ||
158 | , "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include" | ||
159 | , "-I/usr/include/gjs-1.0" | ||
160 | ] | ||
161 | 55 | ||
56 | specs :: CExternalDeclaration a -> [CDeclarationSpecifier a] | ||
57 | specs (CFDefExt (CFunDef specs _ _ _ _)) = specs | ||
58 | specs (CDeclExt (CDecl specs _ _)) = specs | ||
59 | specs _ = [] | ||
162 | 60 | ||
61 | declrSym :: CDeclarator t -> Maybe Ident | ||
62 | declrSym (CDeclr m _ _ _ _) = m | ||
63 | |||
64 | sym :: CExternalDeclaration a -> [Maybe Ident] | ||
65 | sym (CFDefExt (CFunDef specs m _ _ _)) = [ declrSym m ] | ||
66 | sym (CDeclExt (CDecl specs ms _)) = ms >>= \(m,_,_) -> maybe [] (pure . declrSym) m | ||
67 | sym _ = [] | ||
68 | |||
69 | isStatic :: CDeclarationSpecifier a -> Bool | ||
70 | isStatic (CStorageSpec (CStatic _)) = True | ||
71 | isStatic _ = False | ||
72 | |||
73 | capitalize :: String -> String | ||
74 | capitalize xs = concatMap (cap . drop 1) gs | ||
75 | where | ||
76 | gs = groupBy (\a b -> b/='_') $ '_':xs | ||
77 | cap (c:cs) = toUpper c : cs | ||
78 | |||
79 | transField :: CDeclaration t -> [(TH.Name, TH.Bang, TH.Type)] | ||
80 | transField (CDecl [CTypeSpec (CTypeDef ctyp _)] vars _) | ||
81 | = do | ||
82 | let typname = mkName . capitalize . identToString $ ctyp | ||
83 | (var,Nothing,Nothing) <- vars | ||
84 | CDeclr (Just fident) ptrdeclr Nothing [] _ <- maybeToList var | ||
85 | let fieldName = mkName $ identToString fident | ||
86 | ftyp = case ptrdeclr of | ||
87 | [] -> ConT typname | ||
88 | [CPtrDeclr [] _] -> AppT (ConT (mkName "Ptr")) (ConT typname) | ||
89 | [ (fieldName, Bang NoSourceUnpackedness NoSourceStrictness, ftyp) ] | ||
90 | transField (CDecl [CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)] vars _) | ||
91 | | Just typname <- mkName . capitalize . identToString <$> mctyp | ||
92 | = do | ||
93 | (var,Nothing,Nothing) <- vars | ||
94 | CDeclr (Just fident) ptrdeclr Nothing [] _ <- maybeToList var | ||
95 | let fieldName = mkName $ identToString fident | ||
96 | ftyp = case ptrdeclr of | ||
97 | [] -> ConT typname | ||
98 | [CPtrDeclr [] _] -> AppT (ConT (mkName "Ptr")) (ConT typname) | ||
99 | [ (fieldName, Bang NoSourceUnpackedness NoSourceStrictness, ftyp) ] | ||
100 | |||
101 | |||
102 | transField _ = [] | ||
103 | |||
104 | transpile (CDeclExt (CDecl [ CTypeSpec (CSUType | ||
105 | (CStruct CStructTag mbIdent (Just fields) [] _) | ||
106 | _) ] | ||
107 | [] | ||
108 | _) ) | ||
109 | | Just struct_name <- capitalize . identToString <$> mbIdent | ||
110 | , let typ = mkName struct_name | ||
111 | = Just $ returnQ $ DataD [] typ [] Nothing [RecC typ fs] [] | ||
112 | where fs = fields >>= transField | ||
113 | |||
114 | transpile _ = Nothing | ||
115 | |||
116 | |||
117 | isHeaderDecl :: CNode a => a -> Bool | ||
118 | isHeaderDecl = maybe False (isSuffixOf ".h") . fileOfNode | ||
119 | |||
120 | -- bar :: CExternalDeclaration NodeInfo -> () | ||
121 | -- bar (CDeclExt (CDecl xs [] (NodeInfo pos poslen name))) = () | ||
122 | |||
123 | data SymbolInformation c = SymbolInformation | ||
124 | { symbolLocal :: Bool | ||
125 | , symbolStatic :: Bool | ||
126 | , symbolSource :: c | ||
127 | } | ||
128 | deriving (Eq,Ord,Show) | ||
129 | |||
130 | symbolInformation = SymbolInformation | ||
131 | { symbolLocal = False | ||
132 | , symbolStatic = False | ||
133 | , symbolSource = mempty | ||
134 | } | ||
135 | |||
136 | data Transpile c = Transpile | ||
137 | { syms :: Map String (SymbolInformation c) | ||
138 | } | ||
139 | |||
140 | initTranspile = Transpile | ||
141 | { syms = Map.empty | ||
142 | } | ||
143 | |||
144 | -- grokSymbol :: CExternalDeclaration a -> String -> Maybe SymbolInformation -> Maybe SymbolInformation | ||
145 | grokSymbol d k msi = | ||
146 | let si = fromMaybe symbolInformation msi | ||
147 | in Just $ si | ||
148 | { symbolLocal = symbolLocal si || not (isHeaderDecl d) | ||
149 | , symbolStatic = symbolStatic si || any isStatic (specs d) | ||
150 | , symbolSource = d : symbolSource si | ||
151 | } | ||
152 | |||
153 | -- update :: CExternalDeclaration a -> Transpile -> Transpile | ||
154 | update d transpile = transpile | ||
155 | { syms = foldr (\k m -> Map.alter (grokSymbol d k) k m) (syms transpile) | ||
156 | $ map (maybe "" identToString) $ sym d | ||
157 | } | ||
158 | |||
159 | data FunctionSignature t = FunctionSignature | ||
160 | { funReturnType :: t | ||
161 | , funArgTypes :: [t] | ||
162 | } | ||
163 | |||
164 | hsMkName :: String -> HS.QName () | ||
165 | hsMkName str = HS.UnQual () (foo () str) | ||
166 | where | ||
167 | foo = HS.Ident -- alternative: HS.Symbol | ||
168 | |||
169 | hsTypeSpec :: CDeclarationSpecifier t -> [String] | ||
170 | hsTypeSpec (CTypeSpec (CTypeDef ctyp _)) = [capitalize . identToString $ ctyp] | ||
171 | hsTypeSpec (CTypeSpec (CBoolType _)) = ["Bool"] | ||
172 | hsTypeSpec (CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)) = maybeToList $ fmap (capitalize . identToString) mctyp | ||
173 | hsTypeSpec _ = [] | ||
174 | |||
175 | -- hsTransField :: [CDeclarationSpecifier t3] -> [(Maybe (CDeclarator t2), Maybe t1, Maybe t)] -> [HS.Decl ()] | ||
176 | hsTransField ctyps vars | ||
177 | = do | ||
178 | typname <- hsMkName <$> (hsTypeSpec =<< ctyps) | ||
179 | (var,Nothing,Nothing) <- vars | ||
180 | CDeclr (Just fident) ptrdeclr Nothing [] _ <- maybeToList var | ||
181 | let btyp = HS.TyCon () typname | ||
182 | grok bs b = case bs of | ||
183 | [] -> b | ||
184 | (CPtrDeclr [] _:cs) -> HS.TyApp () (HS.TyCon () (hsMkName "Ptr")) (grok cs b) | ||
185 | [CFunDeclr (Right (args,flg)) attrs _] -> let (as,ts) = unzip $ concatMap (\(CDecl rs as _) -> hsTransField rs as) args | ||
186 | in foldr (HS.TyFun ()) b ts | ||
187 | _ -> HS.TyCon () (hsMkName $ show $ map (fmap (const ())) ptrdeclr) | ||
188 | ftyp = grok ptrdeclr btyp | ||
189 | fieldName = identToString fident | ||
190 | [ ( fieldName, ftyp ) ] | ||
191 | {- | ||
192 | transField (CDecl [CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)] vars _) | ||
193 | | Just typname <- mkName . capitalize . identToString <$> mctyp | ||
194 | = do | ||
195 | (var,Nothing,Nothing) <- vars | ||
196 | CDeclr (Just fident) ptrdeclr Nothing [] _ <- maybeToList var | ||
197 | let fieldName = mkName $ identToString fident | ||
198 | ftyp = case ptrdeclr of | ||
199 | [] -> ConT typname | ||
200 | [CPtrDeclr [] _] -> AppT (ConT (mkName "Ptr")) (ConT typname) | ||
201 | [ (fieldName, Bang NoSourceUnpackedness NoSourceStrictness, ftyp) ] | ||
202 | hsTransField _ _ = [] | ||
203 | -} | ||
204 | |||
205 | hsTransFieldExt rs as = concatMap (\(fieldName,ftyp)-> [ HS.TypeSig () [ HS.Ident () fieldName ] ftyp ]) | ||
206 | $ hsTransField rs as | ||
207 | |||
208 | sig (CDeclExt (CDecl rs as _)) = hsTransFieldExt rs as | ||
209 | sig (CFDefExt (CFunDef rs cdeclr [] bdy _)) = hsTransFieldExt rs [(Just cdeclr, Nothing, Nothing)] | ||
210 | |||
211 | body0 (CFDefExt (CFunDef rs cdeclr [] bdy _)) = Just bdy | ||
212 | body0 _ = Nothing | ||
213 | |||
214 | body (CFDefExt (CFunDef rs cdeclr [] (CCompound [] bdy _) _)) = bdy | ||
215 | body _ = [] | ||
216 | |||
217 | data SideEffect = PointerWrite | FunctionCall | ||
218 | |||
219 | calls :: Data t => t -> [CExpression NodeInfo] | ||
220 | calls = everything (++) (mkQ [] (\case { cc@C.CCall {} -> [cc] ; _ -> [] })) | ||
221 | |||
222 | mutations1 e@(CAssign {}) = [e] | ||
223 | mutations1 e@(CUnary CPreIncOp _ _) = [e] | ||
224 | mutations1 e@(CUnary CPreDecOp _ _) = [e] | ||
225 | mutations1 e@(CUnary CPostIncOp _ _) = [e] | ||
226 | mutations1 e@(CUnary CPostDecOp _ _) = [e] | ||
227 | mutations1 _ = [] | ||
228 | |||
229 | mutations :: Data t => t -> [CExpression NodeInfo] | ||
230 | mutations = everything (++) (mkQ [] mutations1) | ||
231 | |||
232 | |||
233 | -- gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> a -> c a | ||
234 | -- | ||
235 | -- gfoldl app con | ||
236 | -- | ||
237 | -- does is to turn such a value into | ||
238 | -- | ||
239 | -- con C `app` x_1 `app` x_2 ... `app` x_n | ||
240 | |||
241 | |||
242 | commented :: String -> String | ||
243 | commented s = unlines $ map ("-- " ++) (lines s) | ||
244 | |||
245 | c2haskell cs (CTranslUnit edecls _) = do | ||
246 | let db = foldr update initTranspile edecls | ||
247 | es = Map.filter (\d -> symbolLocal d && not (symbolStatic d)) (syms db) | ||
248 | forM_ (Map.toList es) $ \(k,si) -> do | ||
249 | putStrLn "" | ||
250 | putStrLn (commented k) | ||
251 | forM_ (symbolSource si) $ \d -> do | ||
252 | putStr $ commented (ppShow (fmap (const ()) d)) | ||
253 | putStr $ commented (show $ pretty d) | ||
254 | mapM_ (putStrLn . HS.prettyPrint) (sig d) | ||
255 | {- | ||
256 | forM_ (body d) $ \stmt -> do | ||
257 | putStr $ commented (take 130 $ show (fmap (const ()) stmt)) | ||
258 | putStr $ commented (ppShow (fmap (const ()) stmt)) | ||
259 | putStrLn $ commented . show . pretty $ stmt | ||
260 | putStr $ commented "calls" | ||
261 | mapM_ (putStr . commented . show . pretty) (calls (body d)) | ||
262 | putStrLn "--" | ||
263 | putStr $ commented "mutations" | ||
264 | mapM_ (putStr . commented . show . pretty) (mutations (body d)) | ||
265 | -} | ||
266 | |||
267 | readComments fname = parseComments 1 1 <$> readFile fname | ||
268 | |||
269 | findCloser !1 (l,c,b) ('*':'/':_) = (l,c+2,b+2) | ||
270 | findCloser !d (l,c,b) ('*':'/':xs) = findCloser (d - 1) (l,c+2,b+2) xs | ||
271 | findCloser !d (l,c,b) ('/':'*':xs) = findCloser (d + 1) (l,c+2,b+2) xs | ||
272 | findCloser !d (l,c,b) ('\n':xs) = findCloser d (l+1,1,b+1) xs | ||
273 | findCloser !d (l,c,b) (_:xs) = findCloser d (l,c+1,b+1) xs | ||
274 | findCloser !d (l,c,b) [] = (l,c,b) | ||
275 | |||
276 | mkComment lin no str = (lin,no,str) | ||
277 | |||
278 | parseComments !lin !col = \case | ||
279 | ('/':'*':cs) -> let (lcnt,col',bcnt) = findCloser 1 (0,col,0) cs | ||
280 | (xs,cs') = splitAt bcnt cs | ||
281 | in mkComment lin col xs : parseComments (lin + lcnt) col' cs' | ||
282 | ('/':'/':cs) -> let (comment,ds) = break (=='\n') cs | ||
283 | in mkComment lin col comment : parseComments (lin + 1) 1 cs | ||
284 | ('\n' : cs) -> parseComments (lin+1) 1 cs | ||
285 | ( x : cs) -> parseComments lin (col+1) cs | ||
286 | [] -> [] | ||
287 | |||
288 | sanitizeArgs :: [String] -> [String] | ||
289 | sanitizeArgs (('-':'M':_):args) = sanitizeArgs args | ||
290 | sanitizeArgs (('-':'O':_):args) = sanitizeArgs args | ||
291 | sanitizeArgs (('-':'c':_):args) = sanitizeArgs args | ||
292 | sanitizeArgs ("-o":args) = sanitizeArgs $ drop 1 args | ||
293 | sanitizeArgs (arg:args) = arg : sanitizeArgs args | ||
294 | sanitizeArgs [] = [] | ||
295 | |||
296 | main :: IO () | ||
163 | main = do | 297 | main = do |
164 | args <- getArgs | 298 | args <- getArgs |
165 | let fname = last args | 299 | let fname = last args |
166 | opts = ["-DGETTEXT_PACKAGE=c2haskell"] ++ init args | 300 | opts = init args |
167 | incs = "-I." : gjs_incs ++ gobj_incs ++ mutter_incs ++ clutter_incs ++ cogl_pango2_incs ++ gtk_incs | 301 | r <- parseCFile (newGCC "gcc") Nothing (sanitizeArgs opts) fname |
168 | r <- parseCFile (newGCC "gcc") Nothing (incs ++ opts) fname | 302 | -- print (fmap prettyUsingInclude r) |
169 | print (fmap prettyUsingInclude r) | 303 | cs <- readComments fname |
304 | either print (c2haskell cs) r | ||