convert.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /* Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016
  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 <stdlib.h>
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17. #include "parser.h"
  18. #include "text.h"
  19. #include "convert.h"
  20. static void expand_cmd_args_to_texi (ELEMENT *e, TEXT *result);
  21. static void convert_to_texinfo_internal (ELEMENT *e, TEXT *result);
  22. #define ADD(x) text_append (result, x)
  23. char *
  24. node_extra_to_texi (NODE_SPEC_EXTRA *nse)
  25. {
  26. TEXT result;
  27. if (!nse)
  28. return "";
  29. text_init (&result);
  30. if (nse->manual_content
  31. && nse->manual_content->contents.number > 0)
  32. {
  33. text_append_n (&result, "(", 1);
  34. convert_to_texinfo_internal (nse->manual_content, &result);
  35. text_append_n (&result, ")", 1);
  36. }
  37. if (nse->node_content
  38. && nse->node_content->contents.number > 0)
  39. {
  40. convert_to_texinfo_internal (nse->node_content, &result);
  41. }
  42. return result.text;
  43. }
  44. static void
  45. expand_cmd_args_to_texi (ELEMENT *e, TEXT *result)
  46. {
  47. enum command_id cmd = e->cmd;
  48. if (cmd)
  49. {
  50. ADD("@"); ADD(command_name(cmd));
  51. }
  52. // TODO extra spaces
  53. // TODO multitable or block command
  54. if (cmd == CM_macro || cmd == CM_rmacro)
  55. {
  56. KEY_PAIR *k;
  57. char *s = 0;
  58. k = lookup_extra_key (e, "arg_line");
  59. if (k)
  60. s = (char *)k->value;
  61. if (s)
  62. {
  63. ADD(s);
  64. return;
  65. }
  66. }
  67. // TODO node
  68. // TODO "fix" arg
  69. if (e->args.number > 0)
  70. {
  71. int braces, arg_nr, i;
  72. static char s[2];
  73. braces = (e->args.list[0]->type == ET_brace_command_arg
  74. || e->args.list[0]->type == ET_brace_command_context);
  75. if (braces)
  76. ADD("{");
  77. if (e->cmd == CM_verb)
  78. {
  79. s[0] = (char ) e->type;
  80. s[1] = '\0';
  81. ADD(s);
  82. }
  83. arg_nr = 0;
  84. for (i = 0; i < e->args.number; i++)
  85. {
  86. if (command_data(cmd).flags & CF_brace)
  87. {
  88. if (arg_nr)
  89. ADD(",");
  90. arg_nr++;
  91. }
  92. convert_to_texinfo_internal (e->args.list[i], result);
  93. }
  94. if (e->cmd == CM_verb)
  95. ADD(s);
  96. if (braces)
  97. ADD("}");
  98. }
  99. }
  100. static void
  101. convert_to_texinfo_internal (ELEMENT *e, TEXT *result)
  102. {
  103. if (e->text.end > 0)
  104. ADD(e->text.text);
  105. else
  106. {
  107. // TODO "fix" argument
  108. if (e->cmd
  109. || e->type == ET_def_line
  110. || e->type == ET_menu_entry
  111. || e->type == ET_menu_comment)
  112. {
  113. expand_cmd_args_to_texi (e, result);
  114. }
  115. if (e->type == ET_bracketed)
  116. ADD("{");
  117. if (e->contents.number > 0)
  118. {
  119. int i;
  120. for (i = 0; i < e->contents.number; i++)
  121. convert_to_texinfo_internal (e->contents.list[i], result);
  122. }
  123. if (e->type == ET_bracketed)
  124. ADD("}");
  125. // TODO: "fix" arg or raw block command
  126. if (command_flags (e) & CF_block)
  127. {
  128. ADD("@end ");
  129. ADD(command_name(e->cmd));
  130. if (command_data(e->cmd).data != BLOCK_raw)
  131. ADD("\n");
  132. }
  133. }
  134. return;
  135. }
  136. #undef ADD
  137. char *
  138. convert_to_texinfo (ELEMENT *e)
  139. {
  140. TEXT result;
  141. if (!e)
  142. return "";
  143. text_init (&result);
  144. convert_to_texinfo_internal (e, &result);
  145. return result.text;
  146. }
  147. /* Very stripped-down version of Texinfo::Convert::Text.
  148. Convert the contents of E to plain text. Suitable for specifying a file
  149. name containing an at sign or braces. Set *SUPERFLUOUS_ARG if the contents
  150. of E are too complicated to convert properly. */
  151. char *
  152. convert_to_text (ELEMENT *e, int *superfluous_arg)
  153. {
  154. #define ADD(x) text_append (&result, x)
  155. TEXT result; int i;
  156. if (!e)
  157. return "";
  158. text_init (&result);
  159. for (i = 0; i < e->contents.number; i++)
  160. {
  161. ELEMENT *e1 = contents_child_by_index (e, i);
  162. if (e1->text.end > 0)
  163. ADD(e1->text.text);
  164. else if (e1->cmd == CM_AT_SIGN)
  165. ADD("@");
  166. else if (e1->cmd == CM_OPEN_BRACE)
  167. ADD("{");
  168. else if (e1->cmd == CM_CLOSE_BRACE)
  169. ADD("}");
  170. else
  171. *superfluous_arg = 1;
  172. }
  173. return result.text;
  174. }
  175. #undef ADD