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