PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/generate-api-docs.c

https://gitlab.com/libvirt/libvirt-php
C | 316 lines | 255 code | 57 blank | 4 comment | 96 complexity | 8a41f8d558576fd3934f06e8a35afce6 MD5 | raw file
Possible License(s): LGPL-2.1
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <stdarg.h>
  5. #include <string.h>
  6. #include <stdbool.h>
  7. typedef struct func_t {
  8. char *name;
  9. int private;
  10. char *desc;
  11. char *version;
  12. int num_args;
  13. char **args;
  14. char *returns;
  15. } func_t;
  16. func_t *functions = NULL;
  17. void bail_error(const char *fmt, ...)
  18. {
  19. va_list ap;
  20. char tmp[64] = { 0 };
  21. va_start(ap, fmt);
  22. vsnprintf(tmp, sizeof(tmp), fmt, ap);
  23. va_end(ap);
  24. fprintf(stderr, "Error: %s\n", tmp);
  25. exit(1);
  26. }
  27. char *ltrim_string(char *str)
  28. {
  29. /* Skip initial comment indentation */
  30. if (strncmp(str, " * ", 3) == 0)
  31. str += 3;
  32. /* Now skip spaces */
  33. while (*str == ' ')
  34. str++;
  35. /* TABs are not acceptable! */
  36. if (*str == '\t')
  37. bail_error("Indent with spaces, not TABs");
  38. return str;
  39. }
  40. void parse_comment(char *line, int func_num, int *arg_num)
  41. {
  42. char *ltrimmed = ltrim_string(line);
  43. if (strncmp(ltrimmed, "Function name:", 14) == 0) {
  44. functions[func_num].name = strdup( ltrim_string( ltrimmed + 14) );
  45. functions[func_num].private = 0;
  46. }
  47. else if (strncmp(ltrimmed, "Private function name:", 22) == 0) {
  48. functions[func_num].name = strdup( ltrim_string( ltrimmed + 22) );
  49. functions[func_num].private = 1;
  50. }
  51. else if (strncmp(ltrimmed, "Since version:", 14) == 0) {
  52. functions[func_num].version = strdup( ltrim_string( ltrimmed + 14) );
  53. }
  54. else if (strncmp(ltrimmed, "Description:", 12) == 0) {
  55. functions[func_num].desc = strdup( ltrim_string( ltrimmed + 12) );
  56. }
  57. else if (strncmp(ltrimmed, "Arguments:", 10) == 0) {
  58. char *str = ltrim_string(ltrimmed + 11);
  59. if (arg_num == NULL)
  60. return;
  61. functions[func_num].num_args = 1;
  62. functions[func_num].args = malloc( sizeof(char *) );
  63. functions[func_num].args[0] = malloc( (strlen(str) + 1) * sizeof(char) );
  64. strcpy(functions[func_num].args[0], str);
  65. *arg_num = 1;
  66. }
  67. else if (strncmp(ltrimmed, "Returns:", 8) == 0) {
  68. char *str = ltrim_string(ltrimmed + 7);
  69. functions[func_num].returns = malloc( (strlen(str) + 1) * sizeof(char));
  70. strcpy(functions[func_num].returns, str);
  71. }
  72. else if ((arg_num != NULL) && (*arg_num > 0)) {
  73. functions[func_num].num_args++;
  74. functions[func_num].args = realloc( functions[func_num].args,
  75. functions[func_num].num_args * sizeof(char *));
  76. functions[func_num].args[functions[func_num].num_args-1] = malloc((strlen(ltrimmed) + 1) * sizeof(char) );
  77. strcpy(functions[func_num].args[functions[func_num].num_args-1], ltrimmed);
  78. *arg_num = *arg_num + 1;
  79. }
  80. }
  81. char *get_lpart(char *str)
  82. {
  83. if (!str || strcmp(str, "None") == 0)
  84. return str;
  85. char *new = strdup(str);
  86. char *tmp = strchr(str, ':');
  87. if (!tmp)
  88. return str;
  89. new[ strlen(new) - strlen(tmp) ] = 0;
  90. return new;
  91. }
  92. char *get_rpart(char *str)
  93. {
  94. if (!str || strcmp(str, "None") == 0)
  95. return str;
  96. char *tmp = strchr(str, ':');
  97. if (!tmp)
  98. return str;
  99. return (++tmp);
  100. }
  101. void free_functions(int function_number)
  102. {
  103. int i, j;
  104. for (i = 0; i <= function_number; i++) {
  105. for (j = 0; j < functions[i].num_args; j++)
  106. free(functions[i].args[j]);
  107. free(functions[i].name);
  108. free(functions[i].desc);
  109. free(functions[i].returns);
  110. }
  111. free(functions);
  112. }
  113. int count_functions(int num_funcs, int private)
  114. {
  115. int i, num = 0;
  116. for (i = 0; i < num_funcs; i++)
  117. if ((functions[i].name != NULL) && (functions[i].private == private))
  118. num++;
  119. return num;
  120. }
  121. int main(int argc, char *argv[])
  122. {
  123. char line[1024] = { 0 };
  124. bool in_comment = false;
  125. int function_number = -1;
  126. int arg_number = 0;
  127. int private = 0;
  128. int idx = 1;
  129. int i, j;
  130. FILE *fp;
  131. if (argc < 3) {
  132. fprintf(stderr, "Syntax: %s [-p|--private] source-file output-in-file\n", argv[0]);
  133. return 1;
  134. }
  135. if ((strcmp(argv[1], "-p") == 0) || (strcmp(argv[1], "--private") == 0)) {
  136. if (argc < 4) {
  137. fprintf(stderr, "Syntax: %s [-p|--private] source-file output-in-file\n", argv[0]);
  138. return 1;
  139. }
  140. private = 1;
  141. idx++;
  142. }
  143. if (access(argv[idx], R_OK) != 0)
  144. bail_error("Cannot open file %s", argv[1]);
  145. if (!(functions = (func_t *)malloc(sizeof(func_t))))
  146. bail_error("Out of memory");
  147. if (!(fp = fopen(argv[idx], "r")))
  148. bail_error("Error while opening %s", argv[1]);
  149. while (true) {
  150. memset(line, 0, sizeof(line));
  151. if (!fgets(line, sizeof(line), fp)) {
  152. if (feof(fp))
  153. break;
  154. bail_error("Unable to read form %s", argv[1]);
  155. }
  156. /* Strip new line characters */
  157. if (line[strlen(line) - 1] == '\n')
  158. line[strlen(line) - 1] = 0;
  159. if (strcmp(line, "/*") == 0) {
  160. function_number++;
  161. in_comment = 1;
  162. if (!(functions = (func_t *) realloc(functions,
  163. sizeof(func_t) * (function_number + 1))))
  164. bail_error("Out of memory");
  165. functions[function_number].name = NULL;
  166. functions[function_number].num_args = 0;
  167. } else {
  168. if (strcmp(line, " */") == 0)
  169. in_comment = 0;
  170. else if (in_comment)
  171. parse_comment(line, function_number, &arg_number);
  172. }
  173. }
  174. fclose(fp);
  175. if (!(fp = fopen(argv[idx+1], "w"))) {
  176. free_functions(function_number);
  177. bail_error("Cannot write %s", argv[2]);
  178. }
  179. fprintf(fp, "<?xml version=\"1.0\"?>\n<html>\n <body>\n");
  180. fprintf(fp,"<h1>%s API Reference guide</h1>\n\n <h3>Functions</h3>\n\n <!-- Links -->\n", (private == 0) ? "PHP" : "Developer's");
  181. fprintf(fp, "<pre>Total number of functions: %d. Functions supported are:<br /><br />\n", count_functions(function_number, private));
  182. for (i = 0; i <= function_number; i++) {
  183. if ((functions[i].name != NULL) && (functions[i].private == private)) {
  184. fprintf(fp, "\t<code class=\"docref\">%s</code>(", functions[i].name);
  185. for (j = 0; j < functions[i].num_args; j++) {
  186. if (strcmp(functions[i].args[j], "None") != 0) {
  187. char *new = get_lpart(functions[i].args[j]);
  188. char *part;
  189. int decrement;
  190. if (new[0] == '@')
  191. new++;
  192. part = strchr(new, ' ');
  193. decrement = (part != NULL) ? strlen( part ) : 0;
  194. if (j > 0)
  195. fprintf(fp, ", ");
  196. new[ strlen(new) - decrement ] = 0;
  197. fprintf(fp, "$%s", new);
  198. }
  199. }
  200. fprintf(fp, ")<br />\n");
  201. }
  202. }
  203. fprintf(fp, "</pre>\n");
  204. for (i = 0; i <= function_number; i++) {
  205. if ((functions[i].name != NULL) && (functions[i].private == private)) {
  206. fprintf(fp, "<h3><a name=\"%s\"><code>%s</code></a></h3>\n", functions[i].name, functions[i].name);
  207. fprintf(fp, "<pre class=\"programlisting\">%s(", functions[i].name);
  208. for (j = 0; j < functions[i].num_args; j++) {
  209. if (strcmp(functions[i].args[j], "None") != 0) {
  210. char *new = get_lpart(functions[i].args[j]);
  211. char *part;
  212. int decrement;
  213. if (new[0] == '@')
  214. new++;
  215. part = strchr(new, ' ');
  216. decrement = (part != NULL) ? strlen( part ) : 0;
  217. if (j > 0)
  218. fprintf(fp, ", ");
  219. new[ strlen(new) - decrement ] = 0;
  220. fprintf(fp, "$%s", new);
  221. }
  222. }
  223. fprintf(fp, ")</pre>\n");
  224. fprintf(fp, "<p>[Since version %s]</p>\n", functions[i].version);
  225. fprintf(fp, "<p>%s.</p>", functions[i].desc);
  226. fprintf(fp, "<div class=\"variablelist\">\n");
  227. fprintf(fp, "\t<table border=\"0\">\n");
  228. fprintf(fp, "\t\t<col align=\"left\" />\n");
  229. fprintf(fp, "\t\t<tbody>\n");
  230. for (j = 0; j < functions[i].num_args; j++) {
  231. if (strcmp(functions[i].args[j], "None") != 0) {
  232. fprintf(fp, "\t\t <tr>\n");
  233. fprintf(fp, "\t\t <td>\n");
  234. fprintf(fp, "\t\t\t<span class=\"term\"><i><tt>%s</tt></i>:</span>\n", get_lpart(functions[i].args[j]) );
  235. fprintf(fp, "\t\t </td>\n");
  236. fprintf(fp, "\t\t <td>\n");
  237. fprintf(fp, "\t\t\t%s\n", get_rpart(functions[i].args[j]));
  238. fprintf(fp, "\t\t </td>\n");
  239. fprintf(fp, "\t\t </tr>\n");
  240. }
  241. }
  242. fprintf(fp, "\t\t <tr>\n");
  243. fprintf(fp, "\t\t <td>\n");
  244. fprintf(fp, "\t\t\t<span class=\"term\"><i><tt>Returns</tt></i>:</span>\n");
  245. fprintf(fp, "\t\t </td>\n");
  246. fprintf(fp, "\t\t <td>\n");
  247. fprintf(fp, "\t\t\t%s\n", functions[i].returns);
  248. fprintf(fp, "\t\t </td>\n");
  249. fprintf(fp, "\t\t </tr>\n");
  250. fprintf(fp, "\t\t</tbody>\n");
  251. fprintf(fp, "\t</table>\n");
  252. fprintf(fp, "</div>\n");
  253. }
  254. }
  255. fclose(fp);
  256. free_functions(function_number);
  257. printf("Documentation has been generated successfully\n");
  258. return 0;
  259. }