cmDependsJavaParserHelper.cxx 7.9 KB

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