NCBI C++ ToolKit
resolver.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: resolver.cpp 89181 2020-03-04 19:52:40Z gouriano $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Viatcheslav Gorelenkov
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
31 #include "resolver.hpp"
32 #include "msvc_prj_utils.hpp"
33 #include "proj_builder_app.hpp"
34 #include <corelib/ncbistr.hpp>
35 #include "ptb_err_codes.hpp"
36 
37 
39 
40 //-----------------------------------------------------------------------------
42 {
43  Clear();
44 }
45 
46 
48 {
49  SetFrom(resolver);
50 }
51 
52 
53 CSymResolver::CSymResolver(const string& file_path)
54 {
55  LoadFrom(file_path, this);
56 }
57 
58 
60 {
61  if (this != &resolver) {
62  Clear();
63  SetFrom(resolver);
64  }
65  return *this;
66 }
67 
68 
70 {
71  Clear();
72 }
73 
74 
75 string CSymResolver::StripDefine(const string& define)
76 {
77  return string(define, 2, define.length() - 3);
78 }
79 
80 
81 void CSymResolver::Resolve(const string& define, list<string>* resolved_def)
82 {
83  resolved_def->clear();
84  string data(define);
85  bool modified = true;
86  while (HasDefine(data) && modified) {
87  modified = false;
88  string::size_type start, prev, end;
89  for (start=0, prev=start-1; ; prev=start) {
90  start = data.find("$(", prev+1);
91  if (start == string::npos) {
92  start = prev;
93  break;
94  }
95  }
96  end = data.find(")", start);
97  if (end == string::npos) {
98  PTB_WARNING_EX(kEmptyStr, ePTB_MacroInvalid, "Possibly incorrect MACRO definition in: " + define);
99  resolved_def->push_back(define);
100  return;
101  }
102  string raw_define = data.substr(start,end-start+1);
103  CExpansionRule exprule;
104  string val_define = FilterDefine(raw_define, exprule, m_Data);
105  string str_define = StripDefine( val_define );
106 
108  m_Cache.find(str_define);
109 
110  if (m != m_Cache.end()) {
111  *resolved_def = m->second;
112  } else {
114  m_Data.m_Contents.find(str_define);
115  if (p != m_Data.m_Contents.end()) {
116  ITERATE(list<string>, n, p->second) {
117  list<string> new_resolved_def;
118  Resolve(*n, &new_resolved_def);
119  copy(new_resolved_def.begin(),
120  new_resolved_def.end(),
121  back_inserter(*resolved_def));
122  }
123  } else {
124  string tmp = GetApp().GetConfigureMacro(str_define);
125  if (!tmp.empty()) {
126  resolved_def->push_back(tmp);
127  }
128  }
129  m_Cache[str_define] = *resolved_def;
130  }
131  if ( !resolved_def->empty() ) {
132  exprule.ApplyRule(*resolved_def);
133  }
134  if ( resolved_def->size() == 1) {
135  modified = true;
136  NStr::ReplaceInPlace(data, raw_define,
137  raw_define != resolved_def->front() ? resolved_def->front() : kEmptyStr);
138  resolved_def->clear();
139  }
140  }
141  if (resolved_def->empty() && !data.empty()) {
142  resolved_def->push_back(data);
143  }
144 }
145 
146 void CSymResolver::Resolve(const string& define, list<string>* resolved_def,
147  const CSimpleMakeFileContents& mdata)
148 {
149  resolved_def->clear();
150  string data(define);
151  bool modified = true;
152  while (HasDefine(data) && modified) {
153  modified = false;
154  string::size_type start, prev, end;
155  for (start=0, prev=start-1; ; prev=start) {
156  start = data.find("$(", prev+1);
157  if (start == string::npos) {
158  start = prev;
159  break;
160  }
161  }
162  end = data.find(")", start);
163  if (end == string::npos) {
164  PTB_WARNING_EX(kEmptyStr, ePTB_MacroInvalid, "Possibly incorrect MACRO definition in: " + define);
165  resolved_def->push_back(define);
166  return;
167  }
168  string raw_define = data.substr(start,end-start+1);
169  CExpansionRule exprule;
170  string val_define = FilterDefine(raw_define, exprule, mdata);
171  string str_define = StripDefine( val_define );
172 
174  mdata.m_Contents.find(str_define);
175  if (p != mdata.m_Contents.end()) {
176  ITERATE(list<string>, n, p->second) {
177  list<string> new_resolved_def;
178  Resolve(*n, &new_resolved_def, mdata);
179  copy(new_resolved_def.begin(),
180  new_resolved_def.end(),
181  back_inserter(*resolved_def));
182  }
183  }
184  if ( resolved_def->empty() ) {
185  Resolve(raw_define, resolved_def);
186  } else {
187  exprule.ApplyRule(*resolved_def);
188  }
189  if ( resolved_def->size() == 1) {
190  modified = true;
191 #if 1
192  if (raw_define == resolved_def->front()) {
193  if (GetApp().GetSite().IsCppflagDescribed(raw_define)) {
194  modified = false;
195  } else {
196  NStr::ReplaceInPlace(data, raw_define, kEmptyStr);
197  }
198  } else {
199  NStr::ReplaceInPlace(data, raw_define, resolved_def->front());
200  }
201 #else
202  NStr::ReplaceInPlace(data, raw_define,
203  raw_define != resolved_def->front() ? resolved_def->front() : kEmptyStr);
204 #endif
205  resolved_def->clear();
206  }
207  }
208  if (resolved_def->empty() && !data.empty()) {
209  resolved_def->push_back(data);
210  }
211 }
212 
213 CSymResolver& CSymResolver::Append(const CSymResolver& src, bool warn_redef)
214 {
215  // Clear cache for resolved defines
216  m_Cache.clear();
217 
218  list<string> redefs;
220  if (m_Data.m_Contents.empty()) {
221  m_Trusted.insert(i->first);
222  } else {
223  if (m_Data.m_Contents.find(i->first) != m_Data.m_Contents.end() &&
224  m_Trusted.find(i->first) == m_Trusted.end() && warn_redef) {
225  redefs.push_back(i->first);
227  "Attempt to redefine already defined macro: " << i->first);
228  }
229  }
230  }
231  // Add contents of src
232  copy(src.m_Data.m_Contents.begin(),
233  src.m_Data.m_Contents.end(),
234  inserter(m_Data.m_Contents, m_Data.m_Contents.end()));
235 
236  ITERATE( list<string>, r, redefs) {
238  *r << "= " << NStr::Join(m_Data.m_Contents[*r]," "));
239  }
240  return *this;
241 }
242 
243 bool CSymResolver::StripSuffix(string& libname, string* suffix)
244 {
245  string suff[] = {"-dll", "-static", ""};
246  for (int i = 0; !suff[i].empty(); ++i) {
247  if (NStr::EndsWith(libname,suff[i])) {
248  if (suffix) {
249  *suffix = suff[i];
250  }
251  NStr::ReplaceInPlace(libname, suff[i], "");
252  return true;
253  }
254  }
255  return false;
256 }
257 
258 bool CSymResolver::IsDefine(const string& param)
259 {
260  return (
261  NStr::StartsWith(param, "$(") &&
262  NStr::EndsWith(param, ")") &&
263  NStr::FindNoCase(param, "$(", 2) == NPOS);
264 }
265 
266 bool CSymResolver::HasDefine(const string& param)
267 {
268  return (param.find("$(") != string::npos && param.find(")") != string::npos );
269 }
270 
271 string CSymResolver::TrimDefine(const string& define)
272 {
273  string::size_type start, end;
274  string trimmed( define);
275  while ((start = trimmed.find("$(")) != string::npos) {
276  end = trimmed.rfind(")");
277  if (end == string::npos) {
278  break;;
279  }
280  trimmed.erase(start,end);
281  }
282  return trimmed;
283 }
284 
285 
286 void CSymResolver::LoadFrom(const string& file_path,
287  CSymResolver * resolver)
288 {
289  resolver->Clear();
290  CSimpleMakeFileContents::LoadFrom(file_path, &resolver->m_Data);
291 }
292 
293 void CSymResolver::AddDefinition(const string& key, const string& value)
294 {
296 }
297 
298 bool CSymResolver::HasDefinition( const string& key) const
299 {
300  return m_Data.HasDefinition(key);
301 }
302 
303 bool CSymResolver::IsEmpty(void) const
304 {
305  return m_Data.m_Contents.empty();
306 }
307 
308 
310 {
312  m_Cache.clear();
313 }
314 
315 
316 void CSymResolver::SetFrom(const CSymResolver& resolver)
317 {
318  m_Data = resolver.m_Data;
319  m_Cache = resolver.m_Cache;
320 }
321 
322 
323 //-----------------------------------------------------------------------------
324 // Filter opt defines like $(SRC_C:.core_%) to $(SRC_C).
325 // or $(OBJMGR_LIBS:dbapi_driver=dbapi_driver-static) to $(OBJMGR_LIBS)
326 string FilterDefine(const string& define)
327 {
328 // if ( !CSymResolver::IsDefine(define) )
329 // return define;
330 
331  string res;
332  for(string::const_iterator p = define.begin(); p != define.end(); ++p) {
333  char ch = *p;
334  if ( !(ch == '$' ||
335  ch == '(' ||
336  ch == '_' ||
337  isalpha((unsigned char) ch) ||
338  isdigit((unsigned char) ch) ) )
339  break;
340  res += ch;
341  }
342  res += ')';
343  return res;
344 }
345 
346 string CSymResolver::FilterDefine(const string& define, CExpansionRule& rule,
348 {
349  rule.Reset();
350 // if (CMsvc7RegSettings::GetMsvcPlatform() == CMsvc7RegSettings::eUnix) {
351 {
352  if ( !CSymResolver::IsDefine(define) )
353  return define;
354  string::size_type start = define.find(':');
355  string::size_type end = define.rfind(')');
356  if (start != string::npos && end != string::npos && end > start) {
357  string textrule = define.substr(start+1, end-start-1);
358  rule.Init(textrule, this, &data);
359  string toreplace(":");
360  toreplace += textrule;
361  return NStr::Replace(define, toreplace, "");
362  }
363  }
364  return ncbi::FilterDefine(define);
365 }
366 
368 {
369  Reset();
370 }
371 CExpansionRule::CExpansionRule(const string& textrule)
372 {
373  Init(textrule);
374 }
376 {
377  m_Rule = other.m_Rule;
378  m_Lvalue = other.m_Lvalue;
379  m_Rvalue = other.m_Rvalue;
380 }
382 {
383  if (this != &other) {
384  m_Rule = other.m_Rule;
385  m_Lvalue = other.m_Lvalue;
386  m_Rvalue = other.m_Rvalue;
387  }
388  return *this;
389 }
391 {
392  m_Rule = eNoop;
393 }
394 void CExpansionRule::Init(const string& textrule,
395  CSymResolver* /*resolver*/, const CSimpleMakeFileContents* data)
396 {
397  Reset();
398  if (NStr::SplitInTwo(textrule, "=", m_Lvalue, m_Rvalue)) {
399  m_Rule = eReplace;
402  if (m_Lvalue.empty() || m_Lvalue == "%") {
403  m_Rule = ePattern;
404  m_Lvalue.clear();
405  } else if (NStr::FindCase(m_Lvalue, "%") != NPOS) {
406  m_Rule = ePattern;
407  }
408  if (m_Rule == ePattern && NStr::FindCase(m_Rvalue, "%") == NPOS) {
409  m_Rvalue = "%" + m_Rvalue;
410  }
411  }
412 }
413 
414 string CExpansionRule::ApplyRule( const string& value) const
415 {
416  if (m_Rule == eNoop) {
417  return value;
418  } else if (value[0] == '$') {
419  return value;
420  } else if (value[0] == '@' && NStr::StartsWith(m_Rvalue, "-D")) {
421  return kEmptyStr;
422  } else if (m_Rule == eReplace && !m_Lvalue.empty()) {
423  if (NStr::EndsWith(value, m_Lvalue)) {
426  }
427  return value;
428  }
429 // else if (m_Rule == ePattern) {
430  string tmp(value);
431  if (!m_Lvalue.empty()) {
432  string begins, ends;
433  if (NStr::SplitInTwo(m_Lvalue, "%", begins, ends)) {
434  if (!begins.empty() && !NStr::StartsWith( value, begins)) {
435  return value;
436  }
437  if (!ends.empty() && !NStr::EndsWith( value, ends)) {
438  return value;
439  }
440  if (!begins.empty()) {
441  NStr::ReplaceInPlace(tmp, begins, "");
442  }
443  if (!ends.empty()) {
444  NStr::ReplaceInPlace(tmp, ends, "");
445  }
446  }
447  }
448  return NStr::Replace( m_Rvalue, "%", tmp);
449 }
450 
451 void CExpansionRule::ApplyRule( list<string>& value) const
452 {
453  if (m_Rule != eNoop) {
454  for (list<string>::iterator i = value.begin(); i != value.end(); ++i) {
455  *i = ApplyRule(*i);;
456  }
457  }
458 }
459 
460 
string m_Rvalue
Definition: resolver.hpp:72
EExpRule m_Rule
Definition: resolver.hpp:70
CExpansionRule & operator=(const CExpansionRule &other)
Definition: resolver.cpp:381
CExpansionRule(void)
Definition: resolver.cpp:367
string ApplyRule(const string &value) const
Definition: resolver.cpp:414
void Init(const string &textrule, CSymResolver *resolver=NULL, const CSimpleMakeFileContents *data=NULL)
Definition: resolver.cpp:394
string m_Lvalue
Definition: resolver.hpp:71
string GetConfigureMacro(string data)
CSimpleMakeFileContents –.
static void LoadFrom(const string &file_path, CSimpleMakeFileContents *fc)
bool HasDefinition(const string &key) const
const string & GetFileName(void) const
void AddDefinition(const string &key, const string &value)
bool IsEmpty(void) const
Definition: resolver.cpp:303
static string TrimDefine(const string &define)
Definition: resolver.cpp:271
void Resolve(const string &define, list< string > *resolved_def)
Definition: resolver.cpp:81
void AddDefinition(const string &key, const string &value)
Definition: resolver.cpp:293
CSymResolver & Append(const CSymResolver &src, bool warn_redef=false)
Definition: resolver.cpp:213
void Clear(void)
Definition: resolver.cpp:309
~CSymResolver(void)
Definition: resolver.cpp:69
void SetFrom(const CSymResolver &resolver)
Definition: resolver.cpp:316
CSymResolver(void)
Definition: resolver.cpp:41
static string StripDefine(const string &define)
Definition: resolver.cpp:75
static void LoadFrom(const string &file_path, CSymResolver *resolver)
Definition: resolver.cpp:286
CSimpleMakeFileContents m_Data
Definition: resolver.hpp:112
static bool HasDefine(const string &param)
Definition: resolver.cpp:266
CSimpleMakeFileContents::TContents m_Cache
Definition: resolver.hpp:114
static bool StripSuffix(string &libname, string *suffix=nullptr)
Definition: resolver.cpp:243
string FilterDefine(const string &define, CExpansionRule &rule, const CSimpleMakeFileContents &data)
Definition: resolver.cpp:346
static bool IsDefine(const string &param)
Definition: resolver.cpp:258
bool HasDefinition(const string &key) const
Definition: resolver.cpp:298
CSymResolver & operator=(const CSymResolver &resolver)
Definition: resolver.cpp:59
set< string > m_Trusted
Definition: resolver.hpp:115
const_iterator begin() const
Definition: map.hpp:151
const_iterator end() const
Definition: map.hpp:152
bool empty() const
Definition: map.hpp:149
void clear()
Definition: map.hpp:169
const_iterator find(const key_type &key) const
Definition: map.hpp:153
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
const_iterator find(const key_type &key) const
Definition: set.hpp:137
const_iterator end() const
Definition: set.hpp:136
The NCBI C++ standard methods for dealing with std::string.
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
static char tmp[3200]
Definition: utf8.c:42
char data[12]
Definition: iconv.c:80
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
string
Definition: cgiapp.hpp:690
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define kEmptyStr
Definition: ncbistr.hpp:123
static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case insensitive search.
Definition: ncbistr.cpp:2984
static bool EndsWith(const CTempString str, const CTempString end, ECase use_case=eCase)
Check if a string ends with a specified suffix value.
Definition: ncbistr.hpp:5424
#define NPOS
Definition: ncbistr.hpp:133
static SIZE_TYPE Find(const CTempString str, const CTempString pattern, ECase use_case=eCase, EDirection direction=eForwardSearch, SIZE_TYPE occurrence=0)
Find the pattern in the string.
Definition: ncbistr.cpp:2882
static string Join(const TContainer &arr, const CTempString &delim)
Join strings using the specified delimiter.
Definition: ncbistr.hpp:2699
static string & Replace(const string &src, const string &search, const string &replace, string &dst, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3305
static SIZE_TYPE FindCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case sensitive search.
Definition: ncbistr.hpp:5484
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5406
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
Definition: ncbistr.cpp:3545
static string & ReplaceInPlace(string &src, const string &search, const string &replace, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3396
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate whitespace in a string.
Definition: ncbistr.cpp:3177
@ eReverseSearch
Search in a backward direction.
Definition: ncbistr.hpp:1947
@ eCase
Case sensitive compare.
Definition: ncbistr.hpp:1205
int i
yy_size_t n
const struct ncbi::grid::netcache::search::fields::KEY key
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
int isalpha(Uchar c)
Definition: ncbictype.hpp:61
int isdigit(Uchar c)
Definition: ncbictype.hpp:64
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
Definition: njn_matrix.hpp:613
CProjBulderApp & GetApp(void)
access to App singleton
@ ePTB_MacroInvalid
@ ePTB_ConfigurationError
#define PTB_WARNING_EX(file, err_code, msg)
string FilterDefine(const string &define)
Definition: resolver.cpp:326
Modified on Fri Sep 20 14:57:53 2024 by modify_doxy.py rev. 669887