compiler.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. Copyright (c) 2020 Sogou, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <string>
  16. #ifdef _WIN32
  17. #include <direct.h>
  18. #define MAXPATHLEN 4096
  19. #else
  20. #include <unistd.h>
  21. #include <sys/param.h>
  22. #include <getopt.h>
  23. #endif
  24. #include "generator.h"
  25. const char *SRPC_VERSION = "0.10.2";
  26. /* LQ - prototype to determine if the file type is thrift */
  27. enum
  28. {
  29. TYPE_UNKNOWN = -1,
  30. TYPE_PROTOBUF = 0,
  31. TYPE_THRIFT = 1,
  32. };
  33. static int check_file_idl_type(const char *filename);
  34. static int parse_origin(int argc, const char *argv[],
  35. struct GeneratorParams& params,
  36. int& idl_type);
  37. #ifndef _WIN32
  38. static int parse_getopt(int argc, char * const *argv,
  39. struct GeneratorParams& params,
  40. int& idl_type);
  41. #endif
  42. static int parse_prefix_dir(std::string& file, std::string& dir);
  43. static int get_idl_type(const char *argv);
  44. static bool is_root(std::string& file);
  45. const char *SRPC_GENERATOR_USAGE = "\
  46. Usage:\n\
  47. %s [protobuf|thrift] <idl_file> <output_dir>\n\n\
  48. Available options(linux):\n\
  49. -f, --idl_file : IDL file name. If multiple files are imported, specify the top one. Will parse recursively.\n\
  50. -o, --output_dir : Output directory.\n\
  51. -i, --input_dir : Specify the directory in which to search for imports.\n\
  52. -s, --skip_skeleton : Skip generating skeleton file. (default: generate)\n\
  53. -v, --version : Show version.\n\
  54. -h, --help : Show usage.\n";
  55. int main(int argc, const char *argv[])
  56. {
  57. int idl_type = TYPE_UNKNOWN;
  58. struct GeneratorParams params;
  59. #ifndef _WIN32
  60. if (parse_origin(argc, argv, params, idl_type) == 0)
  61. {
  62. if (parse_getopt(argc, (char * const *)argv, params, idl_type) != 0)
  63. return 0;
  64. }
  65. #else
  66. parse_origin(argc, argv, params, idl_type);
  67. #endif
  68. if (params.out_dir == NULL || params.idl_file.empty())
  69. {
  70. fprintf(stderr, SRPC_GENERATOR_USAGE, argv[0]);
  71. return 0;
  72. }
  73. if (idl_type == TYPE_UNKNOWN)
  74. idl_type = check_file_idl_type(params.idl_file.data());
  75. if (is_root(params.idl_file))
  76. {
  77. if (params.input_dir.empty())
  78. parse_prefix_dir(params.idl_file, params.input_dir);
  79. else
  80. {
  81. fprintf(stderr, "ERROR: input_dir must encompasses the idl_file %s\n",
  82. params.idl_file.c_str());
  83. return 0;
  84. }
  85. }
  86. else
  87. {
  88. if (params.input_dir.empty() || is_root(params.input_dir) == false)
  89. {
  90. char current_dir[MAXPATHLEN] = {};
  91. getcwd(current_dir, MAXPATHLEN);
  92. current_dir[strlen(current_dir)] = '/';
  93. if (params.input_dir.empty())
  94. params.input_dir = current_dir;
  95. else
  96. params.input_dir = current_dir + params.input_dir;
  97. }
  98. }
  99. Generator gen(idl_type == TYPE_THRIFT ? true : false);
  100. fprintf(stdout, "[Generator Begin]\n");
  101. gen.generate(params);
  102. fprintf(stdout, "[Generator Done]\n");
  103. return 0;
  104. }
  105. int parse_origin(int argc, const char *argv[],
  106. struct GeneratorParams& params, int& idl_type)
  107. {
  108. int idl_file_id = 1;
  109. for (int i = 1; i < argc && i < 4 && argv[i][0] != '-'; i++)
  110. {
  111. if (i == 1) // parse [protobuf|thrift]
  112. {
  113. idl_type = get_idl_type(argv[1]);
  114. if (idl_type != TYPE_UNKNOWN)
  115. {
  116. idl_file_id++;
  117. continue;
  118. }
  119. }
  120. if (i == idl_file_id) // parse <idl_file>
  121. {
  122. int tmp_type = check_file_idl_type(argv[i]);
  123. if (tmp_type == TYPE_UNKNOWN)
  124. {
  125. fprintf(stderr, "ERROR: Invalid IDL file \"%s\".\n", argv[i]);
  126. return -1;
  127. }
  128. if (idl_type == TYPE_UNKNOWN)
  129. idl_type = tmp_type;
  130. params.idl_file = argv[idl_file_id];
  131. }
  132. else // parse <output_dir>
  133. params.out_dir = argv[i];
  134. }
  135. return 0;
  136. }
  137. #ifndef _WIN32
  138. int parse_getopt(int argc, char * const *argv,
  139. struct GeneratorParams& params, int& idl_type)
  140. {
  141. int ch;
  142. static struct option longopts[] = {
  143. { "version", no_argument, NULL, 'v'},
  144. { "idl_file", required_argument, NULL, 'f'},
  145. { "output_dir", required_argument, NULL, 'o'},
  146. { "input_dir", required_argument, NULL, 'i'},
  147. { "skip_skeleton", no_argument, NULL, 's'},
  148. { "help", no_argument, NULL, 'h'}
  149. };
  150. while ((ch = getopt_long(argc, argv, "vf:o:i:sh", longopts, NULL)) != -1)
  151. {
  152. switch (ch)
  153. {
  154. case 'v':
  155. fprintf(stderr, "srpc_generator version %s\n", SRPC_VERSION);
  156. return 1;
  157. case 'f':
  158. if (!params.idl_file.empty())
  159. {
  160. fprintf(stderr, "Error: -i is duplicate with idl_file %s\n",
  161. params.idl_file.c_str());
  162. return -1;
  163. }
  164. params.idl_file = optarg;
  165. break;
  166. case 'o':
  167. if (params.out_dir != NULL)
  168. {
  169. fprintf(stderr, "Error: -o is duplicate with output_dir %s\n",
  170. params.out_dir);
  171. return -1;
  172. }
  173. params.out_dir = optarg;
  174. break;
  175. case 'i':
  176. params.input_dir = optarg;
  177. if (params.input_dir.at(params.input_dir.length() - 1) != '/')
  178. params.input_dir += '/';
  179. break;
  180. case 's':
  181. params.generate_skeleton = false;
  182. break;
  183. case 'h':
  184. break;
  185. default:
  186. return 0;
  187. }
  188. }
  189. return 0;
  190. }
  191. #endif
  192. int get_idl_type(const char *type)
  193. {
  194. if (strcasecmp(type, "protobuf") == 0)
  195. return TYPE_PROTOBUF;
  196. if (strcasecmp(type, "thrift") == 0)
  197. return TYPE_THRIFT;
  198. return TYPE_UNKNOWN;
  199. }
  200. // idl file will not start with -
  201. int check_file_idl_type(const char *filename)
  202. {
  203. size_t len = strlen(filename);
  204. if (len > 6 && strcmp(filename + len - 6, ".proto") == 0)
  205. return TYPE_PROTOBUF;
  206. else if (len > 7 && strcmp(filename + len - 7, ".thrift") == 0)
  207. return TYPE_THRIFT;
  208. return TYPE_UNKNOWN;
  209. }
  210. int parse_prefix_dir(std::string& file, std::string& dir)
  211. {
  212. auto pos = file.find_last_of('/');
  213. if (pos == std::string::npos)
  214. return -1;
  215. dir = file.substr(0, pos + 1);
  216. file = file.substr(pos + 1);
  217. return 0;
  218. }
  219. bool is_root(std::string& file)
  220. {
  221. if (file[0] == '/' || file[1] == ':')
  222. return true;
  223. return false;
  224. }