2 * This file is part of duit.
4 * duit is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
9 * duit is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with duit; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 module utils
.HTODConvert
;
21 private import utils
.DefReader
;
22 private import utils
.GtkWrapper
;
24 private import std
.stdio
;
25 private import std
.file
;
26 private import std
.string
;
27 private import std
.process
;
30 //debug = processLine;
43 public bool contains(int pos
)
45 return (pos
>= vStart
) && (pos
<=vEnd
);
48 public bool includes(int pos
)
56 public bool matches(int start
, int end
)
58 return vStart
== start
63 private Range
*[] ranges
;
65 public void addRange(int start
, int end
, bool exclude
)
67 Range
* range
= new Range
;
70 range
.exclude
= exclude
;
75 * Finds the last range that contains the position and returns it's include value
79 public void include(int pos
)
87 if ( range
.contains(pos
) )
90 incl
= !range
.exclude
;
99 * This is used to pos-process dm htod .d file for duit
100 * to create the htod .d file:
101 * - copy the original .h file to a working directory
102 * - remove all unecessary definitions
103 * - run `wine ~/dm/bin/htod.exe <file.h>`
104 * - run this on the generated .d file
106 public class HTODConvert
113 /** the library id on the system (for instance GL for libGL.so) */
115 /** the .h (or .h pos-processed) to convert to .d */
119 /** convert to dynamic loading */
121 /** mark when the header was already added to the text */
122 bool dynLoadAlreadyOpen
;
123 /** mar when the module and license where already added to the text */
124 bool headerAlreadyAdded
;
129 this(char[] htodFilename
)
131 defReader
= new DefReader(htodFilename
);
138 debug(flow
)(writefln("HTODConvert.process 1"));
139 while ( defReader
.next().length
> 0 )
141 switch ( defReader
.getKey() )
144 debug(flow
)(writefln("HTODConvert.process case prefile"));
145 preFile
= defReader
.getValue();
149 debug(flow
)(writefln("HTODConvert.process case pack"));
150 pack
= defReader
.getValue();
154 debug(flow
)(writefln("HTODConvert.process case libe"));
155 lib
= defReader
.getValue();
159 debug(flow
)(writefln("HTODConvert.process case file 1"));
160 if ( preFile
.length
> 0 )
162 debug(flow
)(writefln("HTODConvert.process case file 2"));
163 processPreFile(preFile
, defReader
.getValue());
164 debug(flow
)(writefln("HTODConvert.process case file 3"));
166 debug(flow
)(writefln("HTODConvert.process case file 4"));
168 debug(flow
)(writefln("HTODConvert.process case file 5"));
169 processFile(defReader
.getValue());
170 debug(flow
)(writefln("HTODConvert.process case file 6 "));
174 debug(flow
)(writefln("HTODConvert.process case dynload"));
175 dynLoadAlreadyOpen
= false;
176 headerAlreadyAdded
= false;
181 debug(flow
)(writefln("HTODConvert.process case outfile"));
182 writeFile(defReader
.getValue());
187 debug(flow
)(writefln("HTODConvert.process case default"));
188 writefln("Unknown key/value = %s/%s", defReader
.getKey(), defReader
.getValue());
195 void processPreFile(char[] preFileName
, char[] fileName
)
197 debug(flow
)(writefln("HTODConvert.processPreFile files: %s > %s", preFileName
, fileName
));
199 args
~= "/home/ruimt/dm/bin/htod.exe";
200 args
~= "/home/ruimt/dm/bin/htod.exe";
205 std
.process
.execvp("wine", args
);
209 // ignore - it always fail - most of the time produces the file
213 void processFile(char[] fileName
)
215 debug(flow
)(writefln("HTODConvert.processFile"));
216 char[] hText
= cast(char[])std
.file
.read(fileName
);
217 char[][] hLines
= std
.string
.splitlines(hText
);
221 while ( i
< hLines
.length
)
224 if ( std
.string
.find(line
,'(')>=0 )
227 if ( std
.string
.find(line
,')')>=0 ) --openBrace
;
228 while ( openBrace
> 0
232 char[] l
= hLines
[i
++];
233 if ( std
.string
.find(l
,')') >=0) --openBrace
;
234 line
~= " " ~ std
.string
.strip(l
);
237 addLine(dText
, line
);
246 void addLine(inout char[] dText
, char[] line
)
248 if ( !startsWith(line
, "//C")
249 && line
!="alias extern GLAPI;"
250 && line
!="alias GLAPIENTRY APIENTRY;"
253 if ( line
== "alias sbyte GLbyte;" )
255 line
= "alias byte GLbyte;";
257 if ( line
== "module wrap/cHeaders/GL/gl;" )
259 line
= "module lib.gl;";
262 if ( line
== "module wrap/cHeaders/GL/glu;" )
264 line
= "module lib.glu;";
267 if ( line
== "import std.c.gl;" )
269 line
= "import lib.gl;";
272 if ( startsWith(line
, "/* Converted to D from" ) )
274 line
= GtkWrapper
.license
;
279 addLineDynLoad(dText
, line
);
290 * If the line is a function definition stores the line to include on the extern(C)
292 * for now a function is a line that ends with ");"
297 void addLineDynLoad(inout char[] dText
, char[] line
)
299 //debug(flow)(writefln("HTODConvert.addLineDynLoad"));
301 if ( headerAlreadyAdded
302 && !dynLoadAlreadyOpen
308 if ( endsWith(line
, ");") )
311 while ( i
<comment
.length
)
313 functions
~= comment
[i
++];
317 debug(functions
)writefln("HTODConvert.addLineDynLoad function[%s] = %s",
318 functions
.length
, line
);
320 else if ( startsWith(line
, "/*")
321 ||
startsWith(line
, " *")
322 ||
startsWith(line
, " */")
330 if ( startsWith(line
, "module") )
332 headerAlreadyAdded
= true;
335 while ( i
<comment
.length
)
337 dText
~= comment
[i
++]~"\n";
344 void openDynLoad(inout char[] dText
)
346 debug(flow
)(writefln("HTODConvert.openDynLoad"));
347 dynLoadAlreadyOpen
= true;
351 "private import std.stdio;\n"
352 "private import "~pack
~"."~pack
~"types;\n"
353 "private import lib.Loader;\n"
354 "private import lib.paths;\n"
363 "private Linker "~lib
~"_Linker;\n"
367 " "~lib
~"_Linker = new Linker(libPath ~ importLibs[LIBRARY."~std
.string
.toupper(lib
)~"] );\n"
368 " "~lib
~"_Linker.link("~lib
~"Links);\n"
369 " debug writefln(\"* Finished static this(): "~lib
~"\");\n"
374 " delete "~lib
~"_Linker;\n"
375 " debug writefln(\"* Finished static ~this(): "~lib
~"\");\n"
382 void closeDynLoad(inout char[] dText
)
385 debug(flow
)(writefln("HTODConvert.closeDynLoad"));
386 dText
~= "\n\nextern(C)\n{\n";
387 foreach ( char[] line
; functions
)
389 dText
~= "\t" ~ line
~"\n";
391 dText
~= "} // extern(C)\n";
393 dText
~= "\n\nSymbol[] "~lib
~"Links = \n";
396 foreach ( char[] line
; functions
)
398 if ( startsWith(line
, "/*")
399 ||
startsWith(line
, " *")
400 ||
startsWith(line
, " */")
404 dText
~= "\t"~line
~"\n";
408 int end
= std
.string
.find(line
,'(');
413 while ( start
> 0 && line
[start
] > ' ' )
417 char[] functionName
= line
[start
+1..end
];
418 if ( functionName
.length
>1)
422 ~"\", cast(void**)& "
440 debug(flow
)(writefln("HTODConvert.clearValues"));
446 bool dynLoadAlreadyOpen
= false;
447 bool headerAlreadyAdded
= false;
448 functions
.length
= 0;
453 void writeFile(char[] fileName
)
455 debug(flow
)(writefln("HTODConvert.writeFile"));
456 debug(flow
)(writefln("HTODConvert.writeFile fileName = %s", fileName
));
457 std
.file
.write(fileName
, dText
);
460 public static bit
startsWith(char[] str, char[] prefix
)
462 return str.length
>= prefix
.length
463 && str[0..prefix
.length
] == prefix
;
466 public static bit
startsWith(char[] str, char prefix
)
468 return str.length
> 0
472 public static bit
endsWith(char[] str, char[] prefix
)
474 return str.length
>= prefix
.length
475 && str[str.length
-prefix
.length
..str.length
] == prefix
;
478 public static bit
endsWith(char[] str, char suffix
)
480 return str.length
>= 1
481 && str[str.length
-1] == suffix
;