]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/texinfo/makeinfo/xml.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / texinfo / makeinfo / xml.c
1 /* xml.c -- xml output.
2    $Id: xml.c,v 1.52 2004/12/19 17:02:23 karl 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 \f
561 char *
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
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
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 /* \f */
654 static int element_stack[256];
655 static int element_stack_index = 0;
656
657 static int
658 xml_current_element (void)
659 {
660   return element_stack[element_stack_index-1];
661 }
662
663 static void
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
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
684 xml_current_stack_index (void)
685 {
686   return element_stack_index;
687 }
688
689 void
690 xml_end_current_element (void)
691 {
692   xml_insert_element (xml_current_element (), END);
693 }
694
695 static void
696 xml_indent (void)
697 {
698   if (xml_indentation_increment > 0)
699     {
700       int i;
701       if (output_paragraph[output_paragraph_offset-1] != '\n')
702         insert ('\n');
703       for (i = 0; i < element_stack_index * xml_indentation_increment; i++)
704         insert (' ');
705     }
706 }
707
708 void
709 xml_start_para (void)
710 {
711   if (xml_in_para || xml_in_footnote
712       || !xml_element_list[xml_current_element()].contains_para)
713     return;
714
715   while (output_paragraph[output_paragraph_offset-1] == '\n')
716     output_paragraph_offset--;
717   xml_indent ();
718
719   insert_string ("<para");
720   if (xml_no_indent)
721     insert_string (" role=\"continues\"");
722   insert_string (">");
723   xml_no_indent = 0;
724   xml_in_para = 1;
725 }
726
727 void
728 xml_end_para (void)
729 {
730   if (!xml_in_para || xml_in_footnote)
731     return;
732
733   while (cr_or_whitespace(output_paragraph[output_paragraph_offset-1]))
734     output_paragraph_offset--;
735
736   insert_string ("</para>");
737   if (xml_indentation_increment > 0)
738     insert ('\n');
739   xml_in_para = 0;
740 }
741
742 void
743 xml_end_document (void)
744 {
745   if (xml_node_open)
746     {
747       if (xml_node_level != -1)
748         {
749           xml_close_sections (xml_node_level);
750           xml_node_level = -1;
751         }
752       xml_insert_element (NODE, END);
753     }
754   else
755     xml_close_sections (xml_node_level);
756
757   xml_insert_element (TEXINFO, END);
758   if (xml_indentation_increment == 0)
759     insert ('\n');
760   insert_string ("<!-- Keep this comment at the end of the file\n\
761 Local variables:\n\
762 mode: sgml\n\
763 sgml-indent-step:1\n\
764 sgml-indent-data:nil\n\
765 End:\n\
766 -->\n");
767   if (element_stack_index != 0)
768     error ("Element stack index : %d\n", element_stack_index);
769 }
770
771 /* MUST be 0 or 1, not true or false values */
772 static int start_element_inserted = 1;
773
774 /* NOTE: We use `elt' rather than `element' in the argument list of
775    the next function, since otherwise the Solaris SUNWspro compiler
776    barfs because `element' is a typedef declared near the beginning of
777    this file.  */
778 void
779 #if defined (VA_FPRINTF) && __STDC__
780 xml_insert_element_with_attribute (int elt, int arg, char *format, ...)
781 #else
782 xml_insert_element_with_attribute (elt, arg, format, va_alist)
783      int elt;
784      int arg;
785      char *format;
786      va_dcl
787 #endif
788 {
789   /* Look at the replace_elements table to see if we have to change the element */
790   if (xml_sort_index)
791       return;
792   if (docbook)
793     {
794       replace_element *element_list = replace_elements;
795       while (element_list->element_to_replace >= 0)
796         {
797           if ( ( (arg == START) &&
798                  (element_list->element_containing == xml_current_element ()) &&
799                  (element_list->element_to_replace == elt) ) ||
800                ( (arg == END) &&
801                  (element_list->element_containing == element_stack[element_stack_index-1-start_element_inserted]) &&
802                  (element_list->element_to_replace == elt) ) )
803             {
804               elt = element_list->element_replacing;
805               break;
806             }
807           element_list ++;
808         }
809
810       /* Forget the element */
811       if (elt < 0)
812         {
813           if (arg == START)
814             start_element_inserted = 0;
815           else
816             /* Replace the default value, for the next time */
817             start_element_inserted = 1;
818           return;
819         }
820     }
821
822   if (!book_started)
823     return;
824
825   if (!xml_dont_touch_items_defs && arg == START)
826     {
827       if (xml_after_table_term && elt != TABLETERM && xml_table_level
828           && !xml_in_item[xml_table_level])
829         {
830           xml_after_table_term = 0;
831           xml_insert_element (ITEM, START);
832           xml_in_item[xml_table_level] = 1;
833         }
834       else if (xml_after_def_term && elt != DEFINITIONTERM)
835         {
836           xml_after_def_term = 0;
837           xml_insert_element (DEFINITIONITEM, START);
838           xml_in_def_item[xml_definition_level] = 1;
839         }
840     }
841
842   if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
843     return;
844
845   if (executing_string && arg == END)
846     switch (elt)
847       {
848       case TABLEITEM:
849         xml_in_tableitem[xml_table_level] = 0;
850         break;
851       case ITEM:
852         xml_in_item[xml_table_level] = 0;
853         break;
854       case DEFINITIONTERM:
855         xml_in_def_item[xml_definition_level] = 0;
856         break;
857       }
858
859   /* We are special-casing FIGURE element for docbook.  It does appear in
860      the tag stack, but not in the output.  This is to make element replacement
861      work beautifully.  */
862   if (docbook && elt == FLOAT)
863     {
864       if (arg == START)
865         xml_push_current_element (elt);
866       else
867         xml_pop_current_element ();
868       return;
869     }
870
871   if (!xml_element_list[elt].name || !strlen (xml_element_list[elt].name))
872     {
873       /*printf ("Warning: Inserting empty element %d\n", elt);*/
874       return;
875     }
876
877   if (arg == START && !xml_in_para && !xml_no_para
878       && xml_element_list[elt].contained_in_para)
879     xml_start_para ();
880
881   if (arg == START && xml_in_para && !xml_element_list[elt].contained_in_para)
882     xml_end_para ();
883
884   if (arg == END && xml_in_para && !xml_element_list[elt].contained_in_para)
885     xml_end_para ();
886
887   if (docbook && xml_table_level && !in_table_title
888       && !xml_in_tableitem[xml_table_level] && !xml_in_item[xml_table_level]
889       && arg == START && elt != TABLEITEM && elt != TABLETERM
890       && !in_indexterm && xml_current_element() == TABLE)
891     {
892       in_table_title = 1;
893       xml_insert_element (TITLE, START);
894     }
895
896   if (arg == START && !xml_in_para && !xml_keep_space
897       && !xml_element_list[elt].contained_in_para)
898     xml_indent ();
899
900   if (arg == START)
901     xml_push_current_element (elt);
902   else
903     xml_pop_current_element ();
904
905   /* Eat one newline before </example> and the like.  */
906   if (!docbook && arg == END
907       && (xml_element_list[elt].keep_space || elt == GROUP)
908       && output_paragraph[output_paragraph_offset-1] == '\n')
909     output_paragraph_offset--;
910
911   /* And eat whitespace before </entry> in @multitables.  */
912   if (arg == END && elt == ENTRY)
913       while (cr_or_whitespace(output_paragraph[output_paragraph_offset-1]))
914     output_paragraph_offset--;
915
916   /* Indent elements that can contain <para>.  */
917   if (arg == END && !xml_in_para && !xml_keep_space
918       && xml_element_list[elt].contains_para)
919     xml_indent ();
920
921   /* Here are the elements we want indented.  These do not contain <para>
922      directly.  */
923   if (arg == END && (elt == MENUENTRY || elt == ITEMIZE || elt == ENUMERATE
924         || elt == TABLEITEM || elt == TABLE
925         || elt == MULTITABLE || elt == TGROUP || elt == THEAD || elt == TBODY
926         || elt == ROW || elt == INFORMALFIGURE
927         || (!docbook && (elt == DEFINITION || elt == DEFINITIONTERM))))
928     xml_indent ();
929
930   insert ('<');
931   if (arg == END)
932     insert ('/');
933   insert_string (xml_element_list[elt].name);
934
935   /*  printf ("%s ", xml_element_list[elt].name);*/
936
937   if (format)
938     {
939       char temp_string[2000]; /* xx no fixed limits */
940 #ifdef VA_SPRINTF
941       va_list ap;
942 #endif
943
944       VA_START (ap, format);
945 #ifdef VA_SPRINTF
946       VA_SPRINTF (temp_string, format, ap);
947 #else
948       sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
949 #endif
950       insert (' ');
951       insert_string (temp_string);
952       va_end (ap);
953     }
954
955   if (arg == START && xml_node_id && elt != NODENAME)
956     {
957       insert_string (" id=\"");
958       insert_string (xml_node_id);
959       insert ('"');
960       free (xml_node_id);
961       xml_node_id = NULL;
962     }
963
964   if (xml_element_list[elt].keep_space)
965     {
966       if (arg == START)
967         {
968           if (!docbook)
969             insert_string (" xml:space=\"preserve\"");
970           xml_keep_space++;
971         }
972       else
973         xml_keep_space--;
974     }
975
976   insert ('>');
977
978   if (!xml_in_para && !xml_element_list[elt].contained_in_para
979       && xml_element_list[elt].contains_para && xml_indentation_increment > 0)
980     insert ('\n');
981
982   xml_just_after_element = 1;
983 }
984
985 /* See the NOTE before xml_insert_element_with_attribute, for why we
986    use `elt' rather than `element' here.  */
987 void
988 xml_insert_element (int elt, int arg)
989 {
990   xml_insert_element_with_attribute (elt, arg, NULL);
991 }
992
993 void
994 xml_insert_entity (char *entity_name)
995 {
996   int saved_escape_html = escape_html;
997
998   if (!book_started)
999     return;
1000   if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
1001     return;
1002
1003   if (!xml_in_para && !xml_no_para && !only_macro_expansion
1004       && xml_element_list[xml_current_element ()].contains_para
1005       && !in_fixed_width_font)
1006     xml_start_para ();
1007
1008   escape_html = 0;
1009   add_char ('&');
1010   escape_html = saved_escape_html;
1011   insert_string (entity_name);
1012   add_char (';');
1013 }
1014
1015 typedef struct _xml_section xml_section;
1016 struct _xml_section {
1017   int level;
1018   char *name;
1019   xml_section *prev;
1020 };
1021
1022 xml_section *last_section = NULL;
1023
1024 void
1025 xml_begin_node (void)
1026 {
1027   first_section_opened = 1;
1028   if (xml_in_abstract)
1029     {
1030       xml_insert_element (ABSTRACT, END);
1031       xml_in_abstract = 0;
1032     }
1033   if (xml_in_bookinfo)
1034     {
1035       xml_insert_element (BOOKINFO, END);
1036       xml_in_bookinfo = 0;
1037     }
1038   if (xml_node_open && ! docbook)
1039     {
1040       if (xml_node_level != -1)
1041         {
1042           xml_close_sections (xml_node_level);
1043           xml_node_level = -1;
1044         }
1045       xml_insert_element (NODE, END);
1046     }
1047   xml_insert_element (NODE, START);
1048   xml_node_open = 1;
1049 }
1050
1051 void
1052 xml_close_sections (int level)
1053 {
1054   if (!first_section_opened)
1055     {
1056       if (xml_in_abstract)
1057         {
1058           xml_insert_element (ABSTRACT, END);
1059           xml_in_abstract = 0;
1060         }
1061       if (xml_in_bookinfo)
1062         {
1063           xml_insert_element (BOOKINFO, END);
1064           xml_in_bookinfo = 0;
1065         }
1066       first_section_opened = 1;
1067     }
1068
1069   while (last_section && last_section->level >= level)
1070     {
1071       xml_section *temp = last_section;
1072       xml_insert_element (xml_element(last_section->name), END);
1073       temp = last_section;
1074       last_section = last_section->prev;
1075       free (temp->name);
1076       free (temp);
1077     }
1078 }
1079
1080 void
1081 xml_open_section (int level, char *name)
1082 {
1083   xml_section *sect = (xml_section *) xmalloc (sizeof (xml_section));
1084
1085   sect->level = level;
1086   sect->name = xmalloc (1 + strlen (name));
1087   strcpy (sect->name, name);
1088   sect->prev = last_section;
1089   last_section = sect;
1090
1091   if (xml_node_open && xml_node_level == -1)
1092     xml_node_level = level;
1093 }
1094
1095 void
1096 xml_start_menu_entry (char *tem)
1097 {
1098   char *string;
1099   discard_until ("* ");
1100
1101   /* The line number was already incremented in reader_loop when we
1102      saw the newline, and discard_until has now incremented again.  */
1103   line_number--;
1104
1105   if (xml_in_menu_entry)
1106     {
1107       if (xml_in_menu_entry_comment)
1108         {
1109           xml_insert_element (MENUCOMMENT, END);
1110           xml_in_menu_entry_comment=0;
1111         }
1112       xml_insert_element (MENUENTRY, END);
1113       xml_in_menu_entry=0;
1114     }
1115   xml_insert_element (MENUENTRY, START);
1116   xml_in_menu_entry=1;
1117
1118   xml_insert_element (MENUNODE, START);
1119   string = expansion (tem, 0);
1120   add_word (string);
1121   xml_insert_element (MENUNODE, END);
1122   free (string);
1123
1124   /* The menu item may use macros, so expand them now.  */
1125   xml_insert_element (MENUTITLE, START);
1126   only_macro_expansion++;
1127   get_until_in_line (1, ":", &string);
1128   only_macro_expansion--;
1129   execute_string ("%s", string); /* get escaping done */
1130   xml_insert_element (MENUTITLE, END);
1131   free (string);
1132
1133   if (looking_at ("::"))
1134     discard_until (":");
1135   else
1136     { /* discard the node name */
1137       get_until_in_line (0, ".", &string);
1138       free (string);
1139     }
1140   input_text_offset++;  /* discard the second colon or the period */
1141   skip_whitespace_and_newlines();
1142   xml_insert_element (MENUCOMMENT, START);
1143   xml_in_menu_entry_comment ++;
1144 }
1145
1146 void
1147 xml_end_menu (void)
1148 {
1149   if (xml_in_menu_entry)
1150     {
1151       if (xml_in_menu_entry_comment)
1152         {
1153           xml_insert_element (MENUCOMMENT, END);
1154           xml_in_menu_entry_comment --;
1155         }
1156       xml_insert_element (MENUENTRY, END);
1157       xml_in_menu_entry--;
1158     }
1159   xml_insert_element (MENU, END);
1160 }
1161
1162 static int xml_last_character;
1163
1164 void
1165 xml_add_char (int character)
1166 {
1167   if (!book_started)
1168       return;
1169   if (docbook && !only_macro_expansion && (in_menu || in_detailmenu))
1170     return;
1171
1172   if (docbook && xml_table_level && !in_table_title
1173       && !xml_in_item[xml_table_level] && !xml_in_tableitem[xml_table_level]
1174       && !cr_or_whitespace (character) && !in_indexterm)
1175     {
1176       in_table_title = 1;
1177       xml_insert_element (TITLE, START);
1178     }
1179
1180   if (!first_section_opened && !xml_in_abstract && !xml_in_book_title
1181       && !xml_no_para && character != '\r' && character != '\n'
1182       && character != ' ' && !is_in_insertion_of_type (copying))
1183     {
1184       if (!xml_in_bookinfo)
1185         {
1186           xml_insert_element (BOOKINFO, START);
1187           xml_in_bookinfo = 1;
1188         }
1189       xml_insert_element (ABSTRACT, START);
1190       xml_in_abstract = 1;
1191     }
1192
1193   if (!xml_sort_index && !xml_in_xref_token && !xml_dont_touch_items_defs)
1194     {
1195       if (xml_after_table_term && xml_table_level
1196           && !xml_in_item[xml_table_level])
1197         {
1198           xml_after_table_term = 0;
1199           xml_insert_element (ITEM, START);
1200           xml_in_item[xml_table_level] = 1;
1201         }
1202       else if (xml_after_def_term)
1203         {
1204           xml_after_def_term = 0;
1205           xml_insert_element (DEFINITIONITEM, START);
1206           xml_in_def_item[xml_definition_level] = 1;
1207         }
1208     }
1209
1210   if (xml_just_after_element && !xml_in_para && !inhibit_paragraph_indentation)
1211     {
1212       if (character == '\r' || character == '\n' || character == '\t' || character == ' ')
1213         return;
1214       xml_just_after_element = 0;
1215     }
1216
1217   if (xml_element_list[xml_current_element()].contains_para
1218       && !xml_in_para && !only_macro_expansion && !xml_no_para
1219       && !cr_or_whitespace (character) && !in_fixed_width_font)
1220     xml_start_para ();
1221
1222   if (xml_in_para && character == '\n' && xml_last_character == '\n'
1223       && !only_macro_expansion && !xml_no_para
1224       && xml_element_list[xml_current_element()].contains_para )
1225     {
1226       xml_end_para ();
1227       xml_just_after_element = 1;
1228       return;
1229     }
1230
1231   if (xml_in_menu_entry_comment && character == '\n' && xml_last_character == '\n')
1232     {
1233       xml_insert_element (MENUCOMMENT, END);
1234       xml_in_menu_entry_comment = 0;
1235       xml_insert_element (MENUENTRY, END);
1236       xml_in_menu_entry = 0;
1237     }
1238
1239   if (xml_in_menu_entry_comment && whitespace(character)
1240       && cr_or_whitespace(xml_last_character))
1241     return;
1242
1243   if (character == '\n' && !xml_in_para && !inhibit_paragraph_indentation)
1244     return;
1245
1246   xml_last_character = character;
1247
1248   if (character == '&' && escape_html)
1249       insert_string ("&amp;");
1250   else if (character == '<' && escape_html)
1251       insert_string ("&lt;");
1252   else if (character == '\n' && !xml_keep_space)
1253     {
1254       if (!xml_in_para && xml_just_after_element && !multitable_active)
1255         return;
1256       else
1257         insert (docbook ? '\n' : ' ');
1258     }
1259   else
1260     insert (character);
1261
1262   return;
1263 }
1264
1265 void
1266 xml_insert_footnote (char *note)
1267 {
1268   if (!xml_in_para)
1269     xml_start_para ();
1270
1271   xml_in_footnote = 1;
1272   xml_insert_element (FOOTNOTE, START);
1273   insert_string ("<para>");
1274   execute_string ("%s", note);
1275   insert_string ("</para>");
1276   xml_insert_element (FOOTNOTE, END);
1277   xml_in_footnote = 0;
1278 }
1279
1280 /* We need to keep the quotation stack ourself, because insertion_stack
1281    loses item_function when we are closing the block, so we don't know
1282    what to close then.  */
1283 typedef struct quotation_elt
1284 {
1285   struct quotation_elt *next;
1286   char *type;
1287 } QUOTATION_ELT;
1288
1289 static QUOTATION_ELT *quotation_stack = NULL;
1290
1291 void
1292 xml_insert_quotation (char *type, int arg)
1293 {
1294   int quotation_started = 0;
1295
1296   if (arg == START)
1297     {
1298       QUOTATION_ELT *new = xmalloc (sizeof (QUOTATION_ELT));
1299       new->type = xstrdup (type);
1300       new->next = quotation_stack;
1301       quotation_stack = new;
1302     }
1303   else
1304     type = quotation_stack->type;
1305
1306   /* Make use of special quotation styles of Docbook if we can.  */
1307   if (docbook && strlen(type))
1308     {
1309       /* Let's assume it started.  */
1310       quotation_started = 1;
1311
1312       if (strcasecmp (type, "tip") == 0)
1313         xml_insert_element (TIP, arg);
1314       else if (strcasecmp (type, "note") == 0)
1315         xml_insert_element (NOTE, arg);
1316       else if (strcasecmp (type, "important") == 0)
1317         xml_insert_element (IMPORTANT, arg);
1318       else if (strcasecmp (type, "warning") == 0)
1319         xml_insert_element (WARNING, arg);
1320       else if (strcasecmp (type, "caution") == 0)
1321         xml_insert_element (CAUTION, arg);
1322       else
1323         /* Didn't find a known quotation type :\ */
1324         quotation_started = 0;
1325     }
1326
1327   if (!quotation_started)
1328     {
1329       xml_insert_element (QUOTATION, arg);
1330       if (strlen(type) && arg == START)
1331         execute_string ("@b{%s:} ", type);
1332     }
1333
1334   if (arg == END)
1335     {
1336       QUOTATION_ELT *temp = quotation_stack;
1337       if (temp == NULL)
1338         return;
1339       quotation_stack = quotation_stack->next;
1340       free(temp->type);
1341       free(temp);
1342     }
1343 }
1344
1345 /* Starting generic docbook floats.  Just starts elt with correct label
1346    and id attributes, and inserts title.  */
1347 void
1348 xml_begin_docbook_float (int elt)
1349 {
1350   if (current_float_used_title ())      /* in a nested float */
1351     {
1352       xml_insert_element (elt, START);  /* just insert the tag */
1353       return;
1354     }
1355
1356
1357   /* OK, need the title, tag, etc. */
1358   if (elt == CARTOUCHE)    /* no labels on <sidebar> */
1359     {
1360        if (strlen (current_float_id ()) == 0)
1361           xml_insert_element (elt, START);
1362        else
1363           xml_insert_element_with_attribute (elt, START,
1364               "id=\"%s\"", xml_id (current_float_id ()));
1365     }
1366   else if (strlen (current_float_id ()) == 0)
1367     xml_insert_element_with_attribute (elt, START, "label=\"\"");
1368   else
1369     xml_insert_element_with_attribute (elt, START,
1370         "id=\"%s\" label=\"%s\"", xml_id (current_float_id ()),
1371         current_float_number ());
1372
1373   xml_insert_element (TITLE, START);
1374   execute_string ("%s", current_float_title ());
1375   xml_insert_element (TITLE, END);
1376
1377   current_float_set_title_used ();      /* mark this title, tag, etc used */
1378 }
1379
1380 /*
1381  * Lists and Tables
1382  */
1383 void
1384 xml_begin_table (int type, char *item_function)
1385 {
1386   switch (type)
1387     {
1388     case ftable:
1389     case vtable:
1390     case table:
1391       /*if (docbook)*/ /* 05-08 */
1392         {
1393           xml_insert_element (TABLE, START);
1394           xml_table_level ++;
1395           xml_in_tableitem[xml_table_level] = 0;
1396           xml_in_item[xml_table_level] = 0;
1397           xml_after_table_term = 0;
1398         }
1399       break;
1400     case itemize:
1401       if (!docbook)
1402         {
1403           xml_insert_element (ITEMIZE, START);
1404           xml_table_level ++;
1405           xml_in_item[xml_table_level] = 0;
1406           xml_insert_element (ITEMFUNCTION, START);
1407           if (*item_function == COMMAND_PREFIX
1408               && item_function[strlen (item_function) - 1] != '}'
1409               && command_needs_braces (item_function + 1))
1410             execute_string ("%s{}", item_function);
1411           else
1412             execute_string ("%s", item_function);
1413           xml_insert_element (ITEMFUNCTION, END);
1414         }
1415       else
1416         {
1417           xml_insert_element_with_attribute (ITEMIZE, START,
1418                                              "mark=\"%s\"",
1419                                              (*item_function == COMMAND_PREFIX) ?
1420                                              &item_function[1] : item_function);
1421           xml_table_level ++;
1422           xml_in_item[xml_table_level] = 0;
1423         }
1424       break;
1425     }
1426 }
1427
1428 void
1429 xml_end_table (int type)
1430 {
1431   switch (type)
1432     {
1433     case ftable:
1434     case vtable:
1435     case table:
1436       if (xml_in_item[xml_table_level])
1437         {
1438           xml_insert_element (ITEM, END);
1439           xml_in_item[xml_table_level] = 0;
1440         }
1441       if (xml_in_tableitem[xml_table_level])
1442         {
1443           xml_insert_element (TABLEITEM, END);
1444           xml_in_tableitem[xml_table_level] = 0;
1445         }
1446       xml_insert_element (TABLE, END);
1447       xml_after_table_term = 0;
1448       xml_table_level --;
1449
1450       break;
1451     case itemize:
1452       if (xml_in_item[xml_table_level])
1453         {
1454           xml_insert_element (ITEM, END);
1455           xml_in_item[xml_table_level] = 0;
1456         }
1457       /* gnat-style manual contains an itemized list without items! */
1458       if (in_table_title)
1459         {
1460           xml_insert_element (TITLE, END);
1461           in_table_title = 0;
1462         }
1463       xml_insert_element (ITEMIZE, END);
1464       xml_table_level --;
1465       break;
1466     }
1467 }
1468
1469 void
1470 xml_begin_item (void)
1471 {
1472   if (xml_in_item[xml_table_level])
1473     xml_insert_element (ITEM, END);
1474
1475   xml_insert_element (ITEM, START);
1476   xml_in_item[xml_table_level] = 1;
1477 }
1478
1479 void
1480 xml_begin_table_item (void)
1481 {
1482   if (!xml_after_table_term)
1483     {
1484       if (xml_in_item[xml_table_level])
1485         xml_insert_element (ITEM, END);
1486       if (xml_in_tableitem[xml_table_level])
1487         xml_insert_element (TABLEITEM, END);
1488
1489       if (in_table_title)
1490         {
1491           in_table_title = 0;
1492           xml_insert_element (TITLE, END);
1493         }
1494       xml_insert_element (TABLEITEM, START);
1495     }
1496   xml_insert_element (TABLETERM, START);
1497   xml_in_tableitem[xml_table_level] = 1;
1498   xml_in_item[xml_table_level] = 0;
1499   xml_after_table_term = 0;
1500 }
1501
1502 void
1503 xml_continue_table_item (void)
1504 {
1505   xml_insert_element (TABLETERM, END);
1506   xml_after_table_term = 1;
1507   xml_in_item[xml_table_level] = 0;
1508 }
1509
1510 void
1511 xml_begin_enumerate (char *enum_arg)
1512 {
1513   if (!docbook)
1514     xml_insert_element_with_attribute (ENUMERATE, START, "first=\"%s\"", enum_arg);
1515   else
1516     {
1517       if (isdigit (*enum_arg))
1518         {
1519           int enum_val = atoi (enum_arg);
1520
1521           /* Have to check the value, not just the first digit.  */
1522           if (enum_val == 0)
1523             xml_insert_element_with_attribute (ENUMERATE, START,
1524                 "numeration=\"arabic\" role=\"0\"", NULL);
1525           else if (enum_val == 1)
1526             xml_insert_element_with_attribute (ENUMERATE, START,
1527                 "numeration=\"arabic\"", NULL);
1528           else
1529             xml_insert_element_with_attribute (ENUMERATE, START,
1530                 "continuation=\"continues\" numeration=\"arabic\"", NULL);
1531         }
1532       else if (isupper (*enum_arg))
1533         {
1534           if (enum_arg[0] == 'A')
1535             xml_insert_element_with_attribute (ENUMERATE, START,
1536                 "numeration=\"upperalpha\"", NULL);
1537           else
1538             xml_insert_element_with_attribute (ENUMERATE, START,
1539                 "continuation=\"continues\" numeration=\"upperalpha\"", NULL);
1540         }
1541       else
1542         {
1543           if (enum_arg[0] == 'a')
1544             xml_insert_element_with_attribute (ENUMERATE, START,
1545                 "numeration=\"loweralpha\"", NULL);
1546           else
1547             xml_insert_element_with_attribute (ENUMERATE, START,
1548                 "continuation=\"continues\" numeration=\"loweralpha\"", NULL);
1549         }
1550     }
1551   xml_table_level ++;
1552   xml_in_item[xml_table_level] = 0;
1553 }
1554
1555 void
1556 xml_end_enumerate (void)
1557 {
1558   if (xml_in_item[xml_table_level])
1559     {
1560       xml_insert_element (ITEM, END);
1561       xml_in_item[xml_table_level] = 0;
1562     }
1563   xml_insert_element (ENUMERATE, END);
1564   xml_table_level --;
1565 }
1566
1567 static void
1568 xml_insert_text_file (char *name_arg)
1569 {
1570   char *fullname = xmalloc (strlen (name_arg) + 4 + 1);
1571   FILE *image_file;
1572   strcpy (fullname, name_arg);
1573   strcat (fullname, ".txt");
1574   image_file = fopen (fullname, "r");
1575   if (image_file)
1576     {
1577       int ch;
1578       int save_inhibit_indentation = inhibit_paragraph_indentation;
1579       int save_filling_enabled = filling_enabled;
1580
1581       xml_insert_element (TEXTOBJECT, START);
1582       xml_insert_element (DISPLAY, START);
1583
1584       inhibit_paragraph_indentation = 1;
1585       filling_enabled = 0;
1586       last_char_was_newline = 0;
1587
1588       /* Maybe we need to remove the final newline if the image
1589          file is only one line to allow in-line images.  On the
1590          other hand, they could just make the file without a
1591          final newline.  */
1592       while ((ch = getc (image_file)) != EOF)
1593         add_char (ch);
1594
1595       inhibit_paragraph_indentation = save_inhibit_indentation;
1596       filling_enabled = save_filling_enabled;
1597
1598       xml_insert_element (DISPLAY, END);
1599       xml_insert_element (TEXTOBJECT, END);
1600
1601       if (fclose (image_file) != 0)
1602         perror (fullname);
1603     }
1604   else
1605     warning (_("@image file `%s' unreadable: %s"), fullname,
1606              strerror (errno));
1607
1608   free (fullname);
1609 }
1610
1611 /* If NAME.EXT is accessible or FORCE is nonzero, insert a docbook
1612    imagedata element for FMT.  Return 1 if inserted something, 0 else.  */
1613
1614 static int
1615 try_docbook_image (const char *name, const char *ext, const char *fmt,
1616                    int force)
1617 {
1618   int used = 0;
1619   char *fullname = xmalloc (strlen (name) + 1 + strlen (ext) + 1);
1620   sprintf (fullname, "%s.%s", name, ext);
1621
1622   if (force || access (fullname, R_OK) == 0)
1623    {
1624      xml_insert_element (IMAGEOBJECT, START);
1625      xml_insert_element_with_attribute (IMAGEDATA, START,
1626        "fileref=\"%s\" format=\"%s\"", fullname, fmt);
1627      xml_insert_element (IMAGEDATA, END);
1628      xml_insert_element (IMAGEOBJECT, END);
1629      used = 1;
1630    }
1631  
1632  free (fullname);
1633  return used;
1634 }
1635
1636
1637 void
1638 xml_insert_docbook_image (char *name_arg)
1639 {
1640   int found = 0;
1641   int elt = xml_in_para ? INLINEIMAGE : MEDIAOBJECT;
1642
1643   if (is_in_insertion_of_type (floatenv))
1644     xml_begin_docbook_float (INFORMALFIGURE);
1645   else if (!xml_in_para)
1646     xml_insert_element (INFORMALFIGURE, START);
1647
1648   xml_no_para++;
1649
1650   xml_insert_element (elt, START);
1651
1652   /* A selected few from http://docbook.org/tdg/en/html/imagedata.html.  */
1653   if (try_docbook_image (name_arg, "eps", "EPS", 0))
1654     found++;
1655   if (try_docbook_image (name_arg, "gif", "GIF", 0))
1656     found++;
1657   if (try_docbook_image (name_arg, "jpg", "JPG", 0))
1658     found++;
1659   if (try_docbook_image (name_arg, "jpeg", "JPEG", 0))
1660     found++;
1661   if (try_docbook_image (name_arg, "pdf", "PDF", 0))
1662     found++;
1663   if (try_docbook_image (name_arg, "png", "PNG", 0))
1664     found++;
1665   if (try_docbook_image (name_arg, "svg", "SVG", 0))
1666     found++;
1667
1668   /* If no luck so far, just assume we'll eventually have a jpg.  */
1669   if (!found)
1670     try_docbook_image (name_arg, "jpg", "JPG", 1);
1671  
1672   xml_insert_text_file (name_arg);
1673   xml_insert_element (elt, END);
1674
1675   xml_no_para--;
1676
1677   if (elt == MEDIAOBJECT)
1678     xml_insert_element (INFORMALFIGURE, END);
1679 }
1680
1681 void
1682 xml_asterisk (void)
1683 {
1684 }
1685
1686
1687 /*
1688  *     INDEX
1689  */
1690 /* Used to separate primary and secondary entries in an index -- we need
1691    to have real multilivel indexing support, not just string analysis.  */
1692 #define INDEX_SEP "@this string will never appear@" /* was , */
1693
1694 typedef struct
1695 {
1696   char *from;
1697   char *to;
1698 } XML_SYNONYM;
1699
1700 static XML_SYNONYM **xml_synonyms = NULL;
1701 static int xml_synonyms_count = 0;
1702
1703 void
1704 xml_insert_indexterm (char *indexterm, char *index)
1705 {
1706   /* @index commands can appear between @item and @itemx, @deffn and @deffnx.  */
1707   if (!docbook)
1708     {
1709       /* Check to see if we need to do index redirection per @synindex.  */
1710       int i;
1711       for (i = 0; i < xml_synonyms_count; i++)
1712         {
1713           if (STREQ (xml_synonyms[i]->from, index))
1714             index = xstrdup (xml_synonyms[i]->to);
1715         }
1716
1717       xml_dont_touch_items_defs++;
1718       xml_insert_element_with_attribute (INDEXTERM, START, "index=\"%s\"", index);
1719       in_indexterm = 1;
1720       execute_string ("%s", indexterm);
1721       xml_insert_element (INDEXTERM, END);
1722       in_indexterm = 0;
1723       xml_dont_touch_items_defs--;
1724     }
1725   else
1726     {
1727       char *primary = NULL, *secondary = NULL;
1728       if (strstr (indexterm+1, INDEX_SEP))
1729         {
1730           primary = xmalloc (strlen (indexterm) + 1);
1731           strcpy (primary, indexterm);
1732           secondary = strstr (primary+1, INDEX_SEP);
1733           *secondary = '\0';
1734           secondary += strlen (INDEX_SEP);
1735         }
1736       xml_insert_element_with_attribute (INDEXTERM, START, "role=\"%s\"", index);
1737       in_indexterm = 1;
1738       xml_insert_element (PRIMARY, START);
1739       if (primary)
1740         execute_string ("%s", primary);
1741       else
1742         execute_string ("%s", indexterm);
1743       xml_insert_element (PRIMARY, END);
1744       if (primary)
1745         {
1746           xml_insert_element (SECONDARY, START);
1747           execute_string ("%s", secondary);
1748           xml_insert_element (SECONDARY, END);
1749         }
1750       xml_insert_element (INDEXTERM, END);
1751       in_indexterm = 0;
1752     }
1753 }
1754
1755
1756 int xml_last_section_output_position = 0;
1757 static char last_division_letter = ' ';
1758 static char index_primary[2000]; /** xx no fixed limit */
1759 static int indexdivempty = 0;
1760
1761 static void
1762 xml_close_indexentry (void)
1763 {
1764   if (!in_indexentry)
1765     return;
1766   if (in_secondary)
1767     xml_insert_element (SECONDARYIE, END);
1768   xml_insert_element (INDEXENTRY, END);
1769   in_secondary = 0;
1770   in_indexentry = 0;
1771 }
1772
1773 void
1774 xml_begin_index (void)
1775 {
1776   typedef struct xml_index_title {
1777       struct xml_index_title *next;
1778       char *title;
1779   } XML_INDEX_TITLE;
1780
1781   static XML_INDEX_TITLE *xml_index_titles = NULL;
1782
1783   if (!handling_delayed_writes)
1784     { /* We assume that we just opened a section, and so that the last output is
1785          <SECTION ID="node-name"><TITLE>Title</TITLE>
1786          where SECTION can be CHAPTER, ...  */
1787
1788       XML_INDEX_TITLE *new = xmalloc (sizeof (XML_INDEX_TITLE));
1789       xml_section *temp = last_section;
1790
1791       int l = output_paragraph_offset-xml_last_section_output_position;
1792       char *tmp = xmalloc (l+1);
1793       char *p = tmp;
1794       strncpy (tmp, (char *) output_paragraph, l);
1795
1796       /* We remove <SECTION */
1797       tmp[l] = '\0';
1798       while (*p != '<')
1799         p++;
1800       while (*p != ' ')
1801         p++;
1802       /* ... and its label attribute.  */
1803       if (strncmp (p, " label=", 7) == 0)
1804         {
1805           p++;
1806           while (*p != ' ')
1807             p++;
1808         }
1809
1810       output_paragraph_offset = xml_last_section_output_position;
1811       xml_last_section_output_position = 0;
1812
1813       xml_pop_current_element (); /* remove section element from elements stack */
1814
1815       if (last_section)
1816         last_section = last_section->prev; /* remove section from sections stack */
1817       if (temp)
1818         {
1819           free (temp->name);
1820           free (temp);
1821         }
1822
1823       new->title = xstrdup (p);
1824       new->next = xml_index_titles;
1825       xml_index_titles = new;
1826     }
1827   else
1828     {
1829       static int xml_index_titles_reversed = 0;
1830
1831       if (!xml_index_titles_reversed)
1832         {
1833           xml_index_titles = (XML_INDEX_TITLE *) reverse_list
1834             ((GENERIC_LIST *) xml_index_titles);
1835           xml_index_titles_reversed = 1;
1836         }
1837
1838       /* We put <INDEX> */
1839       xml_insert_element (PRINTINDEX, START);
1840       if (xml_index_titles)
1841         {
1842           /* Remove the final > */
1843           output_paragraph_offset--;
1844           /* and put  ID="node-name"><TITLE>Title</TITLE> */
1845           insert_string (xml_index_titles->title);
1846           free (xml_index_titles->title);
1847           xml_index_titles = xml_index_titles->next;
1848         }
1849
1850       if (xml_index_divisions)
1851         {
1852           xml_insert_element (INDEXDIV, START);
1853           indexdivempty = 1;
1854         }
1855     }
1856 }
1857
1858 void
1859 xml_end_index (void)
1860 {
1861   xml_close_indexentry ();
1862   if (xml_index_divisions)
1863     xml_insert_element (INDEXDIV, END);
1864   xml_insert_element (PRINTINDEX, END);
1865 }
1866
1867 static void
1868 xml_index_divide (char *entry)
1869 {
1870   char c;
1871   if (strlen (entry) > (strlen (xml_element_list[CODE].name) + 2) &&
1872       strncmp (entry+1, xml_element_list[CODE].name, strlen (xml_element_list[CODE].name)) == 0)
1873     c = entry[strlen (xml_element_list[CODE].name)+2];
1874   else
1875     c = entry[0];
1876   if (tolower (c) != last_division_letter && isalpha (c))
1877     {
1878       last_division_letter = tolower (c);
1879       xml_close_indexentry ();
1880       if (!indexdivempty)
1881         {
1882           xml_insert_element (INDEXDIV, END);
1883           xml_insert_element (INDEXDIV, START);
1884         }
1885       xml_insert_element (TITLE, START);
1886       insert (toupper (c));
1887       xml_insert_element (TITLE, END);
1888     }
1889 }
1890
1891 void
1892 xml_insert_indexentry (char *entry, char *node)
1893 {
1894   char *primary = NULL, *secondary;
1895   if (xml_index_divisions)
1896     xml_index_divide (entry);
1897
1898   indexdivempty = 0;
1899   if (strstr (entry+1, INDEX_SEP))
1900     {
1901       primary = xmalloc (strlen (entry) + 1);
1902       strcpy (primary, entry);
1903       secondary = strstr (primary+1, INDEX_SEP);
1904       *secondary = '\0';
1905       secondary += strlen (INDEX_SEP);
1906
1907       if (in_secondary && strcmp (primary, index_primary) == 0)
1908         {
1909           xml_insert_element (SECONDARYIE, END);
1910           xml_insert_element (SECONDARYIE, START);
1911           execute_string ("%s", secondary);
1912         }
1913       else
1914         {
1915           xml_close_indexentry ();
1916           xml_insert_element (INDEXENTRY, START);
1917           in_indexentry = 1;
1918           xml_insert_element (PRIMARYIE, START);
1919           execute_string ("%s", primary);
1920           xml_insert_element (PRIMARYIE, END);
1921           xml_insert_element (SECONDARYIE, START);
1922           execute_string ("%s", secondary);
1923           in_secondary = 1;
1924         }
1925     }
1926   else
1927     {
1928       xml_close_indexentry ();
1929       xml_insert_element (INDEXENTRY, START);
1930       in_indexentry = 1;
1931       xml_insert_element (PRIMARYIE, START);
1932       execute_string ("%s", entry);
1933     }
1934   add_word (", ");
1935
1936   /* Don't link to @unnumbered sections directly.
1937      We are disabling warnings temporarily, otherwise these xrefs
1938      will cause bogus warnings about missing punctuation.  */
1939   {
1940     extern int print_warnings;
1941     int save_print_warnings = print_warnings;
1942     print_warnings = 0;
1943     execute_string ("%cxref{%s}", COMMAND_PREFIX, xstrdup (node));
1944     print_warnings = save_print_warnings;
1945   }
1946
1947   if (primary)
1948     {
1949       strcpy (index_primary, primary);
1950       /*      xml_insert_element (SECONDARYIE, END);*/
1951       /*     *(secondary-1) = ',';*/ /* necessary ? */
1952       free (primary);
1953     }
1954   else
1955     xml_insert_element (PRIMARYIE, END);
1956
1957   /*  xml_insert_element (INDEXENTRY, END); */
1958 }
1959
1960 void
1961 xml_synindex (char *from, char *to)
1962 {
1963   int i, slot;
1964
1965   slot = -1;
1966   for (i = 0; i < xml_synonyms_count; i++)
1967     if (!xml_synonyms[i])
1968       {
1969         slot = i;
1970         break;
1971       }
1972
1973   if (slot < 0)
1974     {
1975       slot = xml_synonyms_count;
1976       xml_synonyms_count++;
1977
1978       xml_synonyms = (XML_SYNONYM **) xrealloc (xml_synonyms,
1979           (xml_synonyms_count + 1) * sizeof (XML_SYNONYM *));
1980     }
1981
1982   xml_synonyms[slot] = xmalloc (sizeof (XML_SYNONYM));
1983   xml_synonyms[slot]->from = xstrdup (from);
1984   xml_synonyms[slot]->to = xstrdup (to);
1985 }
1986
1987 /*
1988  * MULTITABLE
1989  */
1990
1991 static int multitable_columns_count;
1992 static int *multitable_column_widths;
1993
1994 void
1995 xml_begin_multitable (int ncolumns, int *column_widths)
1996 {
1997   int i;
1998   if (docbook)
1999     {
2000       if (is_in_insertion_of_type (floatenv))
2001         xml_begin_docbook_float (MULTITABLE);
2002       else
2003         xml_insert_element (MULTITABLE, START);
2004
2005       multitable_columns_count = ncolumns;
2006       multitable_column_widths = xmalloc (sizeof (int) * ncolumns);
2007       memcpy (multitable_column_widths, column_widths,
2008           sizeof (int) * ncolumns);
2009
2010       xml_no_para = 1;
2011     }
2012   else
2013     {
2014       xml_insert_element (MULTITABLE, START);
2015       for (i=0; i<ncolumns; i++)
2016         {
2017           xml_insert_element (COLSPEC, START);
2018           add_word_args ("%d", column_widths[i]);
2019           xml_insert_element (COLSPEC, END);
2020         }
2021       xml_no_para = 1;
2022     }
2023 }
2024
2025 static void
2026 xml_begin_multitable_group (void)
2027 {
2028   int i;
2029
2030   xml_insert_element_with_attribute (TGROUP, START, "cols=\"%d\"",
2031       multitable_columns_count);
2032
2033   for (i=0; i < multitable_columns_count; i++)
2034     {
2035       xml_insert_element_with_attribute (COLSPEC, START,
2036           "colwidth=\"%d*\"", multitable_column_widths[i]);
2037       xml_insert_element (COLSPEC, END);
2038     }
2039 }
2040
2041 void
2042 xml_end_multitable_row (int first_row)
2043 {
2044   if (!first_row)
2045     {
2046       xml_insert_element (ENTRY, END);
2047       xml_insert_element (ROW, END);
2048     }
2049
2050   if (headitem_flag)
2051     {
2052       if (!first_row)
2053         {
2054           if (after_headitem)
2055             xml_insert_element (THEAD, END);
2056           else
2057             xml_insert_element (TBODY, END);
2058           xml_insert_element (TGROUP, END);
2059         }
2060
2061       xml_begin_multitable_group ();
2062       xml_insert_element (THEAD, START);
2063     }
2064   else if (first_row)
2065     {
2066       xml_begin_multitable_group ();
2067       xml_insert_element (TBODY, START);
2068     }
2069   else if (after_headitem)
2070     {
2071       xml_insert_element (THEAD, END);
2072       xml_insert_element (TBODY, START);
2073     }
2074   else if (first_row)
2075     xml_insert_element (TBODY, START);
2076
2077   xml_insert_element (ROW, START);
2078   xml_insert_element (ENTRY, START);
2079 }
2080
2081 void
2082 xml_end_multitable_column (void)
2083 {
2084   xml_insert_element (ENTRY, END);
2085   xml_insert_element (ENTRY, START);
2086 }
2087
2088 void
2089 xml_end_multitable (void)
2090 {
2091   xml_insert_element (ENTRY, END);
2092   xml_insert_element (ROW, END);
2093
2094   if (after_headitem)
2095     {
2096       if (docbook)
2097         warning (_("@headitem as the last item of @multitable produces invalid Docbook documents"));
2098       xml_insert_element (THEAD, END);
2099     }
2100   else
2101     xml_insert_element (TBODY, END);
2102
2103   if (docbook)
2104     xml_insert_element (TGROUP, END);
2105
2106   xml_insert_element (MULTITABLE, END);
2107   xml_no_para = 0;
2108 }
2109
2110 /*
2111  * Parameters in @def definitions
2112  */
2113
2114 #define DEFUN_SELF_DELIMITING(c) \
2115   ((c) == '(' || (c) == ')' || (c) == '[' || (c) == ']')
2116
2117 void
2118 xml_process_defun_args (char **defun_args, int auto_var_p)
2119 {
2120   int pending_space = 0;
2121   int just_after_paramtype = 0;
2122
2123   for (;;)
2124     {
2125       char *defun_arg = *defun_args++;
2126
2127       if (defun_arg == NULL)
2128         break;
2129
2130       if (defun_arg[0] == ' ')
2131         {
2132           pending_space = 1;
2133           continue;
2134         }
2135
2136       if (pending_space)
2137         {
2138           add_char (' ');
2139           pending_space = 0;
2140         }
2141
2142       if (DEFUN_SELF_DELIMITING (defun_arg[0]))
2143         {
2144           xml_insert_element (DEFDELIMITER, START);
2145           add_char (defun_arg[0]);
2146           xml_insert_element (DEFDELIMITER, END);
2147           just_after_paramtype = 0;
2148         }
2149       else if (defun_arg[0] == '&')
2150         {
2151           xml_insert_element (DEFPARAM, START);
2152           add_word (defun_arg);
2153           xml_insert_element (DEFPARAM, END);
2154           just_after_paramtype = 0;
2155         }
2156       else if (defun_arg[0] == COMMAND_PREFIX || just_after_paramtype)
2157         {
2158           xml_insert_element (DEFPARAM, START);
2159           execute_string ("%s", defun_arg);
2160           xml_insert_element (DEFPARAM, END);
2161           just_after_paramtype = 0;
2162         }
2163       else if (defun_arg[0] == ',' || defun_arg[0] == ';')
2164         {
2165           xml_insert_element (DEFDELIMITER, START);
2166           add_word (defun_arg);
2167           xml_insert_element (DEFDELIMITER, END);
2168           just_after_paramtype = 0;
2169         }
2170       else if (auto_var_p)
2171         {
2172           xml_insert_element (DEFPARAM, START);
2173           add_word (defun_arg);
2174           xml_insert_element (DEFPARAM, END);
2175           just_after_paramtype = 0;
2176         }
2177       else
2178         {
2179           xml_insert_element (DEFPARAMTYPE, START);
2180           add_word (defun_arg);
2181           xml_insert_element (DEFPARAMTYPE, END);
2182           just_after_paramtype = 1;
2183         }
2184     }
2185 }
2186
2187 void
2188 xml_begin_definition (void)
2189 {
2190   xml_insert_element (DEFINITION, START);
2191   xml_definition_level ++;
2192   xml_in_def_item[xml_definition_level] = 0;
2193 }
2194
2195 void
2196 xml_end_definition (void)
2197 {
2198   if (xml_in_def_item[xml_definition_level])
2199     {
2200       xml_insert_element (DEFINITIONITEM, END);
2201       xml_in_def_item[xml_definition_level] = 0;
2202     }
2203   xml_after_def_term = 0;
2204   xml_insert_element (DEFINITION, END);
2205   xml_definition_level --;
2206 }
2207
2208 void
2209 xml_begin_def_term (int base_type, const char *category,
2210     char *defined_name, char *type_name, char *type_name2)
2211 {
2212   xml_after_def_term = 0;
2213   xml_insert_element (DEFINITIONTERM, START);
2214
2215   /* Index entry */
2216   switch (base_type)
2217     {
2218     case deffn:
2219     case deftypefn:
2220       execute_string ("@findex %s\n", defined_name);
2221       break;
2222     case defvr:
2223     case deftypevr:
2224     case defcv:
2225       execute_string ("@vindex %s\n", defined_name);
2226       break;
2227     case deftypecv:
2228     case deftypeivar:
2229       execute_string ("@vindex %s %s %s\n", defined_name, _("of"), type_name);
2230       break;
2231     case deftypemethod:
2232     case defop:
2233     case deftypeop:
2234       execute_string ("@findex %s %s %s\n", defined_name, _("on"), type_name);
2235       break;
2236     case deftp:
2237       execute_string ("@tindex %s\n", defined_name);
2238       break;
2239     }
2240
2241   /* Start with category.  */
2242   xml_insert_element (DEFCATEGORY, START);
2243   execute_string (docbook ? "--- %s:" : "%s", category);
2244   xml_insert_element (DEFCATEGORY, END);
2245   add_char(' ');
2246
2247   /* Output type name first for typed definitions.  */
2248   switch (base_type)
2249     {
2250     case deffn:
2251     case defvr:
2252     case deftp:
2253       break;
2254
2255     case deftypefn:
2256     case deftypevr:
2257       xml_insert_element (DEFTYPE, START);
2258       execute_string ("%s", type_name);
2259       xml_insert_element (DEFTYPE, END);
2260       add_char (' ');
2261       break;
2262
2263     case deftypecv:
2264     case deftypeivar:
2265     case deftypemethod:
2266     case deftypeop:
2267       xml_insert_element (DEFTYPE, START);
2268       execute_string ("%s", type_name2);
2269       xml_insert_element (DEFTYPE, END);
2270       add_char (' ');
2271       break;
2272
2273     default:
2274       xml_insert_element (DEFCLASS, START);
2275       execute_string ("%s", type_name);
2276       xml_insert_element (DEFCLASS, END);
2277       add_char (' ');
2278       break;
2279     }
2280
2281   /* Categorize rest of the definitions.  */
2282   switch (base_type)
2283     {
2284     case deffn:
2285     case deftypefn:
2286       xml_insert_element (DEFFUNCTION, START);
2287       execute_string ("%s", defined_name);
2288       xml_insert_element (DEFFUNCTION, END);
2289       break;
2290
2291     case defvr:
2292     case deftypevr:
2293       xml_insert_element (DEFVARIABLE, START);
2294       execute_string ("%s", defined_name);
2295       xml_insert_element (DEFVARIABLE, END);
2296       break;
2297
2298     case deftp:
2299       xml_insert_element (DEFDATATYPE, START);
2300       execute_string ("%s", defined_name);
2301       xml_insert_element (DEFDATATYPE, END);
2302       break;
2303
2304     case defcv:
2305     case deftypecv:
2306     case deftypeivar:
2307       xml_insert_element (DEFCLASSVAR, START);
2308       execute_string ("%s", defined_name);
2309       xml_insert_element (DEFCLASSVAR, END);
2310       break;
2311
2312     case defop:
2313     case deftypeop:
2314     case deftypemethod:
2315       /* Operation / Method */
2316       xml_insert_element (DEFOPERATION, START);
2317       execute_string ("%s", defined_name);
2318       xml_insert_element (DEFOPERATION, END);
2319       break;
2320     }
2321 }
2322
2323 void
2324 xml_end_def_term (void)
2325 {
2326   xml_insert_element (DEFINITIONTERM, END);
2327   xml_after_def_term = 1;
2328 }