cmCreateTestSourceList.cxx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Insight Consortium. All rights reserved.
  8. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 "cmCreateTestSourceList.h"
  14. // cmCreateTestSourceList
  15. bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& argsIn)
  16. {
  17. if (argsIn.size() < 3)
  18. {
  19. this->SetError("called with wrong number of arguments.");
  20. return false;
  21. }
  22. std::vector<std::string> args;
  23. cmSystemTools::ExpandListArguments(argsIn, args);
  24. std::vector<std::string>::iterator i = args.begin();
  25. std::string extraInclude;
  26. std::string function;
  27. std::vector<std::string> tests;
  28. // extract extra include and function ot
  29. for(; i != args.end(); i++)
  30. {
  31. if(*i == "EXTRA_INCLUDE")
  32. {
  33. ++i;
  34. if(i == args.end())
  35. {
  36. this->SetError("incorrect arguments to EXTRA_INCLUDE");
  37. return false;
  38. }
  39. extraInclude = *i;
  40. }
  41. else if(*i == "FUNCTION")
  42. {
  43. ++i;
  44. if(i == args.end())
  45. {
  46. this->SetError("incorrect arguments to FUNCTION");
  47. return false;
  48. }
  49. function = *i;
  50. }
  51. else
  52. {
  53. tests.push_back(*i);
  54. }
  55. }
  56. i = tests.begin();
  57. // Name of the source list
  58. const char* sourceList = i->c_str();
  59. ++i;
  60. // Name of the test driver
  61. // make sure they specified an extension
  62. if (cmSystemTools::GetFilenameExtension(*i).size() < 2)
  63. {
  64. this->SetError("You must specify a file extenion for the test driver file.");
  65. return false;
  66. }
  67. std::string driver = m_Makefile->GetCurrentOutputDirectory();
  68. driver += "/";
  69. driver += *i;
  70. ++i;
  71. std::ofstream fout(driver.c_str());
  72. if (!fout)
  73. {
  74. std::string err = "Could not create file ";
  75. err += driver;
  76. err += " for cmCreateTestSourceList command.";
  77. this->SetError(err.c_str());
  78. return false;
  79. }
  80. // Create the test driver file
  81. fout <<
  82. "#include <ctype.h>\n"
  83. "#include <stdio.h>\n"
  84. "#include <string.h>\n"
  85. "#include <stdlib.h>\n";
  86. if(extraInclude.size())
  87. {
  88. fout << "#include \"" << extraInclude << "\"\n";
  89. }
  90. fout <<
  91. "\n"
  92. "// Forward declare test functions\n"
  93. "\n";
  94. std::vector<std::string>::iterator testsBegin = i;
  95. std::vector<std::string> tests_func_name;
  96. // The rest of the arguments consist of a list of test source files.
  97. // Sadly, they can be in directories. Let's find a unique function
  98. // name for the corresponding test, and push it to the tests_func_name
  99. // list.
  100. // For the moment:
  101. // - replace spaces ' ', ':' and '/' with underscores '_'
  102. for(i = testsBegin; i != tests.end(); ++i)
  103. {
  104. if(*i == "EXTRA_INCLUDE")
  105. {
  106. break;
  107. }
  108. std::string func_name;
  109. if (cmSystemTools::GetFilenamePath(*i).size() > 0)
  110. {
  111. func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
  112. cmSystemTools::GetFilenameWithoutLastExtension(*i);
  113. }
  114. else
  115. {
  116. func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
  117. }
  118. cmSystemTools::ConvertToUnixSlashes(func_name);
  119. cmSystemTools::ReplaceString(func_name, " ", "_");
  120. cmSystemTools::ReplaceString(func_name, "/", "_");
  121. cmSystemTools::ReplaceString(func_name, ":", "_");
  122. tests_func_name.push_back(func_name);
  123. fout << "int " << func_name << "(int, char*[]);\n";
  124. }
  125. fout <<
  126. "\n"
  127. "// Create map\n"
  128. "\n"
  129. "typedef int (*MainFuncPointer)(int , char*[]);\n"
  130. "typedef struct\n"
  131. "{\n"
  132. " const char* name;\n"
  133. " MainFuncPointer func;\n"
  134. "} functionMapEntry;\n"
  135. "\n"
  136. "functionMapEntry cmakeGeneratedFunctionMapEntries[] = {\n";
  137. int numTests = 0;
  138. std::vector<std::string>::iterator j;
  139. for(i = testsBegin, j = tests_func_name.begin(); i != tests.end(); ++i, ++j)
  140. {
  141. std::string func_name;
  142. if (cmSystemTools::GetFilenamePath(*i).size() > 0)
  143. {
  144. func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
  145. cmSystemTools::GetFilenameWithoutLastExtension(*i);
  146. }
  147. else
  148. {
  149. func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
  150. }
  151. fout <<
  152. " {\n"
  153. " \"" << func_name << "\",\n"
  154. " " << *j << "\n"
  155. " },\n";
  156. numTests++;
  157. }
  158. fout <<
  159. "};\n"
  160. "\n"
  161. "// Allocate and create a lowercased copy of string\n"
  162. "// (note that it has to be free'd manually)\n"
  163. "\n"
  164. "char* lowercase(const char *string)\n"
  165. "{\n"
  166. " char *new_string, *p;\n"
  167. " new_string = (char *)malloc(sizeof(char) * (size_t)(strlen(string) + 1));\n"
  168. " if (!new_string)\n"
  169. " {\n"
  170. " return NULL;\n"
  171. " }\n"
  172. " strcpy(new_string, string);\n"
  173. " p = new_string;\n"
  174. " while (*p != 0)\n"
  175. " {\n"
  176. " *p = (char)tolower(*p);\n"
  177. " ++p;\n"
  178. " }\n"
  179. " return new_string;\n"
  180. "}\n"
  181. "\n"
  182. "int main(int ac, char *av[])\n"
  183. "{\n"
  184. " int i, NumTests, testNum, partial_match;\n"
  185. " char *arg, *test_name;\n"
  186. " \n"
  187. " NumTests = " << numTests << ";\n"
  188. " \n"
  189. " // If no test name was given\n";
  190. if(function.size())
  191. {
  192. fout << " // process command line with user function\n"
  193. << " " << function << "(&ac, &av);\n";
  194. }
  195. fout <<
  196. " if (ac < 2)\n"
  197. " {\n"
  198. " // Ask for a test\n"
  199. " printf(\"Available tests:\\n\");\n"
  200. " for (i =0; i < NumTests; ++i)\n"
  201. " {\n"
  202. " printf(\"%3d. %s\\n\", i, cmakeGeneratedFunctionMapEntries[i].name);\n"
  203. " }\n"
  204. " printf(\"To run a test, enter the test number: \");\n"
  205. " testNum = 0;\n"
  206. " scanf(\"%d\", &testNum);\n"
  207. " if (testNum >= NumTests)\n"
  208. " {\n"
  209. " printf(\"%3d is an invalid test number.\\n\", testNum);\n"
  210. " return -1;\n"
  211. " }\n"
  212. " return (*cmakeGeneratedFunctionMapEntries[testNum].func)(ac-1, av+1);\n"
  213. " }\n"
  214. " \n"
  215. " // If partial match is requested\n"
  216. " partial_match = (strcmp(av[1], \"-R\") == 0) ? 1 : 0;\n"
  217. " if (partial_match && ac < 3)\n"
  218. " {\n"
  219. " printf(\"-R needs an additional parameter.\\n\");\n"
  220. " return -1;\n"
  221. " }\n"
  222. " \n"
  223. " arg = lowercase(av[1 + partial_match]);\n"
  224. " for (i =0; i < NumTests; ++i)\n"
  225. " {\n"
  226. " test_name = lowercase(cmakeGeneratedFunctionMapEntries[i].name);\n"
  227. " if (partial_match && strstr(test_name, arg) != NULL)\n"
  228. " {\n"
  229. " free(arg);\n"
  230. " free(test_name);\n"
  231. " return (*cmakeGeneratedFunctionMapEntries[i].func)(ac - 2, av + 2);\n"
  232. " }\n"
  233. " else if (!partial_match && strcmp(test_name, arg) == 0)\n"
  234. " {\n"
  235. " free(arg);\n"
  236. " free(test_name);\n"
  237. " return (*cmakeGeneratedFunctionMapEntries[i].func)(ac - 1, av + 1);\n"
  238. " }\n"
  239. " free(test_name);\n"
  240. " }\n"
  241. " free(arg);\n"
  242. " \n"
  243. " // Nothing was run, display the test names\n"
  244. " printf(\"Available tests:\\n\");\n"
  245. " for (i =0; i < NumTests; ++i)\n"
  246. " {\n"
  247. " printf(\"%3d. %s\\n\", i, cmakeGeneratedFunctionMapEntries[i].name);\n"
  248. " }\n"
  249. " printf(\"Failed: %s is an invalid test name.\\n\", av[1]);\n"
  250. " \n"
  251. " return -1;\n"
  252. "}\n";
  253. fout.close();
  254. // Create the source list
  255. cmSourceFile cfile;
  256. std::string sourceListValue;
  257. cfile.SetIsAnAbstractClass(false);
  258. cfile.SetName(cmSystemTools::GetFilenameWithoutExtension(args[1]).c_str(),
  259. m_Makefile->GetCurrentOutputDirectory(),
  260. cmSystemTools::GetFilenameExtension(args[1]).c_str()+1,
  261. false);
  262. m_Makefile->AddSource(cfile);
  263. sourceListValue = args[1];
  264. for(i = testsBegin; i != tests.end(); ++i)
  265. {
  266. cmSourceFile cfile;
  267. cfile.SetIsAnAbstractClass(false);
  268. cfile.SetName(i->c_str(),
  269. m_Makefile->GetCurrentDirectory(),
  270. m_Makefile->GetSourceExtensions(),
  271. m_Makefile->GetHeaderExtensions());
  272. m_Makefile->AddSource(cfile);
  273. sourceListValue += ";";
  274. sourceListValue += *i;
  275. }
  276. m_Makefile->AddDefinition(sourceList, sourceListValue.c_str());
  277. return true;
  278. }