cmVTKWrapTclCommand.cxx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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 "cmVTKWrapTclCommand.h"
  14. // cmVTKWrapTclCommand
  15. bool cmVTKWrapTclCommand::InitialPass(std::vector<std::string> const& argsIn)
  16. {
  17. if(argsIn.size() < 3 )
  18. {
  19. this->SetError("called with incorrect number of arguments");
  20. return false;
  21. }
  22. std::vector<std::string> args;
  23. // keep the library name
  24. this->LibraryName = argsIn[0];
  25. if (argsIn[1] == std::string("SOURCES"))
  26. {
  27. this->Makefile->ExpandSourceListArguments(argsIn, args, 3);
  28. }
  29. else
  30. {
  31. this->Makefile->ExpandSourceListArguments(argsIn, args, 2);
  32. }
  33. // Now check and see if the value has been stored in the cache
  34. // already, if so use that value and don't look for the program
  35. if(!this->Makefile->IsOn("VTK_WRAP_TCL"))
  36. {
  37. return true;
  38. }
  39. // extract the sources and commands parameters
  40. std::vector<std::string> sources;
  41. bool doing_sources = true;
  42. for(std::vector<std::string>::const_iterator j = (args.begin() + 1);
  43. j != args.end(); ++j)
  44. {
  45. if(*j == "SOURCES")
  46. {
  47. doing_sources = true;
  48. }
  49. else if (*j == "COMMANDS")
  50. {
  51. doing_sources = false;
  52. }
  53. else
  54. {
  55. if(doing_sources)
  56. {
  57. sources.push_back(*j);
  58. }
  59. else
  60. {
  61. this->Commands.push_back(*j);
  62. }
  63. }
  64. }
  65. // get the list of classes for this library
  66. if (sources.size())
  67. {
  68. // what is the current source dir
  69. std::string cdir = this->Makefile->GetCurrentDirectory();
  70. // get the resulting source list name
  71. this->SourceList = sources[0];
  72. std::string sourceListValue;
  73. // was the list already populated
  74. const char *def =
  75. this->Makefile->GetDefinition(this->SourceList.c_str());
  76. if (def)
  77. {
  78. sourceListValue = def;
  79. sourceListValue += ";";
  80. }
  81. // Create the init file
  82. std::string res = this->LibraryName;
  83. res += "Init.cxx";
  84. sourceListValue += res;
  85. for(std::vector<std::string>::iterator j = (sources.begin() + 1);
  86. j != sources.end(); ++j)
  87. {
  88. cmSourceFile *curr = this->Makefile->GetSource(j->c_str());
  89. // if we should wrap the class
  90. if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE"))
  91. {
  92. cmSourceFile file;
  93. std::string srcDir = cdir;
  94. if (curr)
  95. {
  96. file.SetProperty("ABSTRACT",curr->GetProperty("ABSTRACT"));
  97. srcDir = cmSystemTools::GetFilenamePath(curr->GetFullPath());
  98. }
  99. std::string srcName = cmSystemTools::GetFilenameWithoutExtension(*j);
  100. std::string newName = srcName + "Tcl";
  101. std::string hname = srcDir + "/" + srcName + ".h";
  102. file.SetName(newName.c_str(),
  103. this->Makefile->GetCurrentOutputDirectory(),
  104. "cxx",false);
  105. this->WrapHeaders.push_back(hname);
  106. // add starting depends
  107. file.GetDepends().push_back(hname);
  108. this->WrapClasses.push_back(file);
  109. sourceListValue += ";";
  110. sourceListValue += newName + ".cxx";
  111. }
  112. }
  113. // add the init file
  114. cmSourceFile cfile;
  115. cfile.SetProperty("ABSTRACT","0");
  116. std::string newName = this->LibraryName;
  117. newName += "Init";
  118. this->CreateInitFile(res);
  119. cfile.SetName(newName.c_str(),
  120. this->Makefile->GetCurrentOutputDirectory(),
  121. "cxx",false);
  122. this->Makefile->AddSource(cfile);
  123. this->Makefile->AddDefinition(this->SourceList.c_str(),
  124. sourceListValue.c_str());
  125. }
  126. return true;
  127. }
  128. void cmVTKWrapTclCommand::FinalPass()
  129. {
  130. // first we add the rules for all the .h to Tcl.cxx files
  131. size_t lastClass = this->WrapClasses.size();
  132. std::vector<std::string> depends;
  133. const char* wtcl =
  134. this->Makefile->GetRequiredDefinition("VTK_WRAP_TCL_EXE");
  135. const char* hints = this->Makefile->GetDefinition("VTK_WRAP_HINTS");
  136. // wrap all the .h files
  137. depends.push_back(wtcl);
  138. if(hints)
  139. {
  140. depends.push_back(hints);
  141. }
  142. for(size_t classNum = 0; classNum < lastClass; classNum++)
  143. {
  144. this->Makefile->AddSource(this->WrapClasses[classNum]);
  145. cmCustomCommandLine commandLine;
  146. commandLine.push_back(wtcl);
  147. commandLine.push_back(this->WrapHeaders[classNum]);
  148. if(hints)
  149. {
  150. commandLine.push_back(hints);
  151. }
  152. commandLine.push_back((this->WrapClasses[classNum].
  153. GetPropertyAsBool("ABSTRACT") ? "0" : "1"));
  154. std::string res = this->Makefile->GetCurrentOutputDirectory();
  155. res += "/";
  156. res += this->WrapClasses[classNum].GetSourceName() + ".cxx";
  157. commandLine.push_back(res);
  158. cmCustomCommandLines commandLines;
  159. commandLines.push_back(commandLine);
  160. std::vector<std::string> outputs;
  161. outputs.push_back(res);
  162. const char* no_comment = 0;
  163. this->Makefile->AddCustomCommandOldStyle(this->LibraryName.c_str(),
  164. outputs,
  165. depends,
  166. this->WrapHeaders[classNum].c_str(),
  167. commandLines,
  168. no_comment);
  169. }
  170. }
  171. bool cmVTKWrapTclCommand::CreateInitFile(std::string& res)
  172. {
  173. /* we have to make sure that the name is the correct case */
  174. std::string kitName = cmSystemTools::Capitalized(this->LibraryName);
  175. std::vector<std::string> classes;
  176. size_t lastClass = this->WrapHeaders.size();
  177. size_t classNum;
  178. for(classNum = 0; classNum < lastClass; classNum++)
  179. {
  180. if (!this->WrapClasses[classNum].GetPropertyAsBool("ABSTRACT"))
  181. {
  182. std::string cls = this->WrapHeaders[classNum];
  183. cls = cls.substr(0,cls.size()-2);
  184. std::string::size_type pos = cls.rfind('/');
  185. if(pos != std::string::npos)
  186. {
  187. cls = cls.substr(pos+1);
  188. }
  189. classes.push_back(cls);
  190. }
  191. }
  192. // open the init file
  193. std::string outFileName =
  194. this->Makefile->GetCurrentOutputDirectory();
  195. outFileName += "/" + res;
  196. return this->WriteInit(kitName.c_str(), outFileName, classes);
  197. }
  198. /* warning this code is also in getclasses.cxx under pcmaker */
  199. bool cmVTKWrapTclCommand::WriteInit(const char *kitName,
  200. std::string& outFileName,
  201. std::vector<std::string>& classes)
  202. {
  203. unsigned int i;
  204. std::string tempOutputFile = outFileName + ".tmp";
  205. FILE *fout = fopen(tempOutputFile.c_str(),"w");
  206. if (!fout)
  207. {
  208. cmSystemTools::Error("Failed to open TclInit file for ",
  209. tempOutputFile.c_str());
  210. cmSystemTools::ReportLastSystemError("");
  211. return false;
  212. }
  213. // capitalized commands just once
  214. std::vector<std::string> capcommands;
  215. for (i = 0; i < this->Commands.size(); i++)
  216. {
  217. capcommands.push_back(cmSystemTools::Capitalized(this->Commands[i]));
  218. }
  219. fprintf(fout,"#include \"vtkTclUtil.h\"\n");
  220. fprintf(fout,"#include \"vtkVersion.h\"\n");
  221. fprintf(fout,"#define VTK_TCL_TO_STRING(x) VTK_TCL_TO_STRING0(x)\n");
  222. fprintf(fout,"#define VTK_TCL_TO_STRING0(x) #x\n");
  223. fprintf(fout,
  224. "extern \"C\"\n"
  225. "{\n"
  226. "#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4) "
  227. "&& (TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE)\n"
  228. " typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,"
  229. "int, CONST84 char *[]);\n"
  230. "#else\n"
  231. " typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,"
  232. "int, char *[]);\n"
  233. "#endif\n"
  234. "}\n"
  235. "\n");
  236. for (i = 0; i < classes.size(); i++)
  237. {
  238. fprintf(fout,"int %sCommand(ClientData cd, Tcl_Interp *interp,\n"
  239. ,classes[i].c_str());
  240. fprintf(fout," int argc, char *argv[]);\n");
  241. fprintf(fout,"ClientData %sNewCommand();\n",classes[i].c_str());
  242. }
  243. if (!strcmp(kitName,"Vtkcommontcl"))
  244. {
  245. fprintf(fout,"int vtkCommand(ClientData cd, Tcl_Interp *interp,\n"
  246. " int argc, char *argv[]);\n");
  247. fprintf(fout,"\nTcl_HashTable vtkInstanceLookup;\n");
  248. fprintf(fout,"Tcl_HashTable vtkPointerLookup;\n");
  249. fprintf(fout,"Tcl_HashTable vtkCommandLookup;\n");
  250. fprintf(fout,"int vtkCommandForward(ClientData cd, Tcl_Interp *interp,\n"
  251. " int argc, char *argv[]){\n"
  252. " return vtkCommand(cd, interp, argc, argv);\n"
  253. "}\n");
  254. }
  255. else
  256. {
  257. fprintf(fout,"\nextern Tcl_HashTable vtkInstanceLookup;\n");
  258. fprintf(fout,"extern Tcl_HashTable vtkPointerLookup;\n");
  259. fprintf(fout,"extern Tcl_HashTable vtkCommandLookup;\n");
  260. }
  261. fprintf(fout,"extern void vtkTclDeleteObjectFromHash(void *);\n");
  262. fprintf(fout,"extern void vtkTclListInstances(Tcl_Interp *interp,"
  263. "ClientData arg);\n");
  264. for (i = 0; i < this->Commands.size(); i++)
  265. {
  266. fprintf(fout,
  267. "\nextern \"C\" {int VTK_EXPORT %s_Init(Tcl_Interp *interp);}\n",
  268. capcommands[i].c_str());
  269. }
  270. fprintf(fout,"\n\nextern \"C\" {int VTK_EXPORT "
  271. "%s_SafeInit(Tcl_Interp *interp);}\n", kitName);
  272. fprintf(fout,"\nextern \"C\" {int VTK_EXPORT %s_Init"
  273. "(Tcl_Interp *interp);}\n", kitName);
  274. /* create an extern ref to the generic delete function */
  275. fprintf(fout,"\nextern void vtkTclGenericDeleteObject(ClientData cd);\n");
  276. if (!strcmp(kitName,"Vtkcommontcl"))
  277. {
  278. fprintf(fout,"extern \"C\"\n{\nvoid "
  279. "vtkCommonDeleteAssocData(ClientData cd)\n");
  280. fprintf(fout," {\n");
  281. fprintf(fout," vtkTclInterpStruct *tis = "
  282. "static_cast<vtkTclInterpStruct*>(cd);\n");
  283. fprintf(fout," delete tis;\n }\n}\n");
  284. }
  285. /* the main declaration */
  286. fprintf(fout,
  287. "\n\nint VTK_EXPORT %s_SafeInit(Tcl_Interp *interp)\n{\n",kitName);
  288. fprintf(fout," return %s_Init(interp);\n}\n",kitName);
  289. fprintf(fout,"\n\nint VTK_EXPORT %s_Init(Tcl_Interp *interp)\n{\n",
  290. kitName);
  291. if (!strcmp(kitName,"Vtkcommontcl"))
  292. {
  293. fprintf(fout,
  294. " vtkTclInterpStruct *info = new vtkTclInterpStruct;\n");
  295. fprintf(fout,
  296. " info->Number = 0; info->InDelete = 0; info->DebugOn = 0;\n");
  297. fprintf(fout,"\n");
  298. fprintf(fout,"\n");
  299. fprintf(fout,
  300. " Tcl_InitHashTable(&info->InstanceLookup, TCL_STRING_KEYS);\n");
  301. fprintf(fout,
  302. " Tcl_InitHashTable(&info->PointerLookup, TCL_STRING_KEYS);\n");
  303. fprintf(fout,
  304. " Tcl_InitHashTable(&info->CommandLookup, TCL_STRING_KEYS);\n");
  305. fprintf(fout, " Tcl_SetAssocData(interp,(char *) "
  306. "\"vtk\",NULL,(ClientData *)info);\n");
  307. fprintf(fout, " Tcl_CreateExitHandler(vtkCommonDeleteAssocData"
  308. ",(ClientData *)info);\n");
  309. /* create special vtkCommand command */
  310. fprintf(fout,
  311. " Tcl_CreateCommand(interp,(char *) \"vtkCommand\",\n"
  312. " reinterpret_cast<vtkTclCommandType>("
  313. "vtkCommandForward),\n"
  314. " (ClientData *)NULL, NULL);\n\n");
  315. }
  316. for (i = 0; i < this->Commands.size(); i++)
  317. {
  318. fprintf(fout," %s_Init(interp);\n", capcommands[i].c_str());
  319. }
  320. fprintf(fout,"\n");
  321. for (i = 0; i < classes.size(); i++)
  322. {
  323. fprintf(fout," vtkTclCreateNew(interp,(char *) \"%s\", %sNewCommand,\n",
  324. classes[i].c_str(), classes[i].c_str());
  325. fprintf(fout," %sCommand);\n",classes[i].c_str());
  326. }
  327. fprintf(fout," char pkgName[]=\"%s\";\n", this->LibraryName.c_str());
  328. fprintf(fout," char pkgVers[]=VTK_TCL_TO_STRING(VTK_MAJOR_VERSION)"
  329. " \".\" "
  330. "VTK_TCL_TO_STRING(VTK_MINOR_VERSION);\n");
  331. fprintf(fout," Tcl_PkgProvide(interp, pkgName, pkgVers);\n");
  332. fprintf(fout," return TCL_OK;\n}\n");
  333. fclose(fout);
  334. // copy the file if different
  335. cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(),
  336. outFileName.c_str());
  337. cmSystemTools::RemoveFile(tempOutputFile.c_str());
  338. return true;
  339. }