1 /* Copyright 2010-2019 Free Software Foundation, Inc.
2
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
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <ctype.h>
20 #include <string.h>
21
22 #include "parser.h"
23 #include "text.h"
24 #include "convert.h"
25
26
27 static void expand_cmd_args_to_texi (ELEMENT *e, TEXT *result);
28 static void convert_to_texinfo_internal (ELEMENT *e, TEXT *result);
29
30
31 #define ADD(x) text_append (result, x)
32
33 /* Return value to be freed by caller. */
34 char *
node_extra_to_texi(NODE_SPEC_EXTRA * nse)35 node_extra_to_texi (NODE_SPEC_EXTRA *nse)
36 {
37 TEXT result;
38
39 if (!nse)
40 return "";
41 text_init (&result);
42
43 if (nse->manual_content
44 && nse->manual_content->contents.number > 0)
45 {
46 text_append_n (&result, "(", 1);
47 convert_to_texinfo_internal (nse->manual_content, &result);
48 text_append_n (&result, ")", 1);
49 }
50 if (nse->node_content
51 && nse->node_content->contents.number > 0)
52 {
53 convert_to_texinfo_internal (nse->node_content, &result);
54 }
55 return result.text;
56 }
57
58 static void
expand_cmd_args_to_texi(ELEMENT * e,TEXT * result)59 expand_cmd_args_to_texi (ELEMENT *e, TEXT *result)
60 {
61 enum command_id cmd = e->cmd;
62 KEY_PAIR *k;
63
64 if (cmd)
65 {
66 ADD("@"); ADD(command_name(cmd));
67 }
68
69 // TODO extra spaces
70 k = lookup_extra (e, "spaces_before_argument");
71 if (k)
72 ADD((char *)k->value);
73
74 // TODO multitable or block command
75
76 if (cmd == CM_macro || cmd == CM_rmacro)
77 {
78 KEY_PAIR *k;
79 char *s = 0;
80 k = lookup_extra (e, "arg_line");
81 if (k)
82 s = (char *)k->value;
83 if (s)
84 {
85 ADD(s);
86 return;
87 }
88 }
89
90 // TODO node
91
92 if (e->args.number > 0)
93 {
94 int braces, arg_nr, i;
95 braces = (e->args.list[0]->type == ET_brace_command_arg
96 || e->args.list[0]->type == ET_brace_command_context);
97 if (braces)
98 ADD("{");
99
100 if (e->cmd == CM_verb)
101 {
102 k = lookup_extra (e, "delimiter");
103 ADD((char *)k->value);
104 }
105
106 arg_nr = 0;
107 for (i = 0; i < e->args.number; i++)
108 {
109 if (command_data(cmd).flags & CF_brace)
110 {
111 if (arg_nr)
112 ADD(",");
113 arg_nr++;
114 }
115 k = lookup_extra (e->args.list[i], "spaces_before_argument");
116 if (k)
117 ADD((char *)k->value);
118 convert_to_texinfo_internal (e->args.list[i], result);
119 k = lookup_extra (e->args.list[i], "spaces_after_argument");
120 if (k)
121 ADD((char *)k->value);
122 }
123
124 if (e->cmd == CM_verb)
125 {
126 k = lookup_extra (e, "delimiter");
127 ADD((char *)k->value);
128 }
129
130 if (braces)
131 ADD("}");
132 }
133 }
134
135 static void
convert_to_texinfo_internal(ELEMENT * e,TEXT * result)136 convert_to_texinfo_internal (ELEMENT *e, TEXT *result)
137 {
138 if (e->text.end > 0)
139 ADD(e->text.text);
140 else
141 {
142 if (e->cmd
143 || e->type == ET_def_line
144 || e->type == ET_menu_entry
145 || e->type == ET_menu_comment)
146 {
147 expand_cmd_args_to_texi (e, result);
148 }
149
150 if (e->type == ET_bracketed
151 || e->type == ET_bracketed_def_content)
152 {
153 KEY_PAIR *k;
154 ADD("{");
155 k = lookup_extra (e, "spaces_before_argument");
156 if (k)
157 ADD((char *)k->value);
158 }
159 if (e->contents.number > 0)
160 {
161 int i;
162 for (i = 0; i < e->contents.number; i++)
163 convert_to_texinfo_internal (e->contents.list[i], result);
164 }
165 if (e->type == ET_bracketed)
166 ADD("}");
167
168 // TODO: raw block command
169 if (command_flags (e) & CF_block)
170 {
171 ADD("@end ");
172 ADD(command_name(e->cmd));
173 if (command_data(e->cmd).data != BLOCK_raw)
174 ADD("\n");
175 }
176 }
177
178 return;
179 }
180 #undef ADD
181
182 /* Return value to be freed by caller. */
183 char *
convert_to_texinfo(ELEMENT * e)184 convert_to_texinfo (ELEMENT *e)
185 {
186 TEXT result;
187
188 if (!e)
189 return strdup ("");
190 text_init (&result);
191 convert_to_texinfo_internal (e, &result);
192 return result.text;
193 }
194
195 /* Very stripped-down version of Texinfo::Convert::Text.
196 Convert the contents of E to plain text. Suitable for specifying a file
197 name containing an at sign or braces. Set *SUPERFLUOUS_ARG if the contents
198 of E are too complicated to convert properly. */
199 char *
convert_to_text(ELEMENT * e,int * superfluous_arg)200 convert_to_text (ELEMENT *e, int *superfluous_arg)
201 {
202 #define ADD(x) text_append (&result, x)
203
204 TEXT result; int i;
205
206 if (!e)
207 return "";
208 text_init (&result);
209 for (i = 0; i < e->contents.number; i++)
210 {
211 ELEMENT *e1 = contents_child_by_index (e, i);
212 if (e1->text.end > 0)
213 ADD(e1->text.text);
214 else if (e1->cmd == CM_AT_SIGN
215 || e1->cmd == CM_atchar)
216 ADD("@");
217 else if (e1->cmd == CM_OPEN_BRACE
218 || e1->cmd == CM_lbracechar)
219 ADD("{");
220 else if (e1->cmd == CM_CLOSE_BRACE
221 || e1->cmd == CM_rbracechar)
222 ADD("}");
223 else
224 *superfluous_arg = 1;
225 }
226 return result.text;
227 }
228 #undef ADD
229
230