1 #include "bindto.h"
2 
3 //(*InternalHeaders(Bindto)
4 #include <wx/intl.h>
5 #include <wx/string.h>
6 //*)
7 
8 #ifndef CB_PRECOMP
9     #include <wx/regex.h>
10     #include <wx/tokenzr.h>
11     #include <wx/textdlg.h>
12     #include <wx/dirdlg.h>
13     #include <wx/msgdlg.h>
14 
15     #include <editormanager.h>
16     #include <cbstyledtextctrl.h>
17     #include <configmanager.h>
18     #include <projectmanager.h>
19     #include <logmanager.h>
20     #include <cbproject.h>
21     #include <compilerfactory.h>
22 #endif
23 
24 //(*IdInit(Bindto)
25 const long Bindto::ID_BTOACTIVEPROJECT = wxNewId();
26 const long Bindto::ID_BTOCURRENTFILE = wxNewId();
27 const long Bindto::ID_TEXTCTRL1 = wxNewId();
28 const long Bindto::ID_STATICTEXT5 = wxNewId();
29 const long Bindto::ID_CHECKBOX9 = wxNewId();
30 const long Bindto::ID_CHECKBOX3 = wxNewId();
31 const long Bindto::ID_TEXTCTRL6 = wxNewId();
32 const long Bindto::ID_STATICTEXT1 = wxNewId();
33 const long Bindto::ID_TEXTCTRL7 = wxNewId();
34 const long Bindto::ID_BUTTON1 = wxNewId();
35 const long Bindto::ID_PANEL2 = wxNewId();
36 const long Bindto::ID_LV_TYPES = wxNewId();
37 const long Bindto::ID_BUTTON_ADD = wxNewId();
38 const long Bindto::ID_BUTTON_COPY = wxNewId();
39 const long Bindto::ID_BUTTON_EDIT = wxNewId();
40 const long Bindto::ID_BUTTON_REMOVE = wxNewId();
41 const long Bindto::ID_BUTTON_DEFAULTS = wxNewId();
42 const long Bindto::ID_PANEL1 = wxNewId();
43 const long Bindto::ID_CHECKBOX4 = wxNewId();
44 const long Bindto::ID_TEXTCTRL4 = wxNewId();
45 const long Bindto::ID_CHECKBOX5 = wxNewId();
46 const long Bindto::ID_TEXTCTRL5 = wxNewId();
47 const long Bindto::ID_PANEL3 = wxNewId();
48 const long Bindto::ID_CHECKBOX1 = wxNewId();
49 const long Bindto::ID_TEXTCTRL2 = wxNewId();
50 const long Bindto::ID_CHECKBOX2 = wxNewId();
51 const long Bindto::ID_TEXTCTRL3 = wxNewId();
52 const long Bindto::ID_PANEL4 = wxNewId();
53 const long Bindto::ID_CHECKBOX6 = wxNewId();
54 const long Bindto::ID_TEXTCTRL8 = wxNewId();
55 const long Bindto::ID_CHECKBOX7 = wxNewId();
56 const long Bindto::ID_CHECKBOX8 = wxNewId();
57 const long Bindto::ID_PANEL6 = wxNewId();
58 const long Bindto::ID_PANEL5 = wxNewId();
59 const long Bindto::ID_NOTEBOOK1 = wxNewId();
60 //*)
61 
62 BEGIN_EVENT_TABLE(Bindto,wxDialog)
63 	//(*EventTable(Bindto)
64 	//*)
65 	EVT_BUTTON  (wxID_OK, Bindto::OnOK)
66 END_EVENT_TABLE()
67 
68 wxString DIM_VAR_KEY = _T("<<@%%@>>");
69 wxString DIM_VAR_KEY2 = _T("&&@%%@&&");
70 wxString PROCNAME_KEY = _T("$procname$");
71 wxString MODULENAME_KEY = _T("$modulename$");
72 wxString MODNAME_KEY = _T("$modname$");
73 wxString CIMPORT_FN_KEY = _T("%%%##@@@@cimport file name%%%@@@");
74 wxString USEMODTDEF_KEY = _T("$#$#%^@@place for use of modules with type definitions$#@%");
75 
Bindto(wxWindow * parent,ParserF * pParser)76 Bindto::Bindto(wxWindow* parent, ParserF* pParser)
77 {
78 	//(*Initialize(Bindto)
79 	wxBoxSizer* BoxSizer10;
80 	wxBoxSizer* BoxSizer11;
81 	wxBoxSizer* BoxSizer12;
82 	wxBoxSizer* BoxSizer13;
83 	wxBoxSizer* BoxSizer14;
84 	wxBoxSizer* BoxSizer15;
85 	wxBoxSizer* BoxSizer16;
86 	wxBoxSizer* BoxSizer17;
87 	wxBoxSizer* BoxSizer18;
88 	wxBoxSizer* BoxSizer19;
89 	wxBoxSizer* BoxSizer1;
90 	wxBoxSizer* BoxSizer20;
91 	wxBoxSizer* BoxSizer2;
92 	wxBoxSizer* BoxSizer3;
93 	wxBoxSizer* BoxSizer4;
94 	wxBoxSizer* BoxSizer5;
95 	wxBoxSizer* BoxSizer6;
96 	wxBoxSizer* BoxSizer7;
97 	wxBoxSizer* BoxSizer8;
98 	wxBoxSizer* BoxSizer9;
99 	wxFlexGridSizer* FlexGridSizer1;
100 	wxFlexGridSizer* FlexGridSizer2;
101 	wxNotebook* nb_settings;
102 	wxPanel* Panel3;
103 	wxStaticText* StaticText10;
104 	wxStaticText* StaticText12;
105 	wxStaticText* StaticText13;
106 	wxStaticText* StaticText14;
107 	wxStaticText* StaticText15;
108 	wxStaticText* StaticText1;
109 	wxStaticText* StaticText2;
110 	wxStaticText* StaticText3;
111 	wxStaticText* StaticText4;
112 	wxStaticText* StaticText5;
113 	wxStaticText* StaticText9;
114 	wxStdDialogButtonSizer* StdDialogButtonSizer1;
115 
116 	Create(parent, wxID_ANY, _("Bind To"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER, _T("wxID_ANY"));
117 	BoxSizer1 = new wxBoxSizer(wxVERTICAL);
118 	BoxSizer6 = new wxBoxSizer(wxHORIZONTAL);
119 	nb_settings = new wxNotebook(this, ID_NOTEBOOK1, wxDefaultPosition, wxDefaultSize, 0, _T("ID_NOTEBOOK1"));
120 	Panel2 = new wxPanel(nb_settings, ID_PANEL2, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL2"));
121 	BoxSizer7 = new wxBoxSizer(wxVERTICAL);
122 	StaticText1 = new wxStaticText(Panel2, wxID_ANY, _("This tool generates a wrapping for Fortran code to be called from the C language."), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
123 	BoxSizer7->Add(StaticText1, 0, wxALL|wxALIGN_LEFT, 5);
124 	StaticText2 = new wxStaticText(Panel2, wxID_ANY, _("Generate wrapping for:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
125 	BoxSizer7->Add(StaticText2, 0, wxTOP|wxLEFT|wxRIGHT|wxALIGN_LEFT, 5);
126 	BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
127 	BoxSizer3->Add(30,0,0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
128 	rb_ActiveProject = new wxRadioButton(Panel2, ID_BTOACTIVEPROJECT, _("Active project"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP, wxDefaultValidator, _T("ID_BTOACTIVEPROJECT"));
129 	BoxSizer3->Add(rb_ActiveProject, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
130 	rb_CurrentFile = new wxRadioButton(Panel2, ID_BTOCURRENTFILE, _("Current file"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BTOCURRENTFILE"));
131 	BoxSizer3->Add(rb_CurrentFile, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
132 	BoxSizer7->Add(BoxSizer3, 0, wxALL|wxALIGN_LEFT, 5);
133 	BoxSizer8 = new wxBoxSizer(wxHORIZONTAL);
134 	StaticText5 = new wxStaticText(Panel2, wxID_ANY, _("BIND(C, name=#):"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
135 	BoxSizer8->Add(StaticText5, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
136 	tc_bindCName = new wxTextCtrl(Panel2, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
137 	tc_bindCName->SetToolTip(_("Write how the names called from C code will be constructed.\nVariables \"$procname$\", \"$modulename$\" and \"$modname$\" will be changed procedure, module and truncated module names corespondingly."));
138 	BoxSizer8->Add(tc_bindCName, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5);
139 	BoxSizer7->Add(BoxSizer8, 0, wxEXPAND, 5);
140 	StaticText16 = new wxStaticText(Panel2, ID_STATICTEXT5, _("Note: $procname$ is changed to the original name of procedure;\n         $modulename$ is changed to the name of module;\n         $modname$ is changed to the truncated name of module."), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT5"));
141 	BoxSizer7->Add(StaticText16, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT, 5);
142 	cb_incompleteWrapperProc = new wxCheckBox(Panel2, ID_CHECKBOX9, _("Don\'t write incomplete (with errors) wrapper procedures"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX9"));
143 	cb_incompleteWrapperProc->SetValue(false);
144 	BoxSizer7->Add(cb_incompleteWrapperProc, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT, 5);
145 	BoxSizer15 = new wxBoxSizer(wxVERTICAL);
146 	cb_globalToOne = new wxCheckBox(Panel2, ID_CHECKBOX3, _("Add wrapper code for global procedures into one file"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX3"));
147 	cb_globalToOne->SetValue(false);
148 	BoxSizer15->Add(cb_globalToOne, 1, wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5);
149 	BoxSizer16 = new wxBoxSizer(wxHORIZONTAL);
150 	BoxSizer16->Add(30,0,0, wxALIGN_CENTER_VERTICAL, 5);
151 	st_globalFilename = new wxStaticText(Panel2, wxID_ANY, _("File name:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
152 	BoxSizer16->Add(st_globalFilename, 0, wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
153 	tc_globalFilename = new wxTextCtrl(Panel2, ID_TEXTCTRL6, _("myprocedures.f90"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL6"));
154 	BoxSizer16->Add(tc_globalFilename, 1, wxLEFT|wxRIGHT|wxEXPAND, 5);
155 	BoxSizer15->Add(BoxSizer16, 1, wxEXPAND, 5);
156 	BoxSizer7->Add(BoxSizer15, 0, wxTOP|wxBOTTOM|wxALIGN_LEFT, 5);
157 	BoxSizer17 = new wxBoxSizer(wxHORIZONTAL);
158 	StaticText7 = new wxStaticText(Panel2, ID_STATICTEXT1, _("Output dir:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
159 	BoxSizer17->Add(StaticText7, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
160 	tc_OutputDir = new wxTextCtrl(Panel2, ID_TEXTCTRL7, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL7"));
161 	BoxSizer17->Add(tc_OutputDir, 1, wxALIGN_CENTER_VERTICAL, 5);
162 	bt_OutputDir = new wxButton(Panel2, ID_BUTTON1, _("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON1"));
163 	BoxSizer17->Add(bt_OutputDir, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
164 	BoxSizer7->Add(BoxSizer17, 0, wxALL|wxEXPAND, 0);
165 	Panel2->SetSizer(BoxSizer7);
166 	BoxSizer7->Fit(Panel2);
167 	BoxSizer7->SetSizeHints(Panel2);
168 	Panel1 = new wxPanel(nb_settings, ID_PANEL1, wxPoint(314,298), wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
169 	BoxSizer2 = new wxBoxSizer(wxVERTICAL);
170 	BoxSizer4 = new wxBoxSizer(wxVERTICAL);
171 	StaticText3 = new wxStaticText(Panel1, wxID_ANY, _("Binding types"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
172 	BoxSizer4->Add(StaticText3, 0, wxTOP|wxLEFT|wxRIGHT|wxALIGN_LEFT, 5);
173 	lv_Types = new wxListView(Panel1, ID_LV_TYPES, wxDefaultPosition, wxSize(500,300), wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES|wxBORDER_SUNKEN, wxDefaultValidator, _T("ID_LV_TYPES"));
174 	BoxSizer4->Add(lv_Types, 1, wxTOP|wxBOTTOM|wxEXPAND, 5);
175 	BoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
176 	bt_Add = new wxButton(Panel1, ID_BUTTON_ADD, _("Add"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_ADD"));
177 	bt_Add->SetToolTip(_("Add a new type"));
178 	BoxSizer5->Add(bt_Add, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
179 	bt_copy = new wxButton(Panel1, ID_BUTTON_COPY, _("Copy"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_COPY"));
180 	bt_copy->SetToolTip(_("Copy selected type to a new one"));
181 	BoxSizer5->Add(bt_copy, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
182 	bt_Edit = new wxButton(Panel1, ID_BUTTON_EDIT, _("Edit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_EDIT"));
183 	bt_Edit->SetToolTip(_("Edit selected type"));
184 	BoxSizer5->Add(bt_Edit, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
185 	bt_Remove = new wxButton(Panel1, ID_BUTTON_REMOVE, _("Remove"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_REMOVE"));
186 	bt_Remove->SetToolTip(_("Remove selected type"));
187 	BoxSizer5->Add(bt_Remove, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
188 	BoxSizer5->Add(-1,-1,1, wxALIGN_CENTER_VERTICAL, 5);
189 	bt_Defaults = new wxButton(Panel1, ID_BUTTON_DEFAULTS, _("Defaults"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_DEFAULTS"));
190 	bt_Defaults->SetToolTip(_("Restore default binding types"));
191 	BoxSizer5->Add(bt_Defaults, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
192 	BoxSizer4->Add(BoxSizer5, 0, wxALL|wxEXPAND, 5);
193 	BoxSizer2->Add(BoxSizer4, 1, wxTOP|wxBOTTOM|wxEXPAND, 5);
194 	Panel1->SetSizer(BoxSizer2);
195 	BoxSizer2->Fit(Panel1);
196 	BoxSizer2->SetSizeHints(Panel1);
197 	Panel3 = new wxPanel(nb_settings, ID_PANEL3, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL3"));
198 	BoxSizer10 = new wxBoxSizer(wxVERTICAL);
199 	StaticText4 = new wxStaticText(Panel3, wxID_ANY, _("Recognize procedure, which name starts/ends with # as a constructor:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
200 	BoxSizer10->Add(StaticText4, 0, wxALL|wxALIGN_LEFT, 5);
201 	BoxSizer11 = new wxBoxSizer(wxHORIZONTAL);
202 	BoxSizer12 = new wxBoxSizer(wxHORIZONTAL);
203 	BoxSizer12->Add(30,0,0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
204 	FlexGridSizer2 = new wxFlexGridSizer(2, 2, 2, 1);
205 	cb_ctorStart = new wxCheckBox(Panel3, ID_CHECKBOX4, _("Constructor starts with:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX4"));
206 	cb_ctorStart->SetValue(false);
207 	FlexGridSizer2->Add(cb_ctorStart, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
208 	tc_ctorStart = new wxTextCtrl(Panel3, ID_TEXTCTRL4, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL4"));
209 	FlexGridSizer2->Add(tc_ctorStart, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
210 	cb_ctorEnd = new wxCheckBox(Panel3, ID_CHECKBOX5, _("Constructor ends with:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX5"));
211 	cb_ctorEnd->SetValue(false);
212 	FlexGridSizer2->Add(cb_ctorEnd, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
213 	tc_ctorEnd = new wxTextCtrl(Panel3, ID_TEXTCTRL5, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL5"));
214 	FlexGridSizer2->Add(tc_ctorEnd, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
215 	BoxSizer12->Add(FlexGridSizer2, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
216 	BoxSizer11->Add(BoxSizer12, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
217 	BoxSizer10->Add(BoxSizer11, 0, wxALL|wxALIGN_LEFT, 0);
218 	Panel3->SetSizer(BoxSizer10);
219 	BoxSizer10->Fit(Panel3);
220 	BoxSizer10->SetSizeHints(Panel3);
221 	Panel4 = new wxPanel(nb_settings, ID_PANEL4, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL4"));
222 	BoxSizer9 = new wxBoxSizer(wxVERTICAL);
223 	StaticText9 = new wxStaticText(Panel4, wxID_ANY, _("Recognize subroutine, which name starts/ends with # as a destructor:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
224 	BoxSizer9->Add(StaticText9, 0, wxALL|wxALIGN_LEFT, 5);
225 	BoxSizer13 = new wxBoxSizer(wxHORIZONTAL);
226 	BoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
227 	BoxSizer14->Add(30,0,0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
228 	FlexGridSizer1 = new wxFlexGridSizer(2, 2, 2, 0);
229 	cb_dtorStart = new wxCheckBox(Panel4, ID_CHECKBOX1, _("Destructor starts with:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX1"));
230 	cb_dtorStart->SetValue(false);
231 	FlexGridSizer1->Add(cb_dtorStart, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
232 	tc_dtorStart = new wxTextCtrl(Panel4, ID_TEXTCTRL2, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL2"));
233 	FlexGridSizer1->Add(tc_dtorStart, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
234 	cb_dtorEnd = new wxCheckBox(Panel4, ID_CHECKBOX2, _("Destructor ends with:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX2"));
235 	cb_dtorEnd->SetValue(false);
236 	FlexGridSizer1->Add(cb_dtorEnd, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
237 	tc_dtorEnd = new wxTextCtrl(Panel4, ID_TEXTCTRL3, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL3"));
238 	FlexGridSizer1->Add(tc_dtorEnd, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0);
239 	BoxSizer14->Add(FlexGridSizer1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0);
240 	BoxSizer13->Add(BoxSizer14, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0);
241 	BoxSizer9->Add(BoxSizer13, 0, wxALL|wxALIGN_LEFT, 0);
242 	StaticText10 = new wxStaticText(Panel4, wxID_ANY, _("Note: a default destructor is created for the derived type if"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
243 	BoxSizer9->Add(StaticText10, 0, wxTOP|wxLEFT|wxRIGHT|wxALIGN_LEFT, 5);
244 	StaticText12 = new wxStaticText(Panel4, wxID_ANY, _("         another destructor is not found."), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
245 	BoxSizer9->Add(StaticText12, 0, wxALL|wxALIGN_LEFT, 0);
246 	Panel4->SetSizer(BoxSizer9);
247 	BoxSizer9->Fit(Panel4);
248 	BoxSizer9->SetSizeHints(Panel4);
249 	Panel5 = new wxPanel(nb_settings, ID_PANEL5, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL5"));
250 	BoxSizer18 = new wxBoxSizer(wxVERTICAL);
251 	StaticText13 = new wxStaticText(Panel5, wxID_ANY, _("This tool can generate Cython code which wraps Fortran. Generated *.pyx file\n can later be compiled into an extention module for the Python language."), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
252 	BoxSizer18->Add(StaticText13, 0, wxALL|wxALIGN_LEFT, 5);
253 	cb_genCython = new wxCheckBox(Panel5, ID_CHECKBOX6, _("Generate Cython files"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX6"));
254 	cb_genCython->SetValue(false);
255 	BoxSizer18->Add(cb_genCython, 0, wxALL|wxALIGN_LEFT, 5);
256 	pn_pyOpts = new wxPanel(Panel5, ID_PANEL6, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL6"));
257 	BoxSizer20 = new wxBoxSizer(wxVERTICAL);
258 	BoxSizer19 = new wxBoxSizer(wxHORIZONTAL);
259 	StaticText14 = new wxStaticText(pn_pyOpts, wxID_ANY, _("Python function names:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
260 	BoxSizer19->Add(StaticText14, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
261 	tc_pyFunName = new wxTextCtrl(pn_pyOpts, ID_TEXTCTRL8, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL8"));
262 	BoxSizer19->Add(tc_pyFunName, 1, wxALIGN_CENTER_VERTICAL, 5);
263 	BoxSizer20->Add(BoxSizer19, 0, wxALL|wxEXPAND, 5);
264 	StaticText15 = new wxStaticText(pn_pyOpts, wxID_ANY, _("Note: $procname$ is changed to the original name of procedure;\n         $modulename$ is changed to the name of module;\n         $modname$ is changed to the truncated name of module."), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
265 	BoxSizer20->Add(StaticText15, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT, 5);
266 	cb_pyGenClass = new wxCheckBox(pn_pyOpts, ID_CHECKBOX7, _("Generate Python class from Fortran module"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX7"));
267 	cb_pyGenClass->SetValue(false);
268 	BoxSizer20->Add(cb_pyGenClass, 0, wxALL|wxALIGN_LEFT, 5);
269 	cb_pyFirstSelf = new wxCheckBox(pn_pyOpts, ID_CHECKBOX8, _("Use first argument of the derived type as \'self\' in Python"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX8"));
270 	cb_pyFirstSelf->SetValue(false);
271 	BoxSizer20->Add(cb_pyFirstSelf, 0, wxALL|wxALIGN_LEFT, 5);
272 	pn_pyOpts->SetSizer(BoxSizer20);
273 	BoxSizer20->Fit(pn_pyOpts);
274 	BoxSizer20->SetSizeHints(pn_pyOpts);
275 	BoxSizer18->Add(pn_pyOpts, 1, wxEXPAND, 5);
276 	Panel5->SetSizer(BoxSizer18);
277 	BoxSizer18->Fit(Panel5);
278 	BoxSizer18->SetSizeHints(Panel5);
279 	nb_settings->AddPage(Panel2, _("General"), false);
280 	nb_settings->AddPage(Panel1, _("Types"), false);
281 	nb_settings->AddPage(Panel3, _("Constructor"), false);
282 	nb_settings->AddPage(Panel4, _("Destructor"), false);
283 	nb_settings->AddPage(Panel5, _("Python"), false);
284 	BoxSizer6->Add(nb_settings, 1, wxALL|wxEXPAND, 5);
285 	BoxSizer1->Add(BoxSizer6, 1, wxEXPAND, 5);
286 	StdDialogButtonSizer1 = new wxStdDialogButtonSizer();
287 	StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_OK, wxEmptyString));
288 	StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_CANCEL, wxEmptyString));
289 	StdDialogButtonSizer1->Realize();
290 	BoxSizer1->Add(StdDialogButtonSizer1, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5);
291 	SetSizer(BoxSizer1);
292 	BoxSizer1->Fit(this);
293 	BoxSizer1->SetSizeHints(this);
294 
295 	Connect(ID_BTOACTIVEPROJECT,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&Bindto::Onrb_ActiveProjectSelect);
296 	Connect(ID_BTOCURRENTFILE,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&Bindto::Onrb_ActiveProjectSelect);
297 	Connect(ID_CHECKBOX3,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&Bindto::Oncb_globalToOneClick);
298 	Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Bindto::Onbt_OutputDirClick);
299 	Connect(ID_BUTTON_ADD,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Bindto::OnAdd);
300 	Connect(ID_BUTTON_COPY,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Bindto::OnCopy);
301 	Connect(ID_BUTTON_EDIT,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Bindto::OnEdit);
302 	Connect(ID_BUTTON_REMOVE,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Bindto::OnRemove);
303 	Connect(ID_BUTTON_DEFAULTS,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Bindto::OnDefaults);
304 	Connect(ID_CHECKBOX4,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&Bindto::OnClick_cbCtorStart);
305 	Connect(ID_CHECKBOX5,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&Bindto::OnClick_cbCtorEnd);
306 	Connect(ID_CHECKBOX1,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&Bindto::OnClick_cbDtorStart);
307 	Connect(ID_CHECKBOX2,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&Bindto::OnClick_cbDtorEnd);
308 	Connect(ID_CHECKBOX6,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&Bindto::Oncb_genCythonClick);
309 	//*)
310 
311     lv_Types->InsertColumn(0,_T("Fortran"));
312     lv_Types->InsertColumn(1,_T("Fortran Bind(C)"));
313     lv_Types->InsertColumn(2,_T("C"));
314 
315 	rb_CurrentFile->SetValue(true);
316     m_pParser = pParser;
317 
318     m_TabSize = -1;
319     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
320     if (ed)
321     {
322         cbStyledTextCtrl* control = ed->GetControl();
323         if (control)
324             m_TabSize = control->GetTabWidth();
325     }
326     if (m_TabSize == -1)
327         m_TabSize = 4;
328 
329     LoadInitialValues();
330     FillTypeList();
331     for (int i=0; i< lv_Types->GetColumnCount(); i++)
332     {
333         lv_Types->SetColumnWidth(i,wxLIST_AUTOSIZE);
334         if (lv_Types->GetColumnWidth(i) > 200)
335             lv_Types->SetColumnWidth(i,200);
336     }
337 
338     tc_bindCName->SetValue(m_BindCName);
339     if (m_CtorStartsWith.IsEmpty())
340     {
341         cb_ctorStart->SetValue(false);
342         tc_ctorStart->SetValue(_T("ctor_"));
343         tc_ctorStart->Enable(false);
344     }
345     else
346     {
347         cb_ctorStart->SetValue(true);
348         tc_ctorStart->SetValue(m_CtorStartsWith);
349         tc_ctorStart->Enable(true);
350     }
351 
352     cb_incompleteWrapperProc->SetValue(!m_WriteIncompleteWrapper);
353     cb_globalToOne->SetValue(m_OneGProcFile);
354     tc_globalFilename->SetValue(m_OneGProcFileName);
355     bool enab = false;
356     if (rb_ActiveProject->GetValue())
357         enab = true;
358     cb_globalToOne->Enable(enab);
359     if (enab && cb_globalToOne->GetValue())
360     {
361         tc_globalFilename->Enable(true);
362         st_globalFilename->Enable(true);
363     }
364     else
365     {
366         tc_globalFilename->Enable(false);
367         st_globalFilename->Enable(false);
368     }
369 
370     GetInitialOutputDir(m_InitialOutputDirFile, m_InitialOutputDirProj);
371     if (rb_CurrentFile->GetValue())
372         tc_OutputDir->SetValue(m_InitialOutputDirFile);
373     else
374         tc_OutputDir->SetValue(m_InitialOutputDirProj);
375 
376     if (m_CtorEndsWith.IsEmpty())
377     {
378         cb_ctorEnd->SetValue(false);
379         tc_ctorEnd->SetValue(_T("_ctor"));
380         tc_ctorEnd->Enable(false);
381     }
382     else
383     {
384         cb_ctorEnd->SetValue(true);
385         tc_ctorEnd->SetValue(m_CtorEndsWith);
386         tc_ctorEnd->Enable(true);
387     }
388 
389     if (m_DtorStartsWith.IsEmpty())
390     {
391         cb_dtorStart->SetValue(false);
392         tc_dtorStart->SetValue(_T("dtor_"));
393         tc_dtorStart->Enable(false);
394     }
395     else
396     {
397         cb_dtorStart->SetValue(true);
398         tc_dtorStart->SetValue(m_DtorStartsWith);
399         tc_dtorStart->Enable(true);
400     }
401 
402     if (m_DtorEndsWith.IsEmpty())
403     {
404         cb_dtorEnd->SetValue(false);
405         tc_dtorEnd->SetValue(_T("_dtor"));
406         tc_dtorEnd->Enable(false);
407     }
408     else
409     {
410         cb_dtorEnd->SetValue(true);
411         tc_dtorEnd->SetValue(m_DtorEndsWith);
412         tc_dtorEnd->Enable(true);
413     }
414 
415     cb_genCython->SetValue(m_PyGenCython);
416     pn_pyOpts->Enable(m_PyGenCython);
417     tc_pyFunName->SetValue(m_PyFuncName);
418     cb_pyGenClass->SetValue(m_PyCreateClass);
419     cb_pyFirstSelf->SetValue(m_PyFirstArgAsSelf);
420 
421     FillC2NumpyTypesMap();
422 }
423 
~Bindto()424 Bindto::~Bindto()
425 {
426 	//(*Destroy(Bindto)
427 	//*)
428 }
FillTypeList()429 void Bindto::FillTypeList()
430 {
431     if (!lv_Types)
432         return;
433 
434     lv_Types->DeleteAllItems();
435     int idx = 0;
436     for ( TypeMap::iterator it=m_TypeMap.begin(); it != m_TypeMap.end(); ++it)
437     {
438         lv_Types->InsertItem(idx, it->first);
439         lv_Types->SetItem(idx, 1, it->second[0]);
440         lv_Types->SetItem(idx, 2, it->second[1]);
441         idx++;
442     }
443 }
444 
FillC2NumpyTypesMap()445 void Bindto::FillC2NumpyTypesMap()
446 {
447     m_C2NumpyTypes[_T("int")] = _T("intc");
448     m_C2NumpyTypes[_T("float")] = _T("float32");
449     m_C2NumpyTypes[_T("double")] = _T("float64");
450     m_C2NumpyTypes[_T("float complex")] = _T("complex64");
451     m_C2NumpyTypes[_T("double complex")] = _T("complex128");
452 }
453 
LoadInitialValues()454 void Bindto::LoadInitialValues()
455 {
456     m_IsTypeMapDefault = false;
457     LoadBindToConfig();
458 
459     if (m_TypeMap.size() == 0)
460         FillTypeMapDefault();
461 }
462 
FillTypeMapDefault()463 void Bindto::FillTypeMapDefault()
464 {
465     wxArrayString fTypes;
466     wxArrayString bTypes;
467     wxArrayString cTypes;
468     fTypes.Add(_T("integer"));
469     bTypes.Add(_T("integer(c_int)"));
470     cTypes.Add(_T("int"));
471 
472     fTypes.Add(_T("integer(8)"));
473     bTypes.Add(_T("integer(c_int64_t)"));
474     cTypes.Add(_T("int64_t"));
475 
476     fTypes.Add(_T("integer(4)"));
477     bTypes.Add(_T("integer(c_int32_t)"));
478     cTypes.Add(_T("int32_t"));
479 
480     fTypes.Add(_T("integer(2)"));
481     bTypes.Add(_T("integer(c_int16_t)"));
482     cTypes.Add(_T("int16_t"));
483 
484     fTypes.Add(_T("integer(1)"));
485     bTypes.Add(_T("integer(c_int8_t)"));
486     cTypes.Add(_T("int8_t"));
487 
488     fTypes.Add(_T("integer(c_int)"));
489     bTypes.Add(_T("integer(c_int)"));
490     cTypes.Add(_T("int"));
491 
492     fTypes.Add(_T("real"));
493     bTypes.Add(_T("real(c_float)"));
494     cTypes.Add(_T("float"));
495 
496     fTypes.Add(_T("real(4)"));
497     bTypes.Add(_T("real(c_float)"));
498     cTypes.Add(_T("float"));
499 
500     fTypes.Add(_T("real(8)"));
501     bTypes.Add(_T("real(c_double)"));
502     cTypes.Add(_T("double"));
503 
504     fTypes.Add(_T("doubleprecision"));
505     bTypes.Add(_T("real(c_double)"));
506     cTypes.Add(_T("double"));
507 
508     fTypes.Add(_T("real(c_float)"));
509     bTypes.Add(_T("real(c_float)"));
510     cTypes.Add(_T("float"));
511 
512     fTypes.Add(_T("real(c_double)"));
513     bTypes.Add(_T("real(c_double)"));
514     cTypes.Add(_T("double"));
515 
516     fTypes.Add(_T("complex"));
517     bTypes.Add(_T("complex(c_float_complex)"));
518     cTypes.Add(_T("float complex"));
519 
520     fTypes.Add(_T("complex*8"));
521     bTypes.Add(_T("complex(c_float_complex)"));
522     cTypes.Add(_T("float complex"));
523 
524     fTypes.Add(_T("complex*16"));
525     bTypes.Add(_T("complex(c_double_complex)"));
526     cTypes.Add(_T("double complex"));
527 
528     fTypes.Add(_T("complex*32"));
529     bTypes.Add(_T("complex(c_long_double_complex)"));
530     cTypes.Add(_T("long double complex"));
531 
532     fTypes.Add(_T("complex(4)"));
533     bTypes.Add(_T("complex(c_float_complex)"));
534     cTypes.Add(_T("float complex"));
535 
536     //requires <complex.h>
537     fTypes.Add(_T("complex(8)"));
538     bTypes.Add(_T("complex(c_double_complex)"));
539     cTypes.Add(_T("double complex"));
540 
541     //requires <complex.h>
542     fTypes.Add(_T("complex(16)"));
543     bTypes.Add(_T("complex(c_long_double_complex)"));
544     cTypes.Add(_T("long double complex"));
545 
546     fTypes.Add(_T("character"));
547     bTypes.Add(_T("character(kind=c_char)"));
548     cTypes.Add(_T("char"));
549 
550     fTypes.Add(_T("character(kind=c_char)"));
551     bTypes.Add(_T("character(kind=c_char)"));
552     cTypes.Add(_T("char"));
553 
554     m_TypeMap.clear();
555     for (size_t i=0; i<fTypes.size(); i++)
556     {
557         wxArrayString ct;
558         ct.Add(bTypes[i]);
559         ct.Add(cTypes[i]);
560         m_TypeMap[fTypes[i]] = ct;
561     }
562     m_IsTypeMapDefault = true;
563 }
564 
LoadBindToConfig()565 void Bindto::LoadBindToConfig()
566 {
567     m_IsTypeMapDefault = false;
568     m_TypeMap.clear();
569     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
570     if (!cfg)
571         return;
572 
573     wxArrayString list = cfg->EnumerateSubPaths(_T("/bind_to"));
574     for (unsigned int i = 0; i < list.GetCount(); ++i)
575     {
576         if (!list[i].StartsWith(_T("type")))
577             continue;
578         wxString fT = cfg->Read(_T("/bind_to/") + list[i] + _T("/f_type"), wxEmptyString);
579         wxString bT = cfg->Read(_T("/bind_to/") + list[i] + _T("/b_type"), wxEmptyString);
580         wxString cT = cfg->Read(_T("/bind_to/") + list[i] + _T("/c_type"), wxEmptyString);
581 
582         if (fT.IsEmpty())
583             continue;
584 
585         wxArrayString bct;
586         bct.Add(bT);
587         bct.Add(cT);
588         m_TypeMap[fT] = bct;
589     }
590 
591     m_WriteIncompleteWrapper = cfg->ReadBool(_T("/bind_to/write_incomplete_wrapper"), true);
592     m_OneGProcFile = cfg->ReadBool(_T("/bind_to/one_gproc_file"), true);
593     m_OneGProcFileName = cfg->Read(_T("/bind_to/one_gproc_filename"), _T("procedures_bc.f90"));
594     m_BindCName = cfg->Read(_T("/bind_to/bind_c_name"), PROCNAME_KEY);
595     m_CtorStartsWith = cfg->Read(_T("/bind_to/ctor_start"), wxEmptyString);
596     m_CtorEndsWith = cfg->Read(_T("/bind_to/ctor_end"), wxEmptyString);
597     m_DtorStartsWith = cfg->Read(_T("/bind_to/dtor_start"), wxEmptyString);
598     m_DtorEndsWith = cfg->Read(_T("/bind_to/dtor_end"), wxEmptyString);
599     m_LogToInt = cfg->ReadBool(_T("/bind_to/log_to_int"), true);
600 
601     m_PyGenCython = cfg->ReadBool(_T("/bind_to/python_generate"), false);
602     m_PyCreateClass = cfg->ReadBool(_T("/bind_to/python_class"), false);
603     m_PyFirstArgAsSelf = cfg->ReadBool(_T("/bind_to/python_firstself"), true);
604     m_PyFuncName = cfg->Read(_T("/bind_to/python_function_name"), PROCNAME_KEY);
605 }
606 
SaveBindToConfig()607 void Bindto::SaveBindToConfig()
608 {
609     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
610     if (!cfg)
611         return;
612     cfg->DeleteSubPath(_T("/bind_to"));
613 
614     if (!m_IsTypeMapDefault) // no need to save default types
615     {
616         TypeMap::iterator it;
617         int count = 0;
618         for (it = m_TypeMap.begin(); it != m_TypeMap.end(); ++it)
619         {
620             wxString fT = it->first;
621             wxString bT = it->second[0];
622             wxString cT = it->second[1];
623 
624             ++count;
625             wxString key;
626             key.Printf(_T("/bind_to/type%d/f_type"), count);
627             cfg->Write(key, fT);
628             key.Printf(_T("/bind_to/type%d/b_type"), count);
629             cfg->Write(key, bT);
630             key.Printf(_T("/bind_to/type%d/c_type"), count);
631             cfg->Write(key, cT);
632         }
633     }
634 
635     cfg->Write(_T("/bind_to/write_incomplete_wrapper"), m_WriteIncompleteWrapper);
636     cfg->Write(_T("/bind_to/one_gproc_file"), m_OneGProcFile);
637     cfg->Write(_T("/bind_to/one_gproc_filename"), m_OneGProcFileName);
638     cfg->Write(_T("/bind_to/bind_c_name"), m_BindCName);
639     cfg->Write(_T("/bind_to/ctor_start"), m_CtorStartsWith);
640     cfg->Write(_T("/bind_to/ctor_end"), m_CtorEndsWith);
641     cfg->Write(_T("/bind_to/dtor_start"), m_DtorStartsWith);
642     cfg->Write(_T("/bind_to/dtor_end"), m_DtorEndsWith);
643     cfg->Write(_T("/bind_to/log_to_int"), m_LogToInt);
644 
645     cfg->Write(_T("/bind_to/python_generate"), m_PyGenCython);
646     cfg->Write(_T("/bind_to/python_class"), m_PyCreateClass);
647     cfg->Write(_T("/bind_to/python_firstself"), m_PyFirstArgAsSelf);
648     cfg->Write(_T("/bind_to/python_function_name"), m_PyFuncName);
649 }
650 
OnOK(wxCommandEvent & event)651 void Bindto::OnOK(wxCommandEvent& event)
652 {
653     BindToIn btin;
654     if (rb_ActiveProject->GetValue())
655         btin = bindToProject;
656     else
657         btin = bindToFile;
658 
659     m_BindCName = tc_bindCName->GetValue();
660     m_BindCName.Replace(_T(" "), _T(""));
661     if (m_BindCName.IsEmpty())
662         m_BindCName = PROCNAME_KEY;
663 
664     m_WriteIncompleteWrapper = !cb_incompleteWrapperProc->GetValue();
665     m_OneGProcFile = cb_globalToOne->GetValue();
666     m_OneGProcFileName = tc_globalFilename->GetValue();
667     if (m_OneGProcFileName.Trim().Trim(false).IsEmpty())
668     {
669         m_OneGProcFileName = _T("procedures_bc.f90");
670     }
671     if (btin == bindToProject && m_OneGProcFile)
672         m_UseOneGlobalFile = true;
673     else
674         m_UseOneGlobalFile = false;
675 
676     m_OutputDir = tc_OutputDir->GetValue().Trim(true).Trim(false);
677     if(!MakeOutputDir())
678     {
679         wxString msg = _("Output directory cannot be created.\nCorrect \"Output dir\" text field.");
680         wxMessageBox(msg, _("Error"), wxICON_ERROR, this);
681         return;
682     }
683 
684     if (cb_ctorStart->GetValue())
685         m_CtorStartsWith = tc_ctorStart->GetValue();
686     else
687         m_CtorStartsWith = wxEmptyString;
688     m_CtorStartsWith.Replace(_T(" "), _T(""));
689 
690     if (cb_ctorEnd->GetValue())
691         m_CtorEndsWith = tc_ctorEnd->GetValue();
692     else
693         m_CtorEndsWith = wxEmptyString;
694     m_CtorEndsWith.Replace(_T(" "), _T(""));
695 
696     if (cb_dtorStart->GetValue())
697         m_DtorStartsWith = tc_dtorStart->GetValue();
698     else
699         m_DtorStartsWith = wxEmptyString;
700     m_DtorStartsWith.Replace(_T(" "), _T(""));
701 
702     if (cb_dtorEnd->GetValue())
703         m_DtorEndsWith = tc_dtorEnd->GetValue();
704     else
705         m_DtorEndsWith = wxEmptyString;
706     m_DtorEndsWith.Replace(_T(" "), _T(""));
707 
708     m_PyGenCython = cb_genCython->GetValue();
709     m_PyFuncName = tc_pyFunName->GetValue();
710     m_PyFuncName.Replace(_T(" "),_T(""));
711     if (m_PyGenCython && !ValidatePyFuncName())
712         return;
713     m_PyCreateClass = cb_pyGenClass->GetValue();
714     m_PyFirstArgAsSelf = cb_pyFirstSelf->GetValue();
715 
716     m_FileWasCreated = false;
717 
718     SaveBindToConfig();
719     MakeBindTo(btin);
720 
721     if (m_CreatedMsg.size() > 0)
722     {
723         size_t nmsg = std::min(m_CreatedMsg.size(),size_t(5));
724         wxString msg;
725         for (size_t i=0; i< nmsg; i++)
726         {
727             msg << m_CreatedMsg.Item(i) << _T("\n");
728         }
729         wxMessageBox( msg, _("Bindto Info"), wxICON_INFORMATION, this);
730     }
731     if (btin == bindToProject && m_FileWasCreated)
732     {
733         wxString msg = _("Generated files were written to ") + m_OutputDir + _(" directory.");
734         wxMessageBox( msg, _("Bindto"), wxICON_INFORMATION, this);
735     }
736 
737     EndModal(wxID_OK);
738 }
739 
MakeBindTo(BindToIn btin)740 void Bindto::MakeBindTo(BindToIn btin)
741 {
742     if (!Manager::Get()->GetEditorManager() || !m_pParser)
743         return;
744 
745     m_TypeDefinedInMap.clear();
746     m_TypeDefinedInGlobMap.clear();
747     m_ProjectBinDir = _T("");
748     m_IsTargetStaticLib = false;
749     cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
750     if (project)
751     {
752         ProjectBuildTarget* bTarget = project->GetBuildTarget(project->GetActiveBuildTarget());
753         if (bTarget)
754         {
755             wxFileName efn(project->GetBasePath());
756             wxFileName ofn(bTarget->GetOutputFilename());
757             wxArrayString dirs = ofn.GetDirs();
758             for (size_t i=0; i<dirs.size(); i++)
759                 efn.AppendDir(dirs[i]);
760             m_ProjectBinDir = efn.GetPath();
761 
762             if (bTarget->GetTargetType() == ttStaticLib)
763                 m_IsTargetStaticLib = true;
764             wxFileName lfn = wxFileName(bTarget->GetOutputFilename());
765             m_TargetLibraryName = lfn.GetName();
766             m_TargetCompilerName = bTarget->GetCompilerID();
767         }
768     }
769 
770     if (btin == bindToProject)
771     {
772         if (!project)
773             return;
774 
775         m_GlobProceduresFile = _T("");
776         m_GlobProceduresFileH = _T("");
777         m_GlobProceduresCInclude.clear();
778         m_GlobLogFunMap.clear();
779         m_GlobWriteStrCtoF = false;
780         m_GlobWriteStrFtoC = false;
781         m_GlobWriteStrLen = false;
782 
783         m_TxtCythonFirstGlob = _T("");
784         m_TxtCythonGlob = _T("");
785 
786         wxArrayString nonFFiles;
787         wxArrayString projFiles;
788         for (FilesList::iterator it = project->GetFilesList().begin(); it != project->GetFilesList().end(); ++it)
789         {
790             projFiles.Add((*it)->file.GetFullPath());
791         }
792         projFiles.Sort();
793         for (size_t i=0; i<projFiles.size(); i++)
794         {
795             FortranSourceForm fsForm;
796             if (g_FortranFileExt.IsFileFortran(projFiles.Item(i), fsForm))
797                 FileBindTo(projFiles.Item(i));
798             else
799                 nonFFiles.Add(projFiles.Item(i));
800         }
801 
802         if (m_UseOneGlobalFile && !m_GlobProceduresFile.IsEmpty())
803         {
804             wxFileName fname(m_OneGProcFileName);
805             fname.SetPath(m_OutputDir);
806 
807             while (fname.FileExists())
808             {
809                 wxString query_overwrite;
810                 query_overwrite << _("Warning:\n")
811                   << _("This tool is about OVERWRITE the following existing file:\n")
812                   << fname.GetFullPath()
813                   << _("\n\nAre you sure that you want to OVERWRITE the file?");
814                 int answ = wxMessageBox(query_overwrite, _("Confirmation"),
815                                  wxICON_WARNING | wxYES_NO | wxNO_DEFAULT, this);
816                 if (answ == wxNO)
817                 {
818                     wxString name = fname.GetFullName();
819                     wxString msg = _("Suggest a new file name:");
820 
821                     wxTextEntryDialog dlg(this, msg, _("File name"), name);
822                     if (dlg.ShowModal() == wxID_OK)
823                     {
824                         name = dlg.GetValue().Trim(true).Trim(false);
825                         if (!name.IsEmpty())
826                             fname.SetFullName(name);
827                     }
828                 }
829                 else if (answ == wxYES)
830                     break;
831                 else
832                 {
833                     wxString msg = _("Generation of the wrapping was canceled!");
834                     wxMessageBox( msg, _("Bindto Info"), wxICON_INFORMATION, this);
835                     return;
836                 }
837             }
838             std::map<wxString,wxString> helpProcMap;
839             wxString helpModHead;
840             GetHelperModule(true, false, helpProcMap, helpModHead);
841             wxString strGlobMod;
842             m_Indent = 0;
843             strGlobMod << _T("module ") << fname.GetName() << _T("\n");
844             m_Indent++;
845             strGlobMod << GetIS() << _T("use, intrinsic :: iso_c_binding\n");
846             if (helpProcMap.size() > 0)
847                 strGlobMod << GetIS() << _T("use :: bindc_helper_bc\n");
848 
849             if (m_TypeDefinedInGlobMap.size() > 0)
850             {
851                 wxString useStr;
852                 for(auto const& mval : m_TypeDefinedInGlobMap)
853                 {
854                     useStr << GetIS(1) << _T("use :: ") << mval.second[0] << _T("\n");
855                 }
856                 strGlobMod << useStr;
857             }
858 
859             strGlobMod << GetIS() << _T("implicit none\n");
860             strGlobMod << _T("contains\n\n");
861 
862             wxString strGlobModEnd = _T("end module\n");
863 
864             wxFile f(fname.GetFullPath(), wxFile::write);
865             cbWrite(f, strGlobMod +
866                     SplitLines(m_GlobProceduresFile,Fortran) + strGlobModEnd + GetEOLStr(), wxFONTENCODING_UTF8);
867             m_FileWasCreated = true;
868 
869             if (!m_GlobProcWarnMessages.IsEmpty())
870                 AddToLogFile(m_GlobProcWarnMessages);
871 
872             wxFileName hfname(fname);
873             hfname.SetExt(_T("h"));
874             if (!m_GlobProceduresFileH.IsEmpty())
875             {
876                 wxString hstr1;
877                 wxString hstr2;
878                 GetHeaderStartEnd(hfname.GetName(), hstr1, hstr2);
879 
880                 StrSet::iterator it;
881                 for (it=m_GlobProceduresCInclude.begin(); it != m_GlobProceduresCInclude.end(); ++it)
882                 {
883                     hstr1 << *it << _T("\n");
884                 }
885 
886                 wxFile hf(hfname.GetFullPath(), wxFile::write);
887                 cbWrite(hf, hstr1 + _T("\n") + SplitLines(m_GlobProceduresFileH,C) + hstr2 + GetEOLStr(), wxFONTENCODING_UTF8);
888             }
889 
890             // Write Cython file for global procedures
891             if (m_PyGenCython)
892             {
893                 wxString txtCythonHead;
894                 txtCythonHead << _T("#!python\n#cython: boundscheck=False, wraparound=False\n");
895                 txtCythonHead << _T("import numpy as np\ncimport numpy as np\n");
896                 if (!m_PyIncludeGlob.empty())
897                 {
898                     StrSet::iterator it;
899                     for (it=m_PyIncludeGlob.begin(); it != m_PyIncludeGlob.end(); ++it)
900                         txtCythonHead << *it << _T("\n");
901                 }
902                 txtCythonHead << _T("\n");
903 
904                 wxFileName pxdfname(fname);
905                 pxdfname.SetExt(_T("pxd"));
906                 wxString pxdfn = pxdfname.GetName();
907                 pxdfn.Append(_T("_f"));
908                 pxdfname.SetName(pxdfn);
909 
910                 txtCythonHead << _T("cimport ") << pxdfn << _T("\n");
911                 m_TxtCythonGlob.Replace(CIMPORT_FN_KEY,pxdfn + _T("."));
912 
913                 wxFileName pyxfname(fname);
914                 pyxfname.SetExt(_T("pyx"));
915                 wxFile pyxf(pyxfname.GetFullPath(), wxFile::write);
916                 cbWrite(pyxf, txtCythonHead + SplitLines(m_TxtCythonGlob,Python) +
917                         GetEOLStr(), wxFONTENCODING_UTF8);
918 
919                 m_PyxFileArr.Add(pyxfname.GetFullPath());
920 
921                 wxString pxdTxt;
922                 pxdTxt << _T("cdef extern from \"") << hfname.GetFullName() << _T("\":\n");
923                 wxFile pxdf(pxdfname.GetFullPath(), wxFile::write);
924                 cbWrite(pxdf, pxdTxt + m_TxtCythonFirstGlob +
925                         GetEOLStr(), wxFONTENCODING_UTF8);
926 
927             }
928 
929             if (!m_GlobProcWarnMessages.IsEmpty())
930                 m_CreatedMsg.Add(_("\nThere were problems met during the generation of wrapping. A message was added to 'bindto.log' file "));
931         }
932 
933         if (m_PyGenCython && !m_PyxFileArr.IsEmpty())
934         {
935 
936 
937             wxFileName sn(m_PyxFileArr.Item(0));
938             wxFileName profn(project->GetFilename());
939             sn.SetName(_T("setup_") + profn.GetName());
940             sn.SetExt(_T("py"));
941             WriteSetupPy(m_PyxFileArr, sn.GetFullPath(), m_ProjectBinDir);
942         }
943 
944         if (nonFFiles.size() > 0)
945         {
946             wxString mstr;
947             if (nonFFiles.size() == 1)
948             {
949                 mstr = _("File \"") + nonFFiles[0] + _("\" was not recognized as a Fortran file.");
950                 mstr << _(" The BindTo was not applied for it.");
951             }
952             else
953             {
954                 mstr = _("Files");
955                 size_t i=0;
956                 size_t imax=5;
957                 while (i < nonFFiles.size() && i < imax)
958                 {
959                     mstr << _("\n\"") << nonFFiles[i] << _T("\"");
960                     i++;
961                 }
962                 if (nonFFiles.size() > imax)
963                     mstr << _T("...\n");
964                 else
965                     mstr << _T("\n");
966                 mstr << wxString::Format(_T("(%d "), int(nonFFiles.size())) << _("files) ");
967                 mstr << _("were not recognized as the Fortran files.");
968                 mstr << _(" The BindTo was not applied for them.");
969             }
970             wxMessageBox(mstr, _("Info"), wxICON_INFORMATION, this);
971         }
972     }
973     else
974     {
975         // Bind current file
976         cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
977         if (!ed)
978             return;
979         m_GlobLogFunMap.clear();
980         FileBindTo(ed->GetFilename());
981     }
982 
983     WriteHelperModFile();
984 }
985 
FileBindTo(const wxString & filename)986 void Bindto::FileBindTo(const wxString& filename)
987 {
988     FortranSourceForm fsForm;
989     if (!g_FortranFileExt.IsFileFortran(filename, fsForm))
990     {
991         wxMessageBox( _("The file \n") + filename +
992                       _("\n is not recognized as a Fortran Source File."), _("Info"),
993                       wxICON_INFORMATION, this);
994         return;
995     }
996     TokenF* fileToken = m_pParser->FindFile(filename);
997 
998     if (!fileToken)
999         return;
1000 
1001     m_CInclude.clear();
1002     m_CStructs = _T("");
1003     m_WarnMessage = _T("");
1004     wxString txtBindGM;
1005     wxString txtBindModFile;
1006     wxString txtHeadersGM;
1007     wxString txtHeadersMod;
1008     bool inModuleGM = false;
1009     m_WriteStrCtoF = false;
1010     m_WriteStrFtoC = false;
1011     m_WriteStrLen = false;
1012     m_LogTypeSet.clear();
1013     m_Indent   = 0;
1014     m_PyIndent = 0;
1015     wxFileName fn(fileToken->m_Filename);
1016     wxString globModName = fn.GetName() + _T("_proc_bc");
1017     m_CurFile = fn.GetFullName();
1018     m_InFortranModule = false;
1019 
1020     wxString txtCythonFirst;
1021     wxString txtCythonFirstGP;
1022     wxString txtCythonGP;
1023     wxString txtCythonModFile;
1024     m_PyInclude.clear();
1025 
1026     TokensArrayF* fchen = &fileToken->m_Children;
1027     for (size_t i=0; i<fchen->GetCount(); i++)
1028     {
1029         if (fchen->Item(i)->m_TokenKind == tkSubroutine ||
1030             fchen->Item(i)->m_TokenKind == tkFunction)
1031         {
1032             if (!inModuleGM && !m_UseOneGlobalFile)
1033             {
1034                 txtBindGM << _T("module ") << globModName << _T("\n");
1035                 m_Indent++;
1036                 txtBindGM << GetIS() << _T("use, intrinsic :: iso_c_binding\n");
1037                 txtBindGM << USEMODTDEF_KEY;
1038                 txtBindGM << _T("$#$#%^@@place for helper module$#@%");
1039                 txtBindGM << GetIS() << _T("implicit none\n");
1040                 txtBindGM << _T("contains\n\n");
1041                 inModuleGM = true;
1042                 txtHeadersGM << _T("// Global procedures\n");
1043                 m_TypeDefinedInMap.clear();
1044             }
1045             m_Indent = 1;
1046             BindProcedure(txtBindGM, txtHeadersGM, txtCythonFirstGP, txtCythonGP, fchen->Item(i), globModName, true);
1047         }
1048         else if (fchen->Item(i)->m_TokenKind == tkModule)
1049         {
1050             wxString txtBindModHeader;
1051             wxString txtBindMod;
1052             wxString txtCythonModHeader;
1053             wxString txtCythonMod;
1054             m_InFortranModule = true;
1055             wxString modName = fchen->Item(i)->m_Name;
1056             m_CurModule = modName;
1057             txtBindModHeader << _T("module ") << modName << _T("_bc\n");
1058             m_Indent = 1;
1059             txtBindModHeader << GetIS() << _T("use :: ") << modName << _T("\n");
1060             txtBindModHeader << GetIS() << _T("use, intrinsic :: iso_c_binding\n");
1061             txtBindModHeader << USEMODTDEF_KEY;
1062             txtBindModHeader << _T("$#$#%^@@place for helper module$#@%");
1063             txtBindModHeader << GetIS() << _T("implicit none\n");
1064             txtBindModHeader << _T("contains\n\n");
1065 
1066             wxString txtHeadersMod_1;
1067             wxString txtHeadersMod_2;
1068             txtHeadersMod_1 << _T("\n// Module '") << modName << _T("' procedures\n");
1069             m_DefinedTypes.clear();
1070             m_DefinedTypesBindC.clear();
1071             m_NoArgConstructors.clear();
1072             m_Deallocators.clear();
1073             m_ModuleChildNames.clear();
1074             m_HasPyClassConstructor = false;
1075             m_TypeDefinedInMap.clear();
1076 
1077             if (m_PyCreateClass)
1078             {
1079                 txtCythonModHeader << _T("\ncdef class ") << modName << _T(":\n");
1080                 txtCythonModHeader << _T("%%%##@@@@Place For Cdefs%%%@@@");
1081                 txtCythonModHeader << _T("@@%##@@@@Place For __init__dealloc__%%%@%%");
1082                 m_PyIndent = 1;
1083             }
1084 
1085             TokensArrayF* mchil = &fchen->Item(i)->m_Children;
1086             for (size_t j=0; j<mchil->GetCount(); j++)
1087             {
1088                 if ((mchil->Item(j)->m_TokenKind == tkSubroutine ||
1089                     mchil->Item(j)->m_TokenKind == tkFunction) &&
1090                     mchil->Item(j)->m_TokenAccess == taPublic)
1091                 {
1092                     m_ModuleChildNames.insert(mchil->Item(j)->m_Name);
1093                 }
1094             }
1095 
1096             for (size_t j=0; j<mchil->GetCount(); j++)
1097             {
1098                 if ((mchil->Item(j)->m_TokenKind == tkSubroutine ||
1099                     mchil->Item(j)->m_TokenKind == tkFunction) &&
1100                     mchil->Item(j)->m_TokenAccess == taPublic)
1101                 {
1102                     BindProcedure(txtBindMod, txtHeadersMod_2, txtCythonFirst, txtCythonMod, mchil->Item(j), modName, false);
1103                 }
1104                 else if (mchil->Item(j)->m_TokenKind == tkInterfaceExplicit &&
1105                          mchil->Item(j)->m_TokenAccess == taPublic)
1106                 {
1107                     TokensArrayF* intchs = &mchil->Item(j)->m_Children;
1108                     for (size_t k=0; k<intchs->GetCount(); k++)
1109                     {
1110                         if ((intchs->Item(k)->m_TokenKind == tkSubroutine ||
1111                             intchs->Item(k)->m_TokenKind == tkFunction) &&
1112                             intchs->Item(k)->m_TokenAccess == taPublic)
1113                         {
1114                             BindProcedure(txtBindMod, txtHeadersMod_2, txtCythonFirst, txtCythonMod, intchs->Item(k), modName, false);
1115                             m_ModuleChildNames.insert(intchs->Item(k)->m_Name);
1116                         }
1117                     }
1118                 }
1119                 else if (mchil->Item(j)->m_TokenKind == tkInterface &&
1120                          mchil->Item(j)->m_TokenAccess == taPublic &&
1121                          !mchil->Item(j)->m_Name.IsEmpty())
1122                 {
1123                     TokensArrayF* intchs = &mchil->Item(j)->m_Children;
1124                     for (size_t k=0; k<intchs->GetCount(); k++)
1125                     {
1126                         wxString iname = intchs->Item(k)->m_Name;
1127                         for (size_t l=0; l<mchil->GetCount(); l++)
1128                         {
1129                             if ((mchil->Item(l)->m_TokenKind == tkSubroutine ||
1130                                 mchil->Item(l)->m_TokenKind == tkFunction) &&
1131                                 mchil->Item(l)->m_TokenAccess == taPrivate &&   // items with taPublic are called separately
1132                                 mchil->Item(l)->m_Name.IsSameAs(iname))
1133                             {
1134                                 BindProcedure(txtBindMod, txtHeadersMod_2, txtCythonFirst, txtCythonMod, mchil->Item(l), modName, false, mchil->Item(j)->m_DisplayName);
1135                                 m_ModuleChildNames.insert(mchil->Item(l)->m_Name);
1136                             }
1137                         }
1138                     }
1139                 }
1140                 else if (mchil->Item(j)->m_TokenKind == tkType &&
1141                          mchil->Item(j)->m_TokenAccess == taPublic)
1142                 {
1143                     wxString tdef = mchil->Item(j)->m_TypeDefinition.Lower();
1144                     tdef.Replace(_T(" "),_T(""));
1145                     if (tdef.Find(_T("bind(c)")) == wxNOT_FOUND)
1146                         m_DefinedTypes.insert(mchil->Item(j)->m_Name);
1147                     else
1148                     {
1149                         // type with bind(c)
1150                         m_DefinedTypesBindC.insert(mchil->Item(j)->m_Name);
1151 
1152                         wxArrayString ct;
1153                         wxString ftype = _T("type(") + mchil->Item(j)->m_Name + _T(")");
1154                         ct.Add(ftype);
1155                         ct.Add(mchil->Item(j)->m_Name);
1156                         m_TypeMap[ftype] = ct;
1157 
1158                         AddToCStruct(mchil->Item(j));
1159                     }
1160                 }
1161             }
1162             wxString txtCythonCtorDtor;
1163             AddConstructors(txtBindMod, txtHeadersMod_2, txtCythonCtorDtor, txtCythonFirst, modName);
1164             AddDestructors(txtBindMod, txtHeadersMod_2, txtCythonCtorDtor, txtCythonFirst, modName);
1165             m_CurModule = wxEmptyString;
1166             m_InFortranModule = false;
1167             m_PyIndent = 0;
1168             if (m_DefinedTypes.size() == 0)
1169                 txtCythonModHeader.Replace(_T("%%%##@@@@Place For Cdefs%%%@@@"),_T(""));
1170             else
1171             {
1172                 wxString txtCythonCdefs;
1173                 for (StrSet::iterator it=m_DefinedTypes.begin(); it!=m_DefinedTypes.end(); ++it)
1174                 {
1175                     txtCythonCdefs << GetIS(1) << _T("cdef void* _") << *it << _T("_cp\n");
1176                 }
1177                 txtCythonModHeader.Replace(_T("%%%##@@@@Place For Cdefs%%%@@@"),txtCythonCdefs);
1178             }
1179 
1180             txtCythonModHeader.Replace(_T("@@%##@@@@Place For __init__dealloc__%%%@%%"), txtCythonCtorDtor);
1181 
1182             if (!txtBindMod.IsEmpty())
1183             {
1184                 txtBindModFile << txtBindModHeader;
1185                 txtBindModFile << txtBindMod;
1186                 txtBindModFile << _T("end module\n\n");
1187             }
1188             if (!txtCythonMod.IsEmpty() || !txtCythonCtorDtor.IsEmpty() || (m_DefinedTypes.size() > 0))
1189             {
1190                 txtCythonModFile << txtCythonModHeader;
1191                 txtCythonModFile << txtCythonMod;
1192             }
1193             if (!txtHeadersMod_2.IsEmpty())
1194                 txtHeadersMod << txtHeadersMod_1 << txtHeadersMod_2;
1195 
1196             if (m_TypeDefinedInMap.size() > 0)
1197             {
1198                 wxString useStr;
1199                 for(auto const& mval : m_TypeDefinedInMap)
1200                 {
1201                     useStr << GetIS(1) << _T("use :: ") << mval.second[0] << _T("\n");
1202                 }
1203                 txtBindModFile.Replace(USEMODTDEF_KEY,useStr);
1204             }
1205             else
1206                 txtBindModFile.Replace(USEMODTDEF_KEY,_T(""));
1207         }
1208     }
1209     if (inModuleGM && !m_UseOneGlobalFile)
1210         txtBindGM << _T("end module\n\n");
1211 
1212     std::map<wxString,wxString> helpModMap;
1213     wxString helpModHead;
1214     GetHelperModule(false, false, helpModMap, helpModHead);
1215     if (helpModMap.size() > 0 && !txtBindGM.empty())
1216         txtBindGM.Replace(_T("$#$#%^@@place for helper module$#@%"),GetIS(1) + _T("use :: bindc_helper_bc\n"));
1217     else if (!txtBindGM.empty())
1218         txtBindGM.Replace(_T("$#$#%^@@place for helper module$#@%"),_T(""));
1219 
1220     if (helpModMap.size() > 0 && !txtBindModFile.empty())
1221         txtBindModFile.Replace(_T("$#$#%^@@place for helper module$#@%"),GetIS(1) + _T("use :: bindc_helper_bc\n"));
1222     else if (!txtBindModFile.empty())
1223         txtBindModFile.Replace(_T("$#$#%^@@place for helper module$#@%"),_T(""));
1224 
1225     if (inModuleGM && !m_UseOneGlobalFile)
1226     {
1227         if (m_TypeDefinedInMap.size() > 0)
1228         {
1229             wxString useStr;
1230             for(auto const& mval : m_TypeDefinedInMap)
1231             {
1232                 useStr << GetIS(1) << _T("use :: ") << mval.second[0] << _T("\n");
1233             }
1234             txtBindGM.Replace(USEMODTDEF_KEY,useStr);
1235         }
1236         else
1237             txtBindGM.Replace(USEMODTDEF_KEY,_T(""));
1238     }
1239 
1240     wxString bfname = CreateBindFilename(filename, false);
1241     if (bfname.IsEmpty())
1242         return;
1243     wxString hname = CreateBindFilename(filename, true);
1244     if (hname.IsEmpty())
1245         return;
1246 
1247     wxString pyname;
1248     if (m_PyGenCython)
1249     {
1250         pyname = CreateCythonFilename(filename);
1251         if (pyname.IsEmpty())
1252             return;
1253     }
1254 
1255     if (m_UseOneGlobalFile)
1256     {
1257         if (!txtBindGM.IsEmpty())
1258         {
1259             m_GlobProceduresFile << _T("\n") << txtBindGM;
1260             m_GlobProcWarnMessages << m_WarnMessage;
1261         }
1262 
1263         if (!txtHeadersGM.IsEmpty())
1264             m_GlobProceduresFileH << _T("\n") << txtHeadersGM;
1265 
1266         if (!txtBindModFile.IsEmpty())
1267         {
1268             wxFile f(bfname, wxFile::write);
1269             cbWrite(f, SplitLines(txtBindModFile,Fortran) + GetEOLStr(), wxFONTENCODING_UTF8);
1270             m_FileWasCreated = true;
1271             AddToLogFile(m_WarnMessage);
1272         }
1273 
1274         if (!m_CInclude.empty())
1275         {
1276             StrSet::iterator it;
1277             for (it=m_CInclude.begin(); it != m_CInclude.end(); ++it)
1278             {
1279                 m_GlobProceduresCInclude.insert(*it);
1280             }
1281         }
1282 
1283         if (!m_GlobWriteStrCtoF)
1284             m_GlobWriteStrCtoF = m_WriteStrCtoF;
1285         if (!m_GlobWriteStrFtoC)
1286             m_GlobWriteStrFtoC = m_WriteStrFtoC;
1287         if (!m_GlobWriteStrLen)
1288             m_GlobWriteStrLen = m_WriteStrLen;
1289 
1290         if (!txtHeadersMod.IsEmpty())
1291         {
1292             wxFileName hfname(hname);
1293             wxString hstr1;
1294             wxString hstr2;
1295             GetHeaderStartEnd(hfname.GetName(), hstr1, hstr2);
1296 
1297             if (!m_CInclude.empty())
1298             {
1299                 StrSet::iterator it;
1300                 for (it=m_CInclude.begin(); it != m_CInclude.end(); ++it)
1301                     hstr1 << *it << _T("\n");
1302             }
1303 
1304             wxFile hf(hname, wxFile::write);
1305             cbWrite(hf, hstr1 + m_CStructs + _T("\n") + SplitLines(txtHeadersMod,C) +
1306                      hstr2 + GetEOLStr(), wxFONTENCODING_UTF8);
1307         }
1308 
1309         if (m_PyGenCython)
1310         {
1311             wxString txtCythonHead;
1312             txtCythonHead << _T("#!python\n#cython: boundscheck=False, wraparound=False\n");
1313             txtCythonHead << _T("import numpy as np\ncimport numpy as np\n");
1314             if (!m_PyInclude.empty())
1315             {
1316                 StrSet::iterator it;
1317                 for (it=m_PyInclude.begin(); it != m_PyInclude.end(); ++it)
1318                 {
1319                     txtCythonHead << *it << _T("\n");
1320                     m_PyIncludeGlob.insert(*it);
1321                 }
1322             }
1323             txtCythonHead << _T("\n");
1324 
1325             wxFileName pxdfname(pyname);
1326             pxdfname.SetExt(_T("pxd"));
1327             wxString pxdfn = pxdfname.GetName();
1328             pxdfn.Append(_T("_f"));
1329             pxdfname.SetName(pxdfn);
1330 
1331             txtCythonHead << _T("cimport ") << pxdfn << _T("\n");
1332             txtCythonModFile.Replace(CIMPORT_FN_KEY,pxdfn + _T("."));
1333 
1334             if (!txtCythonModFile.IsEmpty())
1335             {
1336                 wxFile pyxf(pyname, wxFile::write);
1337                 cbWrite(pyxf, txtCythonHead + SplitLines(txtCythonModFile,Python) +
1338                         GetEOLStr(), wxFONTENCODING_UTF8);
1339                 m_PyxFileArr.Add(pyname);
1340 
1341                 wxString pxdTxt;
1342                 wxFileName hfname(hname);
1343                 pxdTxt << _T("cdef extern from \"") << hfname.GetFullName() << _T("\":\n");
1344                 wxFile pxdf(pxdfname.GetFullPath(), wxFile::write);
1345                 cbWrite(pxdf, pxdTxt + txtCythonFirst +
1346                             GetEOLStr(), wxFONTENCODING_UTF8);
1347             }
1348 
1349             m_TxtCythonFirstGlob << txtCythonFirstGP;
1350             m_TxtCythonGlob << txtCythonGP;
1351         }
1352 
1353         if (!m_WarnMessage.IsEmpty())
1354         {
1355             wxFileName bfn(bfname);
1356             wxString msg;
1357             msg << _("\nThere were problems met during the generation of wrapping.");
1358             msg << _("\nA message was added to 'bindto.log' file.");
1359             m_CreatedMsg.Add(msg);
1360         }
1361     }
1362     else // if(!m_UseOneGlobalFile)
1363     {
1364         wxFile f(bfname, wxFile::write);
1365         cbWrite(f, SplitLines(txtBindGM,Fortran) +
1366                 SplitLines(txtBindModFile,Fortran) + GetEOLStr(), wxFONTENCODING_UTF8);
1367         m_FileWasCreated = true;
1368         AddToLogFile(m_WarnMessage);
1369 
1370         wxFileName hfname(hname);
1371         wxString hstr1;
1372         wxString hstr2;
1373         GetHeaderStartEnd(hfname.GetName(), hstr1, hstr2);
1374 
1375         if (!m_CInclude.empty())
1376         {
1377             StrSet::iterator it;
1378             for (it=m_CInclude.begin(); it != m_CInclude.end(); ++it)
1379                 hstr1 << *it << _T("\n");
1380         }
1381 
1382         wxFile hf(hname, wxFile::write);
1383         cbWrite(hf, hstr1 + m_CStructs + _T("\n") + SplitLines(txtHeadersGM,C) + SplitLines(txtHeadersMod,C) +
1384                  hstr2 + GetEOLStr(), wxFONTENCODING_UTF8);
1385 
1386         wxString txtCythonHead;
1387         txtCythonHead << _T("#!python\n#cython: boundscheck=False, wraparound=False\n");
1388         txtCythonHead << _T("import numpy as np\ncimport numpy as np\n");
1389         if (!m_PyInclude.empty())
1390         {
1391             StrSet::iterator it;
1392             for (it=m_PyInclude.begin(); it != m_PyInclude.end(); ++it)
1393                 txtCythonHead << *it << _T("\n");
1394         }
1395         txtCythonHead << _T("\n");
1396 
1397         wxFileName pxdfname(pyname);
1398         pxdfname.SetExt(_T("pxd"));
1399         wxString pxdfn = pxdfname.GetName();
1400         pxdfn.Append(_T("_f"));
1401         pxdfname.SetName(pxdfn);
1402 
1403         txtCythonHead << _T("cimport ") << pxdfn << _T("\n");
1404         txtCythonGP.Replace(CIMPORT_FN_KEY,pxdfn + _T("."));
1405         txtCythonModFile.Replace(CIMPORT_FN_KEY,pxdfn + _T("."));
1406 
1407         wxString pyFiles;
1408         if (m_PyGenCython)
1409         {
1410             wxFile pyxf(pyname, wxFile::write);
1411             cbWrite(pyxf, txtCythonHead + SplitLines(txtCythonGP,Python) +
1412                     SplitLines(txtCythonModFile,Python) + GetEOLStr(), wxFONTENCODING_UTF8);
1413             wxFileName pyfn(pyname);
1414             pyFiles << _T(", ") << pyfn.GetFullName();
1415 
1416             //write setup*.py
1417             wxArrayString pyxFArr;
1418             pyxFArr.Add(pyname);
1419             pyfn.SetExt(_T("py"));
1420             wxString name = pyfn.GetName();
1421             pyfn.SetName(_T("setup_"+name));
1422             WriteSetupPy(pyxFArr, pyfn.GetFullPath(), m_ProjectBinDir);
1423 
1424             wxString pxdTxt;
1425             pxdTxt << _T("cdef extern from \"") << hfname.GetFullName() << _T("\":\n");
1426             wxFile pxdf(pxdfname.GetFullPath(), wxFile::write);
1427             cbWrite(pxdf, pxdTxt + txtCythonFirstGP + txtCythonFirst +
1428                         GetEOLStr(), wxFONTENCODING_UTF8);
1429         }
1430 
1431         wxFileName bfn(bfname);
1432         m_CreatedMsg.Add(_("Files ") + bfn.GetFullName() + _T(", ") + hfname.GetFullName() + pyFiles + _(" were created in ")
1433                          + hfname.GetPath() + _(" folder."));
1434         if (!m_WarnMessage.IsEmpty())
1435         {
1436             m_CreatedMsg.Add(_("\nThere were problems met during the generation of wrapping.\nA message was added to 'bindto.log' file."));
1437         }
1438     }
1439     m_CurFile = wxEmptyString;
1440 }
1441 
1442 /** \brief Get Indent Spaces
1443  *
1444  * \return wxString Returns required number of spaces
1445  *
1446  */
GetIS(int nint)1447 wxString Bindto::GetIS(int nint)
1448 {
1449     wxString spaces;
1450     if (nint >= 0)
1451         return spaces.Append(' ',m_TabSize*nint);
1452     return spaces.Append(' ',m_TabSize*m_Indent);
1453 }
1454 
CreateBindFilename(const wxString & filename,bool header)1455 wxString Bindto::CreateBindFilename(const wxString& filename, bool header)
1456 {
1457     wxFileName fname(filename);
1458     fname.SetPath(m_OutputDir);
1459     if (header)
1460         fname.SetExt(_T("h"));
1461     else
1462     {
1463         wxString ext = fname.GetExt();
1464         if (ext != _T("f90") && ext != _T("f95") && ext != _T("f03") && ext != _T("f08"))
1465             fname.SetExt(_T("f90"));
1466     }
1467     wxString name = fname.GetName() << _T("_bc");
1468     fname.SetName(name);
1469 
1470     return CheckOverwriteFilename(fname);
1471 }
1472 
CheckOverwriteFilename(wxFileName & fname)1473 wxString Bindto::CheckOverwriteFilename(wxFileName &fname)
1474 {
1475     while (fname.FileExists())
1476     {
1477         wxString query_overwrite;
1478         query_overwrite << _("Warning:\n")
1479            << _("This tool is about OVERWRITE the following existing file:\n")
1480            << fname.GetFullPath()
1481            << _("\n\nAre you sure that you want to OVERWRITE the file?\n\n")
1482            << _("(If you answer 'No' the existing file will be kept.)");
1483         int answ = wxMessageBox(query_overwrite, _("Confirmation"),
1484                          wxICON_QUESTION | wxYES_NO | wxCANCEL | wxNO_DEFAULT, this);
1485         if (answ == wxNO)
1486         {
1487             bool n_changed = false;
1488             wxString name = fname.GetName();
1489             wxRegEx reEnd(_T("_([0-9]*$)"));
1490             if (reEnd.Matches(name))
1491             {
1492                 // increase file number
1493                 wxString sn = reEnd.GetMatch(name, 1);
1494                 long fn;
1495                 if (sn.ToLong(&fn))
1496                 {
1497                     fn++;
1498                     wxString snn;
1499                     snn << fn;
1500                     name = name.Mid(0,name.size()-sn.size()) + snn;
1501                     n_changed = true;
1502                 }
1503             }
1504 
1505             if (!n_changed)
1506             {
1507                 name << _T("_1");
1508             }
1509             fname.SetName(name);
1510         }
1511         else if (answ == wxYES)
1512             break;
1513         else
1514             return wxEmptyString;
1515     }
1516     return fname.GetFullPath();
1517 }
1518 
1519 
BindProcedure(wxString & txtBind,wxString & txtHeaders,wxString & txtPyFirst,wxString & txtPySecond,TokenF * token,const wxString & moduleName,bool isGlobal,wxString callName)1520 void Bindto::BindProcedure(wxString& txtBind, wxString& txtHeaders, wxString& txtPyFirst, wxString& txtPySecond,
1521                            TokenF* token, const wxString& moduleName, bool isGlobal, wxString callName)
1522 {
1523     m_CurProcedure = token->m_Name;
1524     wxString txtBindProc;
1525     wxString txtBindFirst;
1526     wxString txtBindSecond;
1527     wxString txtHeadersThis;
1528     wxString funResVar;
1529     wxString addFunVariable;
1530     wxArrayString funInterface;
1531     wxString cFunResVar;
1532     wxString funTypeDec;
1533     wxArrayString additionalDeclar;
1534     wxArrayString additionalCalls;
1535     wxArrayString additionalCalls2;
1536     std::map<wxString,wxString> changedNamesMap;
1537     wxString procName = token->m_Name + _T("_bc");
1538     wxString cName = GetCName(token->m_Name, moduleName);
1539     bool bindKindSubroutine = true;
1540     if (token->m_TokenKind == tkSubroutine)
1541         txtBindFirst << GetIS() << _T("subroutine ");
1542     else if (token->m_TokenKind == tkFunction)
1543     {
1544         txtBindFirst << GetIS() << _T("function ");
1545         bindKindSubroutine = false;
1546     }
1547     else
1548         // what else can token be?
1549         return;
1550 
1551     wxString txtCythonFirst;
1552     wxString txtCythonSecond;
1553     wxString txtCythonSecond2;
1554     wxString txtCythonSecond3;
1555     wxArrayString additionalDeclarPy;
1556     wxArrayString additionalCallPy2;
1557     StrSet argHideSetPy;
1558     wxArrayString pyLines;
1559     bool nowIsPyConstructor = false;
1560     bool noArgPyConstructor = false;
1561     bool nowIsPyDestructor  = false;
1562     wxString constrTypeName;
1563     wxString constrProcName;
1564     wxString txtCythonConstr1;
1565     wxString txtCythonConstr2;
1566 
1567     txtBindFirst << procName;
1568     m_Indent++;
1569     bool wasChlen = false;
1570     wxArrayString argArr;
1571     wxStringTokenizer tkz(token->m_Args.Lower(), _T("(),[] \t\r\n"), wxTOKEN_STRTOK );
1572     while ( tkz.HasMoreTokens() )
1573         argArr.Add(tkz.GetNextToken());
1574 
1575     txtBindFirst << _T("(");
1576     for (size_t i=0; i<argArr.GetCount(); i++)
1577     {
1578         txtBindFirst << argArr.Item(i);
1579         if (i+1 < argArr.GetCount())
1580             txtBindFirst << _T(", ");
1581     }
1582 
1583     m_BTDirMap.clear();
1584 
1585     if (token->m_TokenKind == tkFunction)
1586     {
1587         funInterface.Add(_T("interface"));
1588         funInterface.Add(_T("function ") + token->m_Name + token->m_Args.Lower());
1589 
1590         wxString funT = GetFunctionDeclaration(token);
1591         m_pTokenCurrent = token;
1592         int itmp;
1593         TypeBind tys = GetBindType(funT, itmp);
1594         if (!tys.wasFound && !m_WriteIncompleteWrapper)
1595         {
1596             m_WarnMessage << _("\nERROR: Function '") << token->m_Name << _("' was not wrapped!\n");
1597             return;
1598         }
1599         else if (!tys.wasFound)
1600             m_WarnMessage << _("\nERROR: Wrapper of '") << token->m_Name << _("' function contains errors.\n");
1601         funTypeDec = tys.fType;
1602         if (tys.cDim.IsEmpty())
1603         {
1604             funResVar = procName;
1605             txtBindSecond << GetIS() << tys.bType << _T(" :: ") << funResVar << _T("\n");
1606             txtHeadersThis << tys.cType << _T(" ") << cName << _T("(");
1607         }
1608         else
1609         {
1610             // If function returns an array, change it to subroutine (void function) with the last array argument.
1611             bindKindSubroutine = true;
1612             txtBindFirst.Replace(_T("function"), _T("subroutine"), false);
1613             funResVar = token->m_Name + _T("_res");
1614             txtBindSecond << GetIS() << tys.bType << _T(", intent(out) :: ") << funResVar << _T("\n");
1615             addFunVariable << _T(", ") + funResVar;
1616             txtHeadersThis << _T("void ") << cName << _T("(");
1617             cFunResVar = tys.cType + _T(" ") + funResVar + tys.cDim;
1618         }
1619         funInterface.Add(funTypeDec + _T(" :: ") + token->m_DisplayName);
1620         if (funTypeDec.StartsWith(_T("character")))
1621         {
1622             additionalDeclar.Add(funTypeDec + _T(" :: ") + funResVar + _T("_f"));
1623             additionalCalls2.Add(_T("call string_copy_f_c(") + funResVar + _T("_f,") + funResVar + _T(")"));
1624             m_WriteStrFtoC = true;
1625         }
1626         else if (!tys.fType.StartsWith(_T("type(c_ptr)")) && tys.bType.StartsWith(_T("type(c_ptr)")))
1627         {
1628             wxString fName = funResVar + _T("_fp");
1629             additionalDeclar.Add(funTypeDec + _T(", pointer :: ") + fName);
1630             additionalCalls.Add(_T("allocate(") + fName + _T(")"));
1631             additionalCalls2.Add(funResVar + _T(" = c_loc(") + fName + _T(")"));
1632             funResVar = fName;
1633         }
1634         else if (tys.fType.StartsWith(_T("logical")) && tys.info.IsSameAs(_T("add_log2int")))
1635         {
1636             wxArrayString logFunNames = GetLogFunNames(tys.fTypeOnly);
1637             additionalDeclar.Add(funTypeDec + _T(" :: ") + funResVar + _T("_f"));
1638             additionalCalls2.Add(funResVar + _T(" = ") + logFunNames[0] + _T("(") + funResVar + _T("_f)"));
1639             changedNamesMap[funResVar] = funResVar + _T("_f");
1640         }
1641 
1642         wxString pyVarName = token->m_Name + _T("_res");
1643         TypePyx tyaPy = GetBindTypePy(tys,_T("@@@"));
1644         if (tyaPy.fDrvTypeName.IsEmpty())
1645         {
1646             wxString pyLin1 = _T("cdef ") + tyaPy.declarPyxFirst + _T(" ") + pyVarName + _T(" = ") + CIMPORT_FN_KEY + cName + _T("(");
1647             pyLines.Add(pyLin1);
1648         }
1649         else if (m_InFortranModule && m_PyCreateClass && !m_HasPyClassConstructor && IsConstructor(token) && m_DefinedTypes.count(tyaPy.fDrvTypeName) == 1)
1650         {
1651             nowIsPyConstructor = true;
1652             m_HasPyClassConstructor = true;
1653             constrTypeName = tyaPy.fDrvTypeName;
1654             if (argArr.GetCount() == 0)
1655             {
1656                 noArgPyConstructor = true;
1657                 m_NoArgConstructors.insert(funTypeDec);
1658             }
1659             wxString pyLin1 = _T("self._") + tyaPy.fDrvTypeName + _T("_cp = ") + CIMPORT_FN_KEY + cName + _T("(");
1660             pyLines.Add(pyLin1);
1661             pyVarName = _T("");
1662         }
1663         else
1664         {
1665             wxString pyClassName;
1666             wxArrayString address;
1667             m_pParser->GetAddressOfToken(token, address);
1668             TokensArrayFlatClass tokensTmp;
1669             TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
1670             m_pParser->FindUseAssociatedTokens(true, address, tyaPy.fDrvTypeName, false, *resultTmp, tkType, false);
1671             if (resultTmp->size() > 0 && resultTmp->Item(0)->m_ParentTokenKind == tkModule)
1672             {
1673                 pyClassName = resultTmp->Item(0)->m_ParentName;
1674             }
1675             wxString pyLin1 = _T("cdef ") + pyClassName + _T(" ") + pyVarName + _T(" = ") + pyClassName + _T("()\n");
1676             pyLines.Add(pyLin1);
1677             pyLin1 = pyVarName + _T(".") + tyaPy.fDrvTypeName + _T("_cp_del_py()\n");
1678             pyLines.Add(pyLin1);
1679             pyLin1 = pyVarName + _T("._") + tyaPy.fDrvTypeName + _T("_cp") + _T(" = ") + CIMPORT_FN_KEY + cName + _T("(");
1680             pyLines.Add(pyLin1);
1681 
1682             if (IsConstructor(token) && m_DefinedTypes.count(tyaPy.fDrvTypeName) == 1 && argArr.GetCount() == 0)
1683                 m_NoArgConstructors.insert(funTypeDec);
1684         }
1685         txtCythonSecond3 = pyVarName;
1686     }
1687     else if (token->m_TokenKind == tkSubroutine)
1688     {
1689         txtHeadersThis << _T("void ") << cName << _T("(");
1690 
1691         wxString pyLin1 = CIMPORT_FN_KEY + cName + _T("(");
1692         pyLines.Add(pyLin1);
1693     }
1694 
1695     wxString pyName_Key = _T("@@@ pyName_Key @@@");
1696     wxString pyName = GetPyName(token->m_Name, moduleName);
1697     if (nowIsPyConstructor)
1698     {
1699         if (noArgPyConstructor)
1700         {
1701             txtCythonSecond << _T("\n") << GetIS(m_PyIndent) << _T("def __cinit__(self, ");
1702         }
1703         else
1704         {
1705             txtCythonConstr1 << _T("\n") << GetIS(m_PyIndent) << _T("def __cinit__(self, ");
1706             txtCythonSecond << _T("\n") << GetIS(m_PyIndent) << _T("cdef ") << pyName << _T("(self, ");
1707             constrProcName = pyName;
1708         }
1709     }
1710     else
1711     {
1712         txtCythonSecond << _T("\n") << GetIS(m_PyIndent) << _T("def ") << pyName_Key << _T("(");
1713         if (m_InFortranModule && m_PyCreateClass)
1714         {
1715             txtCythonSecond << _T("self, ");
1716         }
1717     }
1718     m_PyIndent++;
1719     for (size_t i=0; i<pyLines.GetCount(); i++)
1720     {
1721         txtCythonSecond2 << GetIS(m_PyIndent) << pyLines.Item(i);
1722     }
1723 
1724     ParseBindtoDirectives(token);
1725 
1726     wxArrayString dimVarNames;
1727     wxArrayString dimVarNamesFP;
1728     wxArrayString varNamesOfDim;
1729     wxArrayString varNamesOfDimFP;
1730     wxArrayString morePyIntArgs;
1731     for (size_t i=0; i<argArr.GetCount(); i++)
1732     {
1733         bool usedSelfPy = false;
1734         TokenF* argToken = m_pParser->FindTokenBetweenChildren(token, argArr.Item(i));
1735         if (!argToken)
1736         {
1737             // Should implicit declaration be assumed?
1738             txtHeadersThis << argArr.Item(i) << _T(", ");
1739             continue;
1740         }
1741 
1742         if (argToken->m_TokenKind == tkVariable)
1743         {
1744             m_pTokenCurrent = argToken;
1745             int nDimVarAdd;
1746             TypeBind tys = GetBindType(argToken, nDimVarAdd);
1747             if (!tys.wasFound && !m_WriteIncompleteWrapper)
1748             {
1749                 m_WarnMessage << _("\nERROR: Procedure '") << token->m_Name << _("' was not wrapped!\n");
1750                 return;
1751             }
1752             else if (!tys.wasFound)
1753                 m_WarnMessage << _("\nERROR: Wrapper of '") << token->m_Name << _("' procedure contains errors.\n");
1754             else if (!tys.errMsg.IsEmpty())
1755             {
1756                 if (!m_WriteIncompleteWrapper)
1757                 {
1758                     m_WarnMessage << _("\nERROR: Procedure '") << token->m_Name << _("' was not wrapped!\n");
1759                     m_WarnMessage << _T("    ") << tys.errMsg << _("\n");
1760                     return;
1761                 }
1762                 else
1763                 {
1764                     m_WarnMessage << _("\nERROR: Wrapper of '") << token->m_Name << _("' procedure contains errors.\n");
1765                     m_WarnMessage << _T("    ") << tys.errMsg << _("\n");
1766                 }
1767             }
1768 
1769             if (!tys.fType.StartsWith(_T("type(c_ptr)")) && tys.bType.StartsWith(_T("type(c_ptr)")))
1770             {
1771                 wxString fDec = tys.fType;
1772                 if (fDec.StartsWith(_T("class(")))
1773                     fDec.Replace(_T("class("), _T("type("), false);
1774                 fDec.Replace(_T(", intent(in)"),_T(""));
1775                 fDec.Replace(_T(", intent(out)"),_T(""));
1776                 fDec.Replace(_T(", intent(inout)"),_T(""));
1777                 wxString bvName = argToken->m_Name + _T("_fp");
1778 
1779                 if (IsConstructor(token) && token->m_TokenKind == tkSubroutine && i == 0 && m_DefinedTypes.count(tys.fDrvTypeName) == 1)
1780                 {
1781                     additionalCalls.Add(_T("allocate(") + bvName + _T(")"));
1782                     additionalCalls.Add(argToken->m_Name + _T(" = c_loc(") + bvName + _T(")"));
1783                     if (argArr.GetCount() == 1)
1784                         m_NoArgConstructors.insert(fDec);
1785 
1786                     if (m_InFortranModule && m_PyCreateClass && !m_HasPyClassConstructor)
1787                     {
1788                         nowIsPyConstructor = true;
1789                         m_HasPyClassConstructor = true;
1790                         constrTypeName = tys.fDrvTypeName;
1791                         if (argArr.GetCount() == 1)
1792                         {
1793                             noArgPyConstructor = true;
1794                         }
1795                         else
1796                         {
1797                             txtCythonConstr1 << _T("\n") << GetIS(m_PyIndent-1) << _T("def __cinit__(self, ");
1798                             txtCythonSecond.Replace(_T("def ")+pyName_Key, _T("cdef ")+pyName, false);
1799                             constrProcName = pyName;
1800                         }
1801                     }
1802                 }
1803                 else
1804                 {
1805                     wxString fDecHid;
1806                     int nAD;
1807                     TypeBind tys_tmp;
1808                     HideAssumedShape(fDec, fDecHid, nAD);
1809                     if (nAD > 0)
1810                     {
1811                         size_t nVNini = dimVarNamesFP.size();
1812                         AddDimVariablesFromDoc(dimVarNamesFP, nAD, argToken->m_Name, varNamesOfDimFP, tys_tmp);
1813                         if (nAD > 0)
1814                             AddDimVariables(argArr, dimVarNamesFP, nAD, _T("mdt"), argToken->m_Name, varNamesOfDimFP, tys_tmp);
1815 
1816                         wxString varShape = _T(", [");
1817                         for (size_t ivn = nVNini; ivn<dimVarNamesFP.size(); ivn++)
1818                         {
1819                             varShape << dimVarNamesFP.Item(ivn) << _T(",");
1820                         }
1821                         varShape = varShape.Mid(0,varShape.size()-1) + _T("]");
1822                         additionalCalls.Add(_T("call c_f_pointer(") + argToken->m_Name + _T(", ") + bvName + varShape + _T(")"));
1823                     }
1824                     else
1825                         additionalCalls.Add(_T("call c_f_pointer(") + argToken->m_Name + _T(", ") + bvName + _T(")"));
1826 
1827                     wxString ftname;
1828                     if (fDec.size() > 6)
1829                         ftname = fDec.Mid(5,fDec.size()-6).Trim(true).Trim(false);
1830 
1831                     if (IsDestructor(token) && token->m_TokenKind == tkSubroutine && i == 0 && argArr.GetCount() == 1 &&
1832                         m_DefinedTypes.count(ftname) == 1)
1833                     {
1834                         additionalCalls2.Add(_T("deallocate(") + bvName + _T(")"));
1835                         if (m_Deallocators.count(ftname) == 0)
1836                             m_Deallocators[ftname] = cName;
1837                         nowIsPyDestructor = true;
1838                     }
1839                 }
1840 
1841                 additionalDeclar.Add(fDec + _T(", pointer :: ") + bvName);
1842                 changedNamesMap[argToken->m_Name] = bvName;
1843             }
1844             else
1845             {
1846                 if (nDimVarAdd > 0)
1847                     AddDimVariablesFromDoc(dimVarNames, nDimVarAdd, argToken->m_Name, varNamesOfDim, tys);
1848                 if (nDimVarAdd > 0)
1849                     AddDimVariables(argArr, dimVarNames, nDimVarAdd, _T("m"), argToken->m_Name, varNamesOfDim, tys);
1850             }
1851 
1852             if (tys.fType.StartsWith(_T("character")) && tys.fType.Find(_T("len=1)")) == wxNOT_FOUND)
1853             {
1854                 //character(len=:), allocatable :: fname_f
1855 
1856                 wxString fDec = tys.fType;
1857                 fDec.Replace(_T(", intent(in)"),_T(""));
1858                 fDec.Replace(_T(", intent(out)"),_T(""));
1859                 fDec.Replace(_T(", intent(inout)"),_T(""));
1860                 if (fDec.Find(_T("len=*")) != wxNOT_FOUND)
1861                 {
1862                     wxString str = fDec + _T(", allocatable :: ") + argToken->m_Name + _T("_f");
1863                     str.Replace(_T("len=*"), _T("len=:"));
1864                     additionalDeclar.Add(str);
1865                     if (!wasChlen)
1866                     {
1867                         additionalDeclar.Add(_T("integer :: chlen_bc"));
1868                         wasChlen = true;
1869                     }
1870                     additionalCalls.Add(_T("chlen_bc = string_len(") + argToken->m_Name + _T(")"));
1871                     additionalCalls.Add(_T("allocate(character(len=chlen_bc)::") + argToken->m_Name + _T("_f)"));
1872                     m_WriteStrLen = true;
1873                 }
1874                 else
1875                     additionalDeclar.Add(fDec + _T(" :: ") + argToken->m_Name + _T("_f") + argToken->m_Args.Lower());
1876                 if (tys.fType.Find(_T("intent(out)")) == wxNOT_FOUND)
1877                 {
1878                     additionalCalls.Add(_T("call string_copy_c_f(") + argToken->m_Name + _T(", ") + argToken->m_Name + _T("_f)"));
1879                     m_WriteStrCtoF = true;
1880                 }
1881                 if (tys.fType.Find(_T("intent(in)")) == wxNOT_FOUND)
1882                 {
1883                     additionalCalls2.Add(_T("call string_copy_f_c(") + argToken->m_Name + _T("_f, ") + argToken->m_Name + _T(")"));
1884                     m_WriteStrFtoC = true;
1885                 }
1886                 changedNamesMap[argToken->m_Name] = argToken->m_Name + _T("_f");
1887             }
1888             else if (tys.fType.StartsWith(_T("logical")) && tys.info.IsSameAs(_T("add_log2int")))
1889             {
1890                 wxString fDec = tys.fTypeOnly;
1891                 wxString bvName = argToken->m_Name + _T("_f");
1892                 wxString dims;
1893                 if (!tys.bDim.IsEmpty())
1894                     dims = _T(", dimension") + tys.bDim;
1895 
1896                 additionalDeclar.Add(fDec + dims + _T(" :: ") + bvName);
1897                 wxArrayString logFunNames = GetLogFunNames(tys.fTypeOnly);
1898                 if (tys.fType.Find(_T("intent(out)")) == wxNOT_FOUND)
1899                     additionalCalls.Add(bvName + _T(" = ") + logFunNames[1] + _T("(") + argToken->m_Name + _T(")"));
1900                 if (tys.fType.Find(_T("intent(in)")) == wxNOT_FOUND)
1901                     additionalCalls2.Add(argToken->m_Name + _T(" = ") + logFunNames[0] + _T("(") + bvName + _T(")"));
1902                 changedNamesMap[argToken->m_Name] = bvName;
1903             }
1904             txtBindSecond << GetIS() << tys.bType << _T(" :: ") << argToken->m_Name;
1905             wxString cVarName = argToken->m_Name;
1906             if (cVarName.IsSameAs(_T("this")))
1907                 cVarName << _T("_cp");
1908             txtHeadersThis << tys.cType << _T(" ") << cVarName << tys.cDim << _T(", ");
1909             funInterface.Add(tys.fType + _T(" :: ") + argToken->m_Name);
1910 
1911             TypePyx tyaPy = GetBindTypePy(tys, argToken->m_Name);
1912 
1913             if (tyaPy.fDrvTypeName.IsEmpty())
1914             {
1915                 if (tys.fType.StartsWith(_T("logical")) && tys.info.IsSameAs(_T("add_log2int")))
1916                 {
1917                     wxString intname = _T("int_") + argToken->m_Name;
1918                     if (tyaPy.hide)
1919                     {
1920                         additionalDeclarPy.Add(_T("cdef ") + tyaPy.declarPyxFirst + intname + tyaPy.initStr);
1921                         argHideSetPy.insert(argToken->m_Name);
1922                         wxString declOut = tyaPy.declarPyxFirst;
1923 
1924                         if (declOut.StartsWith(_T("np.ndarray")))
1925                         {
1926                             declOut.Replace(_T("int"), _T("np.uint8_t"));
1927                             declOut.Replace(_T("]"), _T(",cast=True]"));
1928                             wxString strDecl = _T("cdef ") + declOut + _T(" ") + argToken->m_Name + _T(" = np.empty([");
1929                             for (int nd=0; nd<tyaPy.ndim; nd++)
1930                             {
1931                                 strDecl << wxString::Format(intname + _T(".shape[%d],"), nd);
1932                             }
1933                             strDecl << _T("], dtype=np.bool)");
1934                             additionalCallPy2.Add(strDecl);
1935                             additionalCallPy2.Add(argToken->m_Name + _T("[...] = ") + intname);
1936                         }
1937                         else
1938                         {
1939                             declOut.Replace(_T("int"), _T("bint"));
1940                             additionalCallPy2.Add(_T("cdef ") + declOut + _T(" ") + argToken->m_Name + _T(" = ") + intname);
1941                         }
1942                     }
1943                     else
1944                     {
1945                         wxString declInp = tyaPy.declarPyxFirst;
1946                         if (declInp.StartsWith(_T("np.ndarray")))
1947                         {
1948                             declInp.Replace(_T("int"), _T("np.uint8_t"));
1949                             declInp.Replace(_T("]"), _T(",cast=True]"));
1950                             txtCythonSecond << declInp << _T(" ") << argToken->m_Name << _T(", ");
1951                             wxString strDecl = _T("cdef ") + tyaPy.declarPyxFirst + intname + _T(" = ");
1952                             strDecl << _T("np.empty([");
1953                             for (int nd=0; nd<tyaPy.ndim; nd++)
1954                             {
1955                                 strDecl << wxString::Format(argToken->m_Name + _T(".shape[%d],"), nd);
1956                             }
1957                             strDecl << _T("], dtype=np.intc)");
1958                             additionalDeclarPy.Add(strDecl);
1959                             strDecl = intname + _T("[...] = ") + argToken->m_Name;
1960                             additionalDeclarPy.Add(strDecl);
1961                             if (tyaPy.copy)
1962                             {
1963                                 additionalCallPy2.Add(argToken->m_Name + _T("_copy = ") + argToken->m_Name + _T(".copy()"));
1964                                 additionalCallPy2.Add(argToken->m_Name + _T("_copy[...] = ") + intname);
1965                             }
1966                             else
1967                                 additionalCallPy2.Add(argToken->m_Name + _T("[...] = ") + intname);
1968                         }
1969                         else
1970                         {
1971                             declInp.Replace(_T("int"), _T("bint"));
1972                             txtCythonSecond << declInp << _T(" ") << argToken->m_Name << _T(", ");
1973                             additionalDeclarPy.Add(_T("cdef ") + tyaPy.declarPyxFirst + _T(" ") + intname + _T(" = ") + argToken->m_Name);
1974                             if (tyaPy.intent.IsSameAs(_T("out")) || tyaPy.intent.IsSameAs(_T("inout")))
1975                                 additionalCallPy2.Add(argToken->m_Name + _T(" = ") + intname);
1976                         }
1977                     }
1978                     txtCythonSecond2 << _T("&") << intname << tyaPy.callCSecond << _T(", ");
1979                 }
1980                 else if (tyaPy.declarPyxFirst.IsSameAs(_T("char*")))
1981                 {
1982                     if (tyaPy.hide)
1983                     {
1984                         if (tyaPy.initStr.IsEmpty())
1985                             additionalDeclarPy.Add(_T("cdef ") + tyaPy.declarPyxFirst + _T(" ") + argToken->m_Name);
1986                         else
1987                             additionalDeclarPy.Add(argToken->m_Name + tyaPy.initStr);
1988                         argHideSetPy.insert(argToken->m_Name);
1989                     }
1990                     else
1991                         txtCythonSecond << tyaPy.declarPyxFirst << _T(" ") << argToken->m_Name << _T(", ");
1992                     txtCythonSecond2 << argToken->m_Name << _T(", ");
1993                 }
1994                 else
1995                 {
1996                     wxString copystr;
1997                     if (tyaPy.hide)
1998                     {
1999                         wxString dStr = _T("cdef ") + tyaPy.declarPyxFirst + _T(" ") + argToken->m_Name + tyaPy.initStr;
2000                         if (tyaPy.declarPyxFirst.StartsWith(_T("np.ndarray")))
2001                             additionalDeclarPy.Add(dStr);
2002                         else
2003                             additionalDeclarPy.Insert(dStr,0);
2004 
2005                         argHideSetPy.insert(argToken->m_Name);
2006                     }
2007                     else
2008                     {
2009                         if (tyaPy.copy && tyaPy.declarPyxFirst.StartsWith(_T("np.ndarray")))
2010                         {
2011                             additionalDeclarPy.Add(_T("cdef ") + tyaPy.declarPyxFirst << _T(" ") +
2012                                                    argToken->m_Name + _T("_copy = ") + argToken->m_Name + _T(".copy()"));
2013                             copystr = _T("_copy");
2014                         }
2015                         txtCythonSecond << tyaPy.declarPyxFirst << _T(" ") << argToken->m_Name << _T(", ");
2016                     }
2017                     txtCythonSecond2 << _T("&") << argToken->m_Name << copystr << tyaPy.callCSecond << _T(", ");
2018 
2019                     if (tyaPy.addIntArg.size() > 0)
2020                         AddPyArgs(argArr, morePyIntArgs, tyaPy.addIntArg);
2021                 }
2022             }
2023             else
2024             {
2025                 if (i == 0 && m_PyFirstArgAsSelf && m_InFortranModule && m_PyCreateClass &&
2026                     (m_DefinedTypes.count(tyaPy.fDrvTypeName) == 1))
2027                 {
2028                     txtCythonSecond2 << _T("&self._") << tyaPy.fDrvTypeName << _T("_cp") << _T(", ");
2029                     usedSelfPy = true;
2030                 }
2031                 else
2032                 {
2033                     wxString pyClassName;
2034                     wxArrayString address;
2035                     m_pParser->GetAddressOfToken(token, address);
2036                     TokensArrayFlatClass tokensTmp;
2037                     TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
2038                     m_pParser->FindUseAssociatedTokens(true, address, tyaPy.fDrvTypeName, false, *resultTmp, tkType, false);
2039                     if (resultTmp->size() > 0 && resultTmp->Item(0)->m_ParentTokenKind == tkModule)
2040                     {
2041                         pyClassName = resultTmp->Item(0)->m_ParentName;
2042                     }
2043                     txtCythonSecond << pyClassName << _T(" ") << argToken->m_Name << _T(", ");
2044                     txtCythonSecond2 << _T("&") << argToken->m_Name << _T("._") << tyaPy.fDrvTypeName << _T("_cp") << _T(", ");
2045                 }
2046             }
2047 
2048             if ((tyaPy.intent.IsSameAs(_T("out")) || tyaPy.intent.IsSameAs(_T("inout"))) && !usedSelfPy)
2049             {
2050                 if (!txtCythonSecond3.IsEmpty())
2051                     txtCythonSecond3 << _T(", ");
2052                 if (tyaPy.copy && tyaPy.declarPyxFirst.StartsWith(_T("np.ndarray")))
2053                     txtCythonSecond3 << argToken->m_Name << _T("_copy");
2054                 else
2055                     txtCythonSecond3 << argToken->m_Name;
2056             }
2057 
2058             if (nowIsPyConstructor && !noArgPyConstructor)
2059             {
2060                 if (token->m_TokenKind == tkFunction || (i > 0 && token->m_TokenKind == tkSubroutine))
2061                     txtCythonConstr1 << argToken->m_Name << _T("=None") << _T(", ");
2062                 if ((i == 0 && token->m_TokenKind == tkFunction) ||
2063                     (i == 1 && token->m_TokenKind == tkSubroutine))
2064                 {
2065                     txtCythonConstr2 << GetIS(m_PyIndent) << _T("if ") << argToken->m_Name << _T(" is not None:\n");
2066                     txtCythonConstr2 << GetIS(m_PyIndent+1) << _T("self.") << constrProcName << _T("(");
2067                     txtCythonConstr2 << argToken->m_Name << _T(", ");
2068                 }
2069                 else if ((token->m_TokenKind == tkFunction) ||
2070                          (token->m_TokenKind == tkSubroutine && i > 1))
2071                 {
2072                     txtCythonConstr2 << argToken->m_Name << _T(", ");
2073                 }
2074             }
2075 
2076         }
2077         else
2078         {
2079             // it may be a procedure. What then to do?
2080         }
2081         txtBindSecond << _T("\n");
2082 
2083     }
2084     // Deal with assumed-shape arrays
2085     wxArrayString addVarNames;
2086     wxArrayString addVarNamesC;
2087     wxArrayString addVarNamesPy;
2088     wxArrayString addArgNamesPy;
2089     wxArrayString additionalDeclarPy_tmp;
2090     wxArrayString addVarNamesPy_tmp;
2091     StrSet argHideSetPy_tmp;
2092     wxArrayString addArgNamesPy_tmp;
2093     PrepareAssumedShapeVariables(argArr, dimVarNames, additionalDeclar, addVarNames, addVarNamesC, varNamesOfDim,
2094                                  argHideSetPy, additionalDeclarPy, addVarNamesPy, addArgNamesPy);
2095     PrepareAssumedShapeVariables(argArr, dimVarNamesFP, additionalDeclar, addVarNames, addVarNamesC, varNamesOfDimFP,
2096                                  argHideSetPy_tmp, additionalDeclarPy_tmp, addVarNamesPy_tmp, addArgNamesPy_tmp);
2097     for (size_t i=0; i<addVarNames.size(); i++)
2098         txtBindFirst << _T(", ") << addVarNames.Item(i);
2099 
2100     txtBindFirst << addFunVariable;
2101     txtBindFirst << _T(") bind(c,name='") << cName << _T("')\n");
2102 
2103     for (size_t i=0; i<addVarNamesC.size(); i++)
2104         txtHeadersThis << addVarNamesC.Item(i) << _T(", ");
2105     if (token->m_TokenKind == tkFunction && bindKindSubroutine)
2106         txtHeadersThis << cFunResVar << _T(", ");
2107 
2108     if (isGlobal && token->m_TokenKind == tkFunction)
2109     {
2110         if (bindKindSubroutine)
2111         {
2112             funInterface.Add(_T("end function"));
2113             funInterface.Add(_T("end interface"));
2114 
2115             txtBindSecond << _T("\n");
2116             for (size_t i=0; i<funInterface.size(); i++)
2117             {
2118                 if (i==1 || i==2)
2119                     m_Indent++;
2120                 else if (i==funInterface.size()-2 || i==funInterface.size()-1)
2121                     m_Indent--;
2122                 txtBindSecond << GetIS() << funInterface.Item(i) << _T("\n");
2123             }
2124         }
2125         else
2126             txtBindSecond << GetIS() << funTypeDec << _T(" :: ") << token->m_DisplayName << _T("\n");
2127     }
2128 
2129     for (size_t i=0; i<additionalDeclar.size(); i++)
2130         txtBindSecond << GetIS() << additionalDeclar.Item(i) << _T("\n");
2131 
2132     txtBindSecond << _T("\n");
2133     if (txtHeadersThis.EndsWith(_T(", ")))
2134         txtHeadersThis.Truncate(txtHeadersThis.size()-2);
2135     txtHeadersThis << _T(");\n");
2136     txtCythonFirst << GetIS(1) << txtHeadersThis.Mid(0,txtHeadersThis.size()-2) << _T("\n");
2137     for (size_t i=0; i<additionalCalls.size(); i++)
2138         txtBindSecond << GetIS() << additionalCalls.Item(i) << _T("\n");
2139 
2140     if (callName.IsEmpty())
2141         callName = token->m_DisplayName;
2142     if (token->m_TokenKind == tkSubroutine)
2143     {
2144         txtBindSecond << GetIS() << _T("call ") << callName << _T("(");
2145     }
2146     else if (token->m_TokenKind == tkFunction)
2147     {
2148         if (funTypeDec.StartsWith(_T("character")))
2149             txtBindSecond << GetIS() << funResVar << _T("_f = ") << callName << _T("(");
2150         else if (changedNamesMap.count(funResVar) == 0)
2151             txtBindSecond << GetIS() << funResVar << _T(" = ") << callName << _T("(");
2152         else
2153             txtBindSecond << GetIS() << changedNamesMap[funResVar] << _T(" = ") << callName << _T("(");
2154     }
2155 
2156     for (size_t i=0; i<argArr.GetCount(); i++)
2157     {
2158         if (changedNamesMap.count(argArr.Item(i)) == 0)
2159             txtBindSecond << argArr.Item(i);
2160         else
2161             txtBindSecond << changedNamesMap[argArr.Item(i)];
2162         if (i+1 < argArr.GetCount())
2163             txtBindSecond << _T(", ");
2164     }
2165     txtBindSecond << _T(")\n");
2166 
2167     for (size_t i=0; i<additionalCalls2.size(); i++)
2168         txtBindSecond << GetIS() << additionalCalls2.Item(i) << _T("\n");
2169 
2170     m_Indent--;
2171     if (bindKindSubroutine)
2172         txtBindSecond << GetIS() << _T("end subroutine\n\n");
2173     else
2174         txtBindSecond << GetIS() << _T("end function\n\n");
2175     txtBind << txtBindFirst << txtBindSecond;
2176     txtHeaders << txtHeadersThis;
2177 
2178     if (nowIsPyConstructor)
2179         txtCythonSecond.Replace(pyName_Key, _T("__cinit__"), false);
2180     else
2181         txtCythonSecond.Replace(pyName_Key, pyName, false);
2182 
2183     if (nowIsPyConstructor && !noArgPyConstructor)
2184     {
2185         if (txtCythonConstr1.EndsWith(_T(", ")))
2186             txtCythonConstr1.Truncate(txtCythonConstr1.size()-2);
2187         txtCythonConstr1 << _T("):\n");
2188         if (txtCythonConstr2.EndsWith(_T(", ")))
2189             txtCythonConstr2.Truncate(txtCythonConstr2.size()-2);
2190         txtCythonConstr2 << _T(")\n");
2191         for ( StrSet::iterator it=m_DefinedTypes.begin(); it != m_DefinedTypes.end(); ++it)
2192         {
2193             wxString type = *it;
2194             if (constrTypeName.IsSameAs(*it))
2195                 continue;
2196             wxString conName = GetConstructorName(type);
2197             wxString cConName = GetCName(conName, moduleName);
2198             txtCythonConstr2 << GetIS(m_PyIndent+1) << _T("self._") << type << _T("_cp = ");
2199             txtCythonConstr2 << CIMPORT_FN_KEY << cConName << _T("()\n");
2200         }
2201         txtCythonConstr2 << GetIS(m_PyIndent) << _T("else:\n");
2202         for ( StrSet::iterator it=m_DefinedTypes.begin(); it != m_DefinedTypes.end(); ++it)
2203         {
2204             wxString type = *it;
2205             wxString conName = GetConstructorName(type);
2206             wxString cConName = GetCName(conName, moduleName);
2207             txtCythonConstr2 << GetIS(m_PyIndent+1) << _T("self._") << type << _T("_cp = ");
2208             txtCythonConstr2 << CIMPORT_FN_KEY << cConName << _T("()\n");
2209         }
2210     }
2211 
2212     wxString txtCythonMore1;
2213     for (size_t i=0; i<additionalDeclarPy.size(); i++)
2214         txtCythonMore1 << GetIS(m_PyIndent) << additionalDeclarPy.Item(i) << _T("\n");
2215     for (size_t i=0; i<addArgNamesPy.size(); i++)
2216         txtCythonSecond << addArgNamesPy.Item(i) << _T(", ");
2217     for (size_t i=0; i<morePyIntArgs.size(); i++)
2218         txtCythonSecond << _T("int ") << morePyIntArgs.Item(i) << _T(", ");
2219     if (txtCythonSecond.EndsWith(_T(", ")))
2220         txtCythonSecond.Truncate(txtCythonSecond.size()-2);
2221     txtCythonSecond << _T("):\n");
2222     txtCythonSecond << txtCythonMore1;
2223     for (size_t i=0; i<addVarNamesPy.size(); i++)
2224         txtCythonSecond2 << addVarNamesPy.Item(i) << _T(", ");
2225     if (txtCythonSecond2.EndsWith(_T(", ")))
2226         txtCythonSecond2.Truncate(txtCythonSecond2.size()-2);
2227     txtCythonSecond2 << _T(")\n");
2228     txtCythonSecond << txtCythonSecond2;
2229     for (size_t i=0; i<additionalCallPy2.size(); i++)
2230         txtCythonSecond << GetIS(m_PyIndent) << additionalCallPy2.Item(i) << _T("\n");
2231     if (!txtCythonSecond3.IsEmpty())
2232         txtCythonSecond << GetIS(m_PyIndent) << _T("return ") << txtCythonSecond3 << _T("\n");
2233 
2234     if (nowIsPyConstructor && !noArgPyConstructor)
2235     {
2236         txtCythonSecond << txtCythonConstr1;
2237         txtCythonSecond << txtCythonConstr2;
2238     }
2239     else if (nowIsPyDestructor)
2240         txtCythonSecond.clear();
2241 
2242     txtPyFirst << txtCythonFirst;
2243     txtPySecond << txtCythonSecond;
2244     m_PyIndent--;
2245 
2246     m_CurProcedure = wxEmptyString;
2247 }
2248 
2249 
GetBindType(TokenF * token,int & nDimVarAdd)2250 Bindto::TypeBind Bindto::GetBindType(TokenF* token, int& nDimVarAdd)
2251 {
2252     nDimVarAdd = 0;
2253     TypeBind retSt = GetBindType(token->m_TypeDefinition.Lower(), nDimVarAdd);
2254     if (token->m_Args.StartsWith(_T("(")))
2255     {
2256         wxString vDim = GetToken(token->m_Args.Lower(),0);
2257         wxString vDimHid;
2258         int nAssumedDim;
2259         HideAssumedShape(vDim, vDimHid, nAssumedDim);
2260         retSt.bDim = vDimHid;
2261         if (retSt.fType.Find(_T("dimension(")) == wxNOT_FOUND)
2262         {
2263             int itn = retSt.fType.Find(_T(", intent("));
2264             int itn2 = retSt.bType.Find(_T(", intent("));
2265             if (itn == wxNOT_FOUND || itn2 == wxNOT_FOUND)
2266             {
2267                 retSt.fType << _T(", dimension") << vDim;
2268                 if (retSt.fType.StartsWith(_T("type(c_ptr)")) || !retSt.bType.StartsWith(_T("type(c_ptr)")))
2269                     retSt.bType << _T(", dimension") << vDimHid;
2270             }
2271             else
2272             {
2273                 retSt.fType.insert(itn,_T(", dimension")+vDim);
2274                 if (retSt.fType.StartsWith(_T("type(c_ptr)")) || !retSt.bType.StartsWith(_T("type(c_ptr)")))
2275                     retSt.bType.insert(itn2,_T(", dimension")+vDimHid);
2276             }
2277             nDimVarAdd = nAssumedDim;
2278         }
2279         else
2280         {
2281             int idxDim = retSt.fType.Find(_T("dimension("));
2282             wxString vdimOld;
2283             if (idxDim != wxNOT_FOUND)
2284                 vdimOld = GetToken(retSt.fType,idxDim+9);
2285             int idxDim2 = retSt.bType.Find(_T("dimension("));
2286             wxString vdimOld2;
2287             if (idxDim2 != wxNOT_FOUND)
2288                 vdimOld2 = GetToken(retSt.bType,idxDim2+9);
2289             retSt.fType.Replace(vdimOld,vDim);
2290             if (!vdimOld2.IsEmpty())
2291                 retSt.bType.Replace(vdimOld2,vDimHid);
2292             nDimVarAdd = nAssumedDim;
2293         }
2294         retSt.cDim = GetCDims(vDim);
2295 
2296         if (retSt.errMsg.IsEmpty() && retSt.fType.StartsWith(_T("character(")) &&
2297             retSt.fType.Find(_T("len=1)")) == wxNOT_FOUND)
2298         {
2299             retSt.errMsg = _("Error: Call of array of characters from C, when character length/=1, is not supported.");
2300         }
2301     }
2302 
2303     if (retSt.cDim.IsEmpty())
2304         retSt.cType << _T("*"); // variable as C pointer
2305 
2306     return retSt;
2307 }
2308 
2309 
GetBindType(const wxString & declar,int & nDimVarAdd)2310 Bindto::TypeBind Bindto::GetBindType(const wxString& declar, int& nDimVarAdd)
2311 {
2312     wxString declarLw = declar.Lower();
2313     declarLw.Replace(_T(" "),_T(""));
2314 
2315     nDimVarAdd = 0;
2316     wxString ftype;
2317     wxString fCharLen;
2318     wxArrayString fTypeKind = GetTypeAndKind(declarLw);
2319 
2320     if (declarLw.StartsWith(_T("character")))
2321     {
2322         // deal with character type
2323         wxString klstr = fTypeKind.Item(1);
2324         int iLen = klstr.Find(_T("len="));
2325         int iKin = klstr.Find(_T("kind="));
2326         if (iLen != wxNOT_FOUND)
2327         {
2328             int lnd = klstr.Mid(iLen+4).Find(_T(","));
2329             if (lnd == wxNOT_FOUND)
2330             {
2331                 lnd = klstr.Mid(iLen+4).Find(_T(")"));
2332                 if (lnd == wxNOT_FOUND)
2333                     lnd = klstr.size();
2334             }
2335             fCharLen = klstr.Mid(iLen+4,lnd);
2336         }
2337         else if (iKin == wxNOT_FOUND)
2338         {
2339             if (klstr.IsEmpty())
2340                 fCharLen = _T("1");
2341             else
2342                 fCharLen = klstr;
2343         }
2344         else // (iKin != wxNOT_FOUND)
2345         {
2346             fCharLen = _T("1");
2347         }
2348 
2349         wxString fCharKind;
2350         if (iKin != wxNOT_FOUND)
2351         {
2352             int lnd = klstr.Mid(iKin+5).Find(_T(","));
2353             if (lnd == wxNOT_FOUND)
2354             {
2355                 lnd = klstr.Mid(iKin+5).Find(_T(")"));
2356                 if (lnd == wxNOT_FOUND)
2357                     lnd = klstr.size();
2358             }
2359             fCharKind = klstr.Mid(iKin+5,lnd);
2360         }
2361         if (fCharKind.IsEmpty())
2362             ftype = _T("character");
2363         else
2364             ftype = _T("character(kind=") + fCharKind + _T(")");
2365     }
2366     else
2367     {
2368         ftype = fTypeKind.Item(0);
2369         fTypeKind.Item(1).Replace(_T("kind="),_T(""));
2370         if (!fTypeKind.Item(1).IsEmpty())
2371             ftype << _T("(") << fTypeKind.Item(1) << _T(")");
2372     }
2373 
2374     TypeBind retSt;
2375     bool wasNotFound = false;
2376     if (m_TypeMap.count(ftype) == 0)
2377     {
2378         wasNotFound = true;
2379         if (ftype.StartsWith(_T("type(")) || ftype.StartsWith(_T("class(")))
2380         {
2381             int st = ftype.Find('(');
2382             int en = ftype.Find(')');
2383             if (st != wxNOT_FOUND && en != wxNOT_FOUND)
2384             {
2385                 wxString tname = ftype.Mid(st+1,en-st-1);
2386                 wxArrayString address;
2387                 m_pParser->GetAddressOfToken(m_pTokenCurrent->m_pParent, address);
2388                 TokensArrayFlatClass tokensTmp;
2389                 TokensArrayFlat* resultTmp = tokensTmp.GetTokens();
2390                 m_pParser->FindUseAssociatedTokens(true, address, tname, false, *resultTmp, tkType, false);
2391                 if (resultTmp->size() > 0)
2392                 {
2393                     TokenF* typeTok = m_pParser->FindToken(resultTmp->Item(0));
2394                     if (typeTok)
2395                     {
2396                         retSt.fDrvTypeName = typeTok->m_Name;
2397                         wxString tdef = typeTok->m_TypeDefinition.Lower();
2398                         tdef.Replace(_T(" "),_T(""));
2399 
2400                         if (tdef.Find(_T("bind(c)")) != wxNOT_FOUND)
2401                         {
2402                             // type with bind(c)
2403                             wxArrayString ct;
2404                             ct.Add(ftype);
2405                             wxString c_type;
2406                             if (en>st)
2407                                 c_type = ftype.Mid(st+1,en-st-1);
2408                             else
2409                                 c_type = ftype; // something gone wrong
2410                             ct.Add(c_type);
2411                             m_TypeMap[ftype] = ct;
2412                             wasNotFound = false;
2413 
2414                             AddToCStruct(typeTok);
2415                         }
2416                         else
2417                         {
2418                             // type without bind(c)
2419                             wxArrayString ct;
2420                             ct.Add(_T("type(c_ptr)"));
2421                             ct.Add(_T("void*"));
2422                             m_TypeMap[ftype] = ct;
2423                             wasNotFound = false;
2424                         }
2425 
2426                         if (typeTok->m_pParent->m_TokenKind == tkModule)
2427                         {
2428                             wxArrayString tdin;
2429                             tdin.Add(typeTok->m_pParent->m_DisplayName);
2430                             m_TypeDefinedInMap[typeTok->m_Name] = tdin;
2431                             m_TypeDefinedInGlobMap[typeTok->m_Name] = tdin;
2432                         }
2433                     }
2434                 }
2435             }
2436         }
2437     }
2438 
2439     if (wasNotFound && m_LogToInt && fTypeKind.Item(0).IsSameAs(_T("logical")))
2440     {
2441         retSt.fType = ftype;
2442         retSt.fTypeOnly = ftype;
2443         retSt.bType = _T("integer(c_int)");
2444         retSt.cType = _T("int");
2445         retSt.info = _T("add_log2int");
2446     }
2447     else if (wasNotFound)
2448     {
2449         if (m_NotFoundTypes.count(ftype) == 0)
2450         {
2451             m_WarnMessage << _("ERROR: Fortran type '") << ftype << _("' was not found between bind types.\n");
2452             m_WarnMessage << _("File: ") << m_CurFile;
2453             if (!m_CurModule.IsEmpty())
2454                 m_WarnMessage << _("; Module: ") << m_CurModule;
2455             m_WarnMessage << _("; Procedure: ") << m_CurProcedure << _T("\n");
2456             m_NotFoundTypes.insert(ftype);
2457         }
2458         TypeBind emptSt;
2459         emptSt.fType = ftype;
2460         emptSt.wasFound = false;
2461         return emptSt;
2462     }
2463     else
2464     {
2465         wxArrayString retArr = m_TypeMap[ftype]; //size==2
2466         retSt.bType = retArr[0];
2467         retSt.cType = retArr[1];
2468         retSt.fType = ftype;
2469         retSt.cDim = wxEmptyString;
2470     }
2471 
2472     if (retSt.cType.StartsWith(_T("int8_t")) ||
2473         retSt.cType.StartsWith(_T("int16_t")) ||
2474         retSt.cType.StartsWith(_T("int32_t")) ||
2475         retSt.cType.StartsWith(_T("int64_t")))
2476     {
2477         m_CInclude.insert(_T("#include <stdint.h>"));
2478         m_PyInclude.insert(_T("from libc.stdint cimport *"));
2479     }
2480     else if (retSt.cType.StartsWith(_T("float complex")) ||
2481              retSt.cType.StartsWith(_T("double complex")) ||
2482              retSt.cType.StartsWith(_T("long double complex")))
2483     {
2484         m_CInclude.insert(_T("#include <complex.h>"));
2485     }
2486 
2487     int iPos = declarLw.Find(_T("dimension("));
2488     if (iPos != wxNOT_FOUND && retSt.fType.StartsWith(_T("character")) && !fCharLen.IsSameAs(_T("1")))
2489     {
2490         retSt.errMsg = _("Error: Call of array of characters from C, when character length/=1, is not supported.");
2491     }
2492     else if (iPos != wxNOT_FOUND)
2493     {
2494         wxString vdim = GetToken(declarLw,iPos+9);
2495         retSt.fType << _T(", dimension") << vdim;
2496         int nAssumedDim;
2497         wxString vdimHid;
2498         HideAssumedShape(vdim, vdimHid, nAssumedDim);
2499         if (!retSt.fType.StartsWith(_T("type(c_ptr)")) && retSt.bType.StartsWith(_T("type(c_ptr)")))
2500             ;
2501         else
2502         {
2503             retSt.bType << _T(", dimension") << vdimHid;
2504             retSt.bDim = vdimHid;
2505             retSt.cDim << GetCDims(vdim);
2506             nDimVarAdd += nAssumedDim;
2507         }
2508     }
2509 
2510     if (retSt.fType.StartsWith(_T("character(")))
2511     {
2512         int pos = retSt.fType.Find(')',true);
2513         if (pos != wxNOT_FOUND)
2514             retSt.fType = retSt.fType.Mid(0,pos) + _T(",len=")+fCharLen+_T(")");
2515     }
2516     else if (retSt.fType.StartsWith(_T("character")))
2517     {
2518         retSt.fType.Replace(_T("character"), _T("character(len=")+fCharLen+_T(")"));
2519     }
2520 
2521     if (retSt.fType.StartsWith(_T("character")))
2522     {
2523         bool lenIsOne = false;
2524         long numCharLen;
2525         wxString cDim;
2526         if (fCharLen.ToLong(&numCharLen))
2527         {
2528             if (numCharLen == 1)
2529             {
2530                 lenIsOne = true;
2531                 cDim = _T("");
2532             }
2533             else
2534             {
2535                 fCharLen = wxString::Format(_T("%d"),numCharLen+1);
2536                 cDim = GetCDims(_T("(")+fCharLen+_T(")"));
2537             }
2538         }
2539         else if (!fCharLen.IsSameAs(_T("*")))
2540         {
2541             fCharLen << _T("+1");
2542             cDim = _T("");
2543         }
2544         else
2545             cDim = _T("");
2546 
2547         if (!lenIsOne)
2548             retSt.bType << _T(", dimension") << _T("(") << fCharLen << _T(")");
2549         retSt.cDim << cDim;
2550     }
2551 
2552     iPos = declarLw.Find(_T("intent("));
2553     if (iPos != wxNOT_FOUND)
2554     {
2555         wxString vinout = GetToken(declarLw,iPos+6);
2556         retSt.fType << _T(", intent") << vinout;
2557         retSt.bType << _T(", intent") << vinout;
2558     }
2559     retSt.wasFound = true;
2560 
2561     if (declarLw.Find(_T(",allocatable")) != wxNOT_FOUND)
2562     {
2563         retSt.errMsg = _("Error: Allocatable variables can not be called from C.");
2564         retSt.bType << _T(", allocatable");
2565     }
2566 
2567     return retSt;
2568 }
2569 
GetTypeAndKind(wxString decl)2570 wxArrayString Bindto::GetTypeAndKind(wxString decl)
2571 {
2572     wxArrayString fTK;
2573     fTK.Add(_T(""),2);
2574     decl.Replace(_T(" "), _T(""));
2575     wxStringTokenizer tokenizer(decl, _T("(*,"), wxTOKEN_STRTOK);
2576     if (tokenizer.CountTokens() == 0)
2577         return fTK;
2578     else if (tokenizer.CountTokens() == 1)
2579         fTK.Item(0) = tokenizer.GetNextToken();
2580     else
2581     {
2582         fTK.Item(0) = tokenizer.GetNextToken();
2583         wxChar delim = tokenizer.GetLastDelimiter();
2584         if (delim == '(')
2585         {
2586             size_t pos = tokenizer.GetPosition() - 1;
2587             wxString ks = GetToken(decl,pos);
2588             fTK.Item(1) = ks.Mid(1,ks.size()-2);
2589         }
2590         else if (delim == '*')
2591         {
2592             wxString kind = tokenizer.GetNextToken();
2593             if (fTK.Item(0).IsSameAs(_T("complex")))
2594                 fTK.Item(0) << _T("*") << kind;
2595             else
2596                 fTK.Item(1) = kind;
2597         }
2598     }
2599     return fTK;
2600 }
2601 
GetFunctionDeclaration(TokenF * token)2602 wxString Bindto::GetFunctionDeclaration(TokenF* token)
2603 {
2604     wxString funType;
2605     if (!token->m_PartFirst.IsEmpty())
2606     {
2607         wxString strLw = token->m_PartFirst.Lower().Trim(true).Trim(false);
2608         strLw.Replace(_T(" "),_T(""));
2609         wxArrayString ftarr;
2610         ftarr.Add(_T("integer("));
2611         ftarr.Add(_T("real("));
2612         ftarr.Add(_T("doubleprecision("));
2613         ftarr.Add(_T("complex("));
2614         ftarr.Add(_T("logical("));
2615         ftarr.Add(_T("type("));
2616         ftarr.Add(_T("class("));
2617         for (size_t i=0; i<ftarr.size(); i++)
2618         {
2619             int iPos = strLw.Find(ftarr.Item(i));
2620             if (iPos != wxNOT_FOUND)
2621             {
2622                 int tl = ftarr.Item(i).Length()-1;
2623                 wxString vkind = GetToken(strLw,iPos+tl);
2624                 vkind.Replace(_T("kind="),_T(""));
2625                 funType << ftarr.Item(i).Mid(0,tl);
2626                 funType << vkind;
2627                 return funType;
2628             }
2629         }
2630         ftarr.Empty();
2631         ftarr.Add(_T("integer"));
2632         ftarr.Add(_T("real"));
2633         ftarr.Add(_T("doubleprecision"));
2634         ftarr.Add(_T("complex"));
2635         ftarr.Add(_T("logical"));
2636         for (size_t i=0; i<ftarr.size(); i++)
2637         {
2638             int iPos = strLw.Find(ftarr.Item(i));
2639             if (iPos != wxNOT_FOUND)
2640             {
2641                 funType << ftarr.Item(i);
2642                 return funType;
2643             }
2644         }
2645     }
2646 
2647     for (int i=0; i<2; i++)
2648     {
2649         wxString resVName;
2650         if (i == 0)
2651         {
2652             if(!token->m_ResultVariable.IsEmpty())
2653                 resVName = token->m_ResultVariable;
2654             else
2655                 continue;
2656         }
2657         else
2658             resVName = token->m_Name;
2659 
2660         TokenF* argToken = m_pParser->FindTokenBetweenChildren(token, resVName);
2661         if (argToken)
2662         {
2663             if (argToken->m_TokenKind == tkVariable)
2664             {
2665                 m_pTokenCurrent = argToken;
2666                 int itmp;
2667                 TypeBind tys = GetBindType(argToken, itmp);
2668                 funType = tys.fType;
2669                 if (!argToken->m_Args.IsEmpty())
2670                 {
2671                     funType << _T(", dimension") << argToken->m_Args.Lower();
2672                 }
2673                 break;
2674             }
2675         }
2676         else
2677         {
2678             // assume implicit declaration
2679         }
2680     }
2681     return funType;
2682 }
2683 
2684 
GetToken(const wxString & txt,int iPos)2685 wxString Bindto::GetToken(const wxString& txt, int iPos)
2686 {
2687     wxChar openChar;
2688     wxChar closeChar;
2689     if (txt.GetChar(iPos) == '(')
2690     {
2691         openChar = '(';
2692         closeChar = ')';
2693     }
2694     else if (txt.GetChar(iPos) == '[')
2695     {
2696         openChar = '[';
2697         closeChar = ']';
2698     }
2699     else
2700         return wxEmptyString;
2701 
2702     wxString retTxt;
2703     int level = 1;
2704     for (size_t i=iPos+1; i<txt.Length(); i++)
2705     {
2706         if (txt.GetChar(i) == openChar)
2707             level++;
2708         else if (txt.GetChar(i) == closeChar)
2709         {
2710             level--;
2711             if (level == 0)
2712             {
2713                 retTxt << txt.Mid(iPos, i-iPos+1);
2714                 break;
2715             }
2716         }
2717     }
2718     return retTxt;
2719 }
2720 
GetCDims(wxString vdim)2721 wxString Bindto::GetCDims(wxString vdim)
2722 {
2723     //input: (*), (10),    (10,5)  (5,*), (5,3,*), (m,n), (size(a,2),n), (:,:)
2724     //output: "", "[10]", "[5][10]", "",   "",        "",        "",      ""
2725 
2726     if (vdim.Find(_T("size(")) != wxNOT_FOUND)
2727         return _T("");
2728 
2729     wxArrayString dimArr;
2730     wxStringTokenizer tkz(vdim, _T("(), "), wxTOKEN_STRTOK );
2731     while ( tkz.HasMoreTokens() )
2732     {
2733         dimArr.Add(tkz.GetNextToken());
2734     }
2735 
2736     wxString cdims;
2737     for (int i=dimArr.GetCount()-1; i>=0; i--)
2738     {
2739         wxString ds = dimArr.Item(i);
2740         long dl;
2741         if (!ds.ToLong(&dl))
2742             return _T("");
2743         else
2744             cdims << _T("[") << ds << _T("]");
2745     }
2746     return cdims;
2747 }
2748 
2749 
OnAdd(wxCommandEvent & event)2750 void Bindto::OnAdd(wxCommandEvent& event)
2751 {
2752     BindtoNewType addNewType(this);
2753     ShowNewTypeDlg(addNewType);
2754 }
2755 
ShowNewTypeDlg(BindtoNewType & addNewType)2756 void Bindto::ShowNewTypeDlg(BindtoNewType& addNewType)
2757 {
2758     while (true)
2759     {
2760         if (addNewType.ShowModal() == wxID_OK)
2761         {
2762             wxString ft = addNewType.GetFortranType();
2763             wxString bt = addNewType.GetBindCType().Trim(true).Trim(false);
2764             wxString ct = addNewType.GetCType().Trim(true).Trim(false);
2765             PrepateTypes(ft,bt,ct);
2766 
2767             if (m_TypeMap.count(ft) == 0)
2768             {
2769                 wxArrayString bcta;
2770                 bcta.Add(bt);
2771                 bcta.Add(ct);
2772                 m_TypeMap[ft] = bcta;
2773                 m_IsTypeMapDefault = false;
2774                 FillTypeList();
2775                 break;
2776             }
2777             else
2778             {
2779                 wxString mstr = _T("Binding for \"") + ft + _T("\" already defined!");
2780                 wxMessageBox(mstr, _("Error"), wxICON_ERROR, this);
2781             }
2782         }
2783         else
2784             break;
2785     }
2786 }
2787 
PrepateTypes(wxString & ft,wxString & bt,wxString & ct)2788 void Bindto::PrepateTypes(wxString& ft, wxString& bt, wxString& ct)
2789 {
2790     bt.Trim(true).Trim(false);
2791     ct.Trim(true).Trim(false);
2792     ft.Replace(_T(" "),_T(""));
2793     if (ft.StartsWith(_T("character(")))
2794     {
2795         int idx = ft.Find(_T("kind="));
2796         if (idx != wxNOT_FOUND)
2797         {
2798             wxString kn = ft.Mid(idx+5);
2799             int idx1 = kn.Find(',');
2800             int idx2 = kn.Find(')');
2801             if (idx1 != wxNOT_FOUND && idx2 != wxNOT_FOUND)
2802             {
2803                 if (idx1 > idx2)
2804                     kn.Truncate(idx2);
2805                 else
2806                     kn.Truncate(idx1);
2807             }
2808             else if (idx1 != wxNOT_FOUND)
2809                 kn.Truncate(idx1);
2810             else if (idx2 != wxNOT_FOUND)
2811                 kn.Truncate(idx2);
2812             ft = _T("character(kind=") + kn + _T(")");
2813         }
2814         else
2815             ft = _T("character");
2816     }
2817     else if (ft.StartsWith(_T("character")))
2818         ft = _T("character");
2819     else if (ft.StartsWith(_T("integer(")) ||
2820              ft.StartsWith(_T("real(")) ||
2821              ft.StartsWith(_T("complex(")))
2822     {
2823         ft.Replace(_T("kind="),_T(""));
2824     }
2825     else if (ft.StartsWith(_T("integer*")) ||
2826              ft.StartsWith(_T("real*")))
2827     {
2828         ft.Replace(_T("*"),_T("("),false);
2829         ft.Append(_T(")"));
2830     }
2831 }
2832 
OnEdit(wxCommandEvent & event)2833 void Bindto::OnEdit(wxCommandEvent& event)
2834 {
2835     long sel = lv_Types->GetFirstSelected();
2836     if (sel == -1)
2837         return;
2838     wxString ft_old = lv_Types->GetItemText(sel);
2839     wxArrayString bcArr = m_TypeMap[ft_old];
2840     wxString bt_old = bcArr[0];
2841     wxString ct_old = bcArr[1];
2842 
2843     BindtoNewType editNewType(this);
2844     editNewType.SetEditType(ft_old,bt_old,ct_old);
2845     while (true)
2846     {
2847         if (editNewType.ShowModal() == wxID_OK)
2848         {
2849             wxString ft = editNewType.GetFortranType();
2850             wxString bt = editNewType.GetBindCType().Trim(true).Trim(false);
2851             wxString ct = editNewType.GetCType().Trim(true).Trim(false);
2852             PrepateTypes(ft,bt,ct);
2853             if (ft.IsSameAs(ft_old) && bt.IsSameAs(bt_old) && ct.IsSameAs(ct_old))
2854                 break;
2855             else
2856             {
2857                 // type was changed
2858                 m_TypeMap.erase(ft_old);
2859                 wxArrayString bcta;
2860                 bcta.Add(bt);
2861                 bcta.Add(ct);
2862                 m_TypeMap[ft] = bcta;
2863                 m_IsTypeMapDefault = false;
2864                 FillTypeList();
2865                 break;
2866             }
2867         }
2868         else
2869             break;
2870     }
2871 }
2872 
OnRemove(wxCommandEvent & event)2873 void Bindto::OnRemove(wxCommandEvent& event)
2874 {
2875     long sel = lv_Types->GetFirstSelected();
2876     if (sel == -1)
2877         return;
2878     m_TypeMap.erase(lv_Types->GetItemText(sel));
2879     m_IsTypeMapDefault = false;
2880     FillTypeList();
2881 }
2882 
OnDefaults(wxCommandEvent & event)2883 void Bindto::OnDefaults(wxCommandEvent& event)
2884 {
2885     FillTypeMapDefault();
2886     FillTypeList();
2887 }
2888 
SplitLines(const wxString & txt,Language lang)2889 wxString Bindto::SplitLines(const wxString& txt, Language lang)
2890 {
2891     size_t llen;
2892     wxString csym;
2893     wxString comment;
2894     if (lang == Fortran)
2895     {
2896         llen = 132 - 2;
2897         csym = _T(" &");
2898         comment = _T("!");
2899     }
2900     else if (lang == C)
2901     {
2902         llen = 100;
2903         csym = _T("");
2904         comment = _T("//");
2905     }
2906     else if (lang == Python)
2907     {
2908         llen = 100;
2909         csym = _T(" \\");
2910         comment = _T("#");
2911     }
2912     else
2913         return _T("Programming error. This should not happen.");
2914 
2915     wxArrayString txtArrShort;
2916     wxArrayString txtArr;
2917     wxStringTokenizer tkz(txt, _T("\n"), wxTOKEN_RET_EMPTY_ALL);
2918     while ( tkz.HasMoreTokens() )
2919         txtArr.Add(tkz.GetNextToken());
2920 
2921     for (size_t i=0; i<txtArr.size(); i++)
2922     {
2923         wxString codeStr;
2924         wxString comStr;
2925         int idxcom = txtArr[i].Find(comment);
2926         if (idxcom == wxNOT_FOUND)
2927             codeStr = txtArr[i].Trim();
2928         else
2929         {
2930             codeStr = txtArr[i].Mid(0,idxcom).Trim();
2931             comStr = txtArr[i].Mid(idxcom+comment.size());
2932         }
2933         wxString noSpaceCodeStr = codeStr;
2934         noSpaceCodeStr.Trim(false);
2935         size_t nSpace = codeStr.length() - noSpaceCodeStr.length();
2936         if (nSpace > llen/3)
2937             nSpace = llen/3;
2938         while (true)
2939         {
2940             bool isShortStr = true;
2941             if (codeStr.length() > llen)
2942             {
2943                 isShortStr = false;
2944                 wxString leftStr = codeStr.Mid(0,llen);
2945                 wxString rightStr = codeStr.Mid(llen);
2946                 int idx1 = leftStr.Find(',', true);
2947                 int idx2 = leftStr.Find(' ', true);
2948                 int idx3 = leftStr.Find('=', true);
2949                 int idx = std::max(idx1,idx2);
2950                 idx = std::max(idx,idx3);
2951                 if (idx == wxNOT_FOUND)
2952                     isShortStr = true;
2953                 else
2954                 {
2955                     txtArrShort.Add(leftStr.Mid(0,idx+1) + csym);
2956                     wxString spaces;
2957                     codeStr = spaces.Append(' ',nSpace+4) + leftStr.Mid(idx+1) + rightStr;
2958                 }
2959             }
2960 
2961             if (isShortStr)
2962             {
2963                 wxString shortStr = codeStr;
2964 
2965                 if (shortStr.find_first_not_of(_T(" \n")) != wxString::npos && !comStr.IsEmpty())
2966                     shortStr.Append(_T(" ") + comment + comStr);
2967                 else if (!comStr.IsEmpty())
2968                     shortStr.Append(comment + comStr);
2969                 txtArrShort.Add(shortStr);
2970                 break;
2971             }
2972         }
2973     }
2974     wxString txtAll;
2975     for (size_t i=0; i<txtArrShort.size(); i++)
2976     {
2977         txtAll.Append(txtArrShort[i] + _T("\n"));
2978     }
2979     return txtAll;
2980 }
2981 
GetSubStrFtoC(wxArrayString & strFtoC)2982 void Bindto::GetSubStrFtoC(wxArrayString &strFtoC)
2983 {
2984     wxString tab;
2985     tab << GetIS(1);
2986     strFtoC.Add(_T("subroutine string_copy_f_c(f_string, c_string)"));
2987     strFtoC.Add(tab + _T("character(len=*), intent(in) :: f_string"));
2988     strFtoC.Add(tab + _T("character(len=1,kind=c_char), dimension(*), intent(out) :: c_string(*)"));
2989     strFtoC.Add(tab + _T("integer :: i, chlen\n"));
2990     strFtoC.Add(tab + _T("i = 1"));
2991     strFtoC.Add(tab + _T("chlen = len(f_string)"));
2992     strFtoC.Add(tab + _T("do while(c_string(i)/=c_null_char .and. i<=chlen)"));
2993     strFtoC.Add(tab + tab + _T("c_string(i) = f_string(i:i)"));
2994     strFtoC.Add(tab + tab + _T("i = i + 1"));
2995     strFtoC.Add(tab + _T("end do"));
2996     strFtoC.Add(_T("end subroutine"));
2997 }
2998 
GetSubStrCtoF(wxArrayString & strCtoF)2999 void Bindto::GetSubStrCtoF(wxArrayString &strCtoF)
3000 {
3001     wxString tab;
3002     tab << GetIS(1);
3003     strCtoF.Add(_T("subroutine string_copy_c_f(c_string, f_string)"));
3004     strCtoF.Add(tab + _T("character(len=1,kind=c_char), dimension(*), intent(in) :: c_string"));
3005     strCtoF.Add(tab + _T("character(len=*), intent(out) :: f_string"));
3006     strCtoF.Add(tab + _T("integer :: i, chlen\n"));
3007     strCtoF.Add(tab + _T("i = 1"));
3008     strCtoF.Add(tab + _T("chlen = len(f_string)"));
3009     strCtoF.Add(tab + _T("do while(c_string(i)/=c_null_char .and. i<=chlen)"));
3010     strCtoF.Add(tab + tab + _T("f_string(i:i) = c_string(i)"));
3011     strCtoF.Add(tab + tab + _T("i = i + 1"));
3012     strCtoF.Add(tab + _T("end do"));
3013     strCtoF.Add(tab + _T("if (i<=chlen) f_string(i:) = ' '"));
3014     strCtoF.Add(_T("end subroutine"));
3015 }
3016 
GetFunStrLen(wxArrayString & strLen)3017 void Bindto::GetFunStrLen(wxArrayString &strLen)
3018 {
3019     wxString tab;
3020     tab << GetIS(1);
3021     strLen.Add(_T("function string_len(cstr)"));
3022     strLen.Add(tab + _T("integer :: string_len"));
3023     strLen.Add(tab + _T("character(kind=c_char,len=1), dimension(*) :: cstr\n"));
3024     strLen.Add(tab + _T("string_len = 1"));
3025     strLen.Add(tab + _T("do while(cstr(string_len) /= c_null_char)"));
3026     strLen.Add(tab + tab + _T("string_len = string_len + 1"));
3027     strLen.Add(tab + _T("end do"));
3028     strLen.Add(tab + _T("string_len = string_len - 1"));
3029     strLen.Add(_T("end function"));
3030 }
3031 
GetFunLogical(const wxString & logType,const wxString & nameLtoI,const wxString & nameItoL,wxArrayString & funLtoI,wxArrayString & funItoL)3032 void Bindto::GetFunLogical(const wxString& logType, const wxString& nameLtoI, const wxString& nameItoL, wxArrayString& funLtoI, wxArrayString& funItoL)
3033 {
3034     wxString tab;
3035     tab << GetIS(1);
3036     funLtoI.Add(_T("elemental function ") + nameLtoI + _T("(log_val)"));
3037     funLtoI.Add(tab + logType + _T(", intent(in) :: log_val"));
3038     funLtoI.Add(tab + _T("integer(c_int) :: ") + nameLtoI + _T("\n"));
3039     funLtoI.Add(tab + _T("if (log_val) then"));
3040     funLtoI.Add(tab + tab + nameLtoI + _T(" = 1"));
3041     funLtoI.Add(tab + _T("else"));
3042     funLtoI.Add(tab + tab + nameLtoI + _T(" = 0"));
3043     funLtoI.Add(tab + _T("end if"));
3044     funLtoI.Add(_T("end function"));
3045 
3046     funItoL.Add(_T("elemental function ") + nameItoL + _T("(int_val)"));
3047     funItoL.Add(tab + _T("integer(c_int), intent(in) :: int_val"));
3048     funItoL.Add(tab + logType + _T(" :: ") + nameItoL + _T("\n"));
3049     funItoL.Add(tab + nameItoL + _T(" = (int_val /= 0)"));
3050     funItoL.Add(_T("end function"));
3051 }
3052 
GetHelperModule(bool useGlobal,bool getAll,std::map<wxString,wxString> & procMap,wxString & modHead)3053 void Bindto::GetHelperModule(bool useGlobal, bool getAll, std::map<wxString,wxString> &procMap, wxString& modHead)
3054 {
3055     if (!getAll && !useGlobal && !m_WriteStrCtoF && !m_WriteStrFtoC && !m_WriteStrLen && m_LogTypeSet.empty())
3056         return;
3057 
3058     if (!getAll && useGlobal && !m_GlobWriteStrCtoF && !m_GlobWriteStrFtoC && !m_GlobWriteStrLen && m_GlobLogFunMap.empty())
3059         return;
3060 
3061     wxString tab;
3062     tab << GetIS(1);
3063     modHead << _T("module bindc_helper_bc\n");
3064     modHead << tab << _T("use, intrinsic :: iso_c_binding\n");
3065     modHead << tab << _T("implicit none\n");
3066     modHead << _T("contains\n");
3067     if (getAll || (!useGlobal && m_WriteStrLen) || (useGlobal && m_GlobWriteStrLen))
3068     {
3069         wxString help;
3070         help << _T("\n");
3071         wxArrayString strLen;
3072         GetFunStrLen(strLen);
3073         for (size_t i=0;i<strLen.size();i++)
3074             help << tab << strLen.Item(i) << _T("\n");
3075 
3076         procMap[strLen.Item(0)] = help;
3077     }
3078     if (getAll || (!useGlobal && m_WriteStrCtoF) || (useGlobal && m_GlobWriteStrCtoF))
3079     {
3080         wxString help;
3081         help << _T("\n");
3082         wxArrayString strCtoF;
3083         GetSubStrCtoF(strCtoF);
3084         for (size_t i=0;i<strCtoF.size();i++)
3085             help << tab << strCtoF.Item(i) << _T("\n");
3086 
3087         procMap[strCtoF.Item(0)] = help;
3088     }
3089     if (getAll || (!useGlobal && m_WriteStrFtoC) || (useGlobal && m_GlobWriteStrFtoC))
3090     {
3091         wxString help;
3092         help << _T("\n");
3093         wxArrayString strFtoC;
3094         GetSubStrFtoC(strFtoC);
3095         for (size_t i=0;i<strFtoC.size();i++)
3096             help << tab << strFtoC.Item(i) << _T("\n");
3097 
3098         procMap[strFtoC.Item(0)] = help;
3099     }
3100     if (!useGlobal && !m_LogTypeSet.empty())
3101     {
3102         for (StrSet::iterator it=m_LogTypeSet.begin(); it != m_LogTypeSet.end(); ++it)
3103         {
3104             if (m_GlobLogFunMap.count(*it) == 0)
3105                 continue;
3106             wxArrayString funLtoI;
3107             wxArrayString funItoL;
3108             GetFunLogical(*it, m_GlobLogFunMap[*it][0], m_GlobLogFunMap[*it][1], funLtoI, funItoL);
3109             wxString help;
3110             help << _T("\n");
3111             for (size_t i=0;i<funLtoI.size();i++)
3112                 help << tab << funLtoI.Item(i) << _T("\n");
3113             help << _T("\n");
3114             for (size_t i=0;i<funItoL.size();i++)
3115                 help << tab << funItoL.Item(i) << _T("\n");
3116 
3117             procMap[funLtoI.Item(0)] = help;
3118         }
3119     }
3120     if (useGlobal && !m_GlobLogFunMap.empty())
3121     {
3122         for (TypeMap::iterator it=m_GlobLogFunMap.begin(); it != m_GlobLogFunMap.end(); ++it)
3123         {
3124             wxArrayString fnams = it->second;
3125             wxArrayString funLtoI;
3126             wxArrayString funItoL;
3127             GetFunLogical(it->first, fnams[0], fnams[1], funLtoI, funItoL);
3128             wxString help;
3129             help << _T("\n");
3130             for (size_t i=0;i<funLtoI.size();i++)
3131                 help << tab << funLtoI.Item(i) << _T("\n");
3132             help << _T("\n");
3133             for (size_t i=0;i<funItoL.size();i++)
3134                 help << tab << funItoL.Item(i) << _T("\n");
3135 
3136             procMap[funLtoI.Item(0)] = help;
3137         }
3138     }
3139 }
3140 
PrepareAssumedShapeVariables(const wxArrayString & argArr,const wxArrayString & dimVarNames,wxArrayString & additionalDeclar,wxArrayString & addVarNames,wxArrayString & addVarNamesC,const wxArrayString & varNamesOfDim,const StrSet & argHideSetPy,wxArrayString & additionalDeclarPy,wxArrayString & addVarNamesPy,wxArrayString & addArgNamesPy)3141 void Bindto::PrepareAssumedShapeVariables(const wxArrayString& argArr, const wxArrayString& dimVarNames,
3142                                           wxArrayString& additionalDeclar, wxArrayString& addVarNames, wxArrayString& addVarNamesC,
3143                                           const wxArrayString& varNamesOfDim, const StrSet& argHideSetPy,
3144                                           wxArrayString& additionalDeclarPy, wxArrayString& addVarNamesPy, wxArrayString& addArgNamesPy)
3145 {
3146     if (dimVarNames.size() == 0)
3147         return;
3148 
3149     if (dimVarNames.size() != varNamesOfDim.size())
3150         return; // programming error
3151 
3152     wxArrayInt ndims;
3153     wxString varNameOld;
3154     int iShape = 0;
3155     for (size_t i=0; i<varNamesOfDim.size(); i++)
3156     {
3157         if (varNameOld.IsSameAs(varNamesOfDim.Item(i)))
3158             iShape += 1;
3159         else if (i > 0)
3160         {
3161             int nd = iShape + 1;
3162             for (int j=0; j<nd; j++)
3163                 ndims.Add(nd);
3164             iShape = 0;
3165         }
3166         varNameOld = varNamesOfDim.Item(i);
3167     }
3168     int nd = iShape + 1;
3169     for (int j=0; j<nd; j++)
3170         ndims.Add(nd);
3171     if (ndims.size() != dimVarNames.size())
3172     {
3173         Manager::Get()->GetLogManager()->DebugLog(_T("FortranProject: ndims.size() != dimVarNames.size()"));
3174         return; // programming error;
3175     }
3176 
3177     varNameOld = _T("");
3178     for (size_t i=0; i<dimVarNames.size(); i++)
3179     {
3180         if (varNameOld.IsSameAs(varNamesOfDim.Item(i)))
3181             iShape += 1;
3182         else
3183             iShape = 0;
3184         varNameOld = varNamesOfDim.Item(i);
3185 
3186         wxString var = dimVarNames.Item(i);
3187         if (argArr.Index(var) == wxNOT_FOUND && addVarNames.Index(var) == wxNOT_FOUND)
3188         {
3189             additionalDeclar.Add(_T("integer(c_int), intent(in) :: ") + var);
3190             addVarNames.Add(var);
3191             addVarNamesC.Add(_T("int* ") + var);
3192             if (argHideSetPy.count(varNamesOfDim.Item(i)) == 1)
3193             {
3194                 wxString dimVarKeyI = DIM_VAR_KEY + wxString::Format(_T("%d"),iShape);
3195                 for (size_t j=0; j<additionalDeclarPy.size(); j++)
3196                 {
3197                     if (additionalDeclarPy.Item(j).Replace(dimVarKeyI, var, false) > 0)
3198                         break;
3199                 }
3200                 addArgNamesPy.Add(_T("int ") + var);
3201             }
3202             else
3203             {
3204                 int iShapeWrite = ndims[i] - iShape - 1;
3205                 wxString sShape = wxString::Format(_T("%d"),iShapeWrite);
3206                 additionalDeclarPy.Insert(_T("cdef int ") + var + _T(" = ") + varNamesOfDim.Item(i) + _T(".shape[") + sShape + _T("]"), 0);
3207             }
3208             addVarNamesPy.Add(_T("&") + var);
3209         }
3210     }
3211 }
3212 
AddDimVariables(const wxArrayString & argArr,wxArrayString & dimVarNames,int nDimVarAdd,wxString varFirstPart,const wxString & argName,wxArrayString & varNamesOfDim,TypeBind & tys)3213 void Bindto::AddDimVariables(const wxArrayString& argArr, wxArrayString& dimVarNames, int nDimVarAdd, wxString varFirstPart,
3214                              const wxString& argName, wxArrayString& varNamesOfDim, TypeBind& tys)
3215 {
3216     wxString n1 = varFirstPart + _T("%i");
3217     wxString vname;
3218     int i=0;
3219     for (int nd=0; nd<nDimVarAdd; nd++)
3220     {
3221         while (vname.IsEmpty())
3222         {
3223             i++;
3224             wxString vn1 = wxString::Format(n1,i);
3225             if (argArr.Index(vn1) == wxNOT_FOUND && dimVarNames.Index(vn1) == wxNOT_FOUND)
3226                 vname = vn1;
3227         }
3228         dimVarNames.Add(vname);
3229         varNamesOfDim.Add(argName);
3230         tys.bDim.Replace(DIM_VAR_KEY,vname,false);
3231         tys.bType.Replace(DIM_VAR_KEY,vname,false);
3232         vname = wxEmptyString;
3233     }
3234 }
3235 
HideAssumedShape(const wxString & vdim,wxString & vdimHid,int & nAssumedDim)3236 void Bindto::HideAssumedShape(const wxString& vdim, wxString& vdimHid, int& nAssumedDim)
3237 {
3238     vdimHid = vdim;
3239     nAssumedDim = vdimHid.Replace(_T(":"), DIM_VAR_KEY);
3240 }
3241 
AddDimVariablesFromDoc(wxArrayString & dimVarNames,int & nDimVarAdd,const wxString & argName,wxArrayString & varNamesOfDim,TypeBind & tys)3242 void Bindto::AddDimVariablesFromDoc(wxArrayString& dimVarNames, int& nDimVarAdd, const wxString& argName,
3243                                     wxArrayString& varNamesOfDim, TypeBind& tys)
3244 {
3245     // Get dimensions of allocatable array from doc string e.g. dimension(m,n)
3246     if (nDimVarAdd == 0)
3247         return;
3248     if (m_BTDirMap.count(argName) == 0)
3249         return;
3250     BintoDirective btd = m_BTDirMap[argName];
3251     if (int(btd.dim.size()) != nDimVarAdd)
3252         return; // wrong number of variables
3253 
3254     for (size_t i=0; i<btd.dim.size(); i++)
3255     {
3256         dimVarNames.Add(btd.dim.Item(i));
3257         varNamesOfDim.Add(argName);
3258     }
3259     for (size_t i=0; i<btd.dim.size(); i++)
3260     {
3261         tys.bDim.Replace(DIM_VAR_KEY, btd.dim.Item(i),false);
3262         tys.bType.Replace(DIM_VAR_KEY, btd.dim.Item(i),false);
3263     }
3264     nDimVarAdd = 0;
3265 }
3266 
GetCName(const wxString & procName,const wxString & moduleName)3267 wxString Bindto::GetCName(const wxString& procName, const wxString& moduleName)
3268 {
3269     if (m_BindCName.IsEmpty())
3270         return procName;
3271     return GetProcName(procName, moduleName, m_BindCName);
3272 }
3273 
GetProcName(const wxString & procName,const wxString & moduleName,const wxString & nameFrame)3274 wxString Bindto::GetProcName(const wxString& procName, const wxString& moduleName, const wxString& nameFrame)
3275 {
3276     wxString cName = nameFrame;
3277     wxString cName_lw = cName.Lower();
3278     wxString keyProc = PROCNAME_KEY;
3279     wxString keyModule = MODULENAME_KEY;
3280     wxString keyMod = MODNAME_KEY;
3281     int idx = cName_lw.Find(keyProc);
3282     if (idx != wxNOT_FOUND)
3283     {
3284         cName = cName.Mid(0,idx) + procName + cName.Mid(idx+keyProc.Len());
3285         cName_lw = cName.Lower();
3286     }
3287     idx = cName_lw.Find(keyModule);
3288     if (idx != wxNOT_FOUND)
3289     {
3290         cName = cName.Mid(0,idx) + moduleName + cName.Mid(idx+keyModule.Len());
3291         cName_lw = cName.Lower();
3292     }
3293     idx = cName_lw.Find(keyMod);
3294     if (idx != wxNOT_FOUND)
3295     {
3296         wxString modName = moduleName;
3297         modName.Replace(_T("_"),_T(""));
3298         if (modName.Len() > 3)
3299             modName = modName.Mid(0,3);
3300         cName = cName.Mid(0,idx) + modName + cName.Mid(idx+keyMod.Len());
3301     }
3302     return cName;
3303 }
3304 
AddDestructors(wxString & txtBind,wxString & txtHeadersMod,wxString & txtCythonDtor,wxString & txtCythonFirst,const wxString & moduleName)3305 void Bindto::AddDestructors(wxString& txtBind, wxString& txtHeadersMod, wxString& txtCythonDtor, wxString& txtCythonFirst, const wxString& moduleName)
3306 {
3307     if (m_DefinedTypes.size() == 0)
3308         return;
3309 
3310     wxString txtDest;
3311     wxString txtDestH;
3312     for ( StrSet::iterator it=m_DefinedTypes.begin(); it != m_DefinedTypes.end(); ++it)
3313     {
3314         wxString type = *it;
3315         if (m_Deallocators.count(type) == 1)
3316             continue;
3317         wxString destName = type + _T("_dtor");
3318         wxString cDestName = GetCName(destName, moduleName);
3319         txtDest << GetIS() << _T("subroutine ") << destName << _T("_bc") << _T("(this_cp) bind(c,name='") << cDestName << _T("')\n");
3320         m_Indent++;
3321         txtDest << GetIS() << _T("type(c_ptr), intent(in) :: this_cp\n");
3322         txtDest << GetIS() << _T("type(") << type << _T("), pointer :: this_fp\n\n");
3323         txtDest << GetIS() << _T("call c_f_pointer(this_cp, this_fp)\n");
3324         txtDest << GetIS() << _T("deallocate(this_fp)\n");
3325         m_Indent--;
3326         txtDest << GetIS() << _T("end subroutine\n\n");
3327 
3328         txtDestH << _T("void ") << cDestName << _T("(void** this_cp);\n");
3329     }
3330     txtBind << txtDest;
3331     txtHeadersMod << txtDestH;
3332 
3333     wxString txtDestPy;
3334     wxString txtDestPyH;
3335     wxString txtDelPy;
3336     for ( StrSet::iterator it=m_DefinedTypes.begin(); it != m_DefinedTypes.end(); ++it)
3337     {
3338         wxString type = *it;
3339         if (m_Deallocators.count(type) == 1)
3340         {
3341             wxString procName = m_Deallocators[type];
3342             txtDestPy << GetIS(2) << CIMPORT_FN_KEY << procName << _T("(&self._") << type << _T("_cp)\n");
3343             txtDelPy << _T("\n") << GetIS(1) << _T("cdef ")<< type << _T("_cp") << _T("_del_py(self):\n");
3344             txtDelPy << GetIS(2) << CIMPORT_FN_KEY << procName << _T("(&self._") << type << _T("_cp)\n");
3345         }
3346         else
3347         {
3348             wxString destName = type + _T("_dtor");
3349             wxString cDestName = GetCName(destName, moduleName);
3350             txtDestPy << GetIS(2) << CIMPORT_FN_KEY << cDestName << _T("(&self._") << type << _T("_cp)\n");
3351             txtDestPyH << GetIS(1) << _T("void ") << cDestName << _T("(void** this_cp)\n");
3352             txtDelPy << _T("\n") << GetIS(1) << _T("cdef ")<< type << _T("_cp") << _T("_del_py(self):\n");
3353             txtDelPy << GetIS(2) << CIMPORT_FN_KEY << cDestName << _T("(&self._") << type << _T("_cp)\n");
3354         }
3355     }
3356     if (!txtDestPy.IsEmpty())
3357     {
3358         txtCythonDtor << _T("\n") << GetIS(1) << _T("def __dealloc__(self):\n");
3359         txtCythonDtor << txtDestPy;
3360     }
3361     txtCythonFirst << txtDestPyH;
3362     txtCythonDtor << txtDelPy;
3363 
3364 }
3365 
AddConstructors(wxString & txtBind,wxString & txtHeadersMod,wxString & txtCythonCtor,wxString & txtCythonFirst,const wxString & moduleName)3366 void Bindto::AddConstructors(wxString& txtBind, wxString& txtHeadersMod, wxString& txtCythonCtor, wxString& txtCythonFirst, const wxString& moduleName)
3367 {
3368 
3369     if (m_DefinedTypes.size() == 0)
3370         return;
3371 
3372     StrSet noArgAllocatedTypes;
3373     for ( StrSet::iterator it=m_NoArgConstructors.begin(); it != m_NoArgConstructors.end(); ++it)
3374     {
3375         wxString type = *it;
3376         int idx = type.Find(_T("("));
3377         if (idx != wxNOT_FOUND)
3378         {
3379             type = GetToken(type, idx);
3380         }
3381         if (type.size() <= 2)
3382             continue;
3383 
3384         type = type.Mid(1,type.size()-2).Trim(true).Trim(false);
3385         noArgAllocatedTypes.insert(type);
3386     }
3387 
3388     wxString txtCon;
3389     wxString txtConH;
3390     wxString txtConPy;
3391     wxString txtConPyH;
3392     for ( StrSet::iterator it=m_DefinedTypes.begin(); it != m_DefinedTypes.end(); ++it)
3393     {
3394         wxString type = *it;
3395         if (noArgAllocatedTypes.count(type) == 1)
3396             continue;
3397 
3398         wxString conName = GetConstructorName(type);
3399         wxString cConName = GetCName(conName, moduleName);
3400         wxString fConName = conName + _T("_bc");
3401         txtCon << GetIS() << _T("function ") << fConName << _T("() bind(c,name='") << cConName << _T("')\n");
3402         m_Indent++;
3403         txtCon << GetIS() << _T("type(c_ptr) :: ") << fConName << _T("\n");
3404         txtCon << GetIS() << _T("type(") << type << _T("), pointer :: this_fp\n\n");
3405         txtCon << GetIS() << _T("allocate(this_fp)\n");
3406         txtCon << GetIS() << fConName << _T(" = c_loc(this_fp)\n");
3407         m_Indent--;
3408         txtCon << GetIS() << _T("end function\n\n");
3409 
3410         wxString cHeader = _T("void* ") + cConName + _T("()");
3411         txtConH << cHeader << _T(";\n");
3412         m_NoArgConstructors.insert(_T("type(")+type+_T(")"));
3413 
3414         txtConPy << GetIS(2) << _T("self._") << type << _T("_cp = ") << CIMPORT_FN_KEY << cConName << _T("()\n");
3415         txtConPyH << GetIS(1) << cHeader << _T("\n");
3416     }
3417     txtBind << txtCon;
3418     txtHeadersMod << txtConH;
3419     if (!txtConPy.IsEmpty())
3420     {
3421         if (!m_HasPyClassConstructor)
3422         {
3423             txtCythonCtor << _T("\n") << GetIS(1) << _T("def __cinit__(self):\n");
3424             txtCythonCtor << txtConPy;
3425         }
3426         txtCythonFirst << txtConPyH;
3427     }
3428 }
3429 
GetConstructorName(const wxString & type)3430 wxString Bindto::GetConstructorName(const wxString& type)
3431 {
3432     wxString conName = type + _T("_ctor");
3433     if (m_ModuleChildNames.count(conName) == 1)
3434     {
3435         for (int i=2; i<100; i++)
3436         {
3437             conName = wxString::Format(type + _T("%d_ctor"), i);
3438             if (m_ModuleChildNames.count(conName) == 0)
3439                 break;
3440         }
3441     }
3442     return conName;
3443 }
3444 
IsConstructor(TokenF * token)3445 bool Bindto::IsConstructor(TokenF* token)
3446 {
3447     if ((token->m_TokenKind == tkSubroutine || token->m_TokenKind == tkFunction) &&
3448         ((!m_CtorStartsWith.IsEmpty() && token->m_Name.StartsWith(m_CtorStartsWith)) ||
3449         (!m_CtorEndsWith.IsEmpty() && token->m_Name.EndsWith(m_CtorEndsWith))) )
3450         return true;
3451     return false;
3452 }
3453 
IsDestructor(TokenF * token)3454 bool Bindto::IsDestructor(TokenF* token)
3455 {
3456     if ((!m_DtorStartsWith.IsEmpty() && token->m_Name.StartsWith(m_DtorStartsWith)) ||
3457         (!m_DtorEndsWith.IsEmpty() && token->m_Name.EndsWith(m_DtorEndsWith)) )
3458         return true;
3459     return false;
3460 }
3461 
OnClick_cbCtorStart(wxCommandEvent & event)3462 void Bindto::OnClick_cbCtorStart(wxCommandEvent& event)
3463 {
3464     if (cb_ctorStart->IsChecked())
3465         tc_ctorStart->Enable(true);
3466     else
3467     {
3468         if (tc_ctorStart->GetValue().Trim().IsEmpty())
3469             tc_ctorStart->SetValue(_T("ctor_"));
3470         tc_ctorStart->Enable(false);
3471     }
3472 }
3473 
OnClick_cbCtorEnd(wxCommandEvent & event)3474 void Bindto::OnClick_cbCtorEnd(wxCommandEvent& event)
3475 {
3476     if (cb_ctorEnd->IsChecked())
3477         tc_ctorEnd->Enable(true);
3478     else
3479     {
3480         if (tc_ctorEnd->GetValue().Trim().IsEmpty())
3481             tc_ctorEnd->SetValue(_T("_ctor"));
3482         tc_ctorEnd->Enable(false);
3483     }
3484 }
3485 
OnClick_cbDtorStart(wxCommandEvent & event)3486 void Bindto::OnClick_cbDtorStart(wxCommandEvent& event)
3487 {
3488     if (cb_dtorStart->IsChecked())
3489         tc_dtorStart->Enable(true);
3490     else
3491     {
3492         if (tc_dtorStart->GetValue().Trim().IsEmpty())
3493             tc_dtorStart->SetValue(_T("dtor_"));
3494         tc_dtorStart->Enable(false);
3495     }
3496 }
3497 
OnClick_cbDtorEnd(wxCommandEvent & event)3498 void Bindto::OnClick_cbDtorEnd(wxCommandEvent& event)
3499 {
3500     if (cb_dtorEnd->IsChecked())
3501         tc_dtorEnd->Enable(true);
3502     else
3503     {
3504         if (tc_dtorEnd->GetValue().Trim().IsEmpty())
3505             tc_dtorEnd->SetValue(_T("_dtor"));
3506         tc_dtorEnd->Enable(false);
3507     }
3508 }
3509 
Onrb_ActiveProjectSelect(wxCommandEvent & event)3510 void Bindto::Onrb_ActiveProjectSelect(wxCommandEvent& event)
3511 {
3512     bool enab = false;
3513     if (rb_ActiveProject->GetValue())
3514         enab = true;
3515 
3516     cb_globalToOne->Enable(enab);
3517     if (enab && cb_globalToOne->GetValue())
3518     {
3519         tc_globalFilename->Enable(true);
3520         st_globalFilename->Enable(true);
3521     }
3522     else
3523     {
3524         tc_globalFilename->Enable(false);
3525         st_globalFilename->Enable(false);
3526     }
3527 
3528     wxString initstr;
3529     if (rb_ActiveProject->GetValue())
3530         initstr = m_InitialOutputDirFile;
3531     else
3532         initstr = m_InitialOutputDirProj;
3533     wxString dir = tc_OutputDir->GetValue();
3534     if (dir.IsSameAs(initstr))
3535     {
3536         if (rb_ActiveProject->GetValue())
3537             tc_OutputDir->SetValue(m_InitialOutputDirProj);
3538         else
3539             tc_OutputDir->SetValue(m_InitialOutputDirFile);
3540     }
3541 }
3542 
GetPyName(const wxString & procName,const wxString & moduleName)3543 wxString Bindto::GetPyName(const wxString& procName, const wxString& moduleName)
3544 {
3545     if (m_PyFuncName.IsEmpty())
3546         return procName + _T("_f");
3547     return GetProcName(procName, moduleName, m_PyFuncName);
3548 }
3549 
GetBindTypePy(const TypeBind & tya,const wxString & varName)3550 Bindto::TypePyx Bindto::GetBindTypePy(const TypeBind& tya, const wxString& varName)
3551 {
3552     TypePyx tyaPy;
3553     tyaPy.hide = false;
3554     tyaPy.copy = false;
3555     tyaPy.ndim = 0;
3556     wxString fTName;
3557     wxString decPyx = tya.cType;
3558 
3559     if (decPyx.EndsWith(_T("*")))
3560         decPyx = decPyx.Mid(0,decPyx.size()-1);
3561     if (decPyx.IsSameAs(_T("void*")) || decPyx.IsSameAs(_T("void")))
3562     {
3563         if (tya.fType.StartsWith(_T("type(")))
3564             fTName = GetToken(tya.fType,4);
3565         else if (tya.fType.StartsWith(_T("class(")))
3566             fTName = GetToken(tya.fType,5);
3567         if (fTName.StartsWith(_T("(")) && fTName.EndsWith(_T(")")))
3568             fTName = fTName.Mid(1,fTName.size()-2);
3569         decPyx = _T("");
3570     }
3571 
3572     int idx = tya.bType.Find(_T("intent("));
3573     if (idx != wxNOT_FOUND)
3574     {
3575         idx = tya.bType.Find(_T("intent(out)"));
3576         if (idx != wxNOT_FOUND)
3577         {
3578             tyaPy.intent = _T("out");
3579             tyaPy.hide = true;
3580         }
3581         idx = tya.bType.Find(_T("intent(inout)"));
3582         if (idx != wxNOT_FOUND)
3583             tyaPy.intent = _T("inout");
3584         idx = tya.bType.Find(_T("intent(in)"));
3585         if (idx != wxNOT_FOUND)
3586             tyaPy.intent = _T("in");
3587     }
3588 
3589     wxArrayString dirDimArr;
3590     if (m_BTDirMap.count(varName) == 1)
3591     {
3592         const BintoDirective& btd = m_BTDirMap[varName];
3593         if (btd.intent.count(_T("hide")) == 1)
3594             tyaPy.hide = true;
3595         if (btd.intent.count(_T("copy")) == 1)
3596             tyaPy.copy = true;
3597         if (tyaPy.intent.IsEmpty())
3598         {
3599             if (btd.intent.count(_T("in")) == 1 && btd.intent.count(_T("out")) == 1)
3600                 tyaPy.intent = _T("inout");
3601             else if (btd.intent.count(_T("out")) == 1)
3602             {
3603                 tyaPy.intent = _T("out");
3604                 tyaPy.hide = true;
3605             }
3606             else if (btd.intent.count(_T("in")) == 1)
3607                 tyaPy.intent = _T("in");
3608         }
3609         if (tyaPy.hide)
3610             tyaPy.initStr = btd.initStr;
3611         dirDimArr = btd.dim;
3612     }
3613 
3614     idx = tya.bType.Find(_T("dimension("));
3615     size_t ndim = 0;
3616     if (idx != wxNOT_FOUND && !tya.bType.StartsWith(_T("character")))
3617     {
3618         wxString dims = GetToken(tya.bType,idx+9);
3619         if (tyaPy.hide && dims.Find(_T("*")) == wxNOT_FOUND)
3620         {
3621             wxArrayString dimsArr;
3622             wxStringTokenizer tkz(dims, _T("(), "),wxTOKEN_STRTOK);
3623             while ( tkz.HasMoreTokens() )
3624             {
3625                 wxString d1str = tkz.GetNextToken();
3626                 if (d1str.IsSameAs(DIM_VAR_KEY))
3627                     d1str << wxString::Format(_T("%d"),int(dimsArr.size()));
3628                 else if (d1str.StartsWith(DIM_VAR_KEY2))
3629                     d1str = DIM_VAR_KEY + wxString::Format(_T("%d"),int(dimsArr.size()));
3630                 dimsArr.Insert(d1str,0);
3631             }
3632 
3633             ndim = dimsArr.size();
3634             dims = _T("[");
3635             for (size_t i=0; i<ndim; i++)
3636                 dims << dimsArr.Item(i) << _T(",");
3637             dims.Truncate(dims.size()-1);
3638             dims << _T("]");
3639 
3640             wxString npType;
3641             if (m_C2NumpyTypes.count(decPyx) == 1)
3642                 npType = _T("np.") + m_C2NumpyTypes[decPyx];
3643             else
3644                 npType = decPyx;
3645             if (tyaPy.initStr.IsEmpty())
3646                 tyaPy.initStr = _T(" = np.empty(") + dims + _T(", dtype=") + npType + _T(")");
3647             decPyx = wxString::Format(_T("np.ndarray[") + decPyx + _T(",ndim=%d]"), int(ndim));
3648         }
3649         else if (tyaPy.hide && dims.Find(_T("*")) != wxNOT_FOUND && dirDimArr.size() > 0 &&
3650                  GetDimArr(dims).size() == dirDimArr.size())
3651         {
3652             wxString dimsPy = _T("[");
3653             ndim = dirDimArr.size();
3654             for (size_t i=0; i<ndim; i++)
3655                 dimsPy << dirDimArr.Item(i) << _T(",");
3656             dimsPy.Truncate(dimsPy.size()-1);
3657             dimsPy << _T("]");
3658 
3659             wxString npType;
3660             if (m_C2NumpyTypes.count(decPyx) == 1)
3661                 npType = _T("np.") + m_C2NumpyTypes[decPyx];
3662             else
3663                 npType = decPyx;
3664             if (tyaPy.initStr.IsEmpty())
3665                 tyaPy.initStr = _T(" = np.empty(") + dimsPy + _T(", dtype=") + npType + _T(")");
3666             decPyx = wxString::Format(_T("np.ndarray[") + decPyx + _T(",ndim=%d]"), int(ndim));
3667             for (size_t i=0; i<ndim; i++)
3668             {
3669                 wxString name = dirDimArr.Item(i);
3670                 if (name.size() > 0 && (isalpha(name.GetChar(0)) || name.GetChar(0) == '_'))
3671                 {
3672                     bool isWord = true;
3673                     for (size_t j=1; j<name.size(); j++)
3674                     {
3675                         if (!isalnum(name.GetChar(j)) && name.GetChar(0) != '_')
3676                         {
3677                             isWord = false;
3678                             break;
3679                         }
3680                     }
3681 
3682                     if (isWord && (tyaPy.addIntArg.Index(name) == wxNOT_FOUND))
3683                         tyaPy.addIntArg.Add(name);
3684                 }
3685             }
3686         }
3687         else
3688         {
3689             ndim = dims.Replace(_T(","),_T(";")) + 1;
3690             decPyx = wxString::Format(_T("np.ndarray[") + decPyx + _T(",ndim=%d]"), int(ndim));
3691             tyaPy.hide = false;
3692         }
3693     }
3694     tyaPy.declarPyxFirst = decPyx;
3695     if (tya.cType.IsSameAs(_T("char")) || tya.cType.IsSameAs(_T("char*")))
3696     {
3697         tyaPy.declarPyxFirst = _T("char*");
3698         if (tyaPy.hide && !tya.cDim.IsEmpty())
3699         {
3700             wxString dimstr = tya.cDim.Mid(1,tya.cDim.size()-2);
3701             long dl;
3702             if (dimstr.ToLong(&dl))
3703                 tyaPy.initStr = wxString::Format(_T(" = ' '*%d"),dl-1);
3704             else
3705                 tyaPy.initStr = _T(" = ' '*(") + dimstr + _T("-1)");
3706         }
3707         else
3708             tyaPy.hide = false;
3709     }
3710     if (ndim > 0)
3711     {
3712         tyaPy.callCSecond = _T("[");
3713         for (size_t i=0; i<ndim; i++)
3714         {
3715             if (i+1 < ndim)
3716                 tyaPy.callCSecond << _T("0,");
3717             else
3718                 tyaPy.callCSecond << _T("0");
3719         }
3720         tyaPy.callCSecond << _T("]");
3721     }
3722 
3723     if (!fTName.IsEmpty())
3724         tyaPy.fDrvTypeName = fTName;
3725 
3726     tyaPy.ndim = ndim;
3727     return tyaPy;
3728 }
3729 
CreateCythonFilename(const wxString & filename)3730 wxString Bindto::CreateCythonFilename(const wxString& filename)
3731 {
3732     wxFileName fname(filename);
3733     fname.SetPath(m_OutputDir);
3734     fname.SetExt(_T("pyx"));
3735 
3736     return CheckOverwriteFilename(fname);
3737 }
3738 
GetInitialOutputDir(wxString & initialOutputDirFile,wxString & initialOutputDirProj)3739 void Bindto::GetInitialOutputDir(wxString& initialOutputDirFile, wxString& initialOutputDirProj)
3740 {
3741     initialOutputDirFile = _T("bind");
3742     initialOutputDirProj = _T("bind");
3743     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3744     if (ed)
3745     {
3746         wxString fname = UnixFilename(ed->GetFilename());
3747         ProjectsArray* projects = Manager::Get()->GetProjectManager()->GetProjects();
3748         for (size_t i = 0; i < projects->GetCount(); ++i)
3749         {
3750             cbProject* pr = projects->Item(i);
3751             if (pr->GetFileByFilename(fname, false, true))
3752             {
3753                 // file belongs to this project
3754                 wxFileName dirname(pr->GetBasePath(),_T(""));
3755                 dirname.AppendDir(_T("bind"));
3756                 initialOutputDirFile = dirname.GetPath();
3757             }
3758         }
3759     }
3760     cbProject* pr = Manager::Get()->GetProjectManager()->GetActiveProject();
3761     if (pr)
3762     {
3763         wxFileName dirname(pr->GetBasePath(),_T(""));
3764         dirname.AppendDir(_T("bind"));
3765         initialOutputDirProj = dirname.GetPath();
3766     }
3767 }
3768 
MakeOutputDir()3769 bool Bindto::MakeOutputDir()
3770 {
3771     wxFileName dirname = wxFileName::DirName(m_OutputDir);
3772     if (!dirname.DirExists() && !dirname.Mkdir())
3773         return false;
3774     return true;
3775 }
3776 
ValidatePyFuncName()3777 bool Bindto::ValidatePyFuncName()
3778 {
3779     wxString msg;
3780     if (m_PyFuncName.IsEmpty())
3781         msg = _("\"Python function names\" text field cannot be empty.");
3782 
3783     if (!msg.IsEmpty())
3784     {
3785         wxMessageBox( msg, _("Error"), wxICON_ERROR, this);
3786         return false;
3787     }
3788     return true;
3789 }
3790 
GetLogFunNames(const wxString & fType)3791 wxArrayString Bindto::GetLogFunNames(const wxString& fType)
3792 {
3793     wxArrayString funNames;
3794     if (m_GlobLogFunMap.count(fType) == 0)
3795     {
3796         wxString addStr;
3797         if (fType.IsSameAs(_T("logical")))
3798             addStr = _T("");
3799         else if (fType.size() > 8)
3800         {
3801             wxString allStr = fType.Mid(8);
3802             allStr.Replace(_T("("),_T(""));
3803             allStr.Replace(_T(")"),_T(""));
3804             allStr.Replace(_T("*"),_T(""));
3805             allStr.Replace(_T("."),_T(""));
3806             allStr.Replace(_T("_"),_T(""));
3807             for(size_t i=0; i<allStr.size(); i++)
3808             {
3809                 addStr << allStr.GetChar(i);
3810                 wxString fnam = _T("log") + addStr + _T("_to_int");
3811                 bool alreadyHave = false;
3812                 for (TypeMap::iterator it = m_GlobLogFunMap.begin(); it != m_GlobLogFunMap.end(); ++it)
3813                 {
3814                     if (it->second[0].IsSameAs(fnam))
3815                     {
3816                         alreadyHave = true;
3817                         break;
3818                     }
3819                 }
3820                 if (!alreadyHave)
3821                     break;
3822             }
3823         }
3824         m_LogTypeSet.insert(fType);
3825         funNames.Add( _T("log") + addStr + _T("_to_int"));
3826         funNames.Add( _T("int_to_log") + addStr);
3827         m_GlobLogFunMap[fType] = funNames;
3828     }
3829     else
3830     {
3831         m_LogTypeSet.insert(fType);
3832         return m_GlobLogFunMap[fType];
3833     }
3834     return funNames;
3835 }
3836 
Onbt_OutputDirClick(wxCommandEvent & event)3837 void Bindto::Onbt_OutputDirClick(wxCommandEvent& event)
3838 {
3839     wxDirDialog dlg(this, _T("Choose output directory"), tc_OutputDir->GetValue(), wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON);
3840     if (dlg.ShowModal() == wxID_OK)
3841     {
3842          wxString path = dlg.GetPath();
3843          tc_OutputDir->SetValue(path);
3844     }
3845 }
3846 
Oncb_genCythonClick(wxCommandEvent & event)3847 void Bindto::Oncb_genCythonClick(wxCommandEvent& event)
3848 {
3849     bool enpy = cb_genCython->GetValue();
3850     pn_pyOpts->Enable(enpy);
3851 }
3852 
OnCopy(wxCommandEvent & event)3853 void Bindto::OnCopy(wxCommandEvent& event)
3854 {
3855     long sel = lv_Types->GetFirstSelected();
3856     if (sel == -1)
3857         return;
3858     wxString ft_old = lv_Types->GetItemText(sel);
3859     wxArrayString bcArr = m_TypeMap[ft_old];
3860     wxString bt_old = bcArr[0];
3861     wxString ct_old = bcArr[1];
3862 
3863     BindtoNewType newTypeDlg(this);
3864     newTypeDlg.SetEditType(ft_old,bt_old,ct_old);
3865     ShowNewTypeDlg(newTypeDlg);
3866 }
3867 
ParseBindtoDirectives(const TokenF * parentToken)3868 void Bindto::ParseBindtoDirectives(const TokenF* parentToken)
3869 {
3870     m_BTDirMap.clear();
3871 
3872     for (size_t i=0; i < parentToken->m_Children.GetCount(); i++)
3873     {
3874         if (parentToken->m_Children.Item(i)->m_TokenKind == tkBindTo)
3875         {
3876             wxArrayString intentArr;
3877             wxArrayString dimArr;
3878             wxArrayString varNameArr;
3879             wxArrayString initStrArr;
3880             wxString bstr = parentToken->m_Children.Item(i)->m_Args;
3881             bstr.Replace(_T("\t"),_T(" "));
3882             int idx = bstr.Find(_T("::"));
3883             if (idx == wxNOT_FOUND)
3884                 continue; // syntax error
3885 
3886             wxString bstr1 = bstr.Mid(0,idx);
3887             bstr1.Replace(_T(" "),_T(""));
3888             wxString bstr2 = bstr.Mid(idx+2);
3889             bstr2.Replace(_T(" "),_T(""));
3890             idx = bstr1.Find(_T("intent("));
3891             if (idx != wxNOT_FOUND)
3892             {
3893                 wxString strint = GetToken(bstr1, idx+6);
3894                 wxStringTokenizer tkz(strint, _T("(),"), wxTOKEN_STRTOK );
3895                 while ( tkz.HasMoreTokens() )
3896                     intentArr.Add(tkz.GetNextToken());
3897             }
3898             idx = bstr1.Find(_T("dimension("));
3899             if (idx != wxNOT_FOUND)
3900             {
3901                 wxString strdim = GetToken(bstr1, idx+9);
3902                 wxStringTokenizer tkz(strdim, _T("(),"), wxTOKEN_STRTOK );
3903                 while ( tkz.HasMoreTokens() )
3904                     dimArr.Add(tkz.GetNextToken());
3905             }
3906 
3907             wxString bstr2_tmp = bstr2;
3908             wxArrayString tok1arr;
3909             wxArrayString key1arr;
3910             wxString keyA = _T("%%@@%%");
3911             for (int j=0; j<2; j++)
3912             {
3913                 wxString sstart;
3914                 if (j == 0)
3915                     sstart = _T("(");
3916                 else
3917                     sstart = _T("[");
3918 
3919                 for (int k=0; true; k++)
3920                 {
3921                     idx = bstr2_tmp.Find(sstart);
3922                     if (idx == wxNOT_FOUND)
3923                         break;
3924                     wxString s1 = GetToken(bstr2_tmp, idx);
3925                     if (s1.IsEmpty())
3926                         break;
3927                     tok1arr.Add(s1);
3928                     wxString key1 = keyA;
3929                     key1 << j << k;
3930                     key1arr.Add(key1);
3931                     bstr2_tmp.Replace(s1,key1,false);
3932                 }
3933             }
3934 
3935             wxArrayString vars;
3936             wxStringTokenizer tkz(bstr2_tmp, _T(","), wxTOKEN_STRTOK );
3937             while ( tkz.HasMoreTokens() )
3938             {
3939                 wxString var1 = tkz.GetNextToken();
3940                 idx = var1.Find(_T("="));
3941                 if (idx == wxNOT_FOUND)
3942                 {
3943                     varNameArr.Add(var1);
3944                     initStrArr.Add(_T(""));
3945                 }
3946                 else
3947                 {
3948                     varNameArr.Add(var1.Mid(0,idx));
3949                     wxString initStr = _T(" = ") + var1.Mid(idx+1);
3950                     for (int k=tok1arr.size()-1; k>=0; k--)
3951                         initStr.Replace(key1arr.Item(k),tok1arr.Item(k),false);
3952                     initStrArr.Add(initStr);
3953                 }
3954             }
3955 
3956             for (size_t k=0; k<varNameArr.size(); k++)
3957             {
3958                 BintoDirective bto;
3959                 bto.varName = varNameArr.Item(k);
3960                 bto.dim = dimArr;
3961                 bto.initStr = initStrArr.Item(k);
3962                 for (size_t j=0; j<intentArr.size(); j++)
3963                 {
3964                     if (intentArr.Item(j).IsSameAs(_T("inout")))
3965                     {
3966                         bto.intent.insert(_T("in"));
3967                         bto.intent.insert(_T("out"));
3968                     }
3969                     else
3970                         bto.intent.insert(intentArr.Item(j));
3971                 }
3972                 if (m_BTDirMap.count(bto.varName) == 0)
3973                     m_BTDirMap[bto.varName] = bto;
3974             }
3975         }
3976     }
3977 }
3978 
GetDimArr(const wxString & dimStr)3979 wxArrayString Bindto::GetDimArr(const wxString& dimStr)
3980 {
3981     wxArrayString dimArr;
3982     if (!dimStr.StartsWith(_T("(")) || !dimStr.EndsWith(_T(")")))
3983         return dimArr;
3984 
3985     wxString dimStr2 = dimStr.Mid(1,dimStr.size()-2);
3986     wxArrayString tok1arr;
3987     wxArrayString key1arr;
3988     wxString keyA = _T("%%@@%%");
3989     for (int j=0; j<2; j++)
3990     {
3991         wxString keyAB;
3992         wxString sstart;
3993         if (j == 0)
3994             sstart = _T("(");
3995         else
3996             sstart = _T("[");
3997 
3998         for (int k=0; true; k++)
3999         {
4000             int idx = dimStr2.Find(sstart);
4001             if (idx == wxNOT_FOUND)
4002                 break;
4003             wxString s1 = GetToken(dimStr2, idx);
4004             if (s1.IsEmpty())
4005                 break;
4006             tok1arr.Add(s1);
4007             wxString key1 = keyA;
4008             key1 << j << k;
4009             key1arr.Add(key1);
4010             dimStr2.Replace(s1,key1,false);
4011         }
4012     }
4013 
4014     wxArrayString vars;
4015     wxStringTokenizer tkz(dimStr2, _T(","), wxTOKEN_STRTOK );
4016     while ( tkz.HasMoreTokens() )
4017     {
4018         wxString var1 = tkz.GetNextToken();
4019         for (int k=tok1arr.size()-1; k>=0; k--)
4020             var1.Replace(key1arr.Item(k),tok1arr.Item(k),false);
4021         dimArr.Add(var1);
4022     }
4023     return dimArr;
4024 }
4025 
AddPyArgs(const wxArrayString & argArr,wxArrayString & morePyIntArgs,const wxArrayString & addIntArg)4026 void Bindto::AddPyArgs(const wxArrayString& argArr, wxArrayString& morePyIntArgs, const wxArrayString& addIntArg)
4027 {
4028     for (size_t i=0; i<addIntArg.size(); i++)
4029     {
4030         if (argArr.Index(addIntArg.Item(i)) == wxNOT_FOUND && morePyIntArgs.Index(addIntArg.Item(i)) == wxNOT_FOUND)
4031             morePyIntArgs.Add(addIntArg.Item(i));
4032     }
4033 }
4034 
WriteSetupPy(const wxArrayString & pyxFArr,const wxString & setupPyFn,const wxString & binDir)4035 void Bindto::WriteSetupPy(const wxArrayString& pyxFArr, const wxString& setupPyFn, const wxString& binDir)
4036 {
4037     wxFileName sfn(setupPyFn);
4038     wxFileName bdir;
4039     bdir.SetPath(binDir);
4040     bdir.MakeRelativeTo(sfn.GetPath());
4041     wxString pyxFileName;
4042 
4043     if (pyxFArr.size() > 1)
4044     {
4045         // Create one pyx file which includes other
4046         wxFileName cpyxf(pyxFArr.Item(0));
4047         cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
4048         if (project)
4049         {
4050             wxFileName profn(project->GetFilename());
4051             cpyxf.SetName(profn.GetName());
4052         }
4053         else
4054             cpyxf.SetName(_T("project"));
4055 
4056         wxString compyx;
4057         for (size_t i=0; i<pyxFArr.size(); i++)
4058         {
4059             wxFileName pfn(pyxFArr.Item(i));
4060             compyx << _T("include \"") << pfn.GetFullName() << _T("\"\n");
4061         }
4062 
4063         wxFile f(cpyxf.GetFullPath(), wxFile::write);
4064         cbWrite(f, compyx + GetEOLStr(), wxFONTENCODING_UTF8);
4065         pyxFileName = cpyxf.GetFullPath();
4066     }
4067     else
4068         pyxFileName = pyxFArr.Item(0);
4069 
4070     wxString part1;
4071     part1 << _T("# Run this file using:\n");
4072     part1 << _T("# python ") + sfn.GetFullName() + _T(" build_ext --inplace\n\n");
4073     part1 << _T("from distutils.core import setup\n");
4074     part1 << _T("from distutils.extension import Extension\n");
4075     part1 << _T("from Cython.Build import cythonize\n");
4076     part1 << _T("import numpy\n\n");
4077     part1 << _T("extensions = [\n");
4078 
4079     wxString part2;
4080     wxFileName pfn(pyxFileName);
4081     part2 << GetIS(1) << _T("Extension('") << pfn.GetName() << _T("', ['") << pfn.GetFullName() << _T("'],\n");
4082     part2 << GetIS(2) << _T("runtime_library_dirs=['./'],\n");
4083     part2 << GetIS(2) << _T("library_dirs=['") << bdir.GetPath() << _T("'],\n");
4084     part2 << GetIS(2) << _T("include_dirs=[numpy.get_include()],\n");
4085     part2 << GetIS(2) << _T("libraries=[");
4086     if (!m_TargetLibraryName.IsEmpty())
4087     {
4088         wxString shortLN = m_TargetLibraryName;
4089         if (shortLN.StartsWith(_T("lib")))
4090             shortLN = shortLN.Mid(3);
4091         part2 << _T("'") << shortLN << _T("'");
4092         if (m_IsTargetStaticLib && !m_TargetCompilerName.IsEmpty() && CompilerFactory::CompilerInheritsFrom(m_TargetCompilerName, _T("gfortran")))
4093             part2 << _T(", 'gfortran'");
4094     }
4095     part2 << _T("],\n");
4096     part2 << GetIS(2) << _T("),\n");
4097     part2 << GetIS(1) << _T("]\n");
4098 
4099     wxString part3;
4100     part3 << _T("setup(\n");
4101     part3 << GetIS(1) << _T("ext_modules = cythonize(extensions),\n");
4102     part3 << _T(")\n");
4103 
4104     wxFile f(sfn.GetFullPath(), wxFile::write);
4105     cbWrite(f, part1 + part2 + part3 + GetEOLStr(), wxFONTENCODING_UTF8);
4106 }
4107 
Oncb_globalToOneClick(wxCommandEvent & event)4108 void Bindto::Oncb_globalToOneClick(wxCommandEvent& event)
4109 {
4110     bool enab = cb_globalToOne->GetValue();
4111     tc_globalFilename->Enable(enab);
4112     st_globalFilename->Enable(enab);
4113 }
4114 
AddToCStruct(TokenF * typeTok)4115 void Bindto::AddToCStruct(TokenF* typeTok)
4116 {
4117     m_CStructs << _T("\ntypedef struct {\n");
4118     TokensArrayF* pChildren = &typeTok->m_Children;
4119     for (size_t i=0; i<pChildren->GetCount(); i++)
4120     {
4121         if (pChildren->Item(i)->m_TokenKind == tkVariable)
4122         {
4123             int itmp;
4124             TypeBind bindT = GetBindType(pChildren->Item(i), itmp);
4125             m_CStructs << GetIS(1);
4126             wxString cT = bindT.cType;
4127             if (cT.EndsWith(_T("*")))
4128                 cT = cT.Mid(0,cT.Length()-1);
4129             m_CStructs << cT << _T(" ") << pChildren->Item(i)->m_Name << bindT.cDim;
4130             m_CStructs << _T(";\n");
4131         }
4132     }
4133     m_CStructs << _T("} ") << typeTok->m_Name << _T(";\n");
4134 }
4135 
GetHeaderStartEnd(const wxString & hfname,wxString & hStart,wxString & hEnd)4136 void Bindto::GetHeaderStartEnd(const wxString& hfname, wxString& hStart, wxString& hEnd)
4137 {
4138     hStart << _T("#ifdef __cplusplus\n");
4139     hStart << _T("extern \"C\" {\n");
4140     hStart << _T("#endif\n");
4141     hStart << _T("#ifndef ") << hfname.Upper() << _T("_H") << _T("\n");
4142     hStart << _T("#define ") << hfname.Upper() << _T("_H") << _T("\n\n");
4143 
4144     hEnd << _T("\n#endif\n");
4145     hEnd << _T("#ifdef __cplusplus\n");
4146     hEnd << _T("}\n");
4147     hEnd << _T("#endif\n");
4148 }
4149 
WriteHelperModFile()4150 void Bindto::WriteHelperModFile()
4151 {
4152     std::map<wxString,wxString> procMap;
4153     wxString modHead;
4154     GetHelperModule(true, true, procMap, modHead);
4155 
4156     wxString hfstr;
4157     wxFileName fname(_T("bindto_helper.f90"));
4158     fname.SetPath(m_OutputDir);
4159     if (fname.FileExists())
4160     {
4161         wxFile f(fname.GetFullPath(), wxFile::read);
4162         cbRead(f, hfstr);
4163 
4164         int iem = hfstr.Find(_T("end module"));
4165         if (iem != wxNOT_FOUND)
4166             hfstr = hfstr.Mid(0,iem);
4167     }
4168     else
4169         hfstr = modHead;
4170 
4171     std::map<wxString,wxString>::const_iterator it;
4172     wxString key;
4173 
4174     for (it = procMap.begin(); it != procMap.end(); ++it)
4175     {
4176         if (hfstr.Find(it->first) == wxNOT_FOUND)
4177             hfstr.Append(it->second);
4178     }
4179 
4180     hfstr.Append(_T("end module\n"));
4181 
4182     wxFile f(fname.GetFullPath(), wxFile::write);
4183     cbWrite(f, hfstr + GetEOLStr(), wxFONTENCODING_UTF8);
4184 }
4185 
AddToLogFile(const wxString & msg)4186 void Bindto::AddToLogFile(const wxString& msg)
4187 {
4188     if (msg.IsEmpty())
4189         return;
4190 
4191     wxString logstr;
4192     wxFileName fname;
4193     fname.SetPath(m_OutputDir);
4194     fname.SetFullName(_T("bindto.log"));
4195     if (fname.FileExists())
4196     {
4197         wxFile logf(fname.GetFullPath(), wxFile::read);
4198         cbRead(logf, logstr);
4199     }
4200     logstr.append(_T("\n****************************************************************\n"));
4201     logstr.append(msg);
4202     wxFile logf(fname.GetFullPath(), wxFile::write);
4203     cbWrite(logf, logstr);
4204 }
4205