def.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /* Copyright 2010, 2011, 2012, 2013, 2014, 2015
  2. Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #include <string.h>
  14. #include "parser.h"
  15. #include "text.h"
  16. // 1471
  17. void
  18. gather_def_item (ELEMENT *current, enum command_id next_command)
  19. {
  20. enum element_type type;
  21. ELEMENT *def_item;
  22. int contents_count, i;
  23. if (next_command)
  24. type = ET_inter_def_item; /* Between @def*x and @def*. */
  25. else
  26. type = ET_def_item;
  27. if (!current->cmd)
  28. return;
  29. /* Check this isn't an "x" type command.
  30. "This may happen for a construct like:
  31. @deffnx a b @section
  32. but otherwise the end of line will lead to the command closing." */
  33. if (command_data(current->cmd).flags & CF_misc)
  34. return;
  35. def_item = new_element (type);
  36. /* Starting from the end, collect everything that is not a ET_def_line and
  37. put it into the ET_def_item. */
  38. contents_count = current->contents.number;
  39. for (i = 0; i < contents_count; i++)
  40. {
  41. ELEMENT *last_child, *item_content;
  42. last_child = last_contents_child (current);
  43. if (last_child->type == ET_def_line)
  44. break;
  45. item_content = pop_element_from_contents (current);
  46. insert_into_contents (def_item, item_content, 0);
  47. }
  48. if (def_item->contents.number > 0)
  49. add_to_element_contents (current, def_item);
  50. else
  51. destroy_element (def_item);
  52. }
  53. static void
  54. shallow_destroy_element (ELEMENT *e)
  55. {
  56. free (e->text.text);
  57. free (e);
  58. }
  59. // 2335
  60. /* Used for definition line parsing. Return next unit on the line after
  61. a definition command like @deffn. The contents of E is what is remaining
  62. in the argument line. *SPACES_OUT is set to an element with spaces before
  63. the line. */
  64. static ELEMENT *
  65. next_bracketed_or_word (ELEMENT *e, ELEMENT **spaces_out, int join)
  66. {
  67. char *text;
  68. ELEMENT *spaces = 0;
  69. int space_len = 0;
  70. ELEMENT *ret;
  71. ELEMENT *f;
  72. *spaces_out = 0;
  73. if (e->contents.number == 0)
  74. return 0; /* No more arguments */
  75. f = e->contents.list[0];
  76. text = f->text.text;
  77. if (text)
  78. space_len = strspn (text, whitespace_chars);
  79. if (space_len)
  80. {
  81. /* Remove a trailing newline. */
  82. if (text[space_len - 1] == '\n')
  83. {
  84. text[--space_len] == '\0';
  85. f->text.end--;
  86. }
  87. if (space_len)
  88. {
  89. spaces = new_element (ET_spaces);
  90. spaces->parent_type = route_not_in_tree;
  91. text_append_n (&spaces->text, text, space_len);
  92. memmove (f->text.text,
  93. f->text.text + space_len,
  94. f->text.end - space_len + 1);
  95. f->text.end -= space_len;
  96. }
  97. if (f->text.end == 0)
  98. {
  99. (void ) remove_from_contents (e, 0);
  100. shallow_destroy_element (f);
  101. }
  102. *spaces_out = spaces;
  103. }
  104. if (e->contents.number == 0)
  105. return 0; /* No more arguments */
  106. ret = new_element (ET_NONE);
  107. ret->parent_type = route_not_in_tree;
  108. while (e->contents.number > 0)
  109. {
  110. f = e->contents.list[0];
  111. if (f->type == ET_bracketed)
  112. {
  113. (void) remove_from_contents (e, 0);
  114. f->type = ET_bracketed_def_content;
  115. isolate_last_space (f, 0);
  116. add_to_contents_as_array (ret, f);
  117. if (!join)
  118. break;
  119. }
  120. else if (f->cmd) // 2363
  121. {
  122. (void ) remove_from_contents (e, 0);
  123. add_to_contents_as_array (ret, f);
  124. if (!join)
  125. break;
  126. }
  127. else
  128. {
  129. /* Extract span of non-whitespace characters. */
  130. ELEMENT *returned;
  131. int arg_len;
  132. text = f->text.text;
  133. if (!*text)
  134. {
  135. /* Finished with this element */
  136. remove_from_contents (e, 0);
  137. shallow_destroy_element (f);
  138. continue;
  139. }
  140. space_len = strspn (text, whitespace_chars);
  141. if (space_len > 0)
  142. break; /* Finished */
  143. returned = new_element (ET_NONE);
  144. returned->parent_type = route_not_in_tree;
  145. arg_len = strcspn (text, whitespace_chars);
  146. text_append_n (&returned->text, text, arg_len);
  147. memmove (f->text.text, f->text.text + space_len + arg_len,
  148. f->text.end - (space_len + arg_len) + 1);
  149. f->text.end -= space_len + arg_len;
  150. add_to_contents_as_array (ret, returned);
  151. if (!join)
  152. break;
  153. }
  154. }
  155. if (ret->contents.number == 1)
  156. {
  157. ELEMENT *tmp = ret;
  158. ret = ret->contents.list[0];
  159. shallow_destroy_element (tmp);
  160. }
  161. else if (ret->contents.number == 0)
  162. abort ();
  163. return ret;
  164. }
  165. typedef struct {
  166. enum command_id alias;
  167. enum command_id command;
  168. char *category;
  169. } DEF_ALIAS;
  170. DEF_ALIAS def_aliases[] = {
  171. CM_defun, CM_deffn, "Function",
  172. CM_defmac, CM_deffn, "Macro",
  173. CM_defspec, CM_deffn, "Special Form",
  174. CM_defvar, CM_defvr, "Variable",
  175. CM_defopt, CM_defvr, "User Option",
  176. CM_deftypefun, CM_deftypefn, "Function",
  177. CM_deftypevar, CM_deftypevr, "Variable",
  178. CM_defivar, CM_defcv, "Instance Variable",
  179. CM_deftypeivar, CM_deftypecv, "Instance Variable",
  180. CM_defmethod, CM_defop, "Method",
  181. CM_deftypemethod, CM_deftypeop, "Method",
  182. 0, 0, 0
  183. };
  184. static void
  185. add_to_def_args_extra (DEF_ARGS_EXTRA *d, char *label, ELEMENT *arg)
  186. {
  187. if (d->nelements >= d->space - 1)
  188. {
  189. d->space += 5;
  190. d->labels = realloc (d->labels, d->space * sizeof (char *));
  191. d->elements = realloc (d->elements, d->space * sizeof (ELEMENT *));
  192. }
  193. if (arg && arg->hv)
  194. abort ();
  195. if (!arg)
  196. return; /* Probably a bug */
  197. d->labels[d->nelements] = label;
  198. d->elements[d->nelements++] = arg;
  199. d->labels[d->nelements] = 0;
  200. d->elements[d->nelements] = 0;
  201. }
  202. /* Parse the arguments on a def* command line. */
  203. // 2378
  204. DEF_ARGS_EXTRA *
  205. parse_def (enum command_id command, ELEMENT_LIST contents)
  206. {
  207. /* The return value - suitable for "def_args" extra value. */
  208. DEF_ARGS_EXTRA *def_args;
  209. int i, args_start = 0;
  210. ELEMENT *arg_line; /* Copy of argument line. */
  211. ELEMENT *arg, *spaces; /* Arguments and spaces extracted from line. */
  212. ELEMENT *e, *e1;
  213. enum command_id original_command = CM_NONE;
  214. def_args = malloc (sizeof (DEF_ARGS_EXTRA));
  215. memset (def_args, 0, sizeof (DEF_ARGS_EXTRA));
  216. /* Copy contents of argument line. */
  217. arg_line = new_element (ET_NONE);
  218. for (i = contents.list[0]->type != ET_empty_spaces_after_command ? 0 : 1;
  219. i < contents.number; i++)
  220. {
  221. if (contents.list[i]->text.space > 0)
  222. {
  223. /* Copy text to avoid changing the original. */
  224. ELEMENT *copy = new_element (ET_NONE);
  225. copy->parent_type = route_not_in_tree;
  226. copy->parent = 0;
  227. text_init (&copy->text);
  228. text_append_n (&copy->text,
  229. contents.list[i]->text.text,
  230. contents.list[i]->text.end);
  231. add_to_contents_as_array (arg_line, copy);
  232. /* Note that these copied elements should be destroyed with
  233. shallow_destroy_element, not destroy_element, because their
  234. contents and args are shared with in-tree elements. */
  235. }
  236. else
  237. {
  238. add_to_contents_as_array (arg_line, contents.list[i]);
  239. }
  240. }
  241. if (arg_line->contents.number > 0 // 2385
  242. && arg_line->contents.list[0]->type == ET_empty_spaces_after_command)
  243. {
  244. remove_from_contents (arg_line, 0);
  245. }
  246. /* Check for "def alias" - for example @defun for @deffn. */
  247. if (command_data(command).flags & CF_def_alias) // 2387
  248. {
  249. char *category;
  250. int i;
  251. for (i = 0; i < sizeof (def_aliases) / sizeof (*def_aliases); i++)
  252. {
  253. if (def_aliases[i].alias == command)
  254. goto found;
  255. }
  256. abort (); /* Has CF_def_alias but no alias defined. */
  257. found:
  258. /* Prepended content is stuck into contents, so
  259. @defun is converted into
  260. @deffn Function */
  261. category = def_aliases[i].category;
  262. original_command = command;
  263. command = def_aliases[i].command;
  264. /* Used when category text has a space in it. */
  265. e = new_element (ET_bracketed);
  266. insert_into_contents (arg_line, e, 0);
  267. e->parent = 0;
  268. e->parent_type = route_not_in_tree;
  269. e1 = new_element (ET_NONE);
  270. text_append_n (&e1->text, category, strlen (category));
  271. add_to_element_contents (e, e1);
  272. if (global_documentlanguage && *global_documentlanguage)
  273. {
  274. e1->type = ET_untranslated;
  275. add_extra_string (e1, "documentlanguage",
  276. global_documentlanguage);
  277. }
  278. e1->parent_type = route_not_in_tree;
  279. e = new_element (ET_NONE);
  280. text_append_n (&e->text, " ", 1);
  281. insert_into_contents (arg_line, e, 1);
  282. e->parent_type = route_not_in_tree;
  283. }
  284. /* Read arguments as CATEGORY [CLASS] [TYPE] NAME [ARGUMENTS].
  285. Meaning of these:
  286. CATEGORY - type of entity, e.g. "Function"
  287. CLASS - class for object-oriented programming
  288. TYPE - data type of a variable or function return value
  289. NAME - name of entity being documented
  290. ARGUMENTS - arguments to a function or macro */
  291. /* CATEGORY */
  292. arg = next_bracketed_or_word (arg_line, &spaces, 1);
  293. if (!arg)
  294. goto finished;
  295. if (spaces)
  296. add_to_def_args_extra (def_args, "spaces", spaces);
  297. add_to_def_args_extra (def_args, "category", arg);
  298. /* CLASS */
  299. if (command == CM_deftypeop
  300. || command == CM_defcv
  301. || command == CM_deftypecv
  302. || command == CM_defop)
  303. {
  304. arg = next_bracketed_or_word (arg_line, &spaces, 1);
  305. if (spaces)
  306. add_to_def_args_extra (def_args, "spaces", spaces);
  307. if (!arg)
  308. goto finished;
  309. add_to_def_args_extra (def_args, "class", arg);
  310. }
  311. /* TYPE */
  312. if (command == CM_deftypefn
  313. || command == CM_deftypeop
  314. || command == CM_deftypevr
  315. || command == CM_deftypecv)
  316. {
  317. arg = next_bracketed_or_word (arg_line, &spaces, 1);
  318. if (spaces)
  319. add_to_def_args_extra (def_args, "spaces", spaces);
  320. if (!arg)
  321. goto finished;
  322. add_to_def_args_extra (def_args, "type", arg);
  323. }
  324. /* NAME */
  325. /* All command types get a name. */
  326. arg = next_bracketed_or_word (arg_line, &spaces, 1);
  327. if (spaces)
  328. add_to_def_args_extra (def_args, "spaces", spaces);
  329. if (!arg)
  330. goto finished;
  331. add_to_def_args_extra (def_args, "name", arg);
  332. /* ARGUMENTS */
  333. args_start = def_args->nelements;
  334. // 2441
  335. while (arg_line->contents.number > 0)
  336. {
  337. arg = next_bracketed_or_word (arg_line, &spaces, 0);
  338. if (spaces)
  339. add_to_def_args_extra (def_args, "spaces", spaces);
  340. if (!arg)
  341. goto finished;
  342. if (arg->text.end > 0) // 2445
  343. {
  344. ELEMENT *e;
  345. char *p = arg->text.text;
  346. int len;
  347. /* Split this argument into multiple arguments, separated by
  348. separator characters. */
  349. while (1)
  350. {
  351. /* Square and round brackets used for optional arguments
  352. and grouping. Commas allowed as well? */
  353. len = strcspn (p, "[](),");
  354. if (len > 0)
  355. {
  356. e = new_element (ET_NONE);
  357. e->parent_type = route_not_in_tree;
  358. text_append_n (&e->text, p, len);
  359. add_to_def_args_extra (def_args, "arg", e);
  360. p += len;
  361. }
  362. if (!*p)
  363. break;
  364. while (*p && strchr ("[](),", *p))
  365. {
  366. e = new_element (ET_delimiter);
  367. e->parent_type = route_not_in_tree;
  368. text_append_n (&e->text, p++, 1);
  369. add_to_def_args_extra (def_args, "delimiter", e);
  370. }
  371. if (!*p)
  372. break;
  373. }
  374. destroy_element (arg);
  375. }
  376. else
  377. {
  378. add_to_def_args_extra (def_args, "arg", arg);
  379. }
  380. }
  381. finished:
  382. // 2460 - argtype
  383. /* Change some of the left sides to 'typearg'. This matters for
  384. the DocBook output. */
  385. if (args_start > 0
  386. && (command == CM_deftypefn || command == CM_deftypeop
  387. || command == CM_deftp))
  388. {
  389. int i, next_is_type = 1;
  390. for (i = args_start; i < def_args->nelements; i++)
  391. {
  392. if (!strcmp ("spaces", def_args->labels[i]))
  393. {
  394. }
  395. else if (!strcmp ("delimiter", def_args->labels[i]))
  396. {
  397. next_is_type = 1;
  398. }
  399. else if (def_args->elements[i]->cmd
  400. && def_args->elements[i]->cmd != CM_code)
  401. {
  402. next_is_type = 1;
  403. }
  404. else if (next_is_type)
  405. {
  406. def_args->labels[i] = "typearg";
  407. next_is_type = 0;
  408. }
  409. else
  410. next_is_type = 1;
  411. }
  412. }
  413. destroy_element (arg_line);
  414. return def_args;
  415. }