1/* xml.c -- xml output.
2   $Id: xml.c,v 1.3 2019/05/27 07:13:38 otto 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 */
34int xml_index_divisions = 1;
35
36typedef struct _element
37{
38  char name[32];
39  int contains_para;
40  int contained_in_para;
41  int keep_space;
42} element;
43
44element 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
257element 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
468element *xml_element_list = NULL;
469
470
471typedef 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
487replace_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
516int xml_in_menu_entry = 0;
517int xml_in_menu_entry_comment = 0;
518int xml_node_open = 0;
519int xml_node_level = -1;
520int xml_in_para = 0;
521int xml_just_after_element = 0;
522int xml_keep_space = 0;
523
524int xml_no_indent = 0;
525
526int xml_no_para = 0;
527char *xml_node_id = NULL;
528int xml_sort_index = 0;
529
530int xml_in_xref_token = 0;
531int xml_in_bookinfo = 0;
532int xml_in_book_title = 0;
533int 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.  */
537int 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.  */
541static int xml_in_footnote = 0;
542
543static int xml_after_table_term = 0;
544static int book_started = 0;
545static int first_section_opened = 0;
546
547static int xml_in_tableitem[256];
548static int xml_in_item[256];
549static int xml_table_level = 0;
550
551static int xml_in_def_item[256];
552static int xml_definition_level = 0;
553int xml_after_def_term = 0;
554
555static int in_table_title = 0;
556
557static int in_indexentry = 0;
558static int in_secondary = 0;
559static int in_indexterm = 0;
560
561char *
562xml_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
582int
583xml_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
595void
596xml_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/*  */
654static int element_stack[256];
655static int element_stack_index = 0;
656
657static int
658xml_current_element (void)
659{
660  return element_stack[element_stack_index-1];
661}
662
663static void
664xml_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
673static void
674xml_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
683int
684xml_current_stack_index (void)
685{
686  return element_stack_index;
687}
688
689void
690xml_end_current_element (void)
691{
692  xml_insert_element (xml_current_element (), END);
693}
694
695static void
696xml_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
709void
710xml_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
729void
730xml_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
745void
746xml_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\
764Local variables:\n\
765mode: sgml\n\
766sgml-indent-step:1\n\
767sgml-indent-data:nil\n\
768End:\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 */
775static 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.  */
781void
782#if defined (VA_FPRINTF) && __STDC__
783xml_insert_element_with_attribute (int elt, int arg, char *format, ...)
784#else
785xml_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 (!xml_element_list[elt].name || !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.  */
992void
993xml_insert_element (int elt, int arg)
994{
995  xml_insert_element_with_attribute (elt, arg, NULL);
996}
997
998void
999xml_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
1020typedef struct _xml_section xml_section;
1021struct _xml_section {
1022  int level;
1023  char *name;
1024  xml_section *prev;
1025};
1026
1027xml_section *last_section = NULL;
1028
1029void
1030xml_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
1056void
1057xml_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
1085void
1086xml_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
1100void
1101xml_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
1151void
1152xml_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
1167static int xml_last_character;
1168
1169void
1170xml_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 ("&amp;");
1255  else if (character == '<' && escape_html)
1256      insert_string ("&lt;");
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
1270void
1271xml_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.  */
1288typedef struct quotation_elt
1289{
1290  struct quotation_elt *next;
1291  char *type;
1292} QUOTATION_ELT;
1293
1294static QUOTATION_ELT *quotation_stack = NULL;
1295
1296void
1297xml_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.  */
1352void
1353xml_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 */
1388void
1389xml_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
1433void
1434xml_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
1474void
1475xml_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
1484void
1485xml_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
1507void
1508xml_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
1515void
1516xml_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
1560void
1561xml_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
1572static void
1573xml_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
1619static int
1620try_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
1642void
1643xml_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
1686void
1687xml_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
1699typedef struct
1700{
1701  char *from;
1702  char *to;
1703} XML_SYNONYM;
1704
1705static XML_SYNONYM **xml_synonyms = NULL;
1706static int xml_synonyms_count = 0;
1707
1708void
1709xml_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
1761int xml_last_section_output_position = 0;
1762static char last_division_letter = ' ';
1763static char index_primary[2000]; /** xx no fixed limit */
1764static int indexdivempty = 0;
1765
1766static void
1767xml_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
1778void
1779xml_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
1864void
1865xml_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
1873static void
1874xml_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
1897void
1898xml_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
1966void
1967xml_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
1997static int multitable_columns_count;
1998static int *multitable_column_widths;
1999
2000void
2001xml_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
2031static void
2032xml_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
2047void
2048xml_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
2087void
2088xml_end_multitable_column (void)
2089{
2090  xml_insert_element (ENTRY, END);
2091  xml_insert_element (ENTRY, START);
2092}
2093
2094void
2095xml_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
2123void
2124xml_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
2193void
2194xml_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
2201void
2202xml_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
2214void
2215xml_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
2329void
2330xml_end_def_term (void)
2331{
2332  xml_insert_element (DEFINITIONTERM, END);
2333  xml_after_def_term = 1;
2334}
2335