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