1 /* xml.c -- xml output.
2 $Id: xml.c,v 1.4 2024/08/16 22:57:44 guenther Exp $
3
4 Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 Originally written by Philippe Martin <feloy@free.fr>. */
21
22 #include "system.h"
23 #include "makeinfo.h"
24 #include "insertion.h"
25 #include "files.h"
26 #include "float.h"
27 #include "macro.h"
28 #include "cmds.h"
29 #include "lang.h"
30
31 #include "xml.h"
32
33 /* Options */
34 int xml_index_divisions = 1;
35
36 typedef struct _element
37 {
38 char name[32];
39 int contains_para;
40 int contained_in_para;
41 int keep_space;
42 } element;
43
44 element texinfoml_element_list [] = {
45 { "texinfo", 1, 0, 0 },
46 { "setfilename", 0, 0, 0 },
47 { "titlefont", 0, 0, 0 },
48 { "settitle", 0, 0, 0 },
49 { "documentdescription", 1, 0, 0 },
50
51 { "node", 1, 0, 0 },
52 { "nodenext", 0, 0, 0 },
53 { "nodeprev", 0, 0, 0 },
54 { "nodeup", 0, 0, 0 },
55
56 { "chapter", 1, 0, 0 },
57 { "section", 1, 0, 0 },
58 { "subsection", 1, 0, 0 },
59 { "subsubsection", 1, 0, 0 },
60
61 { "top", 1, 0, 0 },
62 { "unnumbered", 1, 0, 0 },
63 { "unnumberedsec", 1, 0, 0 },
64 { "unnumberedsubsec", 1, 0, 0 },
65 { "unnumberedsubsubsec", 1, 0, 0 },
66
67 { "appendix", 1, 0, 0 },
68 { "appendixsec", 1, 0, 0 },
69 { "appendixsubsec", 1, 0, 0 },
70 { "appendixsubsubsec", 1, 0, 0 },
71
72 { "majorheading", 0, 0, 0 },
73 { "chapheading", 0, 0, 0 },
74 { "heading", 0, 0, 0 },
75 { "subheading", 0, 0, 0 },
76 { "subsubheading", 0, 0, 0 },
77
78 { "titlepage", 1, 0, 0 },
79 { "author", 0, 0, 0 },
80 { "booktitle", 0, 0, 0 },
81 { "booksubtitle", 0, 0, 0 },
82
83 { "menu", 1, 0, 0 },
84 { "detailmenu", 1, 0, 0 },
85 { "menuentry", 0, 0, 0 },
86 { "menutitle", 0, 0, 0 },
87 { "menucomment", 0, 0, 0 },
88 { "menunode", 0, 0, 0 },
89 { "nodename", 0, 0, 0 },
90
91 { "acronym", 0, 1, 0 },
92 { "acronymword", 0, 1, 0 },
93 { "acronymdesc", 0, 1, 0 },
94
95 { "abbrev", 0, 1, 0 },
96 { "abbrevword", 0, 1, 0 },
97 { "abbrevdesc", 0, 1, 0 },
98
99 { "tt", 0, 1, 0 },
100 { "code", 0, 1, 0 },
101 { "command", 0, 1, 0 },
102 { "env", 0, 1, 0 },
103 { "file", 0, 1, 0 },
104 { "option", 0, 1, 0 },
105 { "samp", 0, 1, 0 },
106 { "kbd", 0, 1, 0 },
107 { "url", 0, 1, 0 },
108 { "key", 0, 1, 0 },
109 { "var", 0, 1, 0 },
110 { "sc", 0, 1, 0 },
111 { "dfn", 0, 1, 0 },
112 { "emph", 0, 1, 0 },
113 { "strong", 0, 1, 0 },
114 { "cite", 0, 1, 0 },
115 { "notfixedwidth", 0, 1, 0 },
116 { "i", 0, 1, 0 },
117 { "b", 0, 1, 0 },
118 { "r", 0, 1, 0 },
119 { "slanted", 0, 1, 0 },
120 { "sansserif", 0, 1, 0 },
121
122 { "exdent", 0, 0, 0 },
123
124 { "title", 0, 0, 0 },
125 { "ifinfo", 1, 0, 0 },
126 { "sp", 0, 0, 0 },
127 { "center", 1, 0, 0 },
128 { "dircategory", 0, 0, 0 },
129 { "quotation", 1, 0, 0 },
130 { "example", 0, 0, 1 },
131 { "smallexample", 0, 0, 1 },
132 { "lisp", 0, 0, 1 },
133 { "smalllisp", 0, 0, 1 },
134 { "cartouche", 1, 0, 0 },
135 { "copying", 1, 0, 0 },
136 { "format", 0, 0, 1 },
137 { "smallformat", 0, 0, 1 },
138 { "display", 0, 0, 1 },
139 { "smalldisplay", 0, 0, 1 },
140 { "verbatim", 0, 0, 1 },
141 { "footnote", 0, 1, 0 },
142 { "", 0, 1, 0 }, /* LINEANNOTATION (docbook) */
143
144 { "", 1, 0, 0 }, /* TIP (docbook) */
145 { "", 1, 0, 0 }, /* NOTE (docbook) */
146 { "", 1, 0, 0 }, /* IMPORTANT (docbook) */
147 { "", 1, 0, 0 }, /* WARNING (docbook) */
148 { "", 1, 0, 0 }, /* CAUTION (docbook) */
149
150 { "itemize", 0, 0, 0 },
151 { "itemfunction", 0, 0, 0 },
152 { "item", 1, 0, 0 },
153 { "enumerate", 0, 0, 0 },
154 { "table", 0, 0, 0 },
155 { "tableitem", 0, 0, 0 },
156 { "tableterm", 0, 0, 0 },
157
158 { "indexterm", 0, 1, 0 },
159
160 { "math", 0, 1, 0 },
161
162 { "dmn", 0, 1, 0 },
163
164 { "xref", 0, 1, 0 },
165 { "xrefnodename", 0, 1, 0 },
166 { "xrefinfoname", 0, 1, 0 },
167 { "xrefprinteddesc", 0, 1, 0 },
168 { "xrefinfofile", 0, 1, 0 },
169 { "xrefprintedname", 0, 1, 0 },
170
171 { "inforef", 0, 1, 0 },
172 { "inforefnodename", 0, 1, 0 },
173 { "inforefrefname", 0, 1, 0 },
174 { "inforefinfoname", 0, 1, 0 },
175
176 { "uref", 0, 1, 0 },
177 { "urefurl", 0, 1, 0 },
178 { "urefdesc", 0, 1, 0 },
179 { "urefreplacement", 0, 1, 0 },
180
181 { "email", 0, 1, 0 },
182 { "emailaddress", 0, 1, 0 },
183 { "emailname", 0, 1, 0 },
184
185 { "group", 0, 0, 0 },
186 { "float", 1, 0, 0 },
187 { "floattype", 0, 0, 0 },
188 { "floatpos", 0, 0, 0 },
189 { "caption", 0, 0, 0 },
190 { "shortcaption", 0, 0, 0 },
191
192 { "", 0, 0, 0 }, /* TABLE (docbook) */
193 { "", 0, 0, 0 }, /* FIGURE (docbook) */
194 { "", 0, 0, 0 }, /* EXAMPLE (docbook) */
195 { "", 1, 0, 0 }, /* SIDEBAR (docbook) */
196
197 { "printindex", 0, 0, 0 },
198 { "listoffloats", 0, 0, 0 },
199 { "anchor", 0, 1, 0 },
200
201 { "image", 0, 0, 0 },
202 { "inlineimage", 0, 1, 0 },
203 { "alttext", 0, 1, 0 },
204
205 { "", 0, 1, 0 }, /* PRIMARY (docbook) */
206 { "", 0, 1, 0 }, /* SECONDARY (docbook) */
207 { "", 0, 0, 0 }, /* INFORMALFIGURE (docbook) */
208 { "", 0, 0, 0 }, /* MEDIAOBJECT (docbook) */
209 { "", 0, 0, 0 }, /* IMAGEOBJECT (docbook) */
210 { "", 0, 0, 0 }, /* IMAGEDATA (docbook) */
211 { "", 0, 0, 0 }, /* TEXTOBJECT (docbook) */
212 { "", 0, 0, 0 }, /* INDEXENTRY (docbook) */
213 { "", 0, 0, 0 }, /* PRIMARYIE (docbook) */
214 { "", 0, 0, 0 }, /* SECONDARYIE (docbook) */
215 { "", 0, 0, 0 }, /* INDEXDIV (docbook) */
216 { "multitable", 0, 0, 0 },
217 { "", 0, 0, 0 }, /* TGROUP (docbook) */
218 { "columnfraction", 0, 0, 0 },
219 { "thead", 0, 0, 0 },
220 { "tbody", 0, 0, 0 },
221 { "entry", 0, 0, 0 },
222 { "row", 0, 0, 0 },
223 { "", 0, 0, 0 }, /* BOOKINFO (docbook) */
224 { "", 0, 0, 0 }, /* ABSTRACT (docbook) */
225 { "", 0, 0, 0 }, /* REPLACEABLE (docbook) */
226 { "", 0, 0, 0 }, /* ENVAR (docbook) */
227 { "", 0, 0, 0 }, /* COMMENT (docbook) */
228 { "", 0, 0, 0 }, /* FUNCTION (docbook) */
229 { "", 0, 0, 0 }, /* LEGALNOTICE (docbook) */
230
231 { "contents", 0, 0, 0 },
232 { "shortcontents", 0, 0, 0 },
233 { "documentlanguage", 0, 0, 0 },
234
235 { "setvalue", 0, 0, 0 },
236 { "clearvalue", 0, 0, 0 },
237
238 { "definition", 0, 0, 0 },
239 { "definitionterm", 0, 0, 0 },
240 { "definitionitem", 1, 0, 0 },
241 { "defcategory", 0, 0, 0 },
242 { "deffunction", 0, 0, 0 },
243 { "defvariable", 0, 0, 0 },
244 { "defparam", 0, 0, 0 },
245 { "defdelimiter", 0, 0, 0 },
246 { "deftype", 0, 0, 0 },
247 { "defparamtype", 0, 0, 0 },
248 { "defdatatype", 0, 0, 0 },
249 { "defclass", 0, 0, 0 },
250 { "defclassvar", 0, 0, 0 },
251 { "defoperation", 0, 0, 0 },
252
253 { "para", 0, 0, 0 } /* Must be last */
254 /* name / contains para / contained in para / preserve space */
255 };
256
257 element docbook_element_list [] = {
258 { "book", 0, 0, 0 }, /* TEXINFO */
259 { "", 0, 0, 0 }, /* SETFILENAME */
260 { "", 0, 0, 0 }, /* TITLEINFO */
261 { "title", 0, 0, 0 }, /* SETTITLE */
262 { "", 1, 0, 0 }, /* DOCUMENTDESCRIPTION (?) */
263
264 { "", 1, 0, 0 }, /* NODE */
265 { "", 0, 0, 0 }, /* NODENEXT */
266 { "", 0, 0, 0 }, /* NODEPREV */
267 { "", 0, 0, 0 }, /* NODEUP */
268
269 { "chapter", 1, 0, 0 },
270 { "sect1", 1, 0, 0 }, /* SECTION */
271 { "sect2", 1, 0, 0 }, /* SUBSECTION */
272 { "sect3", 1, 0, 0 }, /* SUBSUBSECTION */
273
274 { "chapter", 1, 0, 0 }, /* TOP */
275 { "chapter", 1, 0, 0 }, /* UNNUMBERED */
276 { "sect1", 1, 0, 0 }, /* UNNUMBEREDSEC */
277 { "sect2", 1, 0, 0 }, /* UNNUMBEREDSUBSEC */
278 { "sect3", 1, 0, 0 }, /* UNNUMBEREDSUBSUBSEC */
279
280 { "appendix", 1, 0, 0 },
281 { "sect1", 1, 0, 0 }, /* APPENDIXSEC */
282 { "sect2", 1, 0, 0 }, /* APPENDIXSUBSEC */
283 { "sect3", 1, 0, 0 }, /* APPENDIXSUBSUBSEC */
284
285 { "bridgehead", 0, 0, 0 }, /* MAJORHEADING */
286 { "bridgehead", 0, 0, 0 }, /* CHAPHEADING */
287 { "bridgehead", 0, 0, 0 }, /* HEADING */
288 { "bridgehead", 0, 0, 0 }, /* SUBHEADING */
289 { "bridgehead", 0, 0, 0 }, /* SUBSUBHEADING */
290
291 { "", 0, 0, 0 }, /* TITLEPAGE */
292 { "", 0, 0, 0 }, /* AUTHOR */
293 { "", 0, 0, 0 }, /* BOOKTITLE */
294 { "", 0, 0, 0 }, /* BOOKSUBTITLE */
295
296 { "", 1, 0, 0 }, /* MENU */
297 { "", 1, 0, 0 }, /* DETAILMENU */
298 { "", 1, 0, 0 }, /* MENUENTRY */
299 { "", 0, 0, 0 }, /* MENUTITLE */
300 { "", 1, 0, 0 }, /* MENUCOMMENT */
301 { "", 0, 0, 0 }, /* MENUNODE */
302 { "anchor", 0, 0, 0 }, /* NODENAME */
303
304 { "acronym", 0, 1, 0 },
305 { "", 0, 1, 0 }, /* ACRONYMWORD */
306 { "", 0, 1, 0 }, /* ACRONYMDESC */
307
308 { "abbrev", 0, 1, 0 },
309 { "", 0, 1, 0 }, /* ABBREVWORD */
310 { "", 0, 1, 0 }, /* ABBREVDESC */
311
312 { "literal", 0, 1, 0 }, /* TT */
313 { "literal", 0, 1, 0 }, /* CODE */
314 { "command", 0, 1, 0 }, /* COMMAND */
315 { "envar", 0, 1, 0 }, /* ENV */
316 { "filename", 0, 1, 0 }, /* FILE */
317 { "option", 0, 1, 0 }, /* OPTION */
318 { "literal", 0, 1, 0 }, /* SAMP */
319 { "userinput", 0, 1, 0 }, /* KBD */
320 { "wordasword", 0, 1, 0 }, /* URL */
321 { "keycap", 0, 1, 0 }, /* KEY */
322 { "replaceable", 0, 1, 0 }, /* VAR */
323 { "", 0, 1, 0 }, /* SC */
324 { "firstterm", 0, 1, 0 }, /* DFN */
325 { "emphasis", 0, 1, 0 }, /* EMPH */
326 { "emphasis", 0, 1, 0 }, /* STRONG */
327 { "citetitle", 0, 1, 0 }, /* CITE */
328 { "", 0, 1, 0 }, /* NOTFIXEDWIDTH */
329 { "wordasword", 0, 1, 0 }, /* I */
330 { "emphasis", 0, 1, 0 }, /* B */
331 { "", 0, 1, 0 }, /* R */
332
333 { "", 0, 0, 0 }, /* EXDENT */
334
335 { "title", 0, 0, 0 },
336 { "", 1, 0, 0 }, /* IFINFO */
337 { "", 0, 0, 0 }, /* SP */
338 { "", 1, 0, 0 }, /* CENTER */
339 { "", 0, 0, 0 }, /* DIRCATEGORY */
340 { "blockquote", 1, 0, 0 }, /* QUOTATION */
341 { "screen", 0, 0, 1 }, /* EXAMPLE */
342 { "screen", 0, 0, 1 }, /* SMALLEXAMPLE */
343 { "programlisting", 0, 0, 1 }, /* LISP */
344 { "programlisting", 0, 0, 1 }, /* SMALLLISP */
345 { "", 1, 0, 0 }, /* CARTOUCHE */
346 { "", 1, 0, 0 }, /* COPYING */
347 { "screen", 0, 1, 1 }, /* FORMAT */
348 { "screen", 0, 1, 1 }, /* SMALLFORMAT */
349 { "literallayout", 0, 1, 1 }, /* DISPLAY */
350 { "literallayout", 0, 1, 1 }, /* SMALLDISPLAY */
351 { "screen", 0, 0, 1 }, /* VERBATIM */
352 { "footnote", 0, 1, 0 },
353 { "lineannotation", 0, 1, 0 },
354
355 { "tip", 1, 0, 0 },
356 { "note", 1, 0, 0 },
357 { "important", 1, 0, 0 },
358 { "warning", 1, 0, 0 },
359 { "caution", 1, 0, 0 },
360
361 { "itemizedlist", 0, 0, 0 }, /* ITEMIZE */
362 { "", 0, 0, 0 }, /* ITEMFUNCTION */
363 { "listitem", 1, 0, 0 }, /* ITEM */
364 { "orderedlist", 0, 0, 0 }, /* ENUMERATE */
365 { "variablelist", 0, 0, 0 }, /* TABLE */
366 { "varlistentry", 0, 0, 0 }, /* TABLEITEM */
367 { "term", 0, 0, 0 }, /* TABLETERM */
368
369 { "indexterm", 0, 1, 0 }, /* INDEXTERM */
370
371 { "", 0, 1, 0 }, /* MATH */
372
373 { "", 0, 1, 0 }, /* DIMENSION */
374
375 { "xref", 0, 1, 0 }, /* XREF */
376 { "link", 0, 1, 0 }, /* XREFNODENAME */
377 { "", 0, 1, 0 }, /* XREFINFONAME */
378 { "", 0, 1, 0 }, /* XREFPRINTEDDESC */
379 { "", 0, 1, 0 }, /* XREFINFOFILE */
380 { "", 0, 1, 0 }, /* XREFPRINTEDNAME */
381
382 { "", 0, 1, 0 }, /* INFOREF */
383 { "", 0, 1, 0 }, /* INFOREFNODENAME */
384 { "", 0, 1, 0 }, /* INFOREFREFNAME */
385 { "", 0, 1, 0 }, /* INFOREFINFONAME */
386
387 { "ulink", 0, 1, 0 }, /* UREF */
388 { "", 0, 1, 0 }, /* UREFURL */
389 { "", 0, 1, 0 }, /* UREFDESC */
390 { "", 0, 1, 0 }, /* UREFREPLACEMENT */
391
392 { "ulink", 0, 1, 0 }, /* EMAIL */
393 { "", 0, 1, 0 }, /* EMAILADDRESS */
394 { "", 0, 1, 0 }, /* EMAILNAME */
395
396 { "", 0, 0, 0 }, /* GROUP */
397 { "", 1, 0, 0 }, /* FLOAT */
398 { "", 0, 0, 0 }, /* FLOATTYPE */
399 { "", 0, 0, 0 }, /* FLOATPOS */
400 { "", 0, 0, 0 }, /* CAPTION */
401 { "", 0, 0, 0 }, /* SHORTCAPTION */
402
403 { "table", 0, 1, 0 },
404 { "figure", 0, 1, 0 },
405 { "example", 1, 1, 0 },
406 { "sidebar", 1, 0, 0 },
407
408 { "index", 0, 1, 0 }, /* PRINTINDEX */
409 { "", 0, 1, 0 }, /* LISTOFFLOATS */
410 { "", 0, 1, 0 }, /* ANCHOR */
411
412 { "", 0, 0, 0 }, /* IMAGE */
413 { "inlinemediaobject", 0, 1, 0 }, /* INLINEIMAGE */
414 { "", 0, 0, 0 }, /* IMAGEALTTEXT */
415
416 { "primary", 0, 1, 0 }, /* PRIMARY */
417 { "secondary", 0, 1, 0 },
418 { "informalfigure", 0, 0, 0 },
419 { "mediaobject", 0, 0, 0 },
420 { "imageobject", 0, 1, 0 },
421 { "imagedata", 0, 1, 0 },
422 { "textobject", 0, 1, 0 },
423 { "indexentry", 0, 0, 0 },
424 { "primaryie", 0, 0, 0 },
425 { "secondaryie", 0, 0, 0 },
426 { "indexdiv", 0, 0, 0 },
427 { "informaltable", 0, 0, 0 },
428 { "tgroup", 0, 0, 0 },
429 { "colspec", 0, 0, 0 },
430 { "thead", 0, 0, 0 },
431 { "tbody", 0, 0, 0 },
432 { "entry", 0, 0, 0 },
433 { "row", 0, 0, 0 },
434 { "bookinfo", 0, 0, 0 },
435 { "abstract", 1, 0, 0 },
436 { "replaceable", 0, 0, 0 },
437 { "envar", 0, 1, 0 },
438 { "comment", 0, 0, 0 },
439 { "function", 0, 1, 0 },
440 { "legalnotice", 1, 0, 0 },
441
442 { "", 0, 0, 0 }, /* CONTENTS (xml) */
443 { "", 0, 0, 0 }, /* SHORTCONTENTS (xml) */
444 { "", 0, 0, 0 }, /* DOCUMENT LANGUAGE (xml) */
445
446 { "", 0, 0, 0 }, /* SETVALUE (xml) */
447 { "", 0, 0, 0 }, /* CLEARVALUE (xml) */
448
449 { "blockquote", 1, 0, 0 }, /* DEFINITION */
450 { "screen", 0, 0, 1 }, /* DEFINITIONTERM */
451 { "", 0, 0, 0 }, /* DEFINITIONITEM (xml) */
452 { "", 0, 0, 0 }, /* DEFCATEGORY (xml) */
453 { "function", 0, 0, 0 }, /* DEFFUNCTION */
454 { "varname", 0, 0, 0 }, /* DEFVARIABLE */
455 { "varname", 0, 0, 0 }, /* DEFPARAM */
456 { "", 0, 0, 0 }, /* DEFDELIMITER (xml) */
457 { "returnvalue", 0, 0, 0 }, /* DEFTYPE */
458 { "type", 0, 0, 0 }, /* DEFPARAMTYPE */
459 { "structname", 0, 0, 0 }, /* DEFDATATYPE */
460 { "classname", 0, 0, 0 }, /* DEFCLASS */
461 { "property", 0, 0, 0 }, /* DEFCLASSVAR */
462 { "methodname", 0, 0, 0 }, /* DEFOPERATION */
463
464 { "para", 0, 0, 0 } /* Must be last */
465 /* name / contains para / contained in para / preserve space */
466 };
467
468 element *xml_element_list = NULL;
469
470
471 typedef struct _replace_element
472 {
473 int element_to_replace;
474 int element_containing;
475 int element_replacing;
476 } replace_element;
477
478 /* Elements to replace - Docbook only
479 -------------------
480 if `element_to_replace' have to be inserted
481 as a child of `element_containing,'
482 use `element_replacing' instead.
483
484 A value of `-1' for element_replacing means `do not use any element.'
485 */
486
487 replace_element replace_elements [] = {
488 { I, TABLETERM, EMPH },
489 { B, TABLETERM, EMPH },
490 { TT, CODE, -1 },
491 { EXAMPLE, DISPLAY, -1 },
492 { CODE, DFN, -1 },
493 { CODE, VAR, -1 },
494 { EMPH, CODE, REPLACEABLE },
495 { VAR, VAR, -1},
496 { VAR, B, EMPH},
497 { B, CODE, ENVAR},
498 { CODE, I, EMPH},
499 { SAMP, VAR, -1 },
500 { FORMAT, BOOKINFO, ABSTRACT },
501 { QUOTATION, ABSTRACT, -1},
502 { LINEANNOTATION, LINEANNOTATION, -1 },
503 { LEGALNOTICE, ABSTRACT, -1 },
504 { QUOTATION, QUOTATION, -1 },
505 /* Formal versions of table and image elements. */
506 { MULTITABLE, FLOAT, FLOATTABLE },
507 { INFORMALFIGURE, FLOAT, FLOATFIGURE },
508 { CARTOUCHE, FLOAT, FLOATCARTOUCHE },
509 /* Unnecessary markup in @defun blocks. */
510 { VAR, DEFPARAM, -1 },
511 { CODE, DEFTYPE, -1 },
512 /* Add your elements to replace here */
513 {-1, 0, 0}
514 };
515
516 int xml_in_menu_entry = 0;
517 int xml_in_menu_entry_comment = 0;
518 int xml_node_open = 0;
519 int xml_node_level = -1;
520 int xml_in_para = 0;
521 int xml_just_after_element = 0;
522 int xml_keep_space = 0;
523
524 int xml_no_indent = 0;
525
526 int xml_no_para = 0;
527 char *xml_node_id = NULL;
528 int xml_sort_index = 0;
529
530 int xml_in_xref_token = 0;
531 int xml_in_bookinfo = 0;
532 int xml_in_book_title = 0;
533 int xml_in_abstract = 0;
534
535 /* Non-zero if we are handling an element that can appear between
536 @item and @itemx, @deffn and @deffnx. */
537 int xml_dont_touch_items_defs = 0;
538
539 /* We need to keep footnote state, because elements inside footnote may try
540 to close the previous parent para. */
541 static int xml_in_footnote = 0;
542
543 static int xml_after_table_term = 0;
544 static int book_started = 0;
545 static int first_section_opened = 0;
546
547 static int xml_in_tableitem[256];
548 static int xml_in_item[256];
549 static int xml_table_level = 0;
550
551 static int xml_in_def_item[256];
552 static int xml_definition_level = 0;
553 int xml_after_def_term = 0;
554
555 static int in_table_title = 0;
556
557 static int in_indexentry = 0;
558 static int in_secondary = 0;
559 static int in_indexterm = 0;
560
561 char *
xml_id(char * id)562 xml_id (char *id)
563 {
564 char *tem = xmalloc (strlen (id) + 1);
565 char *p = tem;
566 strcpy (tem, id);
567 while (*p)
568 { /* Check if a character is allowed in ID attributes. This list differs
569 slightly from XML specs that it doesn't contain underscores.
570 See http://xml.coverpages.org/sgmlsyn/sgmlsyn.htm, ``9.3 Name'' */
571 if (!strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.", *p))
572 *p = '-';
573 p++;
574 }
575 p = tem;
576 /* First character can only be a letter. */
577 if (!strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", *p))
578 *p = 'i';
579 return tem;
580 }
581
582 int
xml_element(char * name)583 xml_element (char *name)
584 {
585 int i;
586 for (i=0; i<=PARA; i++)
587 {
588 if (strcasecmp (name, texinfoml_element_list[i].name) == 0)
589 return i;
590 }
591 printf ("Error xml_element\n");
592 return -1;
593 }
594
595 void
xml_begin_document(char * output_filename)596 xml_begin_document (char *output_filename)
597 {
598 if (book_started)
599 return;
600
601 book_started = 1;
602
603 /* Make sure this is the very first string of the output document. */
604 output_paragraph_offset = 0;
605
606 insert_string ("<?xml version=\"1.0\"");
607
608 /* At this point, we register a delayed writing for document encoding,
609 so in the end, proper encoding attribute will be inserted here.
610 Since the user is unaware that we are implicitly executing this
611 command, we should disable warnings temporarily, in order to avoid
612 possible confusion. (ie. if the output is not seekable,
613 register_delayed_write issues a warning.) */
614 {
615 extern int print_warnings;
616 int save_print_warnings = print_warnings;
617 print_warnings = 0;
618 register_delayed_write ("@documentencoding");
619 print_warnings = save_print_warnings;
620 }
621
622 insert_string ("?>\n");
623
624 if (docbook)
625 {
626 insert_string ("<!DOCTYPE book PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\" \"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\" [\n <!ENTITY tex \"TeX\">\n <!ENTITY latex \"LaTeX\">\n]>");
627 xml_element_list = docbook_element_list;
628 }
629 else
630 {
631 insert_string ("<!DOCTYPE texinfo PUBLIC \"-//GNU//DTD TexinfoML V");
632 insert_string (VERSION);
633 insert_string ("//EN\" \"http://www.gnu.org/software/texinfo/dtd/");
634 insert_string (VERSION);
635 insert_string ("/texinfo.dtd\">");
636 xml_element_list = texinfoml_element_list;
637 }
638 if (language_code != last_language_code)
639 {
640 if (docbook)
641 xml_insert_element_with_attribute (TEXINFO, START, "lang=\"%s\"", language_table[language_code].abbrev);
642 else
643 xml_insert_element_with_attribute (TEXINFO, START, "xml:lang=\"%s\"", language_table[language_code].abbrev);
644 }
645 if (!docbook)
646 {
647 xml_insert_element (SETFILENAME, START);
648 insert_string (output_filename);
649 xml_insert_element (SETFILENAME, END);
650 }
651 }
652
653 /* */
654 static int element_stack[256];
655 static int element_stack_index = 0;
656
657 static int
xml_current_element(void)658 xml_current_element (void)
659 {
660 return element_stack[element_stack_index-1];
661 }
662
663 static void
xml_push_current_element(int elt)664 xml_push_current_element (int elt)
665 {
666 element_stack[element_stack_index++] = elt;
667 if (element_stack_index > 200)
668 printf ("*** stack overflow (%d - %s) ***\n",
669 element_stack_index,
670 xml_element_list[elt].name);
671 }
672
673 static void
xml_pop_current_element(void)674 xml_pop_current_element (void)
675 {
676 element_stack_index--;
677 if (element_stack_index < 0)
678 printf ("*** stack underflow (%d - %d) ***\n",
679 element_stack_index,
680 xml_current_element());
681 }
682
683 int
xml_current_stack_index(void)684 xml_current_stack_index (void)
685 {
686 return element_stack_index;
687 }
688
689 void
xml_end_current_element(void)690 xml_end_current_element (void)
691 {
692 xml_insert_element (xml_current_element (), END);
693 }
694
695 static void
xml_indent(void)696 xml_indent (void)
697 {
698 if (xml_indentation_increment > 0)
699 {
700 int i;
701 if (output_paragraph_offset > 0
702 && output_paragraph[output_paragraph_offset-1] != '\n')
703 insert ('\n');
704 for (i = 0; i < element_stack_index * xml_indentation_increment; i++)
705 insert (' ');
706 }
707 }
708
709 void
xml_start_para(void)710 xml_start_para (void)
711 {
712 if (xml_in_para || xml_in_footnote
713 || !xml_element_list[xml_current_element()].contains_para)
714 return;
715
716 while (output_paragraph_offset > 0
717 && output_paragraph[output_paragraph_offset-1] == '\n')
718 output_paragraph_offset--;
719 xml_indent ();
720
721 insert_string ("<para");
722 if (xml_no_indent)
723 insert_string (" role=\"continues\"");
724 insert_string (">");
725 xml_no_indent = 0;
726 xml_in_para = 1;
727 }
728
729 void
xml_end_para(void)730 xml_end_para (void)
731 {
732 if (!xml_in_para || xml_in_footnote)
733 return;
734
735 while (output_paragraph_offset > 0
736 && cr_or_whitespace(output_paragraph[output_paragraph_offset-1]))
737 output_paragraph_offset--;
738
739 insert_string ("</para>");
740 if (xml_indentation_increment > 0)
741 insert ('\n');
742 xml_in_para = 0;
743 }
744
745 void
xml_end_document(void)746 xml_end_document (void)
747 {
748 if (xml_node_open)
749 {
750 if (xml_node_level != -1)
751 {
752 xml_close_sections (xml_node_level);
753 xml_node_level = -1;
754 }
755 xml_insert_element (NODE, END);
756 }
757 else
758 xml_close_sections (xml_node_level);
759
760 xml_insert_element (TEXINFO, END);
761 if (xml_indentation_increment == 0)
762 insert ('\n');
763 insert_string ("<!-- Keep this comment at the end of the file\n\
764 Local variables:\n\
765 mode: sgml\n\
766 sgml-indent-step:1\n\
767 sgml-indent-data:nil\n\
768 End:\n\
769 -->\n");
770 if (element_stack_index != 0)
771 error ("Element stack index : %d\n", element_stack_index);
772 }
773
774 /* MUST be 0 or 1, not true or false values */
775 static int start_element_inserted = 1;
776
777 /* NOTE: We use `elt' rather than `element' in the argument list of
778 the next function, since otherwise the Solaris SUNWspro compiler
779 barfs because `element' is a typedef declared near the beginning of
780 this file. */
781 void
782 #if defined (VA_FPRINTF) && __STDC__
xml_insert_element_with_attribute(int elt,int arg,char * format,...)783 xml_insert_element_with_attribute (int elt, int arg, char *format, ...)
784 #else
785 xml_insert_element_with_attribute (elt, arg, format, va_alist)
786 int elt;
787 int arg;
788 char *format;
789 va_dcl
790 #endif
791 {
792 /* Look at the replace_elements table to see if we have to change the element */
793 if (xml_sort_index)
794 return;
795 if (docbook)
796 {
797 replace_element *element_list = replace_elements;
798 while (element_list->element_to_replace >= 0)
799 {
800 if ( ( (arg == START) &&
801 (element_list->element_containing == xml_current_element ()) &&
802 (element_list->element_to_replace == elt) ) ||
803 ( (arg == END) &&
804 (element_list->element_containing == element_stack[element_stack_index-1-start_element_inserted]) &&
805 (element_list->element_to_replace == elt) ) )
806 {
807 elt = element_list->element_replacing;
808 break;
809 }
810 element_list ++;
811 }
812
813 /* Forget the element */
814 if (elt < 0)
815 {
816 if (arg == START)
817 start_element_inserted = 0;
818 else
819 /* Replace the default value, for the next time */
820 start_element_inserted = 1;
821 return;
822 }
823 }
824
825 if (!book_started)
826 return;
827
828 if (!xml_dont_touch_items_defs && arg == START)
829 {
830 if (xml_after_table_term && elt != TABLETERM && xml_table_level
831 && !xml_in_item[xml_table_level])
832 {
833 xml_after_table_term = 0;
834 xml_insert_element (ITEM, START);
835 xml_in_item[xml_table_level] = 1;
836 }
837 else if (xml_after_def_term && elt != DEFINITIONTERM)
838 {
839 xml_after_def_term = 0;
840 xml_insert_element (DEFINITIONITEM, START);
841 xml_in_def_item[xml_definition_level] = 1;
842 }
843 }
844
845 if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
846 return;
847
848 if (executing_string && arg == END)
849 switch (elt)
850 {
851 case TABLEITEM:
852 xml_in_tableitem[xml_table_level] = 0;
853 break;
854 case ITEM:
855 xml_in_item[xml_table_level] = 0;
856 break;
857 case DEFINITIONTERM:
858 xml_in_def_item[xml_definition_level] = 0;
859 break;
860 }
861
862 /* We are special-casing FIGURE element for docbook. It does appear in
863 the tag stack, but not in the output. This is to make element replacement
864 work beautifully. */
865 if (docbook && elt == FLOAT)
866 {
867 if (arg == START)
868 xml_push_current_element (elt);
869 else
870 xml_pop_current_element ();
871 return;
872 }
873
874 if (!strlen (xml_element_list[elt].name))
875 {
876 /*printf ("Warning: Inserting empty element %d\n", elt);*/
877 return;
878 }
879
880 if (arg == START && !xml_in_para && !xml_no_para
881 && xml_element_list[elt].contained_in_para)
882 xml_start_para ();
883
884 if (arg == START && xml_in_para && !xml_element_list[elt].contained_in_para)
885 xml_end_para ();
886
887 if (arg == END && xml_in_para && !xml_element_list[elt].contained_in_para)
888 xml_end_para ();
889
890 if (docbook && xml_table_level && !in_table_title
891 && !xml_in_tableitem[xml_table_level] && !xml_in_item[xml_table_level]
892 && arg == START && elt != TABLEITEM && elt != TABLETERM
893 && !in_indexterm && xml_current_element() == TABLE)
894 {
895 in_table_title = 1;
896 xml_insert_element (TITLE, START);
897 }
898
899 if (arg == START && !xml_in_para && !xml_keep_space
900 && !xml_element_list[elt].contained_in_para)
901 xml_indent ();
902
903 if (arg == START)
904 xml_push_current_element (elt);
905 else
906 xml_pop_current_element ();
907
908 /* Eat one newline before </example> and the like. */
909 if (!docbook && arg == END
910 && (xml_element_list[elt].keep_space || elt == GROUP)
911 && output_paragraph_offset > 0
912 && output_paragraph[output_paragraph_offset-1] == '\n')
913 output_paragraph_offset--;
914
915 /* And eat whitespace before </entry> in @multitables. */
916 if (arg == END && elt == ENTRY)
917 while (output_paragraph_offset > 0
918 && cr_or_whitespace(output_paragraph[output_paragraph_offset-1]))
919 output_paragraph_offset--;
920
921 /* Indent elements that can contain <para>. */
922 if (arg == END && !xml_in_para && !xml_keep_space
923 && xml_element_list[elt].contains_para)
924 xml_indent ();
925
926 /* Here are the elements we want indented. These do not contain <para>
927 directly. */
928 if (arg == END && (elt == MENUENTRY || elt == ITEMIZE || elt == ENUMERATE
929 || elt == TABLEITEM || elt == TABLE
930 || elt == MULTITABLE || elt == TGROUP || elt == THEAD || elt == TBODY
931 || elt == ROW || elt == INFORMALFIGURE
932 || (!docbook && (elt == DEFINITION || elt == DEFINITIONTERM))))
933 xml_indent ();
934
935 insert ('<');
936 if (arg == END)
937 insert ('/');
938 insert_string (xml_element_list[elt].name);
939
940 /* printf ("%s ", xml_element_list[elt].name);*/
941
942 if (format)
943 {
944 char temp_string[2000]; /* xx no fixed limits */
945 #ifdef VA_SPRINTF
946 va_list ap;
947 #endif
948
949 VA_START (ap, format);
950 #ifdef VA_SPRINTF
951 VA_SPRINTF (temp_string, format, ap);
952 #else
953 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
954 #endif
955 insert (' ');
956 insert_string (temp_string);
957 va_end (ap);
958 }
959
960 if (arg == START && xml_node_id && elt != NODENAME)
961 {
962 insert_string (" id=\"");
963 insert_string (xml_node_id);
964 insert ('"');
965 free (xml_node_id);
966 xml_node_id = NULL;
967 }
968
969 if (xml_element_list[elt].keep_space)
970 {
971 if (arg == START)
972 {
973 if (!docbook)
974 insert_string (" xml:space=\"preserve\"");
975 xml_keep_space++;
976 }
977 else
978 xml_keep_space--;
979 }
980
981 insert ('>');
982
983 if (!xml_in_para && !xml_element_list[elt].contained_in_para
984 && xml_element_list[elt].contains_para && xml_indentation_increment > 0)
985 insert ('\n');
986
987 xml_just_after_element = 1;
988 }
989
990 /* See the NOTE before xml_insert_element_with_attribute, for why we
991 use `elt' rather than `element' here. */
992 void
xml_insert_element(int elt,int arg)993 xml_insert_element (int elt, int arg)
994 {
995 xml_insert_element_with_attribute (elt, arg, NULL);
996 }
997
998 void
xml_insert_entity(char * entity_name)999 xml_insert_entity (char *entity_name)
1000 {
1001 int saved_escape_html = escape_html;
1002
1003 if (!book_started)
1004 return;
1005 if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
1006 return;
1007
1008 if (!xml_in_para && !xml_no_para && !only_macro_expansion
1009 && xml_element_list[xml_current_element ()].contains_para
1010 && !in_fixed_width_font)
1011 xml_start_para ();
1012
1013 escape_html = 0;
1014 add_char ('&');
1015 escape_html = saved_escape_html;
1016 insert_string (entity_name);
1017 add_char (';');
1018 }
1019
1020 typedef struct _xml_section xml_section;
1021 struct _xml_section {
1022 int level;
1023 char *name;
1024 xml_section *prev;
1025 };
1026
1027 xml_section *last_section = NULL;
1028
1029 void
xml_begin_node(void)1030 xml_begin_node (void)
1031 {
1032 first_section_opened = 1;
1033 if (xml_in_abstract)
1034 {
1035 xml_insert_element (ABSTRACT, END);
1036 xml_in_abstract = 0;
1037 }
1038 if (xml_in_bookinfo)
1039 {
1040 xml_insert_element (BOOKINFO, END);
1041 xml_in_bookinfo = 0;
1042 }
1043 if (xml_node_open && ! docbook)
1044 {
1045 if (xml_node_level != -1)
1046 {
1047 xml_close_sections (xml_node_level);
1048 xml_node_level = -1;
1049 }
1050 xml_insert_element (NODE, END);
1051 }
1052 xml_insert_element (NODE, START);
1053 xml_node_open = 1;
1054 }
1055
1056 void
xml_close_sections(int level)1057 xml_close_sections (int level)
1058 {
1059 if (!first_section_opened)
1060 {
1061 if (xml_in_abstract)
1062 {
1063 xml_insert_element (ABSTRACT, END);
1064 xml_in_abstract = 0;
1065 }
1066 if (xml_in_bookinfo)
1067 {
1068 xml_insert_element (BOOKINFO, END);
1069 xml_in_bookinfo = 0;
1070 }
1071 first_section_opened = 1;
1072 }
1073
1074 while (last_section && last_section->level >= level)
1075 {
1076 xml_section *temp = last_section;
1077 xml_insert_element (xml_element(last_section->name), END);
1078 temp = last_section;
1079 last_section = last_section->prev;
1080 free (temp->name);
1081 free (temp);
1082 }
1083 }
1084
1085 void
xml_open_section(int level,char * name)1086 xml_open_section (int level, char *name)
1087 {
1088 xml_section *sect = (xml_section *) xmalloc (sizeof (xml_section));
1089
1090 sect->level = level;
1091 sect->name = xmalloc (1 + strlen (name));
1092 strcpy (sect->name, name);
1093 sect->prev = last_section;
1094 last_section = sect;
1095
1096 if (xml_node_open && xml_node_level == -1)
1097 xml_node_level = level;
1098 }
1099
1100 void
xml_start_menu_entry(char * tem)1101 xml_start_menu_entry (char *tem)
1102 {
1103 char *string;
1104 discard_until ("* ");
1105
1106 /* The line number was already incremented in reader_loop when we
1107 saw the newline, and discard_until has now incremented again. */
1108 line_number--;
1109
1110 if (xml_in_menu_entry)
1111 {
1112 if (xml_in_menu_entry_comment)
1113 {
1114 xml_insert_element (MENUCOMMENT, END);
1115 xml_in_menu_entry_comment=0;
1116 }
1117 xml_insert_element (MENUENTRY, END);
1118 xml_in_menu_entry=0;
1119 }
1120 xml_insert_element (MENUENTRY, START);
1121 xml_in_menu_entry=1;
1122
1123 xml_insert_element (MENUNODE, START);
1124 string = expansion (tem, 0);
1125 add_word (string);
1126 xml_insert_element (MENUNODE, END);
1127 free (string);
1128
1129 /* The menu item may use macros, so expand them now. */
1130 xml_insert_element (MENUTITLE, START);
1131 only_macro_expansion++;
1132 get_until_in_line (1, ":", &string);
1133 only_macro_expansion--;
1134 execute_string ("%s", string); /* get escaping done */
1135 xml_insert_element (MENUTITLE, END);
1136 free (string);
1137
1138 if (looking_at ("::"))
1139 discard_until (":");
1140 else
1141 { /* discard the node name */
1142 get_until_in_line (0, ".", &string);
1143 free (string);
1144 }
1145 input_text_offset++; /* discard the second colon or the period */
1146 skip_whitespace_and_newlines();
1147 xml_insert_element (MENUCOMMENT, START);
1148 xml_in_menu_entry_comment ++;
1149 }
1150
1151 void
xml_end_menu(void)1152 xml_end_menu (void)
1153 {
1154 if (xml_in_menu_entry)
1155 {
1156 if (xml_in_menu_entry_comment)
1157 {
1158 xml_insert_element (MENUCOMMENT, END);
1159 xml_in_menu_entry_comment --;
1160 }
1161 xml_insert_element (MENUENTRY, END);
1162 xml_in_menu_entry--;
1163 }
1164 xml_insert_element (MENU, END);
1165 }
1166
1167 static int xml_last_character;
1168
1169 void
xml_add_char(int character)1170 xml_add_char (int character)
1171 {
1172 if (!book_started)
1173 return;
1174 if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
1175 return;
1176
1177 if (docbook && xml_table_level && !in_table_title
1178 && !xml_in_item[xml_table_level] && !xml_in_tableitem[xml_table_level]
1179 && !cr_or_whitespace (character) && !in_indexterm)
1180 {
1181 in_table_title = 1;
1182 xml_insert_element (TITLE, START);
1183 }
1184
1185 if (!first_section_opened && !xml_in_abstract && !xml_in_book_title
1186 && !xml_no_para && character != '\r' && character != '\n'
1187 && character != ' ' && !is_in_insertion_of_type (copying))
1188 {
1189 if (!xml_in_bookinfo)
1190 {
1191 xml_insert_element (BOOKINFO, START);
1192 xml_in_bookinfo = 1;
1193 }
1194 xml_insert_element (ABSTRACT, START);
1195 xml_in_abstract = 1;
1196 }
1197
1198 if (!xml_sort_index && !xml_in_xref_token && !xml_dont_touch_items_defs)
1199 {
1200 if (xml_after_table_term && xml_table_level
1201 && !xml_in_item[xml_table_level])
1202 {
1203 xml_after_table_term = 0;
1204 xml_insert_element (ITEM, START);
1205 xml_in_item[xml_table_level] = 1;
1206 }
1207 else if (xml_after_def_term)
1208 {
1209 xml_after_def_term = 0;
1210 xml_insert_element (DEFINITIONITEM, START);
1211 xml_in_def_item[xml_definition_level] = 1;
1212 }
1213 }
1214
1215 if (xml_just_after_element && !xml_in_para && !inhibit_paragraph_indentation)
1216 {
1217 if (character == '\r' || character == '\n' || character == '\t' || character == ' ')
1218 return;
1219 xml_just_after_element = 0;
1220 }
1221
1222 if (xml_element_list[xml_current_element()].contains_para
1223 && !xml_in_para && !only_macro_expansion && !xml_no_para
1224 && !cr_or_whitespace (character) && !in_fixed_width_font)
1225 xml_start_para ();
1226
1227 if (xml_in_para && character == '\n' && xml_last_character == '\n'
1228 && !only_macro_expansion && !xml_no_para
1229 && xml_element_list[xml_current_element()].contains_para )
1230 {
1231 xml_end_para ();
1232 xml_just_after_element = 1;
1233 return;
1234 }
1235
1236 if (xml_in_menu_entry_comment && character == '\n' && xml_last_character == '\n')
1237 {
1238 xml_insert_element (MENUCOMMENT, END);
1239 xml_in_menu_entry_comment = 0;
1240 xml_insert_element (MENUENTRY, END);
1241 xml_in_menu_entry = 0;
1242 }
1243
1244 if (xml_in_menu_entry_comment && whitespace(character)
1245 && cr_or_whitespace(xml_last_character))
1246 return;
1247
1248 if (character == '\n' && !xml_in_para && !inhibit_paragraph_indentation)
1249 return;
1250
1251 xml_last_character = character;
1252
1253 if (character == '&' && escape_html)
1254 insert_string ("&");
1255 else if (character == '<' && escape_html)
1256 insert_string ("<");
1257 else if (character == '\n' && !xml_keep_space)
1258 {
1259 if (!xml_in_para && xml_just_after_element && !multitable_active)
1260 return;
1261 else
1262 insert (docbook ? '\n' : ' ');
1263 }
1264 else
1265 insert (character);
1266
1267 return;
1268 }
1269
1270 void
xml_insert_footnote(char * note)1271 xml_insert_footnote (char *note)
1272 {
1273 if (!xml_in_para)
1274 xml_start_para ();
1275
1276 xml_in_footnote = 1;
1277 xml_insert_element (FOOTNOTE, START);
1278 insert_string ("<para>");
1279 execute_string ("%s", note);
1280 insert_string ("</para>");
1281 xml_insert_element (FOOTNOTE, END);
1282 xml_in_footnote = 0;
1283 }
1284
1285 /* We need to keep the quotation stack ourself, because insertion_stack
1286 loses item_function when we are closing the block, so we don't know
1287 what to close then. */
1288 typedef struct quotation_elt
1289 {
1290 struct quotation_elt *next;
1291 char *type;
1292 } QUOTATION_ELT;
1293
1294 static QUOTATION_ELT *quotation_stack = NULL;
1295
1296 void
xml_insert_quotation(char * type,int arg)1297 xml_insert_quotation (char *type, int arg)
1298 {
1299 int quotation_started = 0;
1300
1301 if (arg == START)
1302 {
1303 QUOTATION_ELT *new = xmalloc (sizeof (QUOTATION_ELT));
1304 new->type = xstrdup (type);
1305 new->next = quotation_stack;
1306 quotation_stack = new;
1307 }
1308 else
1309 type = quotation_stack->type;
1310
1311 /* Make use of special quotation styles of Docbook if we can. */
1312 if (docbook && strlen(type))
1313 {
1314 /* Let's assume it started. */
1315 quotation_started = 1;
1316
1317 if (strcasecmp (type, "tip") == 0)
1318 xml_insert_element (TIP, arg);
1319 else if (strcasecmp (type, "note") == 0)
1320 xml_insert_element (NOTE, arg);
1321 else if (strcasecmp (type, "important") == 0)
1322 xml_insert_element (IMPORTANT, arg);
1323 else if (strcasecmp (type, "warning") == 0)
1324 xml_insert_element (WARNING, arg);
1325 else if (strcasecmp (type, "caution") == 0)
1326 xml_insert_element (CAUTION, arg);
1327 else
1328 /* Didn't find a known quotation type :\ */
1329 quotation_started = 0;
1330 }
1331
1332 if (!quotation_started)
1333 {
1334 xml_insert_element (QUOTATION, arg);
1335 if (strlen(type) && arg == START)
1336 execute_string ("@b{%s:} ", type);
1337 }
1338
1339 if (arg == END)
1340 {
1341 QUOTATION_ELT *temp = quotation_stack;
1342 if (temp == NULL)
1343 return;
1344 quotation_stack = quotation_stack->next;
1345 free(temp->type);
1346 free(temp);
1347 }
1348 }
1349
1350 /* Starting generic docbook floats. Just starts elt with correct label
1351 and id attributes, and inserts title. */
1352 void
xml_begin_docbook_float(int elt)1353 xml_begin_docbook_float (int elt)
1354 {
1355 if (current_float_used_title ()) /* in a nested float */
1356 {
1357 xml_insert_element (elt, START); /* just insert the tag */
1358 return;
1359 }
1360
1361
1362 /* OK, need the title, tag, etc. */
1363 if (elt == CARTOUCHE) /* no labels on <sidebar> */
1364 {
1365 if (strlen (current_float_id ()) == 0)
1366 xml_insert_element (elt, START);
1367 else
1368 xml_insert_element_with_attribute (elt, START,
1369 "id=\"%s\"", xml_id (current_float_id ()));
1370 }
1371 else if (strlen (current_float_id ()) == 0)
1372 xml_insert_element_with_attribute (elt, START, "label=\"\"");
1373 else
1374 xml_insert_element_with_attribute (elt, START,
1375 "id=\"%s\" label=\"%s\"", xml_id (current_float_id ()),
1376 current_float_number ());
1377
1378 xml_insert_element (TITLE, START);
1379 execute_string ("%s", current_float_title ());
1380 xml_insert_element (TITLE, END);
1381
1382 current_float_set_title_used (); /* mark this title, tag, etc used */
1383 }
1384
1385 /*
1386 * Lists and Tables
1387 */
1388 void
xml_begin_table(int type,char * item_function)1389 xml_begin_table (int type, char *item_function)
1390 {
1391 switch (type)
1392 {
1393 case ftable:
1394 case vtable:
1395 case table:
1396 /*if (docbook)*/ /* 05-08 */
1397 {
1398 xml_insert_element (TABLE, START);
1399 xml_table_level ++;
1400 xml_in_tableitem[xml_table_level] = 0;
1401 xml_in_item[xml_table_level] = 0;
1402 xml_after_table_term = 0;
1403 }
1404 break;
1405 case itemize:
1406 if (!docbook)
1407 {
1408 xml_insert_element (ITEMIZE, START);
1409 xml_table_level ++;
1410 xml_in_item[xml_table_level] = 0;
1411 xml_insert_element (ITEMFUNCTION, START);
1412 if (*item_function == COMMAND_PREFIX
1413 && item_function[strlen (item_function) - 1] != '}'
1414 && command_needs_braces (item_function + 1))
1415 execute_string ("%s{}", item_function);
1416 else
1417 execute_string ("%s", item_function);
1418 xml_insert_element (ITEMFUNCTION, END);
1419 }
1420 else
1421 {
1422 xml_insert_element_with_attribute (ITEMIZE, START,
1423 "mark=\"%s\"",
1424 (*item_function == COMMAND_PREFIX) ?
1425 &item_function[1] : item_function);
1426 xml_table_level ++;
1427 xml_in_item[xml_table_level] = 0;
1428 }
1429 break;
1430 }
1431 }
1432
1433 void
xml_end_table(int type)1434 xml_end_table (int type)
1435 {
1436 switch (type)
1437 {
1438 case ftable:
1439 case vtable:
1440 case table:
1441 if (xml_in_item[xml_table_level])
1442 {
1443 xml_insert_element (ITEM, END);
1444 xml_in_item[xml_table_level] = 0;
1445 }
1446 if (xml_in_tableitem[xml_table_level])
1447 {
1448 xml_insert_element (TABLEITEM, END);
1449 xml_in_tableitem[xml_table_level] = 0;
1450 }
1451 xml_insert_element (TABLE, END);
1452 xml_after_table_term = 0;
1453 xml_table_level --;
1454
1455 break;
1456 case itemize:
1457 if (xml_in_item[xml_table_level])
1458 {
1459 xml_insert_element (ITEM, END);
1460 xml_in_item[xml_table_level] = 0;
1461 }
1462 /* gnat-style manual contains an itemized list without items! */
1463 if (in_table_title)
1464 {
1465 xml_insert_element (TITLE, END);
1466 in_table_title = 0;
1467 }
1468 xml_insert_element (ITEMIZE, END);
1469 xml_table_level --;
1470 break;
1471 }
1472 }
1473
1474 void
xml_begin_item(void)1475 xml_begin_item (void)
1476 {
1477 if (xml_in_item[xml_table_level])
1478 xml_insert_element (ITEM, END);
1479
1480 xml_insert_element (ITEM, START);
1481 xml_in_item[xml_table_level] = 1;
1482 }
1483
1484 void
xml_begin_table_item(void)1485 xml_begin_table_item (void)
1486 {
1487 if (!xml_after_table_term)
1488 {
1489 if (xml_in_item[xml_table_level])
1490 xml_insert_element (ITEM, END);
1491 if (xml_in_tableitem[xml_table_level])
1492 xml_insert_element (TABLEITEM, END);
1493
1494 if (in_table_title)
1495 {
1496 in_table_title = 0;
1497 xml_insert_element (TITLE, END);
1498 }
1499 xml_insert_element (TABLEITEM, START);
1500 }
1501 xml_insert_element (TABLETERM, START);
1502 xml_in_tableitem[xml_table_level] = 1;
1503 xml_in_item[xml_table_level] = 0;
1504 xml_after_table_term = 0;
1505 }
1506
1507 void
xml_continue_table_item(void)1508 xml_continue_table_item (void)
1509 {
1510 xml_insert_element (TABLETERM, END);
1511 xml_after_table_term = 1;
1512 xml_in_item[xml_table_level] = 0;
1513 }
1514
1515 void
xml_begin_enumerate(char * enum_arg)1516 xml_begin_enumerate (char *enum_arg)
1517 {
1518 if (!docbook)
1519 xml_insert_element_with_attribute (ENUMERATE, START, "first=\"%s\"", enum_arg);
1520 else
1521 {
1522 if (isdigit (*enum_arg))
1523 {
1524 int enum_val = atoi (enum_arg);
1525
1526 /* Have to check the value, not just the first digit. */
1527 if (enum_val == 0)
1528 xml_insert_element_with_attribute (ENUMERATE, START,
1529 "numeration=\"arabic\" role=\"0\"", NULL);
1530 else if (enum_val == 1)
1531 xml_insert_element_with_attribute (ENUMERATE, START,
1532 "numeration=\"arabic\"", NULL);
1533 else
1534 xml_insert_element_with_attribute (ENUMERATE, START,
1535 "continuation=\"continues\" numeration=\"arabic\"", NULL);
1536 }
1537 else if (isupper (*enum_arg))
1538 {
1539 if (enum_arg[0] == 'A')
1540 xml_insert_element_with_attribute (ENUMERATE, START,
1541 "numeration=\"upperalpha\"", NULL);
1542 else
1543 xml_insert_element_with_attribute (ENUMERATE, START,
1544 "continuation=\"continues\" numeration=\"upperalpha\"", NULL);
1545 }
1546 else
1547 {
1548 if (enum_arg[0] == 'a')
1549 xml_insert_element_with_attribute (ENUMERATE, START,
1550 "numeration=\"loweralpha\"", NULL);
1551 else
1552 xml_insert_element_with_attribute (ENUMERATE, START,
1553 "continuation=\"continues\" numeration=\"loweralpha\"", NULL);
1554 }
1555 }
1556 xml_table_level ++;
1557 xml_in_item[xml_table_level] = 0;
1558 }
1559
1560 void
xml_end_enumerate(void)1561 xml_end_enumerate (void)
1562 {
1563 if (xml_in_item[xml_table_level])
1564 {
1565 xml_insert_element (ITEM, END);
1566 xml_in_item[xml_table_level] = 0;
1567 }
1568 xml_insert_element (ENUMERATE, END);
1569 xml_table_level --;
1570 }
1571
1572 static void
xml_insert_text_file(char * name_arg)1573 xml_insert_text_file (char *name_arg)
1574 {
1575 char *fullname = xmalloc (strlen (name_arg) + 4 + 1);
1576 FILE *image_file;
1577 strcpy (fullname, name_arg);
1578 strcat (fullname, ".txt");
1579 image_file = fopen (fullname, "r");
1580 if (image_file)
1581 {
1582 int ch;
1583 int save_inhibit_indentation = inhibit_paragraph_indentation;
1584 int save_filling_enabled = filling_enabled;
1585
1586 xml_insert_element (TEXTOBJECT, START);
1587 xml_insert_element (DISPLAY, START);
1588
1589 inhibit_paragraph_indentation = 1;
1590 filling_enabled = 0;
1591 last_char_was_newline = 0;
1592
1593 /* Maybe we need to remove the final newline if the image
1594 file is only one line to allow in-line images. On the
1595 other hand, they could just make the file without a
1596 final newline. */
1597 while ((ch = getc (image_file)) != EOF)
1598 add_char (ch);
1599
1600 inhibit_paragraph_indentation = save_inhibit_indentation;
1601 filling_enabled = save_filling_enabled;
1602
1603 xml_insert_element (DISPLAY, END);
1604 xml_insert_element (TEXTOBJECT, END);
1605
1606 if (fclose (image_file) != 0)
1607 perror (fullname);
1608 }
1609 else
1610 warning (_("@image file `%s' unreadable: %s"), fullname,
1611 strerror (errno));
1612
1613 free (fullname);
1614 }
1615
1616 /* If NAME.EXT is accessible or FORCE is nonzero, insert a docbook
1617 imagedata element for FMT. Return 1 if inserted something, 0 else. */
1618
1619 static int
try_docbook_image(const char * name,const char * ext,const char * fmt,int force)1620 try_docbook_image (const char *name, const char *ext, const char *fmt,
1621 int force)
1622 {
1623 int used = 0;
1624 char *fullname = xmalloc (strlen (name) + 1 + strlen (ext) + 1);
1625 sprintf (fullname, "%s.%s", name, ext);
1626
1627 if (force || access (fullname, R_OK) == 0)
1628 {
1629 xml_insert_element (IMAGEOBJECT, START);
1630 xml_insert_element_with_attribute (IMAGEDATA, START,
1631 "fileref=\"%s\" format=\"%s\"", fullname, fmt);
1632 xml_insert_element (IMAGEDATA, END);
1633 xml_insert_element (IMAGEOBJECT, END);
1634 used = 1;
1635 }
1636
1637 free (fullname);
1638 return used;
1639 }
1640
1641
1642 void
xml_insert_docbook_image(char * name_arg)1643 xml_insert_docbook_image (char *name_arg)
1644 {
1645 int found = 0;
1646 int elt = xml_in_para ? INLINEIMAGE : MEDIAOBJECT;
1647
1648 if (is_in_insertion_of_type (floatenv))
1649 xml_begin_docbook_float (INFORMALFIGURE);
1650 else if (!xml_in_para)
1651 xml_insert_element (INFORMALFIGURE, START);
1652
1653 xml_no_para++;
1654
1655 xml_insert_element (elt, START);
1656
1657 /* A selected few from http://docbook.org/tdg/en/html/imagedata.html. */
1658 if (try_docbook_image (name_arg, "eps", "EPS", 0))
1659 found++;
1660 if (try_docbook_image (name_arg, "gif", "GIF", 0))
1661 found++;
1662 if (try_docbook_image (name_arg, "jpg", "JPG", 0))
1663 found++;
1664 if (try_docbook_image (name_arg, "jpeg", "JPEG", 0))
1665 found++;
1666 if (try_docbook_image (name_arg, "pdf", "PDF", 0))
1667 found++;
1668 if (try_docbook_image (name_arg, "png", "PNG", 0))
1669 found++;
1670 if (try_docbook_image (name_arg, "svg", "SVG", 0))
1671 found++;
1672
1673 /* If no luck so far, just assume we'll eventually have a jpg. */
1674 if (!found)
1675 try_docbook_image (name_arg, "jpg", "JPG", 1);
1676
1677 xml_insert_text_file (name_arg);
1678 xml_insert_element (elt, END);
1679
1680 xml_no_para--;
1681
1682 if (elt == MEDIAOBJECT)
1683 xml_insert_element (INFORMALFIGURE, END);
1684 }
1685
1686 void
xml_asterisk(void)1687 xml_asterisk (void)
1688 {
1689 }
1690
1691
1692 /*
1693 * INDEX
1694 */
1695 /* Used to separate primary and secondary entries in an index -- we need
1696 to have real multilivel indexing support, not just string analysis. */
1697 #define INDEX_SEP "@this string will never appear@" /* was , */
1698
1699 typedef struct
1700 {
1701 char *from;
1702 char *to;
1703 } XML_SYNONYM;
1704
1705 static XML_SYNONYM **xml_synonyms = NULL;
1706 static int xml_synonyms_count = 0;
1707
1708 void
xml_insert_indexterm(char * indexterm,char * index)1709 xml_insert_indexterm (char *indexterm, char *index)
1710 {
1711 /* @index commands can appear between @item and @itemx, @deffn and @deffnx. */
1712 if (!docbook)
1713 {
1714 /* Check to see if we need to do index redirection per @synindex. */
1715 int i;
1716 for (i = 0; i < xml_synonyms_count; i++)
1717 {
1718 if (STREQ (xml_synonyms[i]->from, index))
1719 index = xstrdup (xml_synonyms[i]->to);
1720 }
1721
1722 xml_dont_touch_items_defs++;
1723 xml_insert_element_with_attribute (INDEXTERM, START, "index=\"%s\"", index);
1724 in_indexterm = 1;
1725 execute_string ("%s", indexterm);
1726 xml_insert_element (INDEXTERM, END);
1727 in_indexterm = 0;
1728 xml_dont_touch_items_defs--;
1729 }
1730 else
1731 {
1732 char *primary = NULL, *secondary = NULL;
1733 if (strstr (indexterm+1, INDEX_SEP))
1734 {
1735 primary = xmalloc (strlen (indexterm) + 1);
1736 strcpy (primary, indexterm);
1737 secondary = strstr (primary+1, INDEX_SEP);
1738 *secondary = '\0';
1739 secondary += strlen (INDEX_SEP);
1740 }
1741 xml_insert_element_with_attribute (INDEXTERM, START, "role=\"%s\"", index);
1742 in_indexterm = 1;
1743 xml_insert_element (PRIMARY, START);
1744 if (primary)
1745 execute_string ("%s", primary);
1746 else
1747 execute_string ("%s", indexterm);
1748 xml_insert_element (PRIMARY, END);
1749 if (primary)
1750 {
1751 xml_insert_element (SECONDARY, START);
1752 execute_string ("%s", secondary);
1753 xml_insert_element (SECONDARY, END);
1754 }
1755 xml_insert_element (INDEXTERM, END);
1756 in_indexterm = 0;
1757 }
1758 }
1759
1760
1761 int xml_last_section_output_position = 0;
1762 static char last_division_letter = ' ';
1763 static char index_primary[2000]; /** xx no fixed limit */
1764 static int indexdivempty = 0;
1765
1766 static void
xml_close_indexentry(void)1767 xml_close_indexentry (void)
1768 {
1769 if (!in_indexentry)
1770 return;
1771 if (in_secondary)
1772 xml_insert_element (SECONDARYIE, END);
1773 xml_insert_element (INDEXENTRY, END);
1774 in_secondary = 0;
1775 in_indexentry = 0;
1776 }
1777
1778 void
xml_begin_index(void)1779 xml_begin_index (void)
1780 {
1781 typedef struct xml_index_title {
1782 struct xml_index_title *next;
1783 char *title;
1784 } XML_INDEX_TITLE;
1785
1786 static XML_INDEX_TITLE *xml_index_titles = NULL;
1787
1788 if (!handling_delayed_writes)
1789 { /* We assume that we just opened a section, and so that the last output is
1790 <SECTION ID="node-name"><TITLE>Title</TITLE>
1791 where SECTION can be CHAPTER, ... */
1792
1793 XML_INDEX_TITLE *new = xmalloc (sizeof (XML_INDEX_TITLE));
1794 xml_section *temp = last_section;
1795
1796 int l = output_paragraph_offset-xml_last_section_output_position;
1797 char *tmp = xmalloc (l+1);
1798 char *p = tmp;
1799 strncpy (tmp, (char *) output_paragraph, l);
1800
1801 /* We remove <SECTION */
1802 tmp[l] = '\0';
1803 while (*p != '<')
1804 p++;
1805 while (*p != ' ')
1806 p++;
1807 /* ... and its label attribute. */
1808 if (strncmp (p, " label=", 7) == 0)
1809 {
1810 p++;
1811 while (*p != ' ')
1812 p++;
1813 }
1814
1815 output_paragraph_offset = xml_last_section_output_position;
1816 xml_last_section_output_position = 0;
1817
1818 xml_pop_current_element (); /* remove section element from elements stack */
1819
1820 if (last_section)
1821 last_section = last_section->prev; /* remove section from sections stack */
1822 if (temp)
1823 {
1824 free (temp->name);
1825 free (temp);
1826 }
1827
1828 new->title = xstrdup (p);
1829 new->next = xml_index_titles;
1830 xml_index_titles = new;
1831 }
1832 else
1833 {
1834 static int xml_index_titles_reversed = 0;
1835
1836 if (!xml_index_titles_reversed)
1837 {
1838 xml_index_titles = (XML_INDEX_TITLE *) reverse_list
1839 ((GENERIC_LIST *) xml_index_titles);
1840 xml_index_titles_reversed = 1;
1841 }
1842
1843 /* We put <INDEX> */
1844 xml_insert_element (PRINTINDEX, START);
1845 if (xml_index_titles)
1846 {
1847 /* Remove the final > */
1848 if (output_paragraph_offset)
1849 output_paragraph_offset--;
1850 /* and put ID="node-name"><TITLE>Title</TITLE> */
1851 insert_string (xml_index_titles->title);
1852 free (xml_index_titles->title);
1853 xml_index_titles = xml_index_titles->next;
1854 }
1855
1856 if (xml_index_divisions)
1857 {
1858 xml_insert_element (INDEXDIV, START);
1859 indexdivempty = 1;
1860 }
1861 }
1862 }
1863
1864 void
xml_end_index(void)1865 xml_end_index (void)
1866 {
1867 xml_close_indexentry ();
1868 if (xml_index_divisions)
1869 xml_insert_element (INDEXDIV, END);
1870 xml_insert_element (PRINTINDEX, END);
1871 }
1872
1873 static void
xml_index_divide(char * entry)1874 xml_index_divide (char *entry)
1875 {
1876 char c;
1877 if (strlen (entry) > (strlen (xml_element_list[CODE].name) + 2) &&
1878 strncmp (entry+1, xml_element_list[CODE].name, strlen (xml_element_list[CODE].name)) == 0)
1879 c = entry[strlen (xml_element_list[CODE].name)+2];
1880 else
1881 c = entry[0];
1882 if (tolower (c) != last_division_letter && isalpha (c))
1883 {
1884 last_division_letter = tolower (c);
1885 xml_close_indexentry ();
1886 if (!indexdivempty)
1887 {
1888 xml_insert_element (INDEXDIV, END);
1889 xml_insert_element (INDEXDIV, START);
1890 }
1891 xml_insert_element (TITLE, START);
1892 insert (toupper (c));
1893 xml_insert_element (TITLE, END);
1894 }
1895 }
1896
1897 void
xml_insert_indexentry(char * entry,char * node)1898 xml_insert_indexentry (char *entry, char *node)
1899 {
1900 char *primary = NULL, *secondary;
1901 if (xml_index_divisions)
1902 xml_index_divide (entry);
1903
1904 indexdivempty = 0;
1905 if (strstr (entry+1, INDEX_SEP))
1906 {
1907 primary = xmalloc (strlen (entry) + 1);
1908 strcpy (primary, entry);
1909 secondary = strstr (primary+1, INDEX_SEP);
1910 *secondary = '\0';
1911 secondary += strlen (INDEX_SEP);
1912
1913 if (in_secondary && strcmp (primary, index_primary) == 0)
1914 {
1915 xml_insert_element (SECONDARYIE, END);
1916 xml_insert_element (SECONDARYIE, START);
1917 execute_string ("%s", secondary);
1918 }
1919 else
1920 {
1921 xml_close_indexentry ();
1922 xml_insert_element (INDEXENTRY, START);
1923 in_indexentry = 1;
1924 xml_insert_element (PRIMARYIE, START);
1925 execute_string ("%s", primary);
1926 xml_insert_element (PRIMARYIE, END);
1927 xml_insert_element (SECONDARYIE, START);
1928 execute_string ("%s", secondary);
1929 in_secondary = 1;
1930 }
1931 }
1932 else
1933 {
1934 xml_close_indexentry ();
1935 xml_insert_element (INDEXENTRY, START);
1936 in_indexentry = 1;
1937 xml_insert_element (PRIMARYIE, START);
1938 execute_string ("%s", entry);
1939 }
1940 add_word (", ");
1941
1942 /* Don't link to @unnumbered sections directly.
1943 We are disabling warnings temporarily, otherwise these xrefs
1944 will cause bogus warnings about missing punctuation. */
1945 {
1946 extern int print_warnings;
1947 int save_print_warnings = print_warnings;
1948 print_warnings = 0;
1949 execute_string ("%cxref{%s}", COMMAND_PREFIX, xstrdup (node));
1950 print_warnings = save_print_warnings;
1951 }
1952
1953 if (primary)
1954 {
1955 strcpy (index_primary, primary);
1956 /* xml_insert_element (SECONDARYIE, END);*/
1957 /* *(secondary-1) = ',';*/ /* necessary ? */
1958 free (primary);
1959 }
1960 else
1961 xml_insert_element (PRIMARYIE, END);
1962
1963 /* xml_insert_element (INDEXENTRY, END); */
1964 }
1965
1966 void
xml_synindex(char * from,char * to)1967 xml_synindex (char *from, char *to)
1968 {
1969 int i, slot;
1970
1971 slot = -1;
1972 for (i = 0; i < xml_synonyms_count; i++)
1973 if (!xml_synonyms[i])
1974 {
1975 slot = i;
1976 break;
1977 }
1978
1979 if (slot < 0)
1980 {
1981 slot = xml_synonyms_count;
1982 xml_synonyms_count++;
1983
1984 xml_synonyms = (XML_SYNONYM **) xrealloc (xml_synonyms,
1985 (xml_synonyms_count + 1) * sizeof (XML_SYNONYM *));
1986 }
1987
1988 xml_synonyms[slot] = xmalloc (sizeof (XML_SYNONYM));
1989 xml_synonyms[slot]->from = xstrdup (from);
1990 xml_synonyms[slot]->to = xstrdup (to);
1991 }
1992
1993 /*
1994 * MULTITABLE
1995 */
1996
1997 static int multitable_columns_count;
1998 static int *multitable_column_widths;
1999
2000 void
xml_begin_multitable(int ncolumns,int * column_widths)2001 xml_begin_multitable (int ncolumns, int *column_widths)
2002 {
2003 int i;
2004 if (docbook)
2005 {
2006 if (is_in_insertion_of_type (floatenv))
2007 xml_begin_docbook_float (MULTITABLE);
2008 else
2009 xml_insert_element (MULTITABLE, START);
2010
2011 multitable_columns_count = ncolumns;
2012 multitable_column_widths = xmalloc (sizeof (int) * ncolumns);
2013 memcpy (multitable_column_widths, column_widths,
2014 sizeof (int) * ncolumns);
2015
2016 xml_no_para = 1;
2017 }
2018 else
2019 {
2020 xml_insert_element (MULTITABLE, START);
2021 for (i=0; i<ncolumns; i++)
2022 {
2023 xml_insert_element (COLSPEC, START);
2024 add_word_args ("%d", column_widths[i]);
2025 xml_insert_element (COLSPEC, END);
2026 }
2027 xml_no_para = 1;
2028 }
2029 }
2030
2031 static void
xml_begin_multitable_group(void)2032 xml_begin_multitable_group (void)
2033 {
2034 int i;
2035
2036 xml_insert_element_with_attribute (TGROUP, START, "cols=\"%d\"",
2037 multitable_columns_count);
2038
2039 for (i=0; i < multitable_columns_count; i++)
2040 {
2041 xml_insert_element_with_attribute (COLSPEC, START,
2042 "colwidth=\"%d*\"", multitable_column_widths[i]);
2043 xml_insert_element (COLSPEC, END);
2044 }
2045 }
2046
2047 void
xml_end_multitable_row(int first_row)2048 xml_end_multitable_row (int first_row)
2049 {
2050 if (!first_row)
2051 {
2052 xml_insert_element (ENTRY, END);
2053 xml_insert_element (ROW, END);
2054 }
2055
2056 if (headitem_flag)
2057 {
2058 if (!first_row)
2059 {
2060 if (after_headitem)
2061 xml_insert_element (THEAD, END);
2062 else
2063 xml_insert_element (TBODY, END);
2064 xml_insert_element (TGROUP, END);
2065 }
2066
2067 xml_begin_multitable_group ();
2068 xml_insert_element (THEAD, START);
2069 }
2070 else if (first_row)
2071 {
2072 xml_begin_multitable_group ();
2073 xml_insert_element (TBODY, START);
2074 }
2075 else if (after_headitem)
2076 {
2077 xml_insert_element (THEAD, END);
2078 xml_insert_element (TBODY, START);
2079 }
2080 else if (first_row)
2081 xml_insert_element (TBODY, START);
2082
2083 xml_insert_element (ROW, START);
2084 xml_insert_element (ENTRY, START);
2085 }
2086
2087 void
xml_end_multitable_column(void)2088 xml_end_multitable_column (void)
2089 {
2090 xml_insert_element (ENTRY, END);
2091 xml_insert_element (ENTRY, START);
2092 }
2093
2094 void
xml_end_multitable(void)2095 xml_end_multitable (void)
2096 {
2097 xml_insert_element (ENTRY, END);
2098 xml_insert_element (ROW, END);
2099
2100 if (after_headitem)
2101 {
2102 if (docbook)
2103 warning (_("@headitem as the last item of @multitable produces invalid Docbook documents"));
2104 xml_insert_element (THEAD, END);
2105 }
2106 else
2107 xml_insert_element (TBODY, END);
2108
2109 if (docbook)
2110 xml_insert_element (TGROUP, END);
2111
2112 xml_insert_element (MULTITABLE, END);
2113 xml_no_para = 0;
2114 }
2115
2116 /*
2117 * Parameters in @def definitions
2118 */
2119
2120 #define DEFUN_SELF_DELIMITING(c) \
2121 ((c) == '(' || (c) == ')' || (c) == '[' || (c) == ']')
2122
2123 void
xml_process_defun_args(char ** defun_args,int auto_var_p)2124 xml_process_defun_args (char **defun_args, int auto_var_p)
2125 {
2126 int pending_space = 0;
2127 int just_after_paramtype = 0;
2128
2129 for (;;)
2130 {
2131 char *defun_arg = *defun_args++;
2132
2133 if (defun_arg == NULL)
2134 break;
2135
2136 if (defun_arg[0] == ' ')
2137 {
2138 pending_space = 1;
2139 continue;
2140 }
2141
2142 if (pending_space)
2143 {
2144 add_char (' ');
2145 pending_space = 0;
2146 }
2147
2148 if (DEFUN_SELF_DELIMITING (defun_arg[0]))
2149 {
2150 xml_insert_element (DEFDELIMITER, START);
2151 add_char (defun_arg[0]);
2152 xml_insert_element (DEFDELIMITER, END);
2153 just_after_paramtype = 0;
2154 }
2155 else if (defun_arg[0] == '&')
2156 {
2157 xml_insert_element (DEFPARAM, START);
2158 add_word (defun_arg);
2159 xml_insert_element (DEFPARAM, END);
2160 just_after_paramtype = 0;
2161 }
2162 else if (defun_arg[0] == COMMAND_PREFIX || just_after_paramtype)
2163 {
2164 xml_insert_element (DEFPARAM, START);
2165 execute_string ("%s", defun_arg);
2166 xml_insert_element (DEFPARAM, END);
2167 just_after_paramtype = 0;
2168 }
2169 else if (defun_arg[0] == ',' || defun_arg[0] == ';')
2170 {
2171 xml_insert_element (DEFDELIMITER, START);
2172 add_word (defun_arg);
2173 xml_insert_element (DEFDELIMITER, END);
2174 just_after_paramtype = 0;
2175 }
2176 else if (auto_var_p)
2177 {
2178 xml_insert_element (DEFPARAM, START);
2179 add_word (defun_arg);
2180 xml_insert_element (DEFPARAM, END);
2181 just_after_paramtype = 0;
2182 }
2183 else
2184 {
2185 xml_insert_element (DEFPARAMTYPE, START);
2186 add_word (defun_arg);
2187 xml_insert_element (DEFPARAMTYPE, END);
2188 just_after_paramtype = 1;
2189 }
2190 }
2191 }
2192
2193 void
xml_begin_definition(void)2194 xml_begin_definition (void)
2195 {
2196 xml_insert_element (DEFINITION, START);
2197 xml_definition_level ++;
2198 xml_in_def_item[xml_definition_level] = 0;
2199 }
2200
2201 void
xml_end_definition(void)2202 xml_end_definition (void)
2203 {
2204 if (xml_in_def_item[xml_definition_level])
2205 {
2206 xml_insert_element (DEFINITIONITEM, END);
2207 xml_in_def_item[xml_definition_level] = 0;
2208 }
2209 xml_after_def_term = 0;
2210 xml_insert_element (DEFINITION, END);
2211 xml_definition_level --;
2212 }
2213
2214 void
xml_begin_def_term(int base_type,const char * category,char * defined_name,char * type_name,char * type_name2)2215 xml_begin_def_term (int base_type, const char *category,
2216 char *defined_name, char *type_name, char *type_name2)
2217 {
2218 xml_after_def_term = 0;
2219 xml_insert_element (DEFINITIONTERM, START);
2220
2221 /* Index entry */
2222 switch (base_type)
2223 {
2224 case deffn:
2225 case deftypefn:
2226 execute_string ("@findex %s\n", defined_name);
2227 break;
2228 case defvr:
2229 case deftypevr:
2230 case defcv:
2231 execute_string ("@vindex %s\n", defined_name);
2232 break;
2233 case deftypecv:
2234 case deftypeivar:
2235 execute_string ("@vindex %s %s %s\n", defined_name, _("of"), type_name);
2236 break;
2237 case deftypemethod:
2238 case defop:
2239 case deftypeop:
2240 execute_string ("@findex %s %s %s\n", defined_name, _("on"), type_name);
2241 break;
2242 case deftp:
2243 execute_string ("@tindex %s\n", defined_name);
2244 break;
2245 }
2246
2247 /* Start with category. */
2248 xml_insert_element (DEFCATEGORY, START);
2249 execute_string (docbook ? "--- %s:" : "%s", category);
2250 xml_insert_element (DEFCATEGORY, END);
2251 add_char(' ');
2252
2253 /* Output type name first for typed definitions. */
2254 switch (base_type)
2255 {
2256 case deffn:
2257 case defvr:
2258 case deftp:
2259 break;
2260
2261 case deftypefn:
2262 case deftypevr:
2263 xml_insert_element (DEFTYPE, START);
2264 execute_string ("%s", type_name);
2265 xml_insert_element (DEFTYPE, END);
2266 add_char (' ');
2267 break;
2268
2269 case deftypecv:
2270 case deftypeivar:
2271 case deftypemethod:
2272 case deftypeop:
2273 xml_insert_element (DEFTYPE, START);
2274 execute_string ("%s", type_name2);
2275 xml_insert_element (DEFTYPE, END);
2276 add_char (' ');
2277 break;
2278
2279 default:
2280 xml_insert_element (DEFCLASS, START);
2281 execute_string ("%s", type_name);
2282 xml_insert_element (DEFCLASS, END);
2283 add_char (' ');
2284 break;
2285 }
2286
2287 /* Categorize rest of the definitions. */
2288 switch (base_type)
2289 {
2290 case deffn:
2291 case deftypefn:
2292 xml_insert_element (DEFFUNCTION, START);
2293 execute_string ("%s", defined_name);
2294 xml_insert_element (DEFFUNCTION, END);
2295 break;
2296
2297 case defvr:
2298 case deftypevr:
2299 xml_insert_element (DEFVARIABLE, START);
2300 execute_string ("%s", defined_name);
2301 xml_insert_element (DEFVARIABLE, END);
2302 break;
2303
2304 case deftp:
2305 xml_insert_element (DEFDATATYPE, START);
2306 execute_string ("%s", defined_name);
2307 xml_insert_element (DEFDATATYPE, END);
2308 break;
2309
2310 case defcv:
2311 case deftypecv:
2312 case deftypeivar:
2313 xml_insert_element (DEFCLASSVAR, START);
2314 execute_string ("%s", defined_name);
2315 xml_insert_element (DEFCLASSVAR, END);
2316 break;
2317
2318 case defop:
2319 case deftypeop:
2320 case deftypemethod:
2321 /* Operation / Method */
2322 xml_insert_element (DEFOPERATION, START);
2323 execute_string ("%s", defined_name);
2324 xml_insert_element (DEFOPERATION, END);
2325 break;
2326 }
2327 }
2328
2329 void
xml_end_def_term(void)2330 xml_end_def_term (void)
2331 {
2332 xml_insert_element (DEFINITIONTERM, END);
2333 xml_after_def_term = 1;
2334 }
2335