Code::Blocks  SVN r11506
macrosmanager.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11465 $
6  * $Id: macrosmanager.cpp 11465 2018-09-11 22:38:32Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/macrosmanager.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include <wx/menu.h>
14 
15  #include "cbworkspace.h"
16  #include "projectmanager.h"
17  #include "editormanager.h"
18  #include "logmanager.h"
19  #include "macrosmanager.h"
20  #include "scriptingmanager.h"
21  #include "manager.h"
22  #include "cbproject.h"
23  #include "cbeditor.h"
24  #include "uservarmanager.h"
25  #include "configmanager.h"
26  #include "globals.h"
27  #include "compilerfactory.h"
28  #include "compiler.h"
29 #endif
30 
31 #include <wx/stdpaths.h> // wxStandardPaths
32 #include <cstdlib>
33 
34 #include "scripting/sqplus/sqplus.h"
36 
37 #include "cbstyledtextctrl.h"
38 
39 using namespace std;
40 
41 template<> MacrosManager* Mgr<MacrosManager>::instance = nullptr;
42 template<> bool Mgr<MacrosManager>::isShutdown = false;
43 
44 static const wxString const_COIN(_T("COIN"));
45 static const wxString const_RANDOM(_T("RANDOM"));
46 static const wxString toNativePath(_T("$TO_NATIVE_PATH{"));
47 static const wxString toUnixPath(_T("$TO_UNIX_PATH{"));
48 static const wxString toWindowsPath(_T("$TO_WINDOWS_PATH{"));
49 
51 {
52  Reset();
53 }
54 
56 {
57 }
58 
59 void MacrosManager::CreateMenu(cb_unused wxMenuBar* menuBar)
60 {
61 }
62 
63 void MacrosManager::ReleaseMenu(cb_unused wxMenuBar* menuBar)
64 {
65 }
66 
68 {
69  wxString tmp(buffer);
70  ReplaceMacros(tmp, target);
71  return tmp;
72 }
73 
75 {
76  m_LastProject = nullptr;
77  m_LastTarget = nullptr;
78  m_ActiveEditorFilename = wxEmptyString;
79  m_ActiveEditorLine = -1;
80  m_ActiveEditorColumn = -1;
81 
85  ClearProjectKeys();
86  m_RE_Unix.Compile(_T("([^$]|^)(\\$[({]?(#?[A-Za-z_0-9.]+)[)} /\\]?)"), wxRE_EXTENDED | wxRE_NEWLINE);
87  m_RE_DOS.Compile(_T("([^%]|^)(%(#?[A-Za-z_0-9.]+)%)"), wxRE_EXTENDED | wxRE_NEWLINE);
88  m_RE_If.Compile(_T("\\$if\\(([^)]*)\\)[::space::]*(\\{([^}]*)\\})(\\{([^}]*)\\})?"), wxRE_EXTENDED | wxRE_NEWLINE);
89  m_RE_IfSp.Compile(_T("[^=!<>]+|(([^=!<>]+)[ ]*(=|==|!=|>|<|>=|<=)[ ]*([^=!<>]+))"), wxRE_EXTENDED | wxRE_NEWLINE);
90  m_RE_Script.Compile(_T("(\\[\\[(.*)\\]\\])"), wxRE_EXTENDED | wxRE_NEWLINE);
91  m_RE_ToAbsolutePath.Compile(_T("\\$TO_ABSOLUTE_PATH{([^}]*)}"),
92 #ifndef __WXMAC__
94 #else
96 #endif
97  m_RE_To83Path.Compile(_T("\\$TO_83_PATH{([^}]*)}"),
98 #ifndef __WXMAC__
99  wxRE_ADVANCED);
100 #else
101  wxRE_EXTENDED);
102 #endif
103  m_RE_RemoveQuotes.Compile(_T("\\$REMOVE_QUOTES{([^}]*)}"),
104 #ifndef __WXMAC__
105  wxRE_ADVANCED);
106 #else
107  wxRE_EXTENDED);
108 #endif
109  m_UserVarMan = Manager::Get()->GetUserVariableManager();
110  srand(time(nullptr));
111  assert(m_RE_Unix.IsValid());
112  assert(m_RE_DOS.IsValid());
113 }
114 
116 {
117  m_Macros.clear();
118 
119  m_Macros[_T("AMP")] = _T("&");
120  m_Macros[_T("CODEBLOCKS")] = m_AppPath;
121  m_Macros[_T("APP_PATH")] = m_AppPath;
122  m_Macros[_T("APP-PATH")] = m_AppPath;
123  m_Macros[_T("APPPATH")] = m_AppPath;
124  m_Macros[_T("DATA_PATH")] = m_DataPath;
125  m_Macros[_T("DATA-PATH")] = m_DataPath;
126  m_Macros[_T("DATAPATH")] = m_DataPath;
127  m_Macros[_T("PLUGINS")] = m_Plugins;
128  m_Macros[_T("LANGUAGE")] = wxLocale::GetLanguageName(wxLocale::GetSystemLanguage());
129  m_Macros[_T("ENCODING")] = wxLocale::GetSystemEncodingName();
130 
131  if (platform::windows)
132  {
133  m_Macros[_T("CMD_NULL")] = _T("NUL");
134 
135  const wxString cmd(_T("cmd /c "));
136  m_Macros[_T("CMD_CP")] = cmd + _T("copy");
137  m_Macros[_T("CMD_RM")] = cmd + _T("del");
138  m_Macros[_T("CMD_MV")] = cmd + _T("move");
139  m_Macros[_T("CMD_MKDIR")] = cmd + _T("md");
140  m_Macros[_T("CMD_RMDIR")] = cmd + _T("rd");
141  }
142  else
143  {
144  m_Macros[_T("CMD_CP")] = _T("cp --preserve=timestamps");
145  m_Macros[_T("CMD_RM")] = _T("rm");
146  m_Macros[_T("CMD_MV")] = _T("mv");
147  m_Macros[_T("CMD_NULL")] = _T("/dev/null");
148  m_Macros[_T("CMD_MKDIR")] = _T("mkdir -p");
149  m_Macros[_T("CMD_RMDIR")] = _T("rmdir");
150  }
151 
153  if (wksp)
154  {
155  m_WorkspaceWxFileName.Assign(wksp->GetFilename());
156  m_WorkspaceFilename = UnixFilename(m_WorkspaceWxFileName.GetFullName());
157  m_WorkspaceName = wksp->GetTitle();
158  m_WorkspaceDir = UnixFilename(m_WorkspaceWxFileName.GetPath());
159  }
160  else
161  {
162  m_WorkspaceWxFileName.Clear();
163  m_WorkspaceFilename = wxEmptyString;
164  m_WorkspaceName = wxEmptyString;
165  m_WorkspaceDir = wxEmptyString;
166  }
167  m_Macros[_T("WORKSPACE_FILE")] = m_WorkspaceFilename;
168  m_Macros[_T("WORKSPACE_FILENAME")] = m_WorkspaceFilename;
169  m_Macros[_T("WORKSPACE_FILE_NAME")] = m_WorkspaceFilename;
170  m_Macros[_T("WORKSPACEFILE")] = m_WorkspaceFilename;
171  m_Macros[_T("WORKSPACEFILENAME")] = m_WorkspaceFilename;
172  m_Macros[_T("WORKSPACENAME")] = m_WorkspaceName;
173  m_Macros[_T("WORKSPACE_NAME")] = m_WorkspaceName;
174  m_Macros[_T("WORKSPACE_DIR")] = m_WorkspaceDir;
175  m_Macros[_T("WORKSPACE_DIRECTORY")] = m_WorkspaceDir;
176  m_Macros[_T("WORKSPACEDIR")] = m_WorkspaceDir;
177  m_Macros[_T("WORKSPACEDIRECTORY")] = m_WorkspaceDir;
178 }
179 
181 {
183  if (ed)
184  {
185  cbStyledTextCtrl* stc = ed->GetControl();
186  if (stc)
187  {
188  wxString text = stc->GetSelectedText();
189  if ( text.size() )
190  return text;
191  else
192  {
193  int iCurrentPos = stc->GetCurrentPos();
194  return stc->GetTextRange(stc->WordStartPosition(iCurrentPos, true),
195  stc->WordEndPosition(iCurrentPos, true));
196  }
197  }
198  }
199 
200  return wxEmptyString;
201 }
202 
203 namespace
204 {
205 template<typename T>
206 void ReadMacros(MacrosMap &macros, T *object)
207 {
208  if (object)
209  {
210  const StringHash& v = object->GetAllVars();
211  for (StringHash::const_iterator it = v.begin(); it != v.end(); ++it)
212  macros[it->first.Upper()] = it->second;
213  }
214 }
215 } // namespace
216 
218 {
219  m_ActiveEditorFilename = wxEmptyString; // invalidate
220  m_ActiveEditorLine = -1; // invalidate
221  m_ActiveEditorColumn = -1; // invalidate
222 
223  // Remove all variables for the old target from the macro map. This makes sure that target
224  // specific variables are reinitialized after every target in a multi target project, where
225  // targets are built one after the other. Also if a variable is not set in a target it won't
226  // be visible because it was set by a previous target in the build order.
227  if (m_LastTarget)
228  {
229  const StringHash& v = m_LastTarget->GetAllVars();
230  for (StringHash::const_iterator it = v.begin(); it != v.end(); ++it)
231  m_Macros.erase(it->first.Upper());
232  }
233 
234  if (editor)
235  {
236  // don't use pointer to editor here, because this might be the same,
237  // even after closing one file and opening a new one
238  if (editor->GetFilename() != m_ActiveEditorFilename)
239  m_ActiveEditorFilename = editor->GetFilename();
240 
241  // (re-) compute column and line but only in case it's a builtin-editor
242  if (editor->IsBuiltinEditor())
243  {
244  cbEditor* cbEd = static_cast<cbEditor*>(editor);
245  cbStyledTextCtrl* cbSTC = cbEd->GetControl();
246  if (cbSTC)
247  {
248  m_ActiveEditorLine = cbSTC->GetCurrentLine() + 1;
249  int pos = cbSTC->GetCurrentPos();
250  if (pos!=-1)
251  m_ActiveEditorColumn = cbSTC->GetColumn(pos) + 1;
252  }
253  }
254  }
255 
256  if (!project)
257  {
258  m_ProjectFilename = wxEmptyString;
259  m_ProjectName = wxEmptyString;
260  m_ProjectDir = wxEmptyString;
261  m_ProjectFiles = wxEmptyString;
262  m_Makefile = wxEmptyString;
263  m_LastProject = nullptr;
264  ClearProjectKeys();
265  m_Macros[_T("PROJECTFILE")] = wxEmptyString;
266  m_Macros[_T("PROJECT_FILE")] = wxEmptyString;
267  m_Macros[_T("PROJECTFILENAME")] = wxEmptyString;
268  m_Macros[_T("PROJECT_FILENAME")] = wxEmptyString;
269  m_Macros[_T("PROJECT_FILE_NAME")] = wxEmptyString;
270  m_Macros[_T("PROJECTNAME")] = wxEmptyString;
271  m_Macros[_T("PROJECT_NAME")] = wxEmptyString;
272  m_Macros[_T("PROJECTDIR")] = wxEmptyString;
273  m_Macros[_T("PROJECT_DIR")] = wxEmptyString;
274  m_Macros[_T("PROJECTDIRECTORY")] = wxEmptyString;
275  m_Macros[_T("PROJECT_DIRECTORY")] = wxEmptyString;
276  m_Macros[_T("PROJECTTOPDIR")] = wxEmptyString;
277  m_Macros[_T("PROJECT_TOPDIR")] = wxEmptyString;
278  m_Macros[_T("PROJECTTOPDIRECTORY")] = wxEmptyString;
279  m_Macros[_T("PROJECT_TOPDIRECTORY")] = wxEmptyString;
280  m_Macros[_T("MAKEFILE")] = wxEmptyString;
281  m_Macros[_T("ALL_PROJECT_FILES")] = wxEmptyString;
282  }
283  else if ( (project != m_LastProject) || (project->GetTitle() != m_ProjectName)
284  || (UnixFilename(project->GetBasePath()) != m_ProjectDir)
285  || (UnixFilename(m_ProjectWxFileName.GetFullName()) != m_ProjectFilename)
286  )
287  {
288  m_LastTarget = nullptr; // reset last target when project changes
289  m_ProjectWxFileName.Assign(project->GetFilename());
290  m_ProjectFilename = UnixFilename(m_ProjectWxFileName.GetFullName());
291  m_ProjectName = project->GetTitle();
292  m_ProjectDir = UnixFilename(project->GetBasePath());
293  m_ProjectTopDir = UnixFilename(project->GetCommonTopLevelPath());
294  m_Makefile = UnixFilename(project->GetMakefile());
295  m_ProjectFiles = wxEmptyString;
296  for (FilesList::iterator it = project->GetFilesList().begin(); it != project->GetFilesList().end(); ++it)
297  {
298  // quote filenames, if they contain spaces
299  wxString out = UnixFilename(((ProjectFile*)*it)->relativeFilename);
300  QuoteStringIfNeeded(out);
301  m_ProjectFiles << out << _T(' ');
302  }
303 
304  ClearProjectKeys();
305  m_Macros[_T("PROJECTFILE")] = m_ProjectFilename;
306  m_Macros[_T("PROJECT_FILE")] = m_ProjectFilename;
307  m_Macros[_T("PROJECTFILENAME")] = m_ProjectFilename;
308  m_Macros[_T("PROJECT_FILENAME")] = m_ProjectFilename;
309  m_Macros[_T("PROJECT_FILE_NAME")] = m_ProjectFilename;
310  m_Macros[_T("PROJECTNAME")] = m_ProjectName;
311  m_Macros[_T("PROJECT_NAME")] = m_ProjectName;
312  m_Macros[_T("PROJECTDIR")] = m_ProjectDir;
313  m_Macros[_T("PROJECT_DIR")] = m_ProjectDir;
314  m_Macros[_T("PROJECTDIRECTORY")] = m_ProjectDir;
315  m_Macros[_T("PROJECT_DIRECTORY")] = m_ProjectDir;
316  m_Macros[_T("PROJECTTOPDIR")] = m_ProjectTopDir;
317  m_Macros[_T("PROJECT_TOPDIR")] = m_ProjectTopDir;
318  m_Macros[_T("PROJECTTOPDIRECTORY")] = m_ProjectTopDir;
319  m_Macros[_T("PROJECT_TOPDIRECTORY")] = m_ProjectTopDir;
320  m_Macros[_T("MAKEFILE")] = m_Makefile;
321  m_Macros[_T("ALL_PROJECT_FILES")] = m_ProjectFiles;
322 
323  for (int i = 0; i < project->GetBuildTargetsCount(); ++i)
324  {
325  ProjectBuildTarget* it_target = project->GetBuildTarget(i);
326  if (!it_target)
327  continue;
328  wxString title = it_target->GetTitle().Upper();
329  while (title.Replace(_T(" "), _T("_")))
330  ; // replace spaces with underscores (what about other invalid chars?)
331  m_Macros[title + _T("_OUTPUT_FILE")] = UnixFilename(it_target->GetOutputFilename());
332  m_Macros[title + _T("_OUTPUT_DIR")] = UnixFilename(it_target->GetBasePath());
333  m_Macros[title + _T("_OUTPUT_BASENAME")] = wxFileName(it_target->GetOutputFilename()).GetName();
334  m_Macros[title + _T("_PARAMETERS")] = it_target->GetExecutionParameters();
335  }
336  m_LastProject = project;
337  }
338 
339  // get compiler variables
340  if (target)
341  {
342  const Compiler* compiler = CompilerFactory::GetCompiler(target->GetCompilerID());
343  ReadMacros(m_Macros, compiler);
344  }
345 
346  ReadMacros(m_Macros, project);
347 
348  if (!target)
349  {
350  m_TargetOutputDir = wxEmptyString;
351  m_TargetName = wxEmptyString;
352  m_TargetOutputBaseName = wxEmptyString;
353  m_TargetOutputFilename = wxEmptyString;
354  m_TargetFilename = wxEmptyString;
355  m_LastTarget = nullptr;
356  }
357  else if ( (target != m_LastTarget) or (target->GetTitle() != m_TargetName) )
358  {
359  wxFileName tod(target->GetOutputFilename());
360  m_TargetOutputDir = UnixFilename(tod.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
361  m_TargetName = UnixFilename(target->GetTitle());
362  m_TargetOutputBaseName = wxFileName(target->GetOutputFilename()).GetName();
363  m_TargetOutputFilename = wxFileName(target->GetOutputFilename()).GetFullName();
364  m_TargetFilename = UnixFilename(target->GetOutputFilename());
365  m_LastTarget = target;
366  }
367 
368  if (target)
369  {
370  ReadMacros(m_Macros, target);
371 
373  {
374  m_Macros[_T("TARGET_CC")] = c->GetPrograms().C;
375  m_Macros[_T("TARGET_CPP")] = c->GetPrograms().CPP;
376  m_Macros[_T("TARGET_LD")] = c->GetPrograms().LD;
377  m_Macros[_T("TARGET_LIB")] = c->GetPrograms().LIB;
378  wxFileName MasterPath;
379  MasterPath.SetPath(c->GetMasterPath(), wxPATH_NATIVE);
380  m_Macros[_T("TARGET_COMPILER_DIR")] = MasterPath.GetPathWithSep(wxPATH_NATIVE);
381  }
382  m_Macros[_T("TARGET_OBJECT_DIR")] = target->GetObjectOutput();
383  }
384 
385  m_Macros[_T("TARGET_OUTPUT_DIR")] = m_TargetOutputDir;
386  m_Macros[_T("TARGET_NAME")] = m_TargetName;
387  m_Macros[_T("TARGET_OUTPUT_BASENAME")] = m_TargetOutputBaseName;
388  m_Macros[_T("TARGET_OUTPUT_FILENAME")] = m_TargetOutputFilename;
389  m_Macros[_T("TARGET_OUTPUT_FILE")] = m_TargetFilename;
390 
391  m_Macros[_T("ACTIVE_EDITOR_FILENAME")] = UnixFilename(m_ActiveEditorFilename);
392  wxFileName fn(m_Macros[_T("ACTIVE_EDITOR_FILENAME")]);
393  m_Macros[_T("ACTIVE_EDITOR_DIRNAME")] = fn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
394  m_Macros[_T("ACTIVE_EDITOR_STEM")] = fn.GetName();
395  m_Macros[_T("ACTIVE_EDITOR_EXT")] = fn.GetExt();
396 
397  wxString temp_str;
398  temp_str.Printf(_T("%d"), m_ActiveEditorLine);
399  m_Macros[_T("ACTIVE_EDITOR_LINE")] = temp_str;
400  temp_str.Printf(_T("%d"), (m_ActiveEditorLine>0) ? m_ActiveEditorLine-1 : -1); // zero based, but keep value for "invalid"
401  m_Macros[_T("ACTIVE_EDITOR_LINE_0")] = temp_str;
402  temp_str.Printf(_T("%d"), m_ActiveEditorColumn);
403  m_Macros[_T("ACTIVE_EDITOR_COLUMN")] = temp_str;
404  temp_str.Printf(_T("%d"), (m_ActiveEditorColumn>0) ? m_ActiveEditorColumn-1 : -1); // zero based, but keep value for "invalid"
405  m_Macros[_T("ACTIVE_EDITOR_COLUMN_0")] = temp_str;
406  m_Macros[_T("ACTIVE_EDITOR_SELECTION")] = GetSelectedText();
407 
408  // Wrapper for WX standard path's methods:
409 
410  // Unix: prefix/share/appname Windows: EXE path
411  m_Macros[_T("GET_DATA_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetDataDir();
412  // Unix: /etc/appname Windows: EXE path
413  m_Macros[_T("GET_LOCAL_DATA_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetLocalDataDir();
414  // Unix: ~ Windows: C:\Documents and Settings\username\Documents
415  m_Macros[_T("GET_DOCUMENTS_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetDocumentsDir();
416  // Unix: /etc Windows: C:\Documents and Settings\All Users\Application Data
417  m_Macros[_T("GET_CONFIG_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetConfigDir();
418  // Unix: ~ Windows: C:\Documents and Settings\username\Application Data\appname
419  m_Macros[_T("GET_USER_CONFIG_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetUserConfigDir();
420  // Unix: ~/.appname Windows: C:\Documents and Settings\username\Application Data
421  m_Macros[_T("GET_USER_DATA_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetUserDataDir();
422  // Unix: ~/.appname Windows: C:\Documents and Settings\username\Local Settings\Application Data\appname
423  m_Macros[_T("GET_USER_LOCAL_DATA_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetUserLocalDataDir();
424  // ALl platforms: A writable, temporary directory
425  m_Macros[_T("GET_TEMP_DIR")] = ((const wxStandardPaths&)wxStandardPaths::Get()).GetTempDir();
426 
428  m_Macros[_T("TDAY")] = now.Format(_T("%Y%m%d"));
429  m_Macros[_T("TODAY")] = now.Format(_T("%Y-%m-%d"));
430  m_Macros[_T("NOW")] = now.Format(_T("%Y-%m-%d-%H.%M"));
431  m_Macros[_T("NOW_L")] = now.Format(_T("%Y-%m-%d-%H.%M.%S"));
432  m_Macros[_T("WEEKDAY")] = now.Format(_T("%A"));
433 
434  wxDateTime nowGMT(now.ToGMT());
435  m_Macros[_T("TDAY_UTC")] = nowGMT.Format(_T("%Y%m%d"));
436  m_Macros[_T("TODAY_UTC")] = nowGMT.Format(_T("%Y-%m-%d"));
437  m_Macros[_T("NOW_UTC")] = nowGMT.Format(_T("%Y-%m-%d-%H.%M"));
438  m_Macros[_T("NOW_L_UTC")] = nowGMT.Format(_T("%Y-%m-%d-%H.%M.%S"));
439  m_Macros[_T("WEEKDAY_UTC")] = nowGMT.Format(_T("%A"));
440 
441  wxDateTime january_1_2010(1, wxDateTime::Jan, 2010, 0, 0, 0, 0);
442  wxTimeSpan ts = now.Subtract(january_1_2010);
443  m_Macros[_T("DAYCOUNT")] = wxString::Format(_T("%d"), ts.GetDays());
444 }
445 
446 void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest)
447 {
448  if (buffer.IsEmpty())
449  return;
450 
451  static const wxString delim(_T("$%["));
452  if ( buffer.find_first_of(delim) == wxString::npos )
453  return;
454 
455  cbProject* project = target
456  ? target->GetParentProject()
459 
460  if (!target)
461  {
462  if (project)
463  {
464  // use the currently compiling target
465  target = project->GetCurrentlyCompilingTarget();
466  // if none,
467  if (!target)
468  // use the last known active target
469  target = project->GetBuildTarget(project->GetActiveBuildTarget());
470  }
471  }
472  if (project != m_LastProject || target != m_LastTarget || (editor && (editor->GetFilename() != m_ActiveEditorFilename))
473  || (project && (UnixFilename(project->GetBasePath()) != m_ProjectDir))
474  || (UnixFilename(m_ProjectWxFileName.GetFullName()) != m_ProjectFilename)
475  || (target && (target->GetTitle() != m_TargetName)) )
476  RecalcVars(project, editor, target);
477 
478  wxString search;
479  wxString replace;
480 
481  if (buffer.find(_T("$if")) != wxString::npos)
482  {
483  while (m_RE_If.Matches(buffer))
484  {
485  search = m_RE_If.GetMatch(buffer, 0);
486  replace = EvalCondition(m_RE_If.GetMatch(buffer, 1), m_RE_If.GetMatch(buffer, 3), m_RE_If.GetMatch(buffer, 5), target);
487  buffer.Replace(search, replace, false);
488  }
489  }
490 
491  while (m_RE_Script.Matches(buffer))
492  {
493  search = m_RE_Script.GetMatch(buffer, 1);
494  replace = Manager::Get()->GetScriptingManager()->LoadBufferRedirectOutput(m_RE_Script.GetMatch(buffer, 2));
495  buffer.Replace(search, replace, false);
496  }
497 
498  while (m_RE_ToAbsolutePath.Matches(buffer))
499  {
500  search = m_RE_ToAbsolutePath.GetMatch(buffer, 0);
501  const wxString relativePath = m_RE_ToAbsolutePath.GetMatch(buffer, 1);
502  wxFileName fn(relativePath);
503  fn.MakeAbsolute();
504  replace = fn.GetFullPath();
505  buffer.Replace(search, replace, false);
506  }
507 
508  while (m_RE_To83Path.Matches(buffer))
509  {
510  search = m_RE_To83Path.GetMatch(buffer, 0);
511  const wxString path = m_RE_To83Path.GetMatch(buffer, 1);
512  wxFileName fn(path);
513  fn.MakeAbsolute(); // make absolute before translating to 8.3 notation
514  replace = fn.GetShortPath();
515  buffer.Replace(search, replace, false);
516  }
517 
518  int index = wxNOT_FOUND;
519  while ((index = buffer.Index(toNativePath.wx_str())) != wxNOT_FOUND)
520  {
521  int end = MatchBrace(buffer, index + toNativePath.Length() - 1);
522  wxString content = buffer.Mid(index + toNativePath.Length(), end - index - toNativePath.Length());
523  ReplaceMacros(content, target, true);
524  buffer.Replace(buffer.Mid(index, end - index + 1), UnixFilename(content), false);
525  }
526 
527  while ((index = buffer.Index(toUnixPath.wx_str())) != wxNOT_FOUND)
528  {
529  int end = MatchBrace(buffer, index + toUnixPath.Length() - 1);
530  wxString content = buffer.Mid(index + toUnixPath.Length(), end - index - toUnixPath.Length());
531  ReplaceMacros(content, target, true);
532  buffer.Replace(buffer.Mid(index, end - index + 1), UnixFilename(content, wxPATH_UNIX), false);
533  }
534 
535  while ((index = buffer.Index(toWindowsPath.wx_str())) != wxNOT_FOUND)
536  {
537  int end = MatchBrace(buffer, index + toWindowsPath.Length() - 1);
538  wxString content = buffer.Mid(index + toWindowsPath.Length(), end - index - toWindowsPath.Length());
539  ReplaceMacros(content, target, true);
540  buffer.Replace(buffer.Mid(index, end - index + 1), UnixFilename(content, wxPATH_WIN), false);
541  }
542 
543  while (m_RE_RemoveQuotes.Matches(buffer))
544  {
545  search = m_RE_RemoveQuotes.GetMatch(buffer, 0);
546  wxString content = m_RE_RemoveQuotes.GetMatch(buffer, 1).Trim().Trim(false);
547  if (content.StartsWith(wxT("$")))
548  ReplaceMacros(content, target, subrequest);
549  if (content.Len()>2 && content.StartsWith(wxT("\"")) && content.EndsWith(wxT("\"")))
550  {
551  replace = content.Mid(1,content.Len()-2); // with first and last char (the quotes) removed
552  buffer.Replace(search, replace, false);
553  }
554  else
555  buffer.Replace(search, content, false);
556  }
557 
558  while (m_RE_Unix.Matches(buffer))
559  {
560  replace.Empty();
561  search = m_RE_Unix.GetMatch(buffer, 2);
562 
563  wxString var = m_RE_Unix.GetMatch(buffer, 3).Upper();
564 
565  if (var.GetChar(0) == _T('#'))
566  replace = UnixFilename(m_UserVarMan->Replace(var));
567  else
568  {
569  if (var.compare(const_COIN) == 0)
570  replace.assign(1u, rand() & 1 ? _T('1') : _T('0'));
571  else if (var.compare(const_RANDOM) == 0)
572  replace = wxString::Format(_T("%d"), rand() & 0xffff);
573  else
574  {
575  MacrosMap::iterator it;
576  if ((it = m_Macros.find(var)) != m_Macros.end())
577  replace = it->second;
578  }
579  }
580 
581  const wxChar l = search.Last(); // make non-braced variables work
582  if (l == _T('/') || l == _T('\\') || l == _T('$') || l == _T(' '))
583  replace.append(l);
584 
585  if (replace.IsEmpty())
586  wxGetEnv(var, &replace);
587 
588  buffer.Replace(search, replace, false);
589  }
590 
591  while (m_RE_DOS.Matches(buffer))
592  {
593  replace.Empty();
594  search = m_RE_DOS.GetMatch(buffer, 2);
595 
596  wxString var = m_RE_DOS.GetMatch(buffer, 3).Upper();
597 
598  if (var.GetChar(0) == _T('#'))
599  replace = UnixFilename(m_UserVarMan->Replace(var));
600  else
601  {
602  if (var.compare(const_COIN) == 0)
603  replace.assign(1u, rand() & 1 ? _T('1') : _T('0'));
604  else if (var.compare(const_RANDOM) == 0)
605  replace = wxString::Format(_T("%d"), rand() & 0xffff);
606  else
607  {
608  MacrosMap::iterator it;
609  if ((it = m_Macros.find(var)) != m_Macros.end())
610  replace = it->second;
611  }
612  }
613 
614  if (replace.IsEmpty())
615  wxGetEnv(var, &replace);
616 
617  buffer.Replace(search, replace, false);
618  }
619 
620  if (!subrequest)
621  {
622  buffer.Replace(_T("%%"), _T("%"));
623  buffer.Replace(_T("$$"), _T("$"));
624  }
625 }
626 
627 wxString MacrosManager::EvalCondition(const wxString& in_cond, const wxString& true_clause, const wxString& false_clause, ProjectBuildTarget* target)
628 {
629  enum condition_codes {EQ = 1, LT = 2, GT = 4, NE = 8};
630 
631  wxString cond(in_cond);
632  wxString result;
633 
634  ReplaceMacros(cond, target, true);
635 
636  if (!m_RE_IfSp.Matches(in_cond))
637  return false_clause;
638 
639 
640  wxString cmpToken(m_RE_IfSp.GetMatch(in_cond, 3).Strip(wxString::both));
641  wxString left(m_RE_IfSp.GetMatch(in_cond, 2).Strip(wxString::both));
642  wxString right(m_RE_IfSp.GetMatch(in_cond, 4).Strip(wxString::both));
643 
644 
645  int compare = left.Cmp(right);
646  if (compare == 0)
647  compare = EQ;
648  else if (compare < 0)
649  compare = LT | NE;
650  else if (compare > 0)
651  compare = GT | NE;
652 
653 
654  if (cmpToken.IsEmpty())
655  {
656  if (cond.IsEmpty() || cond.IsSameAs(_T("0")) || cond.IsSameAs(_T("false")))
657  return false_clause;
658  return true_clause;
659  }
660 
661  int condCode = 0;
662 
663  if (cmpToken.IsSameAs(_T("==")) || cmpToken.IsSameAs(_T("=")))
664  condCode = EQ;
665  if (cmpToken.IsSameAs(_T("<")))
666  condCode = LT;
667  if (cmpToken.IsSameAs(_T(">")))
668  condCode = GT;
669  if (cmpToken.IsSameAs(_T("<=")))
670  condCode = EQ | LT;
671  if (cmpToken.IsSameAs(_T(">=")))
672  condCode = EQ | GT;
673  if (cmpToken.IsSameAs(_T("!=")))
674  condCode = NE;
675 
676  return condCode & compare ? true_clause : false_clause;
677 }
678 
679 int MacrosManager::MatchBrace(const wxString& buffer, int index)
680 {
681  int depth = 0;
682  while (index < (int)buffer.Length())
683  {
684  if (buffer[index] == wxT('{'))
685  ++depth;
686  else if (buffer[index] == wxT('}'))
687  --depth;
688  if (depth == 0)
689  break;
690  ++index;
691  }
692  return index;
693 }
static wxString GetLanguageName(int lang)
~MacrosManager() override
bool wxGetEnv(const wxString &var, wxString *value)
int WordEndPosition(int pos, bool onlyWordCharacters)
Get position of end of word.
int MatchBrace(const wxString &buffer, int index)
UserVariableManager * GetUserVariableManager() const
Definition: manager.cpp:464
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
virtual const wxString & GetExecutionParameters() const
Read the target&#39;s execution parameters.
int Cmp(const wxString &s) const
virtual FilesList & GetFilesList()
Provides an easy way to iterate all the files belonging in this target.
Definition: cbproject.h:685
wxString GetShortPath() const
int GetColumn(int pos) const
Retrieve the column number of a position, taking tab width into account.
static wxStandardPaths & Get()
static const wxString const_RANDOM(_T("RANDOM"))
virtual wxString GetFilename() const
Get the workspace file&#39;s name.
Definition: cbworkspace.h:60
static wxDateTime Now()
void CreateMenu(wxMenuBar *menuBar)
size_t Length() const
static Compiler * GetCompiler(size_t index)
wxString & append(const wxString &str, size_t pos, size_t n)
#define _T(string)
static const wxString toWindowsPath(_T("$TO_WINDOWS_PATH{"))
wxString EvalCondition(const wxString &cond, const wxString &true_clause, const wxString &false_clause, ProjectBuildTarget *target)
const wxString GT(_T(">"))
STL namespace.
wxString GetName() const
#define wxT(string)
#define wxNOT_FOUND
void SetPath(const wxString &path, wxPathFormat format=wxPATH_NATIVE)
Represents a file in a Code::Blocks project.
Definition: projectfile.h:39
ProjectBuildTarget * GetCurrentlyCompilingTarget()
Get a pointer to the currently compiling target.
Definition: cbproject.h:478
size_t find(const wxString &str, size_t nStart=0) const
virtual wxString GetOutputFilename()
Read the target&#39;s output filename.
virtual cbProject * GetParentProject()
int WordStartPosition(int pos, bool onlyWordCharacters)
Get position of start of word.
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
static const wxString toUnixPath(_T("$TO_UNIX_PATH{"))
wxUSE_UNICODE_dependent wxChar
wxString GetSelectedText()
Retrieve the selected text.
const wxString & GetMakefile()
Definition: cbproject.cpp:988
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
wxDateTime Subtract(const wxTimeSpan &diff) const
virtual const wxString & GetFilename() const
Get the editor&#39;s filename (if applicable).
Definition: editorbase.h:45
DLLIMPORT wxString UnixFilename(const wxString &filename, wxPathFormat format=wxPATH_NATIVE)
Definition: globals.cpp:228
wxString GetExt() const
static int GetSystemLanguage()
Represents a Code::Blocks project.
Definition: cbproject.h:96
const wxString & GetActiveBuildTarget() const
Definition: cbproject.cpp:1373
virtual const wxString & GetFilename() const
int GetCurrentLine()
Manually declared methods.
EditorBase * GetActiveEditor()
void RecalcVars(cbProject *project, EditorBase *editor, ProjectBuildTarget *target)
size_t find_first_of(const char *sz, size_t nStart=0) const
void ClearProjectKeys()
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
void Empty()
virtual const wxString & GetTitle() const
Read the target&#39;s title.
static wxString GetSystemEncodingName()
static const wxString const_COIN(_T("COIN"))
size_t Replace(const wxString &strOld, const wxString &strNew, bool replaceAll=true)
wxString LoadBufferRedirectOutput(const wxString &buffer)
Loads a string buffer and captures its output.
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
A workspace class.
Definition: cbworkspace.h:26
bool IsSameAs(const wxString &s, bool caseSensitive=true) const
wxString GetPathWithSep(wxPathFormat format=wxPATH_NATIVE) const
Base class that all "editors" should inherit from.
Definition: editorbase.h:30
int GetCurrentPos() const
Returns the position of the caret.
cbProject * GetActiveProject()
Retrieve the active project.
virtual wxString GetBasePath() const
Read the target&#39;s base path, e.g. if GetFilename() returns "/usr/local/bin/xxx", base path will retur...
const wxString LT(_T("<"))
const wxStringCharType * wx_str() const
wxString GetTextRange(int startPos, int endPos)
Retrieve a range of text.
virtual bool IsBuiltinEditor() const
Is this a built-in editor?
Definition: editorbase.cpp:209
wxString wxEmptyString
wxString & assign(const wxString &str, size_t pos, size_t n)
Definition: manager.h:183
int compare(const wxString &str) const
DLLIMPORT void QuoteStringIfNeeded(wxString &str)
Definition: globals.cpp:260
wxString & Trim(bool fromRight=true)
void ReplaceMacros(wxString &buffer, ProjectBuildTarget *target=nullptr, bool subrequest=false)
int GetBuildTargetsCount()
Definition: cbproject.h:200
static wxString GetDataFolder(bool global=true)
ProjectBuildTarget * GetBuildTarget(int index)
Access a build target.
Definition: cbproject.cpp:1392
cbWorkspace * GetWorkspace()
Get the current workspace filename.
Abstract base class for compilers.
Definition: compiler.h:274
wxString & erase(size_type pos=0, size_type n=npos)
A file editor.
Definition: cbeditor.h:43
bool IsEmpty() const
size_type size() const
void Clear()
wxString GetPath(int flags=wxPATH_GET_VOLUME, wxPathFormat format=wxPATH_NATIVE) const
virtual const wxString & GetCompilerID() const
Read the target&#39;s compiler.
wxString Upper() const
static const size_t npos
size_t Len() const
static wxString GetExecutableFolder()
bool EndsWith(const wxString &suffix, wxString *rest=NULL) const
wxString GetCommonTopLevelPath() const
Definition: cbproject.cpp:423
static wxString GetPluginsFolder(bool global=true)
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
static const wxString toNativePath(_T("$TO_NATIVE_PATH{"))
Represents a Code::Blocks project build target.
wxUniChar GetChar(size_t n) const
wxUniChar Last() const
void ReleaseMenu(wxMenuBar *menuBar)
ScriptingManager * GetScriptingManager() const
Definition: manager.cpp:469
bool MakeAbsolute(const wxString &cwd=wxEmptyString, wxPathFormat format=wxPATH_NATIVE)
int Printf(const wxString &pszFormat,...)
virtual wxString GetObjectOutput() const
Read the target&#39;s objects output dir.
wxString Format(const wxString &format=wxDefaultDateTimeFormat, const TimeZone &tz=Local) const
wxString GetFullPath(wxPathFormat format=wxPATH_NATIVE) const
virtual wxString GetTitle() const
Get the workspace&#39;s title.
Definition: cbworkspace.h:69
int GetDays() const
static wxString Format(const wxString &format,...)
wxString Mid(size_t first, size_t nCount=wxString::npos) const
wxString GetSelectedText()