cmListCommand.cxx 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmListCommand.h"
  14. #include <cmsys/RegularExpression.hxx>
  15. #include <cmsys/SystemTools.hxx>
  16. #include <stdlib.h> // required for atoi
  17. #include <ctype.h>
  18. //----------------------------------------------------------------------------
  19. bool cmListCommand::InitialPass(std::vector<std::string> const& args)
  20. {
  21. if(args.size() < 1)
  22. {
  23. this->SetError("must be called with at least one argument.");
  24. return false;
  25. }
  26. const std::string &subCommand = args[0];
  27. if(subCommand == "LENGTH")
  28. {
  29. return this->HandleLengthCommand(args);
  30. }
  31. if(subCommand == "GET")
  32. {
  33. return this->HandleGetCommand(args);
  34. }
  35. if(subCommand == "APPEND")
  36. {
  37. return this->HandleAppendCommand(args);
  38. }
  39. if(subCommand == "INSERT")
  40. {
  41. return this->HandleInsertCommand(args);
  42. }
  43. if(subCommand == "REMOVE_AT")
  44. {
  45. return this->HandleRemoveAtCommand(args);
  46. }
  47. if(subCommand == "REMOVE_ITEM")
  48. {
  49. return this->HandleRemoveItemCommand(args);
  50. }
  51. std::string e = "does not recognize sub-command "+subCommand;
  52. this->SetError(e.c_str());
  53. return false;
  54. }
  55. //----------------------------------------------------------------------------
  56. bool cmListCommand::GetListString(std::string& listString, const char* var)
  57. {
  58. if ( !var )
  59. {
  60. return false;
  61. }
  62. // get the old value
  63. const char* cacheValue
  64. = this->Makefile->GetDefinition(var);
  65. if(!cacheValue)
  66. {
  67. return false;
  68. }
  69. listString = cacheValue;
  70. return true;
  71. }
  72. //----------------------------------------------------------------------------
  73. bool cmListCommand::GetList(std::vector<std::string>& list, const char* var)
  74. {
  75. std::string listString;
  76. if ( !this->GetListString(listString, var) )
  77. {
  78. return false;
  79. }
  80. // expand the variable
  81. cmSystemTools::ExpandListArgument(listString, list);
  82. return true;
  83. }
  84. //----------------------------------------------------------------------------
  85. bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args)
  86. {
  87. if(args.size() != 3)
  88. {
  89. this->SetError("sub-command LENGTH requires two arguments.");
  90. return false;
  91. }
  92. const std::string& listName = args[1];
  93. const std::string& variableName = args[args.size() - 1];
  94. std::vector<std::string> varArgsExpanded;
  95. // do not check the return value here
  96. // if the list var is not found varArgsExpanded will have size 0
  97. // and we will return 0
  98. this->GetList(varArgsExpanded, listName.c_str());
  99. size_t length = varArgsExpanded.size();
  100. char buffer[1024];
  101. sprintf(buffer, "%d", static_cast<int>(length));
  102. this->Makefile->AddDefinition(variableName.c_str(), buffer);
  103. return true;
  104. }
  105. //----------------------------------------------------------------------------
  106. bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
  107. {
  108. if(args.size() < 4)
  109. {
  110. this->SetError("sub-command GET requires at least three arguments.");
  111. return false;
  112. }
  113. const std::string& listName = args[1];
  114. const std::string& variableName = args[args.size() - 1];
  115. // expand the variable
  116. std::vector<std::string> varArgsExpanded;
  117. if ( !this->GetList(varArgsExpanded, listName.c_str()) )
  118. {
  119. this->Makefile->AddDefinition(variableName.c_str(), "NOTFOUND");
  120. return true;
  121. }
  122. std::string value;
  123. size_t cc;
  124. for ( cc = 2; cc < args.size()-1; cc ++ )
  125. {
  126. int item = atoi(args[cc].c_str());
  127. if (value.size())
  128. {
  129. value += ";";
  130. }
  131. size_t nitem = varArgsExpanded.size();
  132. if ( item < 0 )
  133. {
  134. item = (int)nitem + item;
  135. }
  136. if ( item < 0 || nitem <= (size_t)item )
  137. {
  138. cmOStringStream str;
  139. str << "index: " << item << " out of range (-"
  140. << varArgsExpanded.size() << ", "
  141. << varArgsExpanded.size()-1 << ")";
  142. this->SetError(str.str().c_str());
  143. return false;
  144. }
  145. value += varArgsExpanded[item];
  146. }
  147. this->Makefile->AddDefinition(variableName.c_str(), value.c_str());
  148. return true;
  149. }
  150. //----------------------------------------------------------------------------
  151. bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args)
  152. {
  153. if(args.size() < 3)
  154. {
  155. this->SetError("sub-command APPEND requires at least two arguments.");
  156. return false;
  157. }
  158. const std::string& listName = args[1];
  159. // expand the variable
  160. std::string listString;
  161. this->GetListString(listString, listName.c_str());
  162. size_t cc;
  163. for ( cc = 2; cc < args.size(); ++ cc )
  164. {
  165. if ( listString.size() )
  166. {
  167. listString += ";";
  168. }
  169. listString += args[cc];
  170. }
  171. this->Makefile->AddDefinition(listName.c_str(), listString.c_str());
  172. return true;
  173. }
  174. //----------------------------------------------------------------------------
  175. bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
  176. {
  177. if(args.size() < 4)
  178. {
  179. this->SetError("sub-command INSERT requires at least three arguments.");
  180. return false;
  181. }
  182. const std::string& listName = args[1];
  183. // expand the variable
  184. int item = atoi(args[2].c_str());
  185. std::vector<std::string> varArgsExpanded;
  186. if ( !this->GetList(varArgsExpanded, listName.c_str()) && item != 0)
  187. {
  188. cmOStringStream str;
  189. str << "index: " << item << " out of range (0, 0)";
  190. this->SetError(str.str().c_str());
  191. return false;
  192. }
  193. if ( varArgsExpanded.size() != 0 )
  194. {
  195. size_t nitem = varArgsExpanded.size();
  196. if ( item < 0 )
  197. {
  198. item = (int)nitem + item;
  199. }
  200. if ( item < 0 || nitem <= (size_t)item )
  201. {
  202. cmOStringStream str;
  203. str << "index: " << item << " out of range (-"
  204. << varArgsExpanded.size() << ", "
  205. << (varArgsExpanded.size() == 0?0:(varArgsExpanded.size()-1)) << ")";
  206. this->SetError(str.str().c_str());
  207. return false;
  208. }
  209. }
  210. size_t cc;
  211. size_t cnt = 0;
  212. for ( cc = 3; cc < args.size(); ++ cc )
  213. {
  214. varArgsExpanded.insert(varArgsExpanded.begin()+item+cnt, args[cc]);
  215. cnt ++;
  216. }
  217. std::string value;
  218. for ( cc = 0; cc < varArgsExpanded.size(); cc ++ )
  219. {
  220. if (value.size())
  221. {
  222. value += ";";
  223. }
  224. value += varArgsExpanded[cc];
  225. }
  226. this->Makefile->AddDefinition(listName.c_str(), value.c_str());
  227. return true;
  228. }
  229. //----------------------------------------------------------------------------
  230. bool cmListCommand
  231. ::HandleRemoveItemCommand(std::vector<std::string> const& args)
  232. {
  233. if(args.size() < 3)
  234. {
  235. this->SetError("sub-command REMOVE requires at least two arguments.");
  236. return false;
  237. }
  238. const std::string& listName = args[1];
  239. // expand the variable
  240. std::vector<std::string> varArgsExpanded;
  241. if ( !this->GetList(varArgsExpanded, listName.c_str()) )
  242. {
  243. return false;
  244. }
  245. size_t cc;
  246. for ( cc = 2; cc < args.size(); ++ cc )
  247. {
  248. size_t kk = 0;
  249. while ( kk < varArgsExpanded.size() )
  250. {
  251. if ( varArgsExpanded[kk] == args[cc] )
  252. {
  253. varArgsExpanded.erase(varArgsExpanded.begin()+kk);
  254. }
  255. kk ++;
  256. }
  257. }
  258. std::string value;
  259. for ( cc = 0; cc < varArgsExpanded.size(); cc ++ )
  260. {
  261. if (value.size())
  262. {
  263. value += ";";
  264. }
  265. value += varArgsExpanded[cc];
  266. }
  267. this->Makefile->AddDefinition(listName.c_str(), value.c_str());
  268. return true;
  269. }
  270. //----------------------------------------------------------------------------
  271. bool cmListCommand::HandleRemoveAtCommand(
  272. std::vector<std::string> const& args)
  273. {
  274. if(args.size() < 3)
  275. {
  276. this->SetError("sub-command REMOVE_ITEM requires at least "
  277. "two arguments.");
  278. return false;
  279. }
  280. const std::string& listName = args[1];
  281. // expand the variable
  282. std::vector<std::string> varArgsExpanded;
  283. if ( !this->GetList(varArgsExpanded, listName.c_str()) )
  284. {
  285. return false;
  286. }
  287. size_t cc;
  288. std::vector<size_t> removed;
  289. for ( cc = 2; cc < args.size(); ++ cc )
  290. {
  291. int item = atoi(args[cc].c_str());
  292. size_t nitem = varArgsExpanded.size();
  293. if ( item < 0 )
  294. {
  295. item = (int)nitem + item;
  296. }
  297. if ( item < 0 || nitem <= (size_t)item )
  298. {
  299. cmOStringStream str;
  300. str << "index: " << item << " out of range (-"
  301. << varArgsExpanded.size() << ", "
  302. << varArgsExpanded.size()-1 << ")";
  303. this->SetError(str.str().c_str());
  304. return false;
  305. }
  306. removed.push_back(static_cast<size_t>(item));
  307. }
  308. std::string value;
  309. for ( cc = 0; cc < varArgsExpanded.size(); ++ cc )
  310. {
  311. size_t kk;
  312. bool found = false;
  313. for ( kk = 0; kk < removed.size(); ++ kk )
  314. {
  315. if ( cc == removed[kk] )
  316. {
  317. found = true;
  318. }
  319. }
  320. if ( !found )
  321. {
  322. if (value.size())
  323. {
  324. value += ";";
  325. }
  326. value += varArgsExpanded[cc];
  327. }
  328. }
  329. this->Makefile->AddDefinition(listName.c_str(), value.c_str());
  330. return true;
  331. }