genhooks.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /* Process target.def to create initialization macros definition in
  2. target-hooks-def.h and documentation in target-hooks.texi.
  3. Copyright (C) 2009-2015 Free Software Foundation, Inc.
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 3, or (at your option) any later
  8. version.
  9. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GCC; see the file COPYING3. If not see
  15. <http://www.gnu.org/licenses/>. */
  16. #include "bconfig.h"
  17. #include "system.h"
  18. #include "hashtab.h"
  19. #include "errors.h"
  20. struct hook_desc { const char *doc, *type, *name, *param, *init, *docname; };
  21. static struct hook_desc hook_array[] = {
  22. #define HOOK_VECTOR_1(NAME, FRAGMENT) \
  23. { 0, 0, #NAME, 0, 0, HOOK_TYPE },
  24. #define DEFHOOKPOD(NAME, DOC, TYPE, INIT) \
  25. { DOC, #TYPE, HOOK_PREFIX #NAME, 0, #INIT, HOOK_TYPE },
  26. #define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) \
  27. { DOC, #TYPE, HOOK_PREFIX #NAME, #PARAMS, #INIT, HOOK_TYPE },
  28. #define DEFHOOK_UNDOC(NAME, DOC, TYPE, PARAMS, INIT) \
  29. { "*", #TYPE, HOOK_PREFIX #NAME, #PARAMS, #INIT, HOOK_TYPE },
  30. #include "target.def"
  31. #include "c-family/c-target.def"
  32. #include "common/common-target.def"
  33. #undef DEFHOOK
  34. };
  35. /* For each @Fcode in the first paragraph of the documentation string DOC,
  36. print an @findex directive. HOOK_NAME is the name of the hook this bit of
  37. documentation pertains to. */
  38. static void
  39. emit_findices (const char *doc, const char *hook_name)
  40. {
  41. const char *end = strstr (doc, "\n\n");
  42. const char *fcode;
  43. while ((fcode = strstr (doc, "@Fcode{")) && (!end || fcode < end))
  44. {
  45. fcode += strlen ("@Fcode{");
  46. doc = strchr (fcode, '}');
  47. if (!doc)
  48. fatal ("Malformed @Fcode for hook %s\n", hook_name);
  49. printf ("@findex %.*s\n", (int) (doc - fcode), fcode);
  50. doc = fcode;
  51. }
  52. }
  53. /* Return an upper-case copy of IN. */
  54. static char *
  55. upstrdup (const char *in)
  56. {
  57. char *p, *ret = xstrdup (in);
  58. for (p = ret; *p; p++)
  59. *p = TOUPPER (*p);
  60. return ret;
  61. }
  62. /* Struct for 'start hooks' which start a sequence of consecutive hooks
  63. that are defined in target.def and to be documented in tm.texi. */
  64. struct s_hook
  65. {
  66. char *name;
  67. int pos;
  68. };
  69. static hashval_t
  70. s_hook_hash (const void *p)
  71. {
  72. const struct s_hook *s_hook = (const struct s_hook *)p;
  73. return htab_hash_string (s_hook->name);
  74. }
  75. static int
  76. s_hook_eq_p (const void *p1, const void *p2)
  77. {
  78. return (strcmp (((const struct s_hook *) p1)->name,
  79. ((const struct s_hook *) p2)->name) == 0);
  80. }
  81. /* Read the documentation file with name IN_FNAME, perform substitutions
  82. to incorporate information from hook_array, and emit the result on stdout.
  83. Hooks defined with DEFHOOK / DEFHOOKPOD are emitted at the place of a
  84. matching @hook in the input file; if there is no matching @hook, the
  85. hook is emitted after the hook that precedes it in target.def .
  86. Usually, the emitted hook documentation starts with the hook
  87. signature, followed by the string from the doc field.
  88. The documentation is bracketed in @deftypefn / @deftypevr and a matching
  89. @end.
  90. While emitting the doc field, @Fcode is translated to @code, and an
  91. @findex entry is added to the affected paragraph.
  92. If the doc field starts with '*', the leading '*' is stripped, and the doc
  93. field is otherwise emitted unaltered; no function signature/
  94. @deftypefn/deftypevr/@end is emitted.
  95. In particular, a doc field of "*" means not to emit any ocumentation for
  96. this target.def / hook_array entry at all (there might be documentation
  97. for this hook in the file named IN_FNAME, though).
  98. A doc field of 0 is used to append the hook signature after the previous
  99. hook's signture, so that one description can be used for a group of hooks.
  100. When the doc field is "", @deftypefn/@deftypevr and the hook signature
  101. is emitted, but not the matching @end. This allows all the free-form
  102. documentation to be placed in IN_FNAME, to work around GPL/GFDL
  103. licensing incompatibility issues. */
  104. static void
  105. emit_documentation (const char *in_fname)
  106. {
  107. int i, j;
  108. char buf[1000];
  109. htab_t start_hooks = htab_create (99, s_hook_hash, s_hook_eq_p, (htab_del) 0);
  110. FILE *f;
  111. /* Enter all the start hooks in start_hooks. */
  112. f = fopen (in_fname, "r");
  113. if (!f)
  114. {
  115. perror ("");
  116. fatal ("Couldn't open input file");
  117. }
  118. while (fscanf (f, "%*[^@]"), buf[0] = '\0',
  119. fscanf (f, "@%5[^ \n]", buf) != EOF)
  120. {
  121. void **p;
  122. struct s_hook *shp;
  123. if (strcmp (buf, "hook") != 0)
  124. continue;
  125. buf[0] = '\0';
  126. fscanf (f, "%999s", buf);
  127. shp = XNEW (struct s_hook);
  128. shp->name = upstrdup (buf);
  129. shp->pos = -1;
  130. p = htab_find_slot (start_hooks, shp, INSERT);
  131. if (*p != HTAB_EMPTY_ENTRY)
  132. fatal ("Duplicate placement for hook %s\n", shp->name);
  133. *(struct s_hook **) p = shp;
  134. }
  135. fclose (f);
  136. /* For each hook in hook_array, if it is a start hook, store its position. */
  137. for (i = 0; i < (int) (sizeof hook_array / sizeof hook_array[0]); i++)
  138. {
  139. struct s_hook sh, *shp;
  140. void *p;
  141. if (!hook_array[i].doc || strcmp (hook_array[i].doc, "*") == 0)
  142. continue;
  143. sh.name = upstrdup (hook_array[i].name);
  144. p = htab_find (start_hooks, &sh);
  145. if (p)
  146. {
  147. shp = (struct s_hook *) p;
  148. if (shp->pos >= 0)
  149. fatal ("Duplicate hook %s\n", sh.name);
  150. shp->pos = i;
  151. }
  152. else
  153. fatal ("No place specified to document hook %s\n", sh.name);
  154. free (sh.name);
  155. }
  156. /* Copy input file to stdout, substituting @hook directives with the
  157. corresponding hook documentation sequences. */
  158. f = fopen (in_fname, "r");
  159. if (!f)
  160. {
  161. perror ("");
  162. fatal ("Couldn't open input file");
  163. }
  164. for (;;)
  165. {
  166. struct s_hook sh, *shp;
  167. int c = getc (f);
  168. char *name;
  169. if (c == EOF)
  170. break;
  171. if (c != '@')
  172. {
  173. putchar (c);
  174. continue;
  175. }
  176. buf[0] = '\0';
  177. fscanf (f, "%5[^ \n]", buf);
  178. if (strcmp (buf, "hook") != 0)
  179. {
  180. printf ("@%s", buf);
  181. continue;
  182. }
  183. fscanf (f, "%999s", buf);
  184. sh.name = name = upstrdup (buf);
  185. shp = (struct s_hook *) htab_find (start_hooks, &sh);
  186. if (!shp || shp->pos < 0)
  187. fatal ("No documentation for hook %s\n", sh.name);
  188. i = shp->pos;
  189. do
  190. {
  191. const char *q, *e;
  192. const char *deftype;
  193. const char *doc, *fcode, *p_end;
  194. /* A leading '*' means to output the documentation string without
  195. further processing. */
  196. if (*hook_array[i].doc == '*')
  197. printf ("%s", hook_array[i].doc + 1);
  198. else
  199. {
  200. if (i != shp->pos)
  201. printf ("\n\n");
  202. emit_findices (hook_array[i].doc, name);
  203. /* Print header. Function-valued hooks have a parameter list,
  204. unlike POD-valued ones. */
  205. deftype = hook_array[i].param ? "deftypefn" : "deftypevr";
  206. printf ("@%s {%s} ", deftype, hook_array[i].docname);
  207. if (strchr (hook_array[i].type, ' '))
  208. printf ("{%s}", hook_array[i].type);
  209. else
  210. printf ("%s", hook_array[i].type);
  211. printf (" %s", name);
  212. if (hook_array[i].param)
  213. {
  214. /* Print the parameter list, with the parameter names
  215. enclosed in @var{}. */
  216. printf (" ");
  217. for (q = hook_array[i].param; (e = strpbrk (q, " *,)"));
  218. q = e + 1)
  219. /* Type names like 'int' are followed by a space, sometimes
  220. also by '*'. 'void' should appear only in "(void)". */
  221. if (*e == ' ' || *e == '*' || *q == '(')
  222. printf ("%.*s", (int) (e - q + 1), q);
  223. else
  224. printf ("@var{%.*s}%c", (int) (e - q), q, *e);
  225. }
  226. /* POD-valued hooks sometimes come in groups with common
  227. documentation.*/
  228. for (j = i + 1;
  229. j < (int) (sizeof hook_array / sizeof hook_array[0])
  230. && hook_array[j].doc == 0 && hook_array[j].type; j++)
  231. {
  232. char *namex = upstrdup (hook_array[j].name);
  233. printf ("\n@%sx {%s} {%s} %s",
  234. deftype, hook_array[j].docname,
  235. hook_array[j].type, namex);
  236. }
  237. if (hook_array[i].doc[0])
  238. {
  239. printf ("\n");
  240. /* Print each documentation paragraph in turn. */
  241. for (doc = hook_array[i].doc; *doc; doc = p_end)
  242. {
  243. /* Find paragraph end. */
  244. p_end = strstr (doc, "\n\n");
  245. p_end = (p_end ? p_end + 2 : doc + strlen (doc));
  246. /* Print paragraph, emitting @Fcode as @code. */
  247. for (; (fcode = strstr (doc, "@Fcode{")) && fcode < p_end;
  248. doc = fcode + 2)
  249. printf ("%.*s@", (int) (fcode - doc), doc);
  250. printf ("%.*s", (int) (p_end - doc), doc);
  251. /* Emit function indices for next paragraph. */
  252. emit_findices (p_end, name);
  253. }
  254. printf ("\n@end %s", deftype);
  255. }
  256. }
  257. if (++i >= (int) (sizeof hook_array / sizeof hook_array[0])
  258. || !hook_array[i].doc)
  259. break;
  260. free (name);
  261. sh.name = name = upstrdup (hook_array[i].name);
  262. }
  263. while (!htab_find (start_hooks, &sh));
  264. free (name);
  265. }
  266. }
  267. /* Emit #defines to stdout (this will be redirected to generate
  268. target-hook-def.h) which set target hooks initializer macros
  269. to their default values. These should only be emitted for hooks
  270. whose type is given by DOCNAME. */
  271. static void
  272. emit_init_macros (const char *docname)
  273. {
  274. int i;
  275. const int MAX_NEST = 2;
  276. int print_nest, nest = 0;
  277. for (print_nest = 0; print_nest <= MAX_NEST; print_nest++)
  278. {
  279. for (i = 0; i < (int) (sizeof hook_array / sizeof hook_array[0]); i++)
  280. {
  281. char *name = upstrdup (hook_array[i].name);
  282. if (strcmp (hook_array[i].docname, docname) != 0)
  283. continue;
  284. if (!hook_array[i].type)
  285. {
  286. if (*name)
  287. {
  288. if (nest && nest == print_nest)
  289. printf (" %s, \\\n", name);
  290. nest++;
  291. if (nest > MAX_NEST)
  292. fatal ("Unexpected nesting of %s\n", name);
  293. if (nest == print_nest)
  294. printf ("\n#define %s \\\n { \\\n", name);
  295. }
  296. else
  297. {
  298. if (nest == print_nest)
  299. printf (" }\n");
  300. nest--;
  301. }
  302. continue;
  303. }
  304. if (0 == print_nest)
  305. {
  306. /* Output default definitions of target hooks. */
  307. printf ("#ifndef %s\n#define %s %s\n#endif\n",
  308. name, name, hook_array[i].init);
  309. }
  310. if (nest == print_nest)
  311. printf (" %s, \\\n", name);
  312. }
  313. }
  314. }
  315. int
  316. main (int argc, char **argv)
  317. {
  318. progname = "genhooks";
  319. if (argc >= 3)
  320. emit_documentation (argv[2]);
  321. else
  322. emit_init_macros (argv[1]);
  323. return 0;
  324. }