diff options
Diffstat (limited to 'lib/Numeric/GSL/Special/auto.hs')
-rw-r--r-- | lib/Numeric/GSL/Special/auto.hs | 233 |
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 | |||
3 | import Text.ParserCombinators.Parsec | ||
4 | import System | ||
5 | import Data.List(intersperse, isPrefixOf) | ||
6 | import Data.Char(toUpper,isUpper,toLower) | ||
7 | |||
8 | data Type = Normal Ident | Pointer Ident deriving (Eq, Show) | ||
9 | |||
10 | type Ident = String | ||
11 | |||
12 | data Header = Header Type Ident [(Type,Ident)] deriving Show | ||
13 | |||
14 | headers f = case parse parseHeaders "" f of | ||
15 | Right l -> l | ||
16 | Left s -> error (show s) | ||
17 | |||
18 | |||
19 | rep (c,r) [] = [] | ||
20 | rep (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 | |||
25 | fixlong [] = [] | ||
26 | fixlong "\\" = [] | ||
27 | fixlong ('\\':'\n':xs) = xs | ||
28 | fixlong (x:xs) = x : fixlong xs | ||
29 | |||
30 | |||
31 | safe (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 | |||
41 | fixC s = rep ("gsl_mode_t","int") $ rep ("gsl_sf_result","double") $ rep ("gsl_sf_result_e10","double") $ s | ||
42 | |||
43 | main = 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 | |||
68 | google name = "<http://www.google.com/search?q=" | ||
69 | ++name | ||
70 | ++"&as_sitesearch=www.gnu.org/software/gsl/manual&btnI=Lucky>" | ||
71 | |||
72 | modhead 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 | |||
85 | upperFirst (x:xs) = toUpper x : xs | ||
86 | |||
87 | comment = do | ||
88 | string "/*" | ||
89 | closecomment | ||
90 | spaces | ||
91 | return "comment" | ||
92 | |||
93 | closecomment = try (string "*/") | ||
94 | <|> (do anyChar | ||
95 | closecomment) | ||
96 | |||
97 | ident = do | ||
98 | spaces | ||
99 | id <- many1 (noneOf "()[]* \n\t,;") | ||
100 | spaces | ||
101 | return id | ||
102 | |||
103 | comment' = between (char '(') (char ')') (many $ noneOf ")") | ||
104 | |||
105 | |||
106 | define = do | ||
107 | string "#" | ||
108 | closedefine | ||
109 | spaces | ||
110 | return "define" | ||
111 | |||
112 | closedefine = try (string "\n") | ||
113 | <|> (do anyChar | ||
114 | closedefine) | ||
115 | |||
116 | marks = do | ||
117 | try (string "__BEGIN_DECLS" >> spaces >> return "begin") | ||
118 | <|> | ||
119 | try (string "__END_DECLS" >> spaces >> return "end") | ||
120 | |||
121 | |||
122 | |||
123 | irrelevant = | ||
124 | try comment | ||
125 | <|> | ||
126 | try define | ||
127 | <|> | ||
128 | marks | ||
129 | |||
130 | |||
131 | parseHeaders = many parseHeader | ||
132 | |||
133 | parseHeader = 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 | |||
146 | typ = try t1 <|> t2 | ||
147 | |||
148 | symbol s = spaces >> string s >> spaces | ||
149 | |||
150 | t1 = 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 | |||
160 | t2 = do | ||
161 | t <- ident | ||
162 | spaces | ||
163 | char '*' | ||
164 | spaces | ||
165 | n <- ident | ||
166 | return (Pointer t,n) | ||
167 | |||
168 | pure (Header _ _ args) | fst (last args) == Pointer "gsl_sf_result" = False | ||
169 | | fst (last args) == Pointer "gsl_sf_result_e10" = False | ||
170 | | otherwise = True | ||
171 | |||
172 | showC (Header t n args) = showCt t ++ " " ++ n ++ "(" ++ (concat $ intersperse "," $ map showCa args) ++ ");" | ||
173 | |||
174 | showCt (Normal s) = s | ||
175 | showCt (Pointer s) = s ++ "*" | ||
176 | |||
177 | showCa (t, a) = showCt t ++" "++ a | ||
178 | |||
179 | showH 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 | |||
183 | showHt (Normal (s:ss)) = toUpper s : ss | ||
184 | showHt (Pointer "gsl_sf_result") = "Ptr Double" | ||
185 | showHt (Pointer "gsl_sf_result_e10") = "Ptr ()" | ||
186 | showHt (Pointer (s:ss)) = "Ptr "++toUpper s : ss | ||
187 | |||
188 | showHa (t,a) = showHt t | ||
189 | |||
190 | showFull 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 | |||
195 | fixmd1 = rep ("Gsl_mode_t","Precision") | ||
196 | fixmd2 = rep ("mode"," (precCode mode)") | ||
197 | |||
198 | boiler 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 | |||
203 | isMode (Normal "gsl_mode_t",_) = True | ||
204 | isMode _ = False | ||
205 | |||
206 | hName n = f $ drop 7 n | ||
207 | where f (s:ss) = toLower s : ss | ||
208 | |||
209 | |||
210 | boilerResult 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 | |||
215 | boilerResultE10 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 | |||
220 | boilerBasic h@(Header t n args) = | ||
221 | hName n++" :: "++ (fixmd1 $ concat $ intersperse" -> "$map showHa args) ++" -> " ++showHt t ++ "\n" ++ | ||
222 | hName n ++ " = " ++fixmd2 n | ||
223 | |||
224 | boilerMode 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 | |||
229 | cVar (v:vs) | isUpper v = toLower v : v : vs | ||
230 | | otherwise = v:vs | ||
231 | |||
232 | allArgs args = unwords (map (cVar.snd) args) | ||
233 | initArgs args = unwords (map (cVar.snd) (init args)) \ No newline at end of file | ||