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