summaryrefslogtreecommitdiff
path: root/lib/Numeric/GSL/Special/auto.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric/GSL/Special/auto.hs')
-rw-r--r--lib/Numeric/GSL/Special/auto.hs233
1 files changed, 233 insertions, 0 deletions
diff --git a/lib/Numeric/GSL/Special/auto.hs b/lib/Numeric/GSL/Special/auto.hs
new file mode 100644
index 0000000..d2baff6
--- /dev/null
+++ b/lib/Numeric/GSL/Special/auto.hs
@@ -0,0 +1,233 @@
1-- automatic generation of wrappers for simple GSL special functions
2
3import Text.ParserCombinators.Parsec
4import System
5import Data.List(intersperse, isPrefixOf)
6import Data.Char(toUpper,isUpper,toLower)
7
8data Type = Normal Ident | Pointer Ident deriving (Eq, Show)
9
10type Ident = String
11
12data Header = Header Type Ident [(Type,Ident)] deriving Show
13
14headers f = case parse parseHeaders "" f of
15 Right l -> l
16 Left s -> error (show s)
17
18
19rep (c,r) [] = []
20rep (c,r) f@(x:xs)
21 | c `isPrefixOf` f = r ++ rep (c,r) (drop (length c) f)
22 | otherwise = x:(rep (c,r) xs)
23
24
25fixlong [] = []
26fixlong "\\" = []
27fixlong ('\\':'\n':xs) = xs
28fixlong (x:xs) = x : fixlong xs
29
30
31safe (Header _ _ args) = all ok args
32 || all ok (init args) && kn (last args)
33 where ok ((Normal s),_) | s `elem` ["double","float","int","gsl_mode_t"] = True
34 ok _ = False
35 kn ((Pointer "gsl_sf_result"),_) = True
36 kn ((Pointer "gsl_sf_result_e10"),_) = True
37 kn _ = False
38
39
40
41fixC s = rep ("gsl_mode_t","int") $ rep ("gsl_sf_result","double") $ rep ("gsl_sf_result_e10","double") $ s
42
43main = do
44 args <- getArgs
45 let name = args!!0
46 headerfile =
47 case args of
48 [n] -> "/usr/include/gsl/gsl_sf_"++n++".h"
49 [_,f] -> f
50 file <- readFile headerfile
51
52 putStrLn headerfile
53 --mapM_ print (headers $ fixlong file)
54 let parsed = (headers $ fixlong file)
55 writeFile (name ++".h") (fixC $ unlines $ map showC parsed)
56
57 --putStrLn ""
58 --mapM (\(Header _ n _) -> putStrLn (drop 7 n ++",")) parsed
59 --putStrLn ""
60 --mapM_ (putStrLn.showFull (name ++".h")) parsed
61 let exports = rep (")",") where") $ rep ("(\n","(\n ") $ rep (",\n",", ") $ unlines $ ["("]++intersperse "," (map (\(Header _ n _) -> hName n) (filter safe parsed))++[")"]
62 let defs = unlines $ map (showFull (name ++".h")) parsed
63 let imports = "\nimport Foreign(Ptr)\nimport Numeric.GSL.Special.Internal\n"
64 let mod = modhead name ++ "module Numeric.GSL.Special."++ upperFirst name++exports++imports++defs
65 writeFile (upperFirst name ++ ".hs") mod
66
67
68google name = "<http://www.google.com/search?q="
69 ++name
70 ++"&as_sitesearch=www.gnu.org/software/gsl/manual&btnI=Lucky>"
71
72modhead name = replicate 60 '-' ++ "\n"
73 ++"{- |\n"
74 ++"Module : Numeric.GSL.Special."++upperFirst name++"\n"
75 ++"Copyright : (c) Alberto Ruiz 2006\n"
76 ++"License : GPL-style\n"
77 ++"Maintainer : Alberto Ruiz (aruiz at um dot es)\n"
78 ++"Stability : provisional\n"
79 ++"Portability : uses ffi\n"
80 ++"\nWrappers for selected functions described at:\n\n"
81 ++ google ( "gsl_sf_"++name++".h")
82 ++"\n\n-}\n"
83 ++ replicate 60 '-' ++ "\n\n"
84
85upperFirst (x:xs) = toUpper x : xs
86
87comment = do
88 string "/*"
89 closecomment
90 spaces
91 return "comment"
92
93closecomment = try (string "*/")
94 <|> (do anyChar
95 closecomment)
96
97ident = do
98 spaces
99 id <- many1 (noneOf "()[]* \n\t,;")
100 spaces
101 return id
102
103comment' = between (char '(') (char ')') (many $ noneOf ")")
104
105
106define = do
107 string "#"
108 closedefine
109 spaces
110 return "define"
111
112closedefine = try (string "\n")
113 <|> (do anyChar
114 closedefine)
115
116marks = do
117 try (string "__BEGIN_DECLS" >> spaces >> return "begin")
118 <|>
119 try (string "__END_DECLS" >> spaces >> return "end")
120
121
122
123irrelevant =
124 try comment
125 <|>
126 try define
127 <|>
128 marks
129
130
131parseHeaders = many parseHeader
132
133parseHeader = do
134 spaces
135 many irrelevant
136 spaces
137 (res,name) <- typ
138 spaces
139 args <- between (char '(') (char ')') (sepBy typ (char ','))
140 spaces
141 char ';'
142 spaces
143 many irrelevant
144 return $ Header res name args
145
146typ = try t1 <|> t2
147
148symbol s = spaces >> string s >> spaces
149
150t1 = do
151 t <- try (symbol "const" >> symbol "unsigned" >> ident) -- aaagh
152 <|>
153 try (symbol "const" >> ident)
154 <|>
155 try (symbol "unsigned" >> ident)
156 <|> ident
157 n <- ident
158 return (Normal t,n)
159
160t2 = do
161 t <- ident
162 spaces
163 char '*'
164 spaces
165 n <- ident
166 return (Pointer t,n)
167
168pure (Header _ _ args) | fst (last args) == Pointer "gsl_sf_result" = False
169 | fst (last args) == Pointer "gsl_sf_result_e10" = False
170 | otherwise = True
171
172showC (Header t n args) = showCt t ++ " " ++ n ++ "(" ++ (concat $ intersperse "," $ map showCa args) ++ ");"
173
174showCt (Normal s) = s
175showCt (Pointer s) = s ++ "*"
176
177showCa (t, a) = showCt t ++" "++ a
178
179showH hc h@(Header t n args) = "foreign import ccall \""++hc++" "++n++"\" "++n++" :: "++ (concat$intersperse" -> "$map showHa args) ++" -> " ++ t'
180 where t' | pure h = showHt t
181 | otherwise = "IO("++showHt t++")"
182
183showHt (Normal (s:ss)) = toUpper s : ss
184showHt (Pointer "gsl_sf_result") = "Ptr Double"
185showHt (Pointer "gsl_sf_result_e10") = "Ptr ()"
186showHt (Pointer (s:ss)) = "Ptr "++toUpper s : ss
187
188showHa (t,a) = showHt t
189
190showFull hc h@(Header t n args) = "\n-- | wrapper for "++showC h
191 ++"\n--\n-- "++google n ++"\n"
192 ++ boiler h ++"\n"
193 ++showH hc h
194
195fixmd1 = rep ("Gsl_mode_t","Precision")
196fixmd2 = rep ("mode"," (precCode mode)")
197
198boiler h@(Header t n args) | fst (last args) == Pointer "gsl_sf_result" = boilerResult h
199 | fst (last args) == Pointer "gsl_sf_result_e10" = boilerResultE10 h
200 | any isMode args = boilerMode h
201 | otherwise = boilerBasic h
202
203isMode (Normal "gsl_mode_t",_) = True
204isMode _ = False
205
206hName n = f $ drop 7 n
207 where f (s:ss) = toLower s : ss
208
209
210boilerResult h@(Header t n args) =
211 hName n++" :: "++ (fixmd1 $ concat $ intersperse" -> "$ map showHa (init args)) ++" -> " ++ "(Double,Double)\n" ++
212 hName n ++ " "++ initArgs args ++
213 " = createSFR \""++ hName n ++"\" $ " ++ n ++ " "++ (fixmd2 $ initArgs args)
214
215boilerResultE10 h@(Header t n args) =
216 hName n++" :: "++ (fixmd1 $ concat $ intersperse" -> "$ map showHa (init args)) ++" -> " ++ "(Double,Int,Double)\n" ++
217 hName n ++ " "++ initArgs args ++
218 " = createSFR_E10 \""++ hName n ++"\" $ " ++ n ++ " "++ (fixmd2 $ initArgs args)
219
220boilerBasic h@(Header t n args) =
221 hName n++" :: "++ (fixmd1 $ concat $ intersperse" -> "$map showHa args) ++" -> " ++showHt t ++ "\n" ++
222 hName n ++ " = " ++fixmd2 n
223
224boilerMode h@(Header t n args) =
225 hName n++" :: "++ (fixmd1 $ concat $ intersperse" -> "$ map showHa args) ++" -> " ++ showHt t++"\n" ++
226 hName n ++ " "++ allArgs args ++
227 " = " ++ n ++ " "++ (fixmd2 $ allArgs args)
228
229cVar (v:vs) | isUpper v = toLower v : v : vs
230 | otherwise = v:vs
231
232allArgs args = unwords (map (cVar.snd) args)
233initArgs args = unwords (map (cVar.snd) (init args)) \ No newline at end of file