cmDependsJavaParserHelper.cxx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmDependsJavaParserHelper.h"
  4. #include "cmDependsJavaLexer.h"
  5. #include "cmSystemTools.h"
  6. #include "cm_string_view.hxx"
  7. #include "cmsys/FStream.hxx"
  8. #include <cstdio>
  9. #include <cstdlib>
  10. #include <cstring>
  11. #include <iostream>
  12. #include <utility>
  13. int cmDependsJava_yyparse(yyscan_t yyscanner);
  14. cmDependsJavaParserHelper::cmDependsJavaParserHelper()
  15. {
  16. this->CurrentDepth = 0;
  17. this->UnionsAvailable = 0;
  18. this->LastClassId = 0;
  19. CurrentClass tl;
  20. tl.Name = "*";
  21. this->ClassStack.push_back(std::move(tl));
  22. }
  23. cmDependsJavaParserHelper::~cmDependsJavaParserHelper()
  24. {
  25. this->CleanupParser();
  26. }
  27. void cmDependsJavaParserHelper::CurrentClass::AddFileNamesForPrinting(
  28. std::vector<std::string>* files, const char* prefix, const char* sep) const
  29. {
  30. std::string rname;
  31. if (prefix) {
  32. rname += prefix;
  33. rname += sep;
  34. }
  35. rname += this->Name;
  36. files->push_back(rname);
  37. for (CurrentClass const& nc : this->NestedClasses) {
  38. nc.AddFileNamesForPrinting(files, rname.c_str(), sep);
  39. }
  40. }
  41. void cmDependsJavaParserHelper::DeallocateParserType(char** pt)
  42. {
  43. if (!pt) {
  44. return;
  45. }
  46. if (!*pt) {
  47. return;
  48. }
  49. *pt = nullptr;
  50. this->UnionsAvailable--;
  51. }
  52. void cmDependsJavaParserHelper::AddClassFound(const char* sclass)
  53. {
  54. if (!sclass) {
  55. return;
  56. }
  57. for (std::string const& cf : this->ClassesFound) {
  58. if (cf == sclass) {
  59. return;
  60. }
  61. }
  62. this->ClassesFound.emplace_back(sclass);
  63. }
  64. void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass)
  65. {
  66. for (std::string const& pi : this->PackagesImport) {
  67. if (pi == sclass) {
  68. return;
  69. }
  70. }
  71. this->PackagesImport.emplace_back(sclass);
  72. }
  73. void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line,
  74. int cnt)
  75. {
  76. if (str) {
  77. std::cout << line << " String " << cnt << " exists: ";
  78. unsigned int cc;
  79. for (cc = 0; cc < strlen(str); cc++) {
  80. unsigned char ch = str[cc];
  81. if (ch >= 32 && ch <= 126) {
  82. std::cout << static_cast<char>(ch);
  83. } else {
  84. std::cout << "<" << static_cast<int>(ch) << ">";
  85. break;
  86. }
  87. }
  88. std::cout << "- " << strlen(str) << std::endl;
  89. }
  90. }
  91. void cmDependsJavaParserHelper::Print(const char* place, const char* str)
  92. {
  93. if (this->Verbose) {
  94. std::cout << "[" << place << "=" << str << "]" << std::endl;
  95. }
  96. }
  97. void cmDependsJavaParserHelper::CombineUnions(char** out, const char* in1,
  98. char** in2, const char* sep)
  99. {
  100. size_t len = 1;
  101. if (in1) {
  102. len += strlen(in1);
  103. }
  104. if (*in2) {
  105. len += strlen(*in2);
  106. }
  107. if (sep) {
  108. len += strlen(sep);
  109. }
  110. *out = new char[len];
  111. *out[0] = 0;
  112. if (in1) {
  113. strcat(*out, in1);
  114. }
  115. if (sep) {
  116. strcat(*out, sep);
  117. }
  118. if (*in2) {
  119. strcat(*out, *in2);
  120. }
  121. if (*in2) {
  122. this->DeallocateParserType(in2);
  123. }
  124. this->UnionsAvailable++;
  125. }
  126. void cmDependsJavaParserHelper::CheckEmpty(
  127. int line, int cnt, cmDependsJavaParserHelper::ParserType* pt)
  128. {
  129. int cc;
  130. int kk = -cnt + 1;
  131. for (cc = 1; cc <= cnt; cc++) {
  132. cmDependsJavaParserHelper::ParserType* cpt = pt + kk;
  133. this->SafePrintMissing(cpt->str, line, cc);
  134. kk++;
  135. }
  136. }
  137. void cmDependsJavaParserHelper::PrepareElement(
  138. cmDependsJavaParserHelper::ParserType* me)
  139. {
  140. // Inititalize self
  141. me->str = nullptr;
  142. }
  143. void cmDependsJavaParserHelper::AllocateParserType(
  144. cmDependsJavaParserHelper::ParserType* pt, const char* str, int len)
  145. {
  146. pt->str = nullptr;
  147. if (len == 0) {
  148. len = static_cast<int>(strlen(str));
  149. }
  150. if (len == 0) {
  151. return;
  152. }
  153. this->UnionsAvailable++;
  154. pt->str = new char[len + 1];
  155. strncpy(pt->str, str, len);
  156. pt->str[len] = 0;
  157. this->Allocates.push_back(pt->str);
  158. }
  159. void cmDependsJavaParserHelper::StartClass(const char* cls)
  160. {
  161. CurrentClass cl;
  162. cl.Name = cls;
  163. this->ClassStack.push_back(std::move(cl));
  164. this->CurrentDepth++;
  165. }
  166. void cmDependsJavaParserHelper::EndClass()
  167. {
  168. if (this->ClassStack.empty()) {
  169. std::cerr << "Error when parsing. Current class is null" << std::endl;
  170. abort();
  171. }
  172. if (this->ClassStack.size() <= 1) {
  173. std::cerr << "Error when parsing. Parent class is null" << std::endl;
  174. abort();
  175. }
  176. CurrentClass& current = this->ClassStack.back();
  177. CurrentClass& parent = this->ClassStack[this->ClassStack.size() - 2];
  178. this->CurrentDepth--;
  179. parent.NestedClasses.push_back(current);
  180. this->ClassStack.pop_back();
  181. }
  182. void cmDependsJavaParserHelper::PrintClasses()
  183. {
  184. if (this->ClassStack.empty()) {
  185. std::cerr << "Error when parsing. No classes on class stack" << std::endl;
  186. abort();
  187. }
  188. for (std::string const& f : this->GetFilesProduced()) {
  189. std::cout << " " << f << ".class" << std::endl;
  190. }
  191. }
  192. std::vector<std::string> cmDependsJavaParserHelper::GetFilesProduced()
  193. {
  194. std::vector<std::string> files;
  195. CurrentClass const& toplevel = this->ClassStack.front();
  196. for (CurrentClass const& nc : toplevel.NestedClasses) {
  197. nc.AddFileNamesForPrinting(&files, nullptr, "$");
  198. }
  199. return files;
  200. }
  201. int cmDependsJavaParserHelper::ParseString(const char* str, int verb)
  202. {
  203. if (!str) {
  204. return 0;
  205. }
  206. this->Verbose = verb;
  207. this->InputBuffer = str;
  208. this->InputBufferPos = 0;
  209. this->CurrentLine = 0;
  210. yyscan_t yyscanner;
  211. cmDependsJava_yylex_init(&yyscanner);
  212. cmDependsJava_yyset_extra(this, yyscanner);
  213. int res = cmDependsJava_yyparse(yyscanner);
  214. cmDependsJava_yylex_destroy(yyscanner);
  215. if (res != 0) {
  216. std::cout << "JP_Parse returned: " << res << std::endl;
  217. return 0;
  218. }
  219. if (verb) {
  220. if (!this->CurrentPackage.empty()) {
  221. std::cout << "Current package is: " << this->CurrentPackage << std::endl;
  222. }
  223. std::cout << "Imports packages:";
  224. if (!this->PackagesImport.empty()) {
  225. std::vector<std::string>::iterator it;
  226. for (it = this->PackagesImport.begin(); it != this->PackagesImport.end();
  227. ++it) {
  228. std::cout << " " << *it;
  229. }
  230. }
  231. std::cout << std::endl;
  232. std::cout << "Depends on:";
  233. if (!this->ClassesFound.empty()) {
  234. for (std::string const& cf : this->ClassesFound) {
  235. std::cout << " " << cf;
  236. }
  237. }
  238. std::cout << std::endl;
  239. std::cout << "Generated files:" << std::endl;
  240. this->PrintClasses();
  241. if (this->UnionsAvailable != 0) {
  242. std::cout << "There are still " << this->UnionsAvailable
  243. << " unions available" << std::endl;
  244. }
  245. }
  246. this->CleanupParser();
  247. return 1;
  248. }
  249. void cmDependsJavaParserHelper::CleanupParser()
  250. {
  251. for (char* allocate : this->Allocates) {
  252. delete[] allocate;
  253. }
  254. this->Allocates.erase(this->Allocates.begin(), this->Allocates.end());
  255. }
  256. int cmDependsJavaParserHelper::LexInput(char* buf, int maxlen)
  257. {
  258. if (maxlen < 1) {
  259. return 0;
  260. }
  261. if (this->InputBufferPos < this->InputBuffer.size()) {
  262. buf[0] = this->InputBuffer[this->InputBufferPos++];
  263. if (buf[0] == '\n') {
  264. this->CurrentLine++;
  265. }
  266. return 1;
  267. }
  268. buf[0] = '\n';
  269. return 0;
  270. }
  271. void cmDependsJavaParserHelper::Error(const char* str)
  272. {
  273. unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
  274. fprintf(stderr, "JPError: %s (%lu / Line: %d)\n", str, pos,
  275. this->CurrentLine);
  276. std::cerr << "String: ["
  277. << cm::string_view{ this->InputBuffer }.substr(
  278. this->InputBufferPos, 30)
  279. << "]" << std::endl;
  280. }
  281. void cmDependsJavaParserHelper::UpdateCombine(const char* str1,
  282. const char* str2)
  283. {
  284. if (this->CurrentCombine.empty() && str1 != nullptr) {
  285. this->CurrentCombine = str1;
  286. }
  287. this->CurrentCombine += ".";
  288. this->CurrentCombine += str2;
  289. }
  290. int cmDependsJavaParserHelper::ParseFile(const char* file)
  291. {
  292. if (!cmSystemTools::FileExists(file)) {
  293. return 0;
  294. }
  295. cmsys::ifstream ifs(file);
  296. if (!ifs) {
  297. return 0;
  298. }
  299. std::string fullfile;
  300. std::string line;
  301. while (cmSystemTools::GetLineFromStream(ifs, line)) {
  302. fullfile += line + "\n";
  303. }
  304. return this->ParseString(fullfile.c_str(), 0);
  305. }