alternative to assert
[gtkD.git] / wrap / utils / DuitClass.d
blob1cf25d641892270d6546670019fa923cbee51b7c
1 /*
2 * This file is part of duit.
3 *
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.
8 *
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.DuitClass;
21 //debug = getBlock;
22 //debug = getUntil;
23 //debug = Funct;
24 //debug = stringToDuit;
25 //debug = tokenToDuit;
26 //debug = endFunction;
27 //debug = defines;
28 //debug = functName;
29 //debug = noPrefixes;
30 //debug = functionType;
31 //debug = declaration;
32 //debug = structs;
33 //debug = enums;
34 //debug = enumPrefix;
35 //debug = unions;
36 //debug = parmType;
37 //debug = parmName;
38 //debug = enumToDuit;
39 //debug = getParent;
40 //debug = getSignal;
41 //debug = signalFunction;
42 //debug = stockItems;
43 //debug = gTypes;
44 //debug = implements;
45 //debug = getMember;
47 //version = noGtkBody;
49 /**
50 * Creates a Duit class
53 public class DuitClass
56 private import std.ctype;
57 private import std.path;
58 private import std.stdio;
60 private import utils.HtmlStrip;
61 private import utils.WrapperIF;
62 private import utils.convparms;
63 private import utils.funct;
65 private WrapperIF wrapper;
66 private char[] inAPI;
67 private char[][] inLines;
68 int currLine;
70 private int status = 0;
71 private int countBlock = 0;
73 ConvParms* convParms;
75 bool isInterface;
76 char[] iFaceChar = "";
78 private char[] parentName; /// gtk parent struct
79 private char[] duitParentName; /// duit parent name
80 private char[] duitParentNamePrefix; /// duit parent name package
82 private char[][] externalDeclarations; /// the external definition to pass to the wrapper
84 private char[][] collectedAliases; /// public, module level type aliases
85 private char[][] collectedEnums; /// public, module level definitions of enums
86 private char[][] stockEnums; /// special enums for the SotckID
87 private char[][] gTypes; /// special enums for G_TYPE_*
88 private char[][] stockChars; /// the char[] value for the stockIDs
89 private char[][] collectedStructs; /// public, module level definitions of structs
90 private char[][] collectedTypes; /// public, module level definitions of other types
91 private char[][] collectedFuncts; /// public, module level definitions of functions
92 private char[][] collectedUnions; /// public, module level definitions of unions
93 private char[][] collectedConstants;/// public, module level constants
96 private char[] duitText;
98 private char[][] properties;
99 private char[][] styleProperties;
100 private char[][] signals;
101 private char[][] description;
102 char[][] members;
104 int[char[]] functionSignatures;
105 int[char[]] gtkStructs;
108 private bit needSignalImports;
110 private char[] tabs; /// used for simple indentation
112 public this (WrapperIF wrapper )
114 this.wrapper = wrapper;
117 public char[][] getExternalDeclarations()
119 return externalDeclarations;
122 public char[][] getAliases()
124 return collectedAliases;
127 public char[][] getConstants()
129 return collectedConstants;
132 public char[][] getEnums()
134 return collectedEnums;
136 public char[][] getStockEnums()
138 return stockEnums;
140 public char[][] getStockChars()
142 return stockChars;
145 public char[][] getGTypes()
147 return gTypes;
150 public char[][] getStructs()
152 return collectedStructs;
155 public char[][] getTypes()
157 return collectedTypes;
160 public char[][] getFuncts()
162 return collectedFuncts;
165 public char[][] getUnions()
167 return collectedUnions;
170 public int getError()
172 return status;
175 private int[char[]] getCleanSigns()
177 int[char[]] cleanSignature;
178 return cleanSignature;
181 public void openDuitClass(char[] inAPI, ConvParms* convParms)
183 this.inAPI = inAPI;
184 isInterface = convParms.interf.length > 0;
185 if ( isInterface ) iFaceChar = ";";
186 else iFaceChar = "";
187 HtmlStrip stripper = new HtmlStrip();
188 inLines = std.string.splitlines(stripper.strip(inAPI));
189 //writefln("new API\n%s",inAPI);
191 functionSignatures = getCleanSigns();
192 gtkStructs = getCleanSigns();
194 this.convParms = convParms;
196 collectedAliases.length = 0;
197 collectedEnums.length = 0;
198 stockEnums.length = 0;
199 stockChars.length = 0;
200 gTypes.length = 0;
201 collectedStructs.length = 0;
202 collectedUnions.length = 0;
203 collectedTypes.length = 0;
204 collectedFuncts.length = 0;
205 collectedConstants.length = 0;
207 needSignalImports = true;
209 externalDeclarations ~= "";
210 externalDeclarations ~= "// " ~ convParms.outPack ~ '.' ~ convParms.clss;
211 externalDeclarations ~= "";
213 duitText = wrapper.getLicense();
215 convParms.appendAsComment(duitText);
217 duitText ~= "module "~convParms.outPack~".";
218 if ( convParms.clss.length > 0 )
220 duitText ~= convParms.outFile;
222 else if ( convParms.outFile.length > 0 )
224 duitText ~= convParms.outFile;
226 duitText ~= ";\n\n";
228 // moved to class level
229 duitText ~= "private import "~convParms.outPack ~ "."~convParms.outPack~"types;\n\n";
230 duitText ~= "private import lib."~convParms.outPack ~ ";\n\n";
232 // moved back to class level
233 foreach( char[] imprt ; convParms.imprts )
235 duitText ~= "private import "~imprt~";\n";
238 properties.length = 0;
239 styleProperties.length = 0;
240 signals.length = 0;
242 readDuitClass(convParms);
245 // moved to GdkWrapper.d
246 append(text, collectedAliases, tabs);
247 append(text, collectedEnums, tabs);
248 append(text, collectedStructs, tabs);
249 append(text, collectedTypes, tabs);
250 append(text, collectedFuncts, tabs);
251 append(text, collectedUnions, tabs);
254 if ( wrapper.includeComments() )
256 append(duitText, description, tabs);
259 // reset the parent name
260 parentName = null;
261 duitParentName = "";
263 char[][] classHead = openClass(convParms);
264 append(duitText, classHead, tabs);
269 private void readDuitClass(ConvParms* convParms)
271 description = getDescription();
272 properties ~= getProperties();
273 styleProperties ~= getStyleProperties();
274 signals ~= getSignals();
276 members ~= getMembers(convParms);
280 public void mergeDuitClass(char[] inAPI, ConvParms* convParms)
282 this.inAPI = inAPI;
283 HtmlStrip stripper = new HtmlStrip();
284 inLines = std.string.splitlines(stripper.strip(inAPI));
285 //writefln("new API\n%s",inAPI);
287 this.convParms = convParms;
289 readDuitClass(convParms);
291 if ( wrapper.includeComments() )
293 append(duitText, description, tabs);
298 public char[] closeDuitClass(char[] inAPI, ConvParms* convParms)
300 mergeDuitClass(inAPI, convParms);
302 append(duitText, properties, tabs);
303 append(duitText, styleProperties, tabs);
304 append(duitText, signals, tabs);
306 append(duitText, members, tabs);
308 duitText ~= closeClass(convParms);
310 return duitText;
314 * Gets the name to the output file
315 * Params:
316 * outputRoot =
317 * Returns:
319 public char[] getOutFile(char[] outputRoot, char[] srcOut)
321 char[] outF = std.path.join(outputRoot, srcOut);
322 outF = std.path.join(outF, convParms.outPack);
323 outF = std.path.join(outF, (convParms.clss.length>0 ? convParms.outFile : convParms.outFile));
324 return outF~".d";
328 * Appends to the main text with the correct indentation
329 * Params:
330 * text = The main text
331 * lines = The lines to append
332 * tabs = The indentation to use
334 public static void append(inout char[] text, char[][] lines, inout char[] tabs)
336 foreach(char[] line ; lines )
338 char[] ln = std.string.strip(line);
339 if ( endsWith(ln, '}')
340 || endsWith(ln, "};")
341 || startsWith(ln, "}")
342 || startsWith(ln, "* }")
343 || startsWith(ln, "// }")
346 if ( tabs.length > 0 ) tabs.length = tabs.length -1;
348 if ( startsWith(ln, '*') )
350 text ~= tabs ~" "~ ln ~ "\n";
352 else
354 text ~= tabs ~ ln ~ "\n";
356 if ( endsWith(ln,'{') )//&& !startsWith(line, " *") )
358 tabs ~= '\t';
364 * Checks if we are a template and if the parent name
365 * Params:
366 * parentName =
367 * Returns:
369 private char[] getClassHeader(ConvParms* convParms, char[] parentName)
371 char[] h;
372 if ( convParms.interf.length > 0 )
374 h = "public interface "~convParms.interf;
376 else if ( convParms.templ.length == 0 )
378 h = "public class "~convParms.clss;
380 else
382 h = "public template "~convParms.clss~"(";
384 foreach ( int count, char[] tp ; convParms.templ )
386 if ( count > 0 )
388 h ~= ", ";
390 h ~= tp;
392 h ~= ")";
394 if ( parentName.length > 0 )
396 h ~= " : " ~ parentName;
398 return h;
402 * Create the class header.
403 * If the class name is empty this is not a class so no header is created
404 * Params:
405 * clss = The class Name
406 * Returns:
408 private char[][] openClass(ConvParms* convParms)
410 char[][] text;
411 if ( convParms.clss.length > 0 )
413 getParent();
414 if ( duitParentName.length > 0
415 && duitParentNamePrefix.length > 0
418 text ~= "private import "~duitParentNamePrefix~"."~duitParentName~";\n";
420 text ~= getClassHeader(convParms, duitParentName)
421 ~ getImplements(convParms, duitParentName);
422 // char[] implements = getImplements(convParms, duitParentName);
423 // if ( implements.length > 0 )
424 // {
425 // text ~= implements;
426 // }
427 text ~= "{";
430 // moved from module level
431 //text ~= "private import "~convParms.outPack ~ "."~convParms.outPack~"types;\n\n";
432 //text ~= "private import lib."~convParms.outPack ~ ";\n\n";
434 // moved to module level - AND BACK AGAIN
435 //foreach( char[] imprt ; convParms.imprts )
437 // text ~= "private import "~imprt~";";
440 char[] flipG(char[] inStr)
442 char[] flipped = inStr.dup;
444 if ( flipped[0] == 'G' )
446 flipped = flipped[1..flipped.length] ~ 'G';
449 return flipped;
452 if ( convParms.strct.length > 0 )
454 char[] gtkStruct = convParms.realStrct.length > 0
455 ? convParms.realStrct
456 : convParms.strct;
457 char[] var = toVar(gtkStruct.dup);
458 text ~= "";
459 if ( !isInterface )
461 text ~= "/** the main Gtk struct */";
462 text ~= "protected "~gtkStruct~"* "~var~";";
463 text ~= "";
466 if ( convParms.clss.length > 0 )
468 text ~= "";
470 if ( convParms.templ.length > 0 )
472 text ~= "public "~gtkStruct~"* get"~convParms.clss~"Struct()"~iFaceChar;
473 if ( !isInterface )
475 text ~= "{";
476 text ~= "return cast("~gtkStruct~"*)getStruct();";
477 text ~= "}";
479 text ~= "";
481 else
483 text ~= "public "~gtkStruct~"* get"~convParms.clss~"Struct()"~iFaceChar;
484 if ( !isInterface )
486 text ~= "{";
487 text ~= "return " ~ var ~ ';';
488 text ~= "}";
489 text ~= "";
491 text ~= "";
492 text ~= "/** the main Gtk struct as a void* */";
493 text ~= "protected void* getStruct()"~iFaceChar;
494 if ( !isInterface )
496 text ~= "{";
497 text ~= "return cast(void*)" ~ var ~ ';';
498 text ~= "}";
500 text ~= "";
501 if ( "GObject" != convParms.strct )
503 // GObject has a specific constructor for the struct
504 if ( !isInterface )
506 text ~= "/**";
507 text ~= " * Sets our main struct and passes it to the parent class";
508 text ~= " */";
509 text ~= "public this ("~gtkStruct~"* "~var~")"~iFaceChar;
510 text ~= "{";
511 if ( parentName.length > 0 )
513 text ~= "super("~castToParent(var)~");";
515 text ~= "this."~var~" = "~var~";";
516 text ~= "}";
523 addStaticClassCode(convParms, text);
525 return text;
530 * Adds the class code from the conversion parameters.
531 * If current output is a interface the body functions
532 * will be removed (at least we'll try to remove it)
533 * Params:
534 * convParms =
536 private void addStaticClassCode(ConvParms* convParms, inout char[][] text)
538 char[] code;
540 if ( isInterface ) code = convParms.interfaceCode;
541 else code = convParms.classCode;
543 if ( code.length > 0 )
545 text ~= "";
546 foreach ( char[] line ; std.string.splitlines(code))
548 text ~= std.string.strip(line);
553 private char[] castToParent(char[] var)
555 return "cast("~parentName~"*)"~var;
559 * Converts a type to a var.
560 * lower case the first letter
561 * Params:
562 * type =
563 * Returns:
565 public static char[] toVar(char[] type)
567 if ( type.length > 0 )
569 type[0] = std.ctype.tolower(type[0]);
571 if ( type.endsWith("_t") )
573 type = type[0..type.length-2];
575 return type;
579 * Close the class by adding the final brace
580 * If the class name is empty this is not a class so no closing is necessary
581 * Params:
582 * clss = The class name
583 * Returns:
585 private char[] closeClass(ConvParms* convParms)
587 if ( tabs.length > 0 )
589 tabs.length = tabs.length -1;
591 return convParms.clss.length>0 ? "}\n" : "\n";
595 * Read the parent class under "Object Hierarchy" section
596 * or get from the extend on the convParms
597 * Params:
598 * clss =
599 * Returns:
601 private char[] getParent()
603 debug(getParent) writefln("getParent for %s ", convParms.outFile);
605 if ( parentName is null )
607 if ( convParms.extend.length > 0 )
609 parentName = convParms.extend.dup;
610 duitParentName = convertClassName(convParms.extend, duitParentNamePrefix);
612 else
614 int i = moveToBlockStart("Object Hierarchy", inLines);
615 i += 2;
616 while ( i < inLines.length && !startsWith(std.string.strip(inLines[i]), "+----") )
618 debug(getParent)writefln("\t skip line %s", inLines[i]);
619 ++i;
621 debug(getParent)
623 writefln("getParent 1 ");
624 for ( int j=i-3 ;j<inLines.length && j<i+5 ; j++)
626 writefln("\t getParent line = %s", inLines[j]);
628 if ( i<inLines.length ) writefln("\t getParent first line = %s", inLines[i]);
630 char[] parent;
631 char[] current;
632 char[] next;
634 if ( i < inLines.length )
636 next = std.string.strip(inLines[i-1]); // many times "GObject"
637 if ( next != "GInterface" )
639 current = next;
642 char[] gtkStruct = convParms.strct;
643 if ( convParms.realStrct.length > 0 )
645 gtkStruct = convParms.realStrct;
647 while ( i < inLines.length
648 && startsWith(std.string.strip(inLines[i]), "+----")
649 && current != gtkStruct
652 parent = current;
653 next = inLines[i][6..inLines[i].length];
654 if ( "GInitiallyUnowned" != next )
656 current = next.dup;
657 debug(getParent) writefln("\t current = %s", current);
659 ++i;
661 if ( gtkStruct == current && parent.length>0 )
663 parentName = parent.dup;
664 duitParentName = convertClassName(parentName, duitParentNamePrefix);
668 return parentName;
671 private char[] convertClassName(char[] gName, inout char[] prefix)
673 char[] conv;
674 if ( startsWith(gName, "Gtk") ) prefix = "Gtk";
675 else if ( startsWith(gName, "Gdk") ) prefix = "Gdk";
676 else if ( startsWith(gName, "Atk") ) prefix = "Atk";
677 else if ( startsWith(gName, "G") ) prefix = "G";
679 conv = gName[prefix.length..gName.length];
680 if ( conv == "Object" )
682 conv ~= prefix;
684 debug(getParent)writefln("convertClassName %s >>> %s", gName, conv);
685 prefix = std.string.tolower(prefix);
686 if ( prefix == "g")
688 prefix = "gobject";
690 return conv;
694 * Under "Implemented Interfaces" section
695 * Params:
696 * clss =
697 * Returns:
699 private char[] getImplements(ConvParms* convParms, char[] parentName)
701 char[] impls;
702 foreach ( int count, char[] impl ; convParms.impl )
704 if ( count > 0 || parentName.length > 0)
706 impls ~= ", ";
708 else if ( count == 0 || parentName.length == 0)
710 impls ~= "/+implements+/ ";
712 impls ~= impl;
714 return impls;
717 private char[][] getProperties()
719 char[][] text;
721 return text;
724 private char[][] getStyleProperties()
726 char[][] text;
728 return text;
733 * All the signals
734 * Returns:
736 private char[][] getSignals()
738 char[][] text;
739 debug(getSignal) writefln("\tgetSignals");
741 int i = moveToBlockStart("Signal Details", inLines);
742 i += 2;
743 debug(getSignal)if(i<inLines.length)writefln("\t %s", inLines[i]);
745 while ( i<inLines.length && startsWith(inLines[i], "The \"") )
747 text ~= getSignal(i, inLines);
748 while ( i<inLines.length && !startsWith(inLines[i], "The \"") )
750 debug(getSignal) writefln("\tgoto next\t%s", inLines[i]);
751 ++i;
755 return text;
758 private char[][] getSignal(inout int i, char[][] lines)
760 debug(getSignal) writefln("\tgetSignal %s", lines[i]);
761 char[][] text;
762 int endPos = std.string.rfind(lines[i], '"');
763 if ( endPos > 5 )
765 char[] signalName = lines[i][5..endPos];
767 ++i;
768 char[] funct = getSignalFunctionDeclaration(i, lines);
769 char[][] comments;
770 if ( wrapper.includeComments )
772 comments ~= "/**";
773 while ( i<lines.length && lines[i] != "<hr>" )
775 debug(getSignal) writefln("\t\t%s", lines[i]);
776 comments ~= " * "~lines[i];
777 ++i;
779 comments ~= "*/";
782 Funct fun;
783 fun.init(funct, convParms);
785 char[] duitSignal = signalNameToDuit(signalName);
786 char[] delegateDeclaration = fun.getDelegateDeclaration(convParms, 1);
788 addSignalImports(text);
789 text ~= delegateDeclaration ~ "[] on" ~ duitSignal~"Listeners;" ;
790 addAddListener(text, signalName, duitSignal, delegateDeclaration);
791 addExternCallback(text, fun, duitSignal, delegateDeclaration);
793 return text;
797 void addExternCallback(inout char[][] text, Funct fun, char[] duitSignal, char[] dlg)
799 if ( !isInterface )
801 text ~= "extern(C) static void callBack"~duitSignal~"("
802 ~fun.getCallbackParameters(0, convParms, wrapper.getAliases())
803 ~")";
804 text ~= "{";
805 text ~= " bit consumed = false;";
806 text ~= "";
807 text ~= " foreach ( "~dlg~" dlg ; "~getClassVar(convParms)~".on"~duitSignal~"Listeners )";
808 text ~= " {";
809 char[] dlgCall = "dlg("~fun.getCallbackVars(convParms, wrapper.getAliases())~");";
810 //if ( dlgCall == "dlg(widget, container);" )
812 // // special case
813 // dlgCall = "dlg(new Widget(widget), container);";
815 text ~= " "~dlgCall;
816 text ~= " }";
817 text ~= " ";
818 text ~= " return consumed;";
819 text ~= "}";
820 text ~= "";
824 void addAddListener(inout char[][] text, char[] signalName, char[] duitSignalName, char[] dlg)
826 text ~= "void addOn"~duitSignalName~"("~dlg~" dlg)"~iFaceChar;
827 if ( !isInterface )
829 text ~= "{";
830 text ~= "if ( !(\""~signalName~"\" in connectedSignals) )";
831 text ~= "{";
833 // TODO move this to the config files or read it from the Gtk docs (how?)
834 switch ( signalName )
836 case "button-press-event": text ~= "addEvents(EventMask.BUTTON_PRESS_MASK);"; break;
837 case "button-release-event": text ~= "addEvents(EventMask.BUTTON_RELEASE_MASK);"; break;
838 case "motion-notify-event": text ~= "addEvents(EventMask.POINTER_MOTION_MASK);"; break;
839 default:
840 break;
843 text ~= " Signals.connectData(";
844 text ~= " getStruct(), ";
845 text ~= " \""~signalName~"\", ";
846 text ~= " cast(GCallback)&callBack"~duitSignalName~", ";
847 text ~= " this, ";
848 text ~= " null, ";
849 //text ~= " ConnectFlags.AFTER);";
850 text ~= " cast(ConnectFlags)0);";
851 //text ~= " 0);";
852 text ~= " connectedSignals[\""~signalName~"\"] = 1;";
853 text ~= "}";
854 text ~= "on"~duitSignalName~"Listeners ~= dlg;";
855 text ~= "}";
860 public static char[] getClassVar(ConvParms* convParms)
862 char[] cv;
864 if ( convParms.clss.length > 0 )
866 cv = convParms.clss.dup;
867 cv[0] = std.ctype.tolower(cv[0]);
870 return cv;
873 private char[] signalNameToDuit(char[] signalName)
875 char[] signalDuit;
877 char pc = ' ';
878 foreach ( int count, char c ; signalName )
880 if ( count == 0 )
882 signalDuit ~= std.ctype.toupper(c);
884 else
886 if ( c!='-' && c!='_' )
888 if ( pc=='-' || pc=='_' )
890 signalDuit ~= std.ctype.toupper(c);
892 else
894 signalDuit ~= c;
898 pc = c;
901 //writefln("signalDuit = %s", signalDuit);
903 if ( "MapEvent" != signalDuit
904 && "UnmapEvent" != signalDuit
905 && endsWith(signalDuit, "Event") )
907 signalDuit = signalDuit[0..signalDuit.length-5];
910 return signalDuit;
914 * adding:
915 * "private import gobject.Signals;"
916 * "private import gdk.gdktypes;"
917 * Params:
918 * text =
920 void addSignalImports(inout char[][] text)
922 if ( needSignalImports )
924 text ~= "";
925 text ~= "// imports for the signal processing";
926 text ~= "private import gobject.Signals;";
927 text ~= "private import gdk.gdktypes;";
928 if ( !isInterface )
930 text ~= "int[char[]] connectedSignals;";
932 text ~= "";
934 needSignalImports = false;
939 private char[] getSignalFunctionDeclaration(inout int line, char[][] lines)
941 debug(signalFunction)writefln("getSignalFunctionDeclaration");
942 char[] funct;
943 while ( line<lines.length
944 && std.string.find(lines[line], ":")<0
947 funct ~= lines[line]~ " ";
948 debug(endFunction)writefln("funct line = >>>%s<<< endWith(\");\") = ",
949 lines[line],
950 endsWith(lines[line], ");")
952 ++line;
954 if ( line<lines.length && std.string.find(lines[line], ":")>0 )
956 funct ~= lines[line++];
958 return funct;
963 private char[][] getMembers(ConvParms* convParms)
965 currLine = 0;
966 getUntil("Details");
968 char[][] text;
970 while ( currLine < inLines.length )
972 text ~= getMember(convParms.prefixes);
975 return text;
978 private char[][] getMember(char[][] prefixes)
980 char[][] lines = convParms.text.dup;
981 convParms.text.length = 0;
982 lines ~= getUntil("<hr>");
983 char[][] member;
985 //debug(structs){
986 // writefln("lines[1] = %s", lines[1]);
987 //}else debug(enums){
988 // writefln("lines[1] = %s", lines[1]);
992 debug(getMember)
994 writefln("getMember:");
995 foreach (char[] line ; lines )
997 writefln("\t%s", line);
1000 if ( lines.length < 2 )
1002 return member;
1006 member ~= "";
1007 if ( endsWith(lines[0],"()") )
1009 member ~= getFunction(lines, prefixes);
1011 else if ( startsWith(lines[1], "typedef enum") )
1013 if ( !convParms.strictPrefix
1014 && !isInterface
1017 collectEnums(lines, convParms);
1020 else if ( startsWith(lines[1], "typedef struct")
1021 || startsWith(lines[1], "struct")
1024 if ( !convParms.strictPrefix
1025 && !isInterface
1028 collectStructs(lines, convParms);
1031 else if ( startsWith(lines[0], "union") )
1033 if ( !convParms.strictPrefix
1034 && !isInterface
1037 collectUnions(lines, convParms);
1040 else if ( startsWith(lines[1], "typedef") )
1042 if ( !convParms.strictPrefix
1043 && !isInterface
1046 collectAliases(lines, convParms);
1049 else if ( startsWith(lines[0], "GTK_STOCK_") )
1051 if ( !isInterface )
1053 collectStockItems(lines, convParms);
1056 else if ( startsWith(lines[0], "G_TYPE_")
1057 && convParms.outFile == "Type"
1060 if ( !isInterface )
1062 collectGTypes(lines, convParms);
1066 return member;
1070 private void collectGTypes(char[][] lines, ConvParms* convParms)
1072 debug(gTypes)writefln("gype lines\n\t%s\n\t%s\n\t%s",lines[0],lines[1],lines[2]);
1073 int defLine = 1;
1074 if ( lines.length > 0
1075 && std.string.find(lines[defLine],"G_TYPE_MAKE_FUNDAMENTAL")>=0
1076 && endsWith(lines[defLine],")")
1077 && std.string.find(lines[defLine],"<<") < 0
1080 int pos = std.string.find(lines[defLine], "(");
1081 if ( pos > 0 )
1083 int posf = std.string.find(lines[defLine], ")");
1084 if ( posf>pos )
1086 gTypes ~= lines[0][7..lines[0].length]
1087 ~ " = "~lines[defLine][pos+1..posf]~"<<2"
1088 ~ ",";
1094 // we expect all stock constants to be defined in one file
1095 int stockCurrEnum;
1098 private void collectStockItems(char[][] lines, ConvParms* convParms)
1100 debug(stockItems)writefln("stock items lines\n\t%s\n\t%s\n\t%s",lines[0],lines[1],lines[2]);
1101 int defLine = 1;
1102 if ( lines.length > 0 && startsWith(lines[defLine],"#define GTK_") )
1104 char[] line = lines[defLine];
1105 char[] stockID;
1106 char[] stockValue;
1108 int pos = std.string.find(line[12..line.length],' ')+12;
1109 debug(stockItems)writefln("pos=%s", pos);
1110 if ( pos > 12 )
1112 stockID = line[12..pos];
1113 if ( startsWith(stockID, "STOCK_") )
1115 stockID = stockID[6..stockID.length];
1117 debug(stockItems)writefln("\t\tstockID = %s", stockID);
1118 if ( stockID.length>0 )
1120 stockValue = std.string.strip(line[pos+1..line.length]);
1121 debug(stockItems)writefln("\t\tstockValue = %s", stockValue);
1122 if ( stockValue.length>2
1123 && stockValue[0] == '"'
1124 && endsWith(stockValue, '"')
1127 int ln = defLine+1;
1128 stockEnums ~= "";
1129 stockEnums ~= "/**";
1130 while ( ln < lines.length && lines[ln][0] > ' ' )
1132 stockEnums ~= " * "~lines[ln++].dup;
1134 stockEnums ~= " */";
1135 stockEnums ~= stockID~",";
1136 stockChars ~= "\""~stockValue[1..stockValue.length-1]~"\",";
1137 //collectedConstants ~=
1138 // "const StockID "~stockID
1139 // ~" = cast(StockID)\""~stockValue[1..stockValue.length-1]~"\";";
1148 private void collectAliases(char[][] lines, ConvParms* convParms)
1150 int pos = 0;
1151 char[][] tokens = std.string.split(until(pos, lines[1], ';'));
1153 char[] alis = "public alias " ~ tokens[1] ~ ' ' ~ tokens[2] ~ ';';
1155 collectedAliases ~= "";
1156 collectedAliases ~= "/**";
1157 int ln = 1;
1158 while ( ln < lines.length && lines[ln][0] > ' ' )
1160 collectedAliases ~= " * "~lines[ln++].dup;
1162 collectedAliases ~= " */";
1163 collectedAliases ~= stringToDuit(alis, convParms, wrapper.getAliases());
1167 private char[] getEnumPrefix(char[] enumName, char[] enumEntry)
1169 debug(enumPrefix)writefln("%s.%s", enumName, enumEntry);
1170 char[] prefix;
1171 char[] upper = std.string.toupper(enumName.dup);
1172 int n = 0;
1173 int e = 0;
1175 bool endOfStrings()
1177 bool v = (n>=upper.length) || (e>=enumEntry.length);
1178 debug(enumPrefix) if (v) writefln("\t ended by endfStrings");
1179 return v;
1182 bool isUnderscore()
1184 bool v = enumEntry[e] == '_';
1185 return v;
1188 bool sameChar()
1190 bool v = upper[n] == enumEntry[e];
1191 debug(enumPrefix) if (!v) writefln("\t ended by sameChar");
1192 return v;
1195 bool isSuffix()
1197 bool v = upper.length-n == 4
1198 && ( upper[n..n+4]=="TYPE"
1199 || upper[n..n+4]=="FLAG"
1200 || upper[n..n+4]=="MODE"
1202 debug(enumPrefix) if (v) writefln("\t ended by isSuffix");
1203 return v;
1206 while ( !endOfStrings()
1207 && ( isUnderscore()
1209 ( sameChar() && !isSuffix() )
1213 if ( upper[n] == enumEntry[e] )
1215 ++n;
1216 ++e;
1218 else
1220 ++e;
1225 if ( e < enumEntry.length )
1227 while ( e >0 && enumEntry[e]!= '_' )
1229 --e;
1234 if ( e<enumEntry.length && enumEntry[e] == '_' )
1236 ++e;
1239 prefix = enumEntry[0..e];
1240 debug(enumPrefix) writefln("\t%s", prefix);
1241 return prefix;
1244 private void collectEnums(char[][] lines, ConvParms* convParms)
1246 char[] enumName = lines[0][5..lines[0].length];
1247 char[] duitEnumName;
1249 bool isGdkPrefix(char[] name)
1251 return
1252 startsWith(enumName, "Gdk")
1257 if ( startsWith(enumName, "Gtk")
1258 || isGdkPrefix(enumName)
1261 duitEnumName = enumName[3..enumName.length];
1262 if ( duitEnumName == "Function" ) duitEnumName = "Funct";
1264 else if ( startsWith(enumName, "G") )
1266 duitEnumName = enumName[1..enumName.length];
1268 //char[] enumName = removeUnderscore(lines[0][5..lines[0].length]);
1269 debug(enums)writefln("enum %s", enumName);
1270 char[][] values;
1271 // skipp until the start of the enumerations
1272 int pos = 1;
1273 while ( pos<lines.length
1274 && !endsWith(std.string.strip(lines[pos]),'{')
1275 && !startsWith(std.string.strip(lines[pos]),'{')
1276 && !startsWith(lines[pos], "typedef enum {")
1279 debug(enums)writefln("\tskipp line: %s", lines[pos]);
1280 ++pos;
1282 ++pos;
1283 bit invalidDEnum = false;
1284 if ( pos<lines.length && lines[pos][0] != '}' )
1286 char[] enumPrefix = getEnumPrefix(enumName, std.string.strip(lines[pos].dup));
1287 int prefixLength = enumPrefix.length;
1288 while ( pos<lines.length && lines[pos][0] != '}' )
1290 debug(enums)writefln("\tenum line %s", lines[pos]);
1292 char[] value = std.string.strip(lines[pos++].dup);
1293 debug(enums)writefln("\traw %s", value);
1294 value = enumToDuit(enumName, value, convParms, wrapper);
1295 debug(enums)writefln("\tprocessed %s", value);
1297 //if ( std.string.find(value, ":") >= 0 )
1299 // invalidDEnum = true;
1300 // debug(structs)writefln("- INVALID >>>%s<<<", value);
1302 //else
1303 if ( startsWith(value, '#') )
1305 // ignore
1306 debug(enums)writefln("= IGNORED >>>%s<<<", value);
1308 else
1312 char[] replace(char[] s, char[] from, char[] to)
1314 char[] p;
1315 if ( from.length == 0 )
1317 p = s.dup;
1319 else
1321 int i;
1322 int istart;
1324 istart = 0;
1325 while (istart < s.length)
1327 i = std.string.find(s[istart .. s.length], from);
1328 if (i == -1)
1330 p ~= s[istart .. s.length];
1331 break;
1333 p ~= s[istart .. istart + i];
1334 p ~= to;
1335 istart += i + from.length;
1338 return p;
1342 debug(enumPrefix)writefln("\t\t%s", value);
1343 char[] v = replace(value, enumPrefix, "");
1344 if ( v.length > 2 )
1346 switch (v[0..3])
1348 case "2BI": v = "TOO_"~v[1..v.length]; break;
1349 case "2BU": v = "DOUBLE_"~v[1..v.length]; break;
1350 case "3BU": v = "TRIPPLE_"~v[1..v.length]; break;
1351 default:
1352 // nothing
1353 break;
1357 values ~= v;
1359 //debug(enumPrefix)writefln("-> %s", value[prefixLength..value.length]);
1360 // if ( startsWith(value, enumPrefix) )
1361 // {
1362 // values ~= value[prefixLength..value.length];
1363 // }
1364 // else
1365 // {
1366 // values ~= value;
1367 // debug(enumPrefix)writefln();
1368 // }
1369 debug(enums)writefln("+ ADDED >>>%s<<<", v);
1373 ++pos;
1374 if ( pos < lines.length )
1376 collectedEnums ~= "/**";
1377 while ( pos < lines.length && lines[pos][0] > ' ' )
1379 collectedEnums ~= " * "~lines[pos++].dup;
1381 collectedEnums ~= " */";
1383 if ( invalidDEnum )
1385 collectedEnums ~= "// TODO ";
1386 collectedEnums ~= "// public enum "~enumName;
1388 else
1390 collectedEnums ~= "public enum "~enumName;
1392 collectedEnums ~= "{";
1393 foreach ( char[] value ; values )
1395 debug(enums)writefln("\t\t%s", value);
1396 collectedEnums ~= stringToDuit(value, convParms, wrapper.getAliases());
1398 collectedEnums ~= "}";
1399 if ( duitEnumName.length > 0
1400 && !startsWith(duitEnumName, "Gdk")
1403 collectedEnums ~= "alias "~enumName~" "~duitEnumName ~ ";";
1404 collectedEnums ~= "";
1410 private void collectUnions(char[][] lines, ConvParms* convParms)
1412 char[] unionName = lines[0][6..lines[0].length];
1413 if ( unionName == "cairo_path_data_t" )
1415 collectedUnions ~= "";
1416 collectedUnions ~= "// skipped union "~unionName;
1417 collectedUnions ~= "";
1418 return;
1420 debug(unions)writefln("union %s", unionName);
1421 char[][] values;
1422 int pos = 3;
1423 while ( pos<lines.length && lines[pos][0] != '}' )
1425 debug(unions)writefln("\tunion line %s", lines[pos]);
1426 char[] value = std.string.strip(lines[pos++].dup);
1427 debug(unions)writefln("\traw %s", value);
1428 value = stringToDuit(value, convParms, wrapper.getAliases());
1429 debug(unions)writefln("\tprocessed %s", value);
1430 values ~= value;
1432 ++pos;
1433 if ( pos < lines.length )
1435 collectedUnions ~= "/**";
1436 while ( pos < lines.length && lines[pos][0] > ' ' )
1438 collectedUnions ~= " * "~lines[pos++].dup;
1440 collectedUnions ~= " */";
1442 collectedUnions ~= "public struct "~unionName;
1443 collectedUnions ~= "{";
1444 collectedUnions ~= "union";
1445 collectedUnions ~= "{";
1446 foreach ( char[] value ; values )
1448 debug(unions)writefln("\t\t%s", value);
1449 collectedUnions ~= value;
1451 collectedUnions ~= "}";
1452 collectedUnions ~= "}";
1455 private void collectStructs(char[][] lines, ConvParms* convParms)
1457 char[] structName = lines[0].dup;
1458 if ( startsWith(structName, "struct ") )
1460 structName = structName[7..structName.length];
1462 debug(structs)writefln("found typdef struct = %s", structName);
1463 bit includeStruct = true;
1464 int nStructs = 0;
1465 while ( includeStruct && nStructs < convParms.noStructs.length )
1467 includeStruct = ! (structName == convParms.noStructs[nStructs++]);
1469 if ( includeStruct )
1471 char[][] structDef; /// all elements of the struct
1472 bit invalidDStruct = false;
1473 int pos = 1;
1474 if ( lines[1][lines[1].length-1] == '{' )
1476 ++pos;
1477 while ( pos < lines.length && lines[pos][0] != '}' )
1479 //invalidDStruct = true;
1480 structDef ~= lines[pos].dup;
1481 //if ( std.string.find(lines[pos], ":") >= 0 )
1483 // invalidDStruct = true;
1484 // debug(structs)writefln("- INVALID >>>%s<<<", lines[pos]);
1486 //else
1487 if ( std.string.find(lines[pos], "[") >= 0 )
1489 invalidDStruct = true;
1490 debug(structs)writefln("- INVALID ([)>>>%s<<<", lines[pos]);
1492 else if ( std.string.find(lines[pos], "{") >= 0 )
1494 invalidDStruct = true;
1495 debug(structs)writefln("- INVALID ({)>>>%s<<<", lines[pos]);
1497 else if ( startsWith(std.string.strip(lines[pos]), '#') )
1499 // ignore
1500 debug(structs)writefln("= IGNORED >>>%s<<<", lines[pos]);
1502 else if ( !primitiveType(lines[pos]) )
1504 switch ( structName )
1507 // case "GtkWidget"
1508 // ,"GdkRectangle"
1509 // ,"GdkWindow"
1510 // ,"GObject"
1511 // ,"GtkAllocation"
1512 // :
1513 // // not invalid
1514 // break;
1516 default:
1517 if ( std.string.find(structName, "Event")>=0 )
1519 // try build a D struct
1521 else
1523 invalidDStruct = true;
1524 debug(structs)writefln("- INVALID (not primitive) >>>%s<<<", lines[pos]);
1526 break;
1529 else
1531 debug(structs)writefln("+ ADDED >>>%s<<<", lines[pos]);
1533 ++pos;
1537 if ( pos < lines.length )
1539 collectedStructs ~= "";
1540 char[] line = lines[pos];
1541 ++pos;
1542 char[] gtkStruct = convParms.realStrct.length > 0
1543 ? convParms.realStrct
1544 : convParms.strct;
1546 if ( pos < lines.length && lines[pos][0] > ' ' )
1548 collectedStructs ~= "/**";
1549 if ( structName == gtkStruct )
1551 collectedStructs ~= " * Main Gtk struct.";
1553 while ( pos < lines.length && lines[pos][0] > ' ' )
1555 collectedStructs ~= " * "~lines[pos++].dup;
1557 collectedStructs ~= " */";
1559 else if ( structName == gtkStruct )
1561 collectedStructs ~= "/**";
1562 collectedStructs ~= " * Main Gtk struct.";
1563 collectedStructs ~= " */";
1566 if ( (!invalidDStruct
1567 || "GValue"==structName
1568 || "GError"==structName
1570 && structDef.length>0 )
1572 collectedStructs ~= "public struct "~structName~"\n{";
1574 bool bitField = false; // if we are in a bit field
1576 foreach ( char[] def; structDef )
1578 char[] elem = stringToDuit(def, convParms, wrapper.getAliases());
1579 if ( std.string.find(def, ":") >= 0 )
1581 if ( !bitField )
1583 bitField = true;
1584 // just assume uint for now
1585 // TODO get the type
1586 collectedStructs ~= "\tuint bitfield;";
1587 collectedStructs ~= "//" ~ elem;
1590 else
1592 bitField = false;
1593 collectedStructs ~= elem;
1596 collectedStructs ~= "\n}";
1597 // char[] duitStructName;
1598 // if ( startsWith(structName, "Gtk")
1599 // || startsWith(structName, "Gdk")
1600 // )
1601 // {
1602 // duitStructName = structName[3..structName.length];
1603 // }
1604 // else if ( startsWith(structName, "G") )
1605 // {
1606 // duitStructName = structName[1..structName.length];
1607 // }
1608 // if ( duitStructName.length > 0
1609 // && "Color"!=duitStructName
1610 // && "Rectangle"!=duitStructName
1611 // && "Bitmap"!=duitStructName
1612 // )
1613 // {
1614 // collectedStructs ~= "\nalias "~structName~" "~duitStructName~";\n";
1615 // }
1617 else //if ( structDef.length > 0 )
1619 switch ( structName )
1621 // TODO "public struct GdkEventClient;" comfuses DMD!!!???
1622 case "GdkEventClient":
1623 collectedStructs ~= "public struct "~structName~"{}";
1624 break;
1626 default:
1627 collectedStructs ~= "public struct "~structName~"{}";
1628 break;
1630 foreach ( char[] def; structDef )
1632 collectedStructs ~= "// "~stringToDuit(def, convParms, wrapper.getAliases());
1633 collectedStructs ~= "// "~convParms.inFile;
1636 collectedStructs ~= "";
1640 bit primitiveType(char[] line)
1642 int p=0;
1643 skipBlank(p, line);
1644 char[] type = untilBlank(p, line);
1645 return (type in wrapper.getAliases()) !is null;
1648 public static void skipBlank(inout int p, char[] text)
1650 while( p<text.length && text[p]<=' ' )
1652 ++p;
1656 public static void skip(inout int p, char[] text, char s)
1658 while( p<text.length && text[p]==s)
1660 ++p;
1664 public static char[] untilBlank(inout int p, char[] text)
1666 int start=p;
1667 while ( p<text.length && text[p]>' ')
1669 ++p;
1671 return text[start..p];
1674 public static char[] untilBlank(inout int p, char[] text, char[] s)
1676 int start=p;
1677 while ( p<text.length && text[p]>' ' && std.string.find(s,text[p])<0 )
1679 ++p;
1681 return text[start..p];
1684 public static char[] until(inout int p, char[] text, char s)
1686 int start=p;
1687 while ( p<text.length && text[p]!=s)
1689 ++p;
1691 return text[start..p];
1694 public static char[] until(inout int p, char[] text, char[] s)
1696 int start=p;
1697 while ( p<text.length && std.string.find(s,text[p])<0 )
1699 ++p;
1701 return text[start..p];
1704 private char[] getFunctionDeclaration(inout int line, char[][] lines)
1706 char[] funct;
1707 while ( line<lines.length
1708 && (!endsWith(lines[line], ");")
1709 && !startsWith(funct, "#define"))
1712 funct ~= lines[line]~ " ";
1713 debug(endFunction)writefln("funct line = >>>%s<<< endWith(\");\") = ",
1714 lines[line],
1715 endsWith(lines[line], ");")
1717 ++line;
1719 if ( line<lines.length && endsWith(lines[line], ");") )
1721 funct ~= lines[line++];
1724 return funct;
1727 private char[][] getFunction(char[][] lines, char[][] prefixes)
1729 char[][] member;
1731 int line = 1;
1733 char[] funct = getFunctionDeclaration(line, lines);
1735 Funct fun;
1736 fun.init(funct, convParms);
1740 * Checks restrictions on the functions to include
1741 * Params:
1742 * lines =
1743 * prefix =
1744 * Returns:
1746 bit includeFunction(ConvParms* convParms)
1748 bit inc = true;
1750 int nPrefix = 0;
1751 while ( inc && nPrefix<convParms.noPrefixes.length )
1753 debug(noPrefixes)writefln("\ttest noPrefix %s ?= %s", fun.name, convParms.noPrefixes[nPrefix]);
1754 inc = !startsWith(fun.name, convParms.noPrefixes[nPrefix++]);
1756 if ( inc )
1758 inc = false;
1760 if ( convParms.containsPrefix(fun.name) )
1762 debug(noPrefixes)writefln("included by name");
1763 inc = true;
1765 else if ( convParms.strictPrefix && convParms.prefixes.length>0 )
1767 debug(noPrefixes) writefln("dropped by strictPrefix");
1768 inc = false;
1770 else
1772 inc = true;
1773 debug(noPrefixes)if ( !inc) writefln("dropped by noPrefixes");
1776 //debug(noPrefixes)writefln("%s : %s (%s)", (inc?"included":"dropped"),fun.name, convParms.prefix);
1777 return inc;
1780 if ( includeFunction(convParms) )
1782 if ( funct[0] == '#' )
1784 if ( !convParms.strictPrefix )
1786 collectedTypes ~= "";
1787 debug(defines)writefln("it's define: %s",funct);
1788 // comment
1789 if ( wrapper.includeComments() )
1791 collectedTypes ~= "/*";
1792 while ( line<lines.length )
1794 collectedTypes ~= " * "~lines[line++];
1796 collectedTypes ~= " */";
1798 collectedTypes ~= "// TODO";
1799 // body
1800 collectedTypes ~= "// "~funct;
1804 else
1806 debug(functName) writefln("funct name = %s", fun.name);
1807 if ( fun.name.length==0 || fun.name[0] == '(' )
1809 if ( !isInterface )
1811 if ( !convParms.strictPrefix )
1813 collectedFuncts ~= "";
1814 // comment
1815 if ( wrapper.includeComments() )
1817 collectedFuncts ~= "/*";
1818 while ( line<lines.length )
1820 collectedFuncts ~= " * "~lines[line++];
1822 collectedFuncts ~= " */";
1823 collectedFuncts ~= "// "~funct;
1825 // body
1826 collectedFuncts ~= getFunction(funct, convParms);
1830 else // the regular function
1832 bit tooSoon = false; // reject for 2.10
1833 // comment
1834 void addComments()
1836 if ( wrapper.includeComments() )
1838 member ~= "/**";
1839 while ( line<lines.length )
1841 //if ( !tooSoon )
1843 // tooSoon = lines[line]=="Since 2.10";
1845 member ~= " * "~lines[line++];
1847 member ~= " */";
1851 if ( tooSoon )
1853 addComments();
1854 member ~= "// next release";
1856 else
1858 if ( !isInterface )
1860 externalDeclarations ~= fun.getExternal(convParms, wrapper.getAliases());
1862 // body
1863 if ( !convParms.omitCode(fun.name) )
1865 char[] rawDeclaration = fun.declaration(convParms,wrapper.getAliases());
1866 char[] duitDeclaration = stringToDuit(rawDeclaration,convParms,wrapper.getAliases());
1867 debug(declaration) writefln("Declaration\n\t%s\n\t%s",rawDeclaration, duitDeclaration);
1868 addComments();
1869 member ~= duitDeclaration~iFaceChar;
1870 if ( !isInterface )
1872 member ~= "{";
1873 member ~= "// "~funct;
1874 version( noGtkBody )
1876 // switch ( fun.typeWrap )
1877 // {
1878 // case "void": break;
1879 // case "int", "uint", "bit", "long", "ulong"
1880 // member ~= "return 0;";
1881 // break;
1883 // case "int", "uint", "bit", "long", "ulong"
1884 // member ~= "return 0;";
1885 // break;
1887 // case "char[]": member ~= "return "";"; break;
1888 // default: member ~= "return null;"; break;
1889 // }
1891 else
1893 member ~= fun.bod(convParms, wrapper.getAliases());
1895 member ~= "}";
1897 checkIfDupFunction(fun);
1898 checkIfGtkStructs(fun);
1905 return member;
1908 private void checkIfDupFunction(Funct fun)
1910 char[] signature = fun.convName~'('~fun.getWrapParametersType()~')';
1911 if ( signature in functionSignatures )
1913 writefln("######################## duplicated function %s", signature);
1915 else
1917 functionSignatures[signature] = 1;
1923 * Prints out the potential Gtk struct to be wrapped
1924 * so that the wrap parameter can be set on the APILookupXXX.txt
1925 * TODO assume all structs are to be wrapped an explicitly declare the ones not to be wrapped
1926 * Params:
1927 * fun =
1929 private void checkIfGtkStructs(Funct fun)
1931 bit found = false;
1932 void check(char[] type)
1934 if ( startsWith(type, 'G')
1935 && endsWith(type, '*')
1938 if ( type in gtkStructs )
1940 // nothing
1942 else
1944 found = true;
1945 gtkStructs[type] = 1;
1946 //writefln("######################## Gtk struct found %s\t\t%s",
1947 // type,
1948 // fun.convName~"("~fun.getWrapParametersType()~")"
1949 // );
1951 char[] strct = type.dup;
1952 char[] dName = "";
1953 char[] pack = "";
1954 if ( startsWith(strct, "Gtk") )
1956 pack = "gtk";
1957 dName = strct[3..strct.length-1];
1958 //dName[0] = std.ctype.tolower(dName[0]);
1960 else if ( startsWith(strct, "Gdk") )
1962 pack = "gdk";
1963 dName = strct[3..strct.length-1];
1964 //dName[0] = std.ctype.tolower(dName[0]);
1965 if ( dName == "Pixbuf") pack = "gdkpixbuf";
1967 else if ( startsWith(strct, "G") )
1969 dName = strct[1..strct.length-1];
1970 switch ( dName )
1972 case "Object":
1974 if ( pack == "g" )
1976 pack = "gobject"; dName = "ObjectG";
1978 else if ( pack == "gdk" )
1980 dName = "ObjectG";
1982 else if ( pack == "gtk" )
1984 dName = "ObjectGtk";
1986 else if ( pack == "atk" )
1988 dName = "ObjectAtk";
1990 break;
1991 case "Closure": pack = "gobject"; break;
1992 case "Type": pack = "gobject"; break;
1993 case "Value": pack = "gobject"; break;
1994 case "List": pack = "glib"; dName = "ListG"; break;
1995 case "SList": pack = "glib"; dName = "ListSG"; break;
1996 case "String": pack = "glib"; dName = "StringG"; break;
1997 case "IOChannel": pack = "glib"; break;
1998 case "Quark": pack = "glib"; break;
1999 case "ParmSpec": pack = "gobject"; break;
2000 case "TypeModule": pack = "gobject"; break;
2001 case "Flags": pack = "gobject"; break;
2002 case "Enums": pack = "gobject"; break;
2003 default:
2004 pack = "g";
2005 break;
2008 debug(structs)writefln("import: %s.%s", pack, dName);
2009 debug(structs)writefln("structWrap: %s %s", strct, dName);
2014 if ( !fun.ctor
2015 && !endsWith(fun.convName, "Struct")
2018 check(fun.typeWrap);
2020 foreach ( int count , char[] parm ; fun.parmsWrap )
2022 if ( count > 0 || parm != convParms.strct~'*' )
2024 check(parm);
2030 * Params:
2031 * line = The API line of the function
2032 * convParms = the Conversion parameters
2033 * Returns:
2035 private char[] getFunction(char[] line, ConvParms* convParms)
2037 debug(functionType) writefln("\ngetFunction line = %s", line);
2038 // void (*GChildWatchFunc) (GPid pid, gint status, gpointer data);
2039 // public typedef extern(C) void function(int, int, void*) GChildWatchFunc;
2040 char[] f = "public typedef extern(C) ";
2041 int pos = 0;
2042 char[] type = until(pos, line, "(");
2043 until(pos, line, "*");
2044 skip(pos, line, '*');
2045 char[] name = until(pos, line, ")");
2047 //adjustTypeName(type, name);
2049 f ~= stringToDuit(type, convParms, wrapper.getAliases());
2050 f ~= " function (";
2052 until(pos, line, "(");
2053 skip(pos, line, '(');
2054 skipBlank(pos, line);
2056 char[] sourceParms = std.string.strip(until(pos, line, ")"));
2057 char[] parms;
2059 if ( sourceParms != "void" )
2061 int sPos = 0;
2062 int count = 0;
2063 debug(functionType) writefln("sourceParms = %s", sourceParms);
2064 while ( sPos < sourceParms.length )
2066 skipBlank(sPos, sourceParms);
2067 debug(functionType)writefln("parms sPos=%s [%s]",sPos, sourceParms[sPos..sourceParms.length]);
2068 if (count++ > 0 )
2070 parms ~= ", ";
2072 char[] pType = untilBlank(sPos, sourceParms);
2073 fixType(pType, sPos, sourceParms);
2075 char[] pName = until(sPos, sourceParms, ",)");
2077 debug(parmType)writefln("\tParameter type before = %s", pType);
2078 debug(parmName)writefln("\tParameter name before = %s", pName);
2079 adjustTypeName(pType, pName);
2080 debug(parmType)writefln("\tParameter type after = %s", pType);
2081 debug(parmName)writefln("\tParameter name after = %s", pName);
2083 parms ~= tokenToDuit(pType, convParms, wrapper.getAliases());
2084 ++sPos;
2088 f ~= parms ~ ") " ~ name ~ ";";
2090 return f;
2094 * Wraps a set of lines in the block documentation comment
2095 * Returns: The comment formated for D block documentation comment
2097 private char[][] getDescription()
2099 char[][] desc;
2100 desc ~= "";
2101 desc ~= tabs ~ "/**";
2102 char[][] block = getBlock ("Description", "Details");
2103 foreach ( char[] line; block )
2105 desc ~= " * " ~ line;
2107 desc ~= tabs ~ " */";
2109 return desc;
2114 * Finds a block of lines delimited by the marker lines from the start of the text
2115 * Params:
2116 * startLine = The Start marker line
2117 * endLine = The end marker line
2118 * Returns: The block os lines
2120 private char[][] getBlock(char[] startLine, char[] endLine)
2122 currLine = 0;
2124 debug(getBlock) writefln("getBlock for ]%s,%s[", startLine, endLine);
2126 // TODO use slicing instead of this array
2127 char[][] block;
2129 while ( currLine<inLines.length && inLines[currLine]!=startLine )
2131 debug(getBlock) writefln("-\t\t[%s]%s",currLine,inLines[currLine]);
2132 ++currLine;
2135 return getUntil(endLine);
2138 private int moveToBlockStart(char[] startLine, char[][] inLines)
2140 int startPos = 0;
2141 while ( startPos < inLines.length && inLines[startPos]!= startLine )
2143 ++startPos;
2145 return startPos;
2149 * Gets all the non empty lines until a marker line
2150 * Params:
2151 * endLine = the marker line
2152 * Returns:
2154 private char[][] getUntil(char[] endLine)
2156 bit end = false;
2158 char[][] block;
2160 while ( currLine < inLines.length && !end )
2162 if ( inLines[currLine] == endLine )
2164 end = true;
2165 debug(getUntil) writefln("getBlock end at line %s",currLine,"\n");
2167 else
2169 if ( std.string.strip(inLines[currLine]).length > 0 )
2171 block ~= inLines[currLine];
2173 debug(getUntil) writefln("+[%s]%s",currLine,inLines[currLine]);
2175 ++currLine;
2177 return block;
2181 * Converts a GTK strin to a Duit string.
2182 * This removes the "_" and capitalises the next letter and converts the basic types
2183 * Params:
2184 * gString =
2185 * Returns:
2187 public static char[] stringToDuit(char[] gString, ConvParms* convParms, char[][char[]] aliases, bit caseConvert=true)
2189 char[] converted;
2191 int pos = 0 ;
2192 char[] seps = " \n\r\t\f\v()[]*,;";
2194 char c = ' ';
2195 char pc;
2196 int start = 0;
2197 int end = 0;
2198 while ( pos < gString.length )
2200 pc = c;
2201 c = gString[pos];
2202 if ( std.string.find(seps,c) >= 0 )
2204 end = pos;
2205 converted ~= tokenToDuit(gString[start..end], convParms, aliases, caseConvert);
2206 if ( c=='*' )
2208 //if ( pc==' ' )
2210 // converted.length = converted.length-1;
2212 //converted ~= "[] ";
2213 converted ~= c;
2216 else if ( c<=' ' )
2218 if ( converted.length >0 && converted[converted.length-1] != ' ' )
2220 converted ~= ' ';
2222 c = ' ';
2224 else
2226 converted ~= c;
2228 start = pos+1;
2230 ++pos;
2232 if ( pos > start )
2234 converted ~= tokenToDuit(gString[start..pos], convParms, aliases, caseConvert);
2236 return converted;
2240 public static char[] idsToDuit(char[] gToken, ConvParms* convParms, char[][char[]] aliases, bit caseConvert=true)
2242 char[] converted = tokenToDuit(gToken, convParms, aliases, caseConvert);
2243 switch ( converted )
2245 case "alias" : converted = "alia"; break;
2246 case "class" : converted = "clss"; break;
2247 default:
2248 // done
2249 break;
2251 return converted;
2255 * Convert for normal Duit conversion and after verifies if is necessary to use a enumType for references enum values
2256 * Params:
2257 * enumType =
2258 * gToken =
2259 * convParms =
2260 * aliases =
2261 * caseConvert =
2262 * Returns:
2264 public static char[] enumToDuit(char[] enumType, char[] gToken, ConvParms* convParms, WrapperIF wrapper, bit caseConvert=true)
2266 debug(enumToDuit)writefln("enumLine (%s) BEFORE %s", enumType, gToken);
2267 char[] converted = stringToDuit(gToken, convParms, wrapper.getAliases());
2269 int pos = std.string.find(converted, '=');
2270 debug(enumToDuit)writefln("\t pos = %s", pos);
2271 if ( pos > 0 )
2273 char[] refValue = std.string.strip(converted.dup[pos+1..converted.length]);
2274 debug(enumToDuit)writefln("\t refValue = %s", refValue);
2275 bit needComa = false;
2276 if ( endsWith(refValue, ',') )
2278 refValue = std.string.strip(refValue[0..refValue.length-1]);
2279 needComa = true;
2281 debug(enumToDuit)writefln("\t refValue = %s", refValue);
2283 debug(enumToDuit)
2285 foreach(char[] key ; wrapper.getEnumTypes().keys)
2287 writefln("\t\t [%s] = %s", key, wrapper.getEnumTypes()[key]);
2291 if ( refValue in wrapper.getEnumTypes() )
2293 converted = converted[0..pos+1]
2294 ~ " "
2295 ~ wrapper.getEnumTypes()[refValue]
2296 //~ "."
2297 //~ refValue
2298 ~ (needComa ? "," : "" )
2302 debug(enumToDuit)writefln("enumLine (%s) AFTER %s", enumType, converted);
2304 return converted;
2308 * Converts a GTK token to a Dui token
2309 * This removes the "_" and capitalises the next letter and converts the basic types.
2310 * Doesn't do it if it's cairo name
2311 * Params:
2312 * gToken =
2313 * Returns:
2315 public static char[] tokenToDuit(char[] gToken, ConvParms* convParms, char[][char[]] aliases, bit caseConvert=true)
2317 char[] converted;
2319 //debug(tokenToDuit) writefln("gToken=>>>%s<<< (prefix=%s)", gToken, convParms.prefix);
2321 if ( (aliases !is null) && (gToken in aliases) )
2323 converted = aliases[gToken];
2325 else if ( endsWith(gToken, "_t") && startsWith(gToken,"cairo_") )
2327 converted = gToken.dup;
2329 else if ( caseConvert )
2331 removePrefix(gToken, convParms);
2332 converted = removeUnderscore(gToken);
2333 // do it again after the gToken is converted
2334 if ( (aliases !is null) && (gToken in aliases) )
2336 converted = aliases[gToken];
2339 else
2341 converted = gToken.dup;
2344 debug(tokenToDuit) writefln("converted=>>>%s<<<\n", converted);
2346 return converted;
2350 public static char[] removePrefix(inout char[] gToken, char[] prefix)
2352 if ( startsWith(gToken, prefix) )
2354 gToken = gToken[prefix.length..gToken.length];
2356 return gToken;
2359 public static char[] removePrefix(inout char[] gToken, ConvParms* convParms)
2361 //debug(tokenToDuit) writefln("gToken.length > prefix.length %s",gToken.length > convParms.prefix.length);
2362 char[] prefix = convParms.getPrefix(gToken);
2363 if ( prefix.length > 0 )
2365 gToken = gToken[prefix.length..gToken.length];
2367 debug(tokenToDuit) writefln("gToken after prefix = %s",gToken);
2369 return gToken;
2373 public static char[] removeUnderscore(char[] gToken)
2375 char[] converted;
2377 char c = ' ';
2378 char pc = ' ';
2379 char ppc = ' ';
2380 int pos = 0;
2381 while ( pos < gToken.length )
2383 c = gToken[pos];
2384 if ( pc == '_' )
2386 c = std.ctype.toupper(c);
2388 else if ( c == '_' && std.ctype.islower(pc) )
2390 pc = c;
2391 c = '\0';
2394 if ( c > '\0' )
2396 if ( ppc == '_'
2397 && pc == 'g'
2398 && c == 'l'
2399 && gToken.length-1 > pos
2400 && gToken[pos+1] == '_'
2403 c = 'L';
2405 ppc = pc;
2406 pc = gToken[pos];
2407 converted ~= c;
2409 ++pos;
2411 return converted;
2416 * Moves '*' and 'const' and trailing '[]' from the name to the type token
2417 * Params:
2418 * type =
2419 * name =
2421 public static void adjustTypeName(inout char[] type, inout char[] name)
2423 debug(type)writefln("type before %s", type);
2424 debug(name)writefln("name before %s", name);
2425 name = std.string.strip(name);
2426 while ( name.length > 0
2427 && (DuitClass.startsWith(name,"const") || name[0] == '*' )
2430 if ( name[0] == '*' )
2432 type ~= '*';
2433 name = std.string.strip(name[1..name.length]);
2435 else
2437 name = std.string.strip(name[5..name.length]);
2439 name = std.string.strip(name);
2441 while ( DuitClass.endsWith(name, "[]") )
2443 type ~= "[]";
2444 name = std.string.strip(name[0..name.length-2]);
2446 debug(type)writefln("type after %s", type);
2447 debug(name)writefln("name after %s", name);
2451 * Consumes "const" and "unsigned" adding "u" to the type when "unsigned" is found
2452 * (? uchar will become just char)
2453 * Params:
2454 * type =
2455 * p =
2456 * text =
2458 public static void fixType(inout char[] type, inout int p, inout char[] text)
2460 if ( type == "const" )
2462 DuitClass.skipBlank(p, text);
2463 type = untilBlank(p, text);
2465 if ( type == "unsigned" )
2467 DuitClass.skipBlank(p, text);
2468 type = "u" ~ untilBlank(p, text);
2470 // if ( type == "uchar" )
2471 // {
2472 // type = "char";
2473 // }
2479 public static bit startsWith(char[] str, char[] prefix)
2481 return str.length >= prefix.length
2482 && str[0..prefix.length] == prefix;
2485 public static bit startsWith(char[] str, char prefix)
2487 return str.length > 0
2488 && str[0] == prefix;
2491 public static bit endsWith(char[] str, char[] suffix)
2493 return str.length >= suffix.length
2494 && str[str.length-suffix.length..str.length] == suffix;
2497 public static bit endsWith(char[] str, char suffix)
2499 return str.length >= 1
2500 && str[str.length-1] == suffix;