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